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(url::Url),
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
75                .install_update(Some(&url), None)
76                .await
77                .map_err(UpdateError::InstallError)?;
78        }
79        UpdateUrlSource::UseDefault => {
80            let () = updater.install_update(None, None).await.map_err(UpdateError::InstallError)?;
81        }
82    }
83    Ok(())
84}
85
86/// Installs all packages and writes the Fuchsia ZBI from the latest build on the given channel.
87///
88/// The following conditions are expected to be met:
89/// * Network services (fuchsia.net.name.Lookup and fuchsia.posix.socket.Provider) are available in
90///   the /svc/ directory.
91/// * `pkg-recovery.cml` should be a child of this component, and all
92///   dependencies specified in its 'offer' section should be available in the
93///   out directory of the component running this code prior to this function
94///   being called.
95///
96/// If successful, a reboot should be the only thing necessary to boot Fuchsia.
97///
98/// # Arguments
99/// * `channel_name` - The channel to update from.
100/// * `version` - Version to report as the current installed version.
101/// * `omaha_cfg` - The |OmahaConfig| to use for Omaha. If None, the update will not use Omaha to
102///   determine the updater URL.
103pub async fn download_and_apply_update(
104    channel_name: &str,
105    version: &str,
106    omaha_cfg: Option<OmahaConfig>,
107) -> Result<(), UpdateError> {
108    let updater = Updater::new().map_err(UpdateError::UpdaterConnectError)?;
109    let update_url_source = if let Some(omaha_cfg) = omaha_cfg {
110        UpdateUrlSource::OmahaConfig(omaha_cfg)
111    } else {
112        UpdateUrlSource::UseDefault
113    };
114    download_and_apply_update_with_updater(updater, channel_name, version, update_url_source).await
115}