Skip to main content

isolated_ota/
lib.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#![allow(clippy::let_unit_value)]
6
7use isolated_swd::omaha;
8use isolated_swd::updater::Updater;
9use thiserror::Error;
10
11#[derive(Debug, Error)]
12pub enum UpdateError {
13    #[error("error launching pkg-cache")]
14    PkgCacheLaunchError(#[source] anyhow::Error),
15
16    #[error("error launching pkg-resolver")]
17    PkgResolverLaunchError(#[source] anyhow::Error),
18
19    #[error("error launching system-updater and installing update")]
20    InstallError(#[source] anyhow::Error),
21
22    #[error("error setting up resources")]
23    FidlError(#[source] fidl::Error),
24
25    #[error("IO error occurred")]
26    IoError(#[source] std::io::Error),
27
28    #[error("error connecting to system-updater")]
29    UpdaterConnectError(#[source] anyhow::Error),
30}
31
32pub struct OmahaConfig {
33    /// The app_id to use for Omaha.
34    pub app_id: String,
35    /// The URL of the Omaha server.
36    pub server_url: String,
37}
38
39/// How to obtain the URL for the update package.
40pub enum UpdateUrlSource {
41    /// Obtain the update package URL from an Omaha server.
42    OmahaConfig(OmahaConfig),
43
44    /// Use this URL.
45    UpdateUrl(http::Uri),
46
47    /// Use the default update package URL "fuchsia-pkg://fuchsia.com/update".
48    UseDefault,
49}
50
51/// Installs all packages and writes the Fuchsia ZBI from the latest build on the given channel.
52///
53/// Has the same arguments as `download_and_apply_update`, but allows passing in
54/// pre-configured components for testing.
55pub async fn download_and_apply_update_with_updater(
56    mut updater: Updater,
57    channel_name: &str,
58    version: &str,
59    update_url_source: UpdateUrlSource,
60) -> Result<(), UpdateError> {
61    match update_url_source {
62        UpdateUrlSource::OmahaConfig(cfg) => {
63            let () = omaha::install_update(
64                updater,
65                cfg.app_id,
66                cfg.server_url,
67                version.to_owned(),
68                channel_name.to_owned(),
69            )
70            .await
71            .map_err(UpdateError::InstallError)?;
72        }
73        UpdateUrlSource::UpdateUrl(url) => {
74            let () = updater.install_update(Some(&url)).await.map_err(UpdateError::InstallError)?;
75        }
76        UpdateUrlSource::UseDefault => {
77            let () = updater.install_update(None).await.map_err(UpdateError::InstallError)?;
78        }
79    }
80    Ok(())
81}
82
83/// Installs all packages and writes the Fuchsia ZBI from the latest build on the given channel.
84///
85/// The following conditions are expected to be met:
86/// * Network services (fuchsia.net.name.Lookup and fuchsia.posix.socket.Provider) are available in
87///   the /svc/ directory.
88/// * `pkg-recovery.cml` should be a child of this component, and all
89///   dependencies specified in its 'offer' section should be available in the
90///   out directory of the component running this code prior to this function
91///   being called.
92///
93/// If successful, a reboot should be the only thing necessary to boot Fuchsia.
94///
95/// # Arguments
96/// * `channel_name` - The channel to update from.
97/// * `version` - Version to report as the current installed version.
98/// * `omaha_cfg` - The |OmahaConfig| to use for Omaha. If None, the update will not use Omaha to
99///   determine the updater URL.
100pub async fn download_and_apply_update(
101    channel_name: &str,
102    version: &str,
103    omaha_cfg: Option<OmahaConfig>,
104) -> Result<(), UpdateError> {
105    let updater = Updater::new().map_err(UpdateError::UpdaterConnectError)?;
106    let update_url_source = if let Some(omaha_cfg) = omaha_cfg {
107        UpdateUrlSource::OmahaConfig(omaha_cfg)
108    } else {
109        UpdateUrlSource::UseDefault
110    };
111    download_and_apply_update_with_updater(updater, channel_name, version, update_url_source).await
112}