Esempio n. 1
0
/**
 * rpmostreed_sysroot_populate :
 *
 * loads internals and starts monitoring
 *
 * Returns: True on success
 */
gboolean
rpmostreed_sysroot_populate (RpmostreedSysroot *self,
			     GCancellable *cancellable,
                             GError **error)
{
  gboolean ret = FALSE;
  g_autoptr(GFile) sysroot_file = NULL;
  const char *sysroot_path;

  g_return_val_if_fail (self != NULL, FALSE);

  sysroot_path = rpmostree_sysroot_get_path (RPMOSTREE_SYSROOT (self));
  sysroot_file = g_file_new_for_path (sysroot_path);
  self->ot_sysroot = ostree_sysroot_new (sysroot_file);

  /* This creates and caches an OstreeRepo instance inside
   * OstreeSysroot to ensure subsequent ostree_sysroot_get_repo()
   * calls won't fail.
   */
  if (!ostree_sysroot_get_repo (self->ot_sysroot, &self->repo, cancellable, error))
    goto out;

  if (!sysroot_populate_deployments_unlocked (self, NULL, error))
    goto out;

  if (self->monitor == NULL)
    {
      const char *sysroot_path = gs_file_get_path_cached (ostree_sysroot_get_path (self->ot_sysroot));
      g_autofree char *sysroot_deploy_path = g_build_filename (sysroot_path, "ostree/deploy", NULL);
      g_autoptr(GFile) sysroot_deploy = g_file_new_for_path (sysroot_deploy_path);
      
      self->monitor = g_file_monitor (sysroot_deploy, 0, NULL, error);

      if (self->monitor == NULL)
        goto out;

      self->sig_changed = g_signal_connect (self->monitor,
                                            "changed",
                                            G_CALLBACK (on_deploy_changed),
                                            self);
    }

  ret = TRUE;
out:
  return ret;
}
gboolean
ot_admin_builtin_os_init (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  GOptionContext *context;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  gboolean ret = FALSE;
  const char *osname = NULL;
  g_autoptr(GFile) deploy_dir = NULL;
  g_autoptr(GFile) dir = NULL;

  context = g_option_context_new ("OSNAME - Initialize empty state for given operating system");

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

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

  if (argc < 2)
    {
      ot_util_usage_error (context, "OSNAME must be specified", error);
      goto out;
    }

  osname = argv[1];

  deploy_dir = ot_gfile_get_child_build_path (ostree_sysroot_get_path (sysroot), "ostree", "deploy", osname, NULL);

  /* Ensure core subdirectories of /var exist, since we need them for
   * dracut generation, and the host will want them too.
   */
  g_clear_object (&dir);
  dir = ot_gfile_get_child_build_path (deploy_dir, "var", "tmp", NULL);
  if (!gs_file_ensure_directory (dir, TRUE, cancellable, error))
    goto out;
  if (chmod (gs_file_get_path_cached (dir), 01777) < 0)
    {
      gs_set_error_from_errno (error, errno);
      goto out;
    }

  g_clear_object (&dir);
  dir = ot_gfile_get_child_build_path (deploy_dir, "var", "lib", NULL);
  if (!gs_file_ensure_directory (dir, TRUE, cancellable, error))
    goto out;

  g_clear_object (&dir);
  dir = ot_gfile_get_child_build_path (deploy_dir, "var", "run", NULL);
  if (!g_file_test (gs_file_get_path_cached (dir), G_FILE_TEST_IS_SYMLINK))
    {
      if (symlink ("../run", gs_file_get_path_cached (dir)) < 0)
        {
          gs_set_error_from_errno (error, errno);
          goto out;
        }
    }

  dir = ot_gfile_get_child_build_path (deploy_dir, "var", "lock", NULL);
  if (!g_file_test (gs_file_get_path_cached (dir), G_FILE_TEST_IS_SYMLINK))
    {
      if (symlink ("../run/lock", gs_file_get_path_cached (dir)) < 0)
        {
          gs_set_error_from_errno (error, errno);
          goto out;
        }
    }

  g_print ("%s initialized as OSTree root\n", gs_file_get_path_cached (deploy_dir));

  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
gboolean
ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  GOptionContext *context;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
  g_autofree char *origin_remote = NULL;
  g_autofree char *origin_ref = NULL;
  g_autofree char *origin_refspec = NULL;
  g_autofree char *new_revision = NULL;
  g_autoptr(GFile) deployment_path = NULL;
  g_autoptr(GFile) deployment_origin_path = NULL;
  glnx_unref_object OstreeDeployment *merge_deployment = NULL;
  glnx_unref_object OstreeDeployment *new_deployment = NULL;
  GSConsole *console = NULL;
  gboolean in_status_line = FALSE;
  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;

  console = gs_console_get ();
  if (console)
    {
      gs_console_begin_status_line (console, "", NULL, NULL);
      in_status_line = TRUE;
      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 (in_status_line)
    {
      gs_console_end_status_line (console, NULL, NULL);
      in_status_line = FALSE;
    }

  if (!changed)
    {
      g_print ("No update available.\n");
    }
  else
    {
      g_autoptr(GFile) real_sysroot = g_file_new_for_path ("/");

      if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
        goto out;

      if (opt_reboot && g_file_equal (ostree_sysroot_get_path (sysroot), real_sysroot))
        {
          gs_subprocess_simple_run_sync (NULL, GS_SUBPROCESS_STREAM_DISPOSITION_INHERIT,
                                         cancellable, error,
                                         "systemctl", "reboot", NULL);
        }
    }

  ret = TRUE;
 out:
  if (in_status_line)
    gs_console_end_status_line (console, NULL, NULL);
  if (context)
    g_option_context_free (context);
  return ret;
}
Esempio n. 4
0
gboolean
ostree_admin_option_context_parse (GOptionContext *context,
                                   const GOptionEntry *main_entries,
                                   int *argc,
                                   char ***argv,
                                   OstreeAdminBuiltinFlags flags,
                                   OstreeSysroot **out_sysroot,
                                   GCancellable *cancellable,
                                   GError **error)
{
  g_autoptr(GFile) sysroot_path = NULL;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  gboolean success = FALSE;

  /* Entries are listed in --help output in the order added.  We add the
   * main entries ourselves so that we can add the --sysroot entry first. */

  g_option_context_add_main_entries (context, global_admin_entries, NULL);

  if (!ostree_option_context_parse (context, main_entries, argc, argv, OSTREE_BUILTIN_FLAG_NO_REPO, NULL, cancellable, error))
    goto out;

  if (opt_sysroot != NULL)
    sysroot_path = g_file_new_for_path (opt_sysroot);

  sysroot = ostree_sysroot_new (sysroot_path);

  if (flags & OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER)
    {
      GFile *path = ostree_sysroot_get_path (sysroot);

      /* If sysroot path is "/" then user must be root. */
      if (!g_file_has_parent (path, NULL) && getuid () != 0)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
                       "You must be root to perform this command");
          goto out;
        }
    }

  if (opt_print_current_dir)
    {
      g_autoptr(GPtrArray) deployments = NULL;
      OstreeDeployment *first_deployment;
      g_autoptr(GFile) deployment_file = NULL;
      g_autofree char *deployment_path = NULL;

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

      deployments = ostree_sysroot_get_deployments (sysroot);
      if (deployments->len == 0)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Unable to find a deployment in sysroot");
          goto out;
        }
      first_deployment = deployments->pdata[0];
      deployment_file = ostree_sysroot_get_deployment_directory (sysroot, first_deployment);
      deployment_path = g_file_get_path (deployment_file);

      g_print ("%s\n", deployment_path);

      /* The g_autoptr, g_autofree etc. don't happen when we explicitly
       * exit, making valgrind complain about leaks */
      g_clear_object (&sysroot);
      g_clear_object (&sysroot_path);
      g_clear_object (&deployment_file);
      g_clear_pointer (&deployments, g_ptr_array_unref);
      g_clear_pointer (&deployment_path, g_free);
      exit (EXIT_SUCCESS);
    }

  if ((flags & OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED) == 0)
    {
      /* Released when sysroot is finalized, or on process exit */
      if (!ot_admin_sysroot_lock (sysroot, error))
        goto out;
    }

  if (out_sysroot)
    *out_sysroot = g_steal_pointer (&sysroot);

  success = TRUE;

out:
  return success;
}
Esempio n. 5
0
gboolean
ot_admin_builtin_switch (int argc, char **argv, OstreeSysroot *sysroot, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  GOptionContext *context;
  const char *new_provided_refspec = NULL;
  gs_unref_object OstreeRepo *repo = NULL;
  gs_free char *origin_refspec = NULL;
  gs_free char *origin_remote = NULL;
  gs_free char *origin_ref = NULL;
  gs_free char *new_remote = NULL;
  gs_free char *new_ref = NULL;
  gs_free char *new_refspec = NULL;
  gs_free char *new_revision = NULL;
  gs_unref_object GFile *deployment_path = NULL;
  gs_unref_object GFile *deployment_origin_path = NULL;
  gs_unref_object OstreeDeployment *merge_deployment = NULL;
  gs_unref_object OstreeDeployment *new_deployment = NULL;
  gs_unref_object OstreeSysrootUpgrader *upgrader = NULL;
  gs_unref_object OstreeAsyncProgress *progress = NULL;
  gboolean changed;
  GSConsole *console = NULL;
  gboolean in_status_line = FALSE;
  GKeyFile *old_origin;
  GKeyFile *new_origin = NULL;

  context = g_option_context_new ("REF - Construct new tree from current origin and deploy it, if it changed");
  g_option_context_add_main_entries (context, options, NULL);

  if (!g_option_context_parse (context, &argc, &argv, error))
    goto out;

  if (argc < 2)
    {
      ot_util_usage_error (context, "REF must be specified", error);
      goto out;
    }

  new_provided_refspec = argv[1];

  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;

  old_origin = ostree_sysroot_upgrader_get_origin (upgrader);
  origin_refspec = g_key_file_get_string (old_origin, "origin", "refspec", NULL);
  
  if (!ostree_parse_refspec (origin_refspec, &origin_remote, &origin_ref, error))
    goto out;

  /* Allow just switching remotes */
  if (g_str_has_suffix (new_provided_refspec, ":"))
    {
      new_remote = g_strdup (new_provided_refspec);
      new_remote[strlen(new_remote)-1] = '\0';
      new_ref = g_strdup (origin_ref);
    }
  else
    {
      if (!ostree_parse_refspec (new_provided_refspec, &new_remote, &new_ref, error))
        goto out;
    }
  
  if (!new_remote)
    new_refspec = g_strconcat (origin_remote, ":", new_ref, NULL);
  else
    new_refspec = g_strconcat (new_remote, ":", new_ref, NULL);
  
  if (strcmp (origin_refspec, new_refspec) == 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Old and new refs are equal: %s", new_refspec);
      goto out;
    }

  new_origin = ostree_sysroot_origin_new_from_refspec (sysroot, new_refspec);
  if (!ostree_sysroot_upgrader_set_origin (upgrader, new_origin, cancellable, error))
    goto out;

  console = gs_console_get ();
  if (console)
    {
      gs_console_begin_status_line (console, "", NULL, NULL);
      in_status_line = TRUE;
      progress = ostree_async_progress_new_and_connect (ot_common_pull_progress, console);
    }

  /* Always allow older...there's not going to be a chronological
   * relationship necessarily.
   */
  if (!ostree_sysroot_upgrader_pull (upgrader, 0,
                                     OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
                                     progress, &changed,
                                     cancellable, error))
    goto out;

  if (in_status_line)
    {
      gs_console_end_status_line (console, NULL, NULL);
      in_status_line = FALSE;
    }

  if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
    goto out;

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

  if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
    goto out;

  g_print ("Deleting ref '%s:%s'\n", origin_remote, origin_ref);
  ostree_repo_transaction_set_ref (repo, origin_remote, origin_ref, NULL);
  
  if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
    goto out;
  
  {
    gs_unref_object GFile *real_sysroot = g_file_new_for_path ("/");
      
    if (opt_reboot && g_file_equal (ostree_sysroot_get_path (sysroot), real_sysroot))
      {
        gs_subprocess_simple_run_sync (NULL, GS_SUBPROCESS_STREAM_DISPOSITION_INHERIT,
                                       cancellable, error,
                                       "systemctl", "reboot", NULL);
      }
  }

  ret = TRUE;
 out:
  if (in_status_line)
    gs_console_end_status_line (console, NULL, NULL);
  if (new_origin)
    g_key_file_unref (new_origin);
  if (context)
    g_option_context_free (context);
  return ret;
}