Exemple #1
0
gboolean
ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  g_autoptr(GOptionContext) context = NULL;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
  g_autoptr(GKeyFile) origin = NULL;
  glnx_unref_object OstreeAsyncProgress *progress = NULL;
  gboolean changed;
  OstreeSysrootUpgraderPullFlags upgraderpullflags = 0;

  context = g_option_context_new ("Construct new tree from current origin and deploy it, if it changed");

  if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
                                          OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER,
                                          &sysroot, cancellable, error))
    goto out;

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  upgrader = ostree_sysroot_upgrader_new_for_os (sysroot, opt_osname,
                                                 cancellable, error);
  if (!upgrader)
    goto out;

  origin = ostree_sysroot_upgrader_dup_origin (upgrader);
  if (origin != NULL)
    {
      gboolean origin_changed = FALSE;

      if (opt_override_commit != NULL)
        {
          /* Override the commit to pull and deploy. */
          g_key_file_set_string (origin, "origin",
                                 "override-commit",
                                 opt_override_commit);
          origin_changed = TRUE;
        }
      else
        {
          /* Strip any override-commit from the origin file so
           * we always upgrade to the latest available commit. */
          origin_changed = g_key_file_remove_key (origin, "origin",
                                                  "override-commit", NULL);
        }

      /* Should we consider requiring --discard-hotfix here? */
      origin_changed |= g_key_file_remove_key (origin, "origin", "unlocked", NULL);

      if (origin_changed)
        {
          /* XXX GCancellable parameter is not used. */
          if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, NULL, error))
            goto out;
        }
    }

  { g_auto(GLnxConsoleRef) console = { 0, };
    glnx_console_lock (&console);

    if (console.is_tty)
      progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);

    if (opt_allow_downgrade)
      upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;
    
    if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags,
                                       progress, &changed,
                                       cancellable, error))
      goto out;

    if (progress)
      ostree_async_progress_finish (progress);
  }

  if (!changed)
    {
      g_print ("No update available.\n");
    }
  else
    {
      if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
        goto out;

      if (opt_reboot)
        {
          if (!ot_admin_execve_reboot (sysroot, error))
            goto out;
        }
    }

  ret = TRUE;
 out:
  return ret;
}
gboolean
ot_admin_builtin_upgrade (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
  g_autoptr(GOptionContext) context = g_option_context_new ("");

  g_autoptr(OstreeSysroot) sysroot = NULL;
  if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
                                          OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER,
                                          invocation, &sysroot, cancellable, error))
    return FALSE;

  if (opt_pull_only && opt_deploy_only)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Cannot simultaneously specify --pull-only and --deploy-only");
      return FALSE;
    }
  else if (opt_pull_only && opt_reboot)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Cannot simultaneously specify --pull-only and --reboot");
      return FALSE;
    }

  g_autoptr(OstreeSysrootUpgrader) upgrader =
    ostree_sysroot_upgrader_new_for_os (sysroot, opt_osname,
                                        cancellable, error);
  if (!upgrader)
    return FALSE;

  g_autoptr(GKeyFile) origin = ostree_sysroot_upgrader_dup_origin (upgrader);
  if (origin != NULL)
    {
      gboolean origin_changed = FALSE;

      if (opt_override_commit != NULL)
        {
          /* Override the commit to pull and deploy. */
          g_key_file_set_string (origin, "origin",
                                 "override-commit",
                                 opt_override_commit);
          origin_changed = TRUE;
        }
      else
        {
          /* Strip any override-commit from the origin file so
           * we always upgrade to the latest available commit. */
          origin_changed = g_key_file_remove_key (origin, "origin",
                                                  "override-commit", NULL);
        }

      /* Should we consider requiring --discard-hotfix here? */
      origin_changed |= g_key_file_remove_key (origin, "origin", "unlocked", NULL);

      if (origin_changed)
        {
          /* XXX GCancellable parameter is not used. */
          if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, NULL, error))
            return FALSE;
        }
    }

  gboolean changed;
  OstreeSysrootUpgraderPullFlags upgraderpullflags = 0;
  if (opt_deploy_only)
    upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_SYNTHETIC;

  { g_auto(GLnxConsoleRef) console = { 0, };
    glnx_console_lock (&console);

    g_autoptr(OstreeAsyncProgress) progress = NULL;
    if (console.is_tty)
      progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);

    if (opt_allow_downgrade)
      upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;

    if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags,
                                       progress, &changed,
                                       cancellable, error))
      {
        /* In the pull-only case, we do a cleanup here to ensure that if
         * multiple commits were pulled, we garbage collect any old
         * partially-pulled intermediate commits before pulling more. This is
         * really a best practice in general, but for maximum compatiblity, we
         * only do cleanup if a user specifies the new --pull-only option.
         * Otherwise, we would break the case of trying to deploy a commit that
         * isn't directly referenced.
         */
        if (opt_pull_only)
          (void) ostree_sysroot_cleanup (sysroot, NULL, NULL);
        return FALSE;
      }

    if (progress)
      ostree_async_progress_finish (progress);
  }

  if (!changed)
    {
      g_print ("No update available.\n");
    }
  else
    {
      if (!opt_pull_only)
        {
          if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
            return FALSE;
        }

      if (opt_reboot)
        {
          if (!ot_admin_execve_reboot (sysroot, error))
            return FALSE;
        }
    }

  return TRUE;
}
static gboolean
package_diff_transaction_execute (RpmostreedTransaction *transaction,
                                  GCancellable *cancellable,
                                  GError **error)
{
  PackageDiffTransaction *self;
  OstreeSysroot *sysroot;

  glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
  glnx_unref_object OstreeAsyncProgress *progress = NULL;
  glnx_unref_object OstreeRepo *repo = NULL;
  g_autoptr(GKeyFile) origin = NULL;
  g_autofree gchar *origin_description = NULL;

  OstreeSysrootUpgraderPullFlags upgrader_flags = 0;
  gboolean upgrading = FALSE;
  gboolean changed = FALSE;
  gboolean ret = FALSE;

  self = (PackageDiffTransaction *) transaction;
  sysroot = rpmostreed_transaction_get_sysroot (transaction);
  upgrader = ostree_sysroot_upgrader_new_for_os (sysroot,
                                                 self->osname,
                                                 cancellable,
                                                 error);
  if (upgrader == NULL)
    goto out;

  if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
    goto out;

  origin = ostree_sysroot_upgrader_dup_origin (upgrader);

  /* Determine if we're upgrading before we set the refspec. */
  upgrading = (self->refspec == NULL && self->revision == NULL);

  if (self->refspec != NULL)
    {
      if (!change_upgrader_refspec (sysroot, upgrader,
                                    self->refspec, cancellable,
                                    NULL, NULL, error))
        goto out;
    }
  else if (origin != NULL)
    {
      self->refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
      if (self->refspec == NULL)
        {
          g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                               "Could not find refspec for booted deployment");
        }
    }
  else
    {
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Booted deployment has no origin");
      goto out;
    }

  progress = ostree_async_progress_new ();
  rpmostreed_transaction_connect_download_progress (transaction, progress);
  rpmostreed_transaction_connect_signature_progress (transaction, repo);

  if (self->revision != NULL)
    {
      g_autofree char *checksum = NULL;
      g_autofree char *version = NULL;

      upgrader_flags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;

      if (!rpmostreed_parse_revision (self->revision,
                                      &checksum,
                                      &version,
                                      error))
        goto out;

      if (version != NULL)
        {
          rpmostreed_transaction_emit_message_printf (transaction,
                                                      "Resolving version '%s'",
                                                      version);

          if (!rpmostreed_repo_lookup_version (repo,
                                               self->refspec,
                                               version,
                                               progress,
                                               cancellable,
                                               &checksum,
                                               error))
            goto out;
        }

      g_key_file_set_string (origin, "origin", "override-commit", checksum);

      if (!ostree_sysroot_upgrader_set_origin (upgrader, origin,
                                               cancellable, error))
        goto out;
    }
  else if (upgrading)
    {
      if (g_key_file_remove_key (origin, "origin", "override-commit", NULL))
        {
          if (!ostree_sysroot_upgrader_set_origin (upgrader, origin,
                                                   cancellable, error))
            goto out;
        }
    }

  origin_description = ostree_sysroot_upgrader_get_origin_description (upgrader);
  if (origin_description != NULL)
    rpmostreed_transaction_emit_message_printf (transaction,
                                                "Updating from: %s",
                                                origin_description);

  if (!ostree_sysroot_upgrader_pull_one_dir (upgrader,
					     "/usr/share/rpm",
					     0, upgrader_flags,
					     progress,
					     &changed,
					     cancellable,
					     error))
    goto out;

  rpmostree_transaction_emit_progress_end (RPMOSTREE_TRANSACTION (transaction));

  if (!changed)
    {
      if (upgrading)
        rpmostreed_transaction_emit_message_printf (transaction,
                                                    "No upgrade available.");
      else
        rpmostreed_transaction_emit_message_printf (transaction,
                                                    "No change.");
    }

  ret = TRUE;
out:
  return ret;
}