Exemple #1
0
void
storage_volume_group_update (StorageVolumeGroup *self,
                             gboolean ignore_locks,
                             StorageVolumeGroupCallback *done,
                             gpointer done_user_data)
{
  struct UpdateData *data;
  const gchar *args[6];
  int i;

  i = 0;
  args[i++] = STORAGED_HELPER_EXEC_NAME;
  args[i++] = "-b";
  if (ignore_locks)
    args[i++] = "-f";
  args[i++] = "show";
  args[i++] = self->name;
  args[i++] = NULL;

  data = g_new0 (struct UpdateData, 1);
  data->self = g_object_ref (self);
  data->done = done;
  data->done_user_data = done_user_data;

  storage_daemon_spawn_for_variant (storage_daemon_get (), args, G_VARIANT_TYPE ("a{sv}"),
                                    update_with_variant, data);
}
Exemple #2
0
void
storage_block_update_pv (StorageBlock *self,
                         StorageVolumeGroup *group,
                         GVariant *pv_info)
{
  StorageDaemon *daemon;

  g_return_if_fail (STORAGE_IS_BLOCK (self));

  daemon = storage_daemon_get ();

  if (group)
    {
     if (self->iface_physical_volume == NULL)
        {
          self->iface_physical_volume = storage_physical_volume_new ();
          storage_physical_volume_update (self->iface_physical_volume, group, pv_info);
          storage_daemon_publish (daemon, storage_block_get_object_path (self), FALSE, self->iface_physical_volume);
        }
      else
        {
          storage_physical_volume_update (self->iface_physical_volume, group, pv_info);
        }
    }
  else
    {
      if (self->iface_physical_volume != NULL)
        {
          storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_physical_volume);
          g_object_unref (self->iface_physical_volume);
          self->iface_physical_volume = NULL;
        }
    }

}
Exemple #3
0
static void
storage_volume_group_dispose (GObject *obj)
{
  StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (obj);
  GHashTableIter iter;
  const gchar *path;
  gpointer value;

  self->need_publish = FALSE;

  /* Dispose all the volumes, should unpublish */
  g_hash_table_iter_init (&iter, self->logical_volumes);
  while (g_hash_table_iter_next (&iter, NULL, &value))
      g_object_run_dispose (value);
  g_hash_table_remove_all (self->logical_volumes);
  g_hash_table_remove_all (self->physical_volumes);

  if (self->info)
    {
      g_variant_unref (self->info);
      self->info = NULL;
    }

  update_all_blocks (self);

  path = storage_volume_group_get_object_path (self);
  if (path != NULL)
    storage_daemon_unpublish (storage_daemon_get (), path, self);

  G_OBJECT_CLASS (storage_volume_group_parent_class)->dispose (obj);
}
Exemple #4
0
static gboolean
handle_create_thin_volume (LvmVolumeGroup *group,
                           GDBusMethodInvocation *invocation,
                           const gchar *arg_name,
                           guint64 arg_size,
                           const gchar *arg_pool,
                           GVariant *options)
{
  StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group);
  CompleteClosure *complete;
  StorageJob *job;
  StorageDaemon *daemon;
  StorageLogicalVolume *pool;
  gchar *size;

  daemon = storage_daemon_get ();

  pool = storage_daemon_find_thing (daemon, arg_pool, STORAGE_TYPE_LOGICAL_VOLUME);
  if (pool == NULL)
    {
      g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
                                             "Not a valid logical volume");
      return TRUE;
    }

  arg_size -= arg_size % 512;

  size = g_strdup_printf ("%" G_GUINT64_FORMAT "b", arg_size);

  job = storage_daemon_launch_spawned_job (daemon, self,
                                           "lvm-vg-create-volume",
                                           storage_invocation_get_caller_uid (invocation),
                                           NULL, /* GCancellable */
                                           0,    /* uid_t run_as_uid */
                                           0,    /* uid_t run_as_euid */
                                           NULL,  /* input_string */
                                           "lvcreate",
                                           storage_volume_group_get_name (self),
                                           "--thinpool", storage_logical_volume_get_name (pool),
                                           "-V", size, "-n", arg_name, NULL);

  complete = g_new0 (CompleteClosure, 1);
  complete->invocation = g_object_ref (invocation);
  complete->wait_thing = g_object_ref (self);
  complete->wait_name = g_strdup (arg_name);

  /* Wait for the job to finish */
  g_signal_connect (job, "completed", G_CALLBACK (on_create_complete), complete);

  /* Wait for the object to appear */
  complete->wait_sig = g_signal_connect_data (daemon,
                                              "published::StorageLogicalVolume",
                                              G_CALLBACK (on_create_logical_volume),
                                              complete, complete_closure_free, 0);

  g_free (size);
  g_object_unref (pool);
  return TRUE;
}
Exemple #5
0
static gboolean
handle_add_device (LvmVolumeGroup *group,
                   GDBusMethodInvocation  *invocation,
                   const gchar *new_member_device_objpath,
                   GVariant *options)
{
  StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group);
  StorageJob *job;
  StorageDaemon *daemon;
  StorageManager *manager;
  GError *error = NULL;
  StorageBlock *new_member_device = NULL;

  daemon = storage_daemon_get ();
  manager = storage_daemon_get_manager (daemon);

  new_member_device = storage_manager_find_block (manager, new_member_device_objpath);
  if (new_member_device == NULL)
    {
      g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
                                             "The given object is not a valid block");
    }
  else if (!storage_block_is_unused (new_member_device, &error))
    {
      g_dbus_method_invocation_take_error (invocation, error);
    }
  else if (!storage_util_wipe_block (storage_block_get_device (new_member_device), &error))
    {
      g_dbus_method_invocation_take_error (invocation, error);
    }
  else
    {
      job = storage_daemon_launch_spawned_job (daemon, self,
                                               "lvm-vg-add-device",
                                               storage_invocation_get_caller_uid (invocation),
                                               NULL, /* GCancellable */
                                               0,    /* uid_t run_as_uid */
                                               0,    /* uid_t run_as_euid */
                                               NULL,  /* input_string */
                                               "vgextend",
                                               storage_volume_group_get_name (self),
                                               storage_block_get_device (new_member_device),
                                               NULL);

      g_signal_connect_data (job, "completed", G_CALLBACK (on_adddev_complete),
                             g_object_ref (invocation), (GClosureNotify)g_object_unref, 0);
    }

  g_clear_object (&new_member_device);
  return TRUE; /* returning TRUE means that we handled the method invocation */
}
Exemple #6
0
static gboolean
handle_create_plain_volume (LvmVolumeGroup *group,
                            GDBusMethodInvocation *invocation,
                            const gchar *arg_name,
                            guint64 arg_size,
                            GVariant *options)
{
  StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group);
  CompleteClosure *complete;
  StorageJob *job;
  StorageDaemon *daemon;
  GPtrArray *argv;

  daemon = storage_daemon_get ();

  arg_size -= arg_size % 512;

  argv = g_ptr_array_new_with_free_func (g_free);
  g_ptr_array_add (argv, g_strdup ("lvcreate"));
  g_ptr_array_add (argv, g_strdup (storage_volume_group_get_name (self)));
  g_ptr_array_add (argv, g_strdup_printf ("-L%" G_GUINT64_FORMAT "b", arg_size));
  g_ptr_array_add (argv, g_strdup ("-n"));
  g_ptr_array_add (argv, g_strdup (arg_name));
  g_ptr_array_add (argv, NULL);

  job = storage_daemon_launch_spawned_jobv (daemon, self,
                                            "lvm-vg-create-volume",
                                            storage_invocation_get_caller_uid (invocation),
                                            NULL, /* GCancellable */
                                            0,    /* uid_t run_as_uid */
                                            0,    /* uid_t run_as_euid */
                                            NULL,  /* input_string */
                                            (const gchar **)argv->pdata);

  complete = g_new0 (CompleteClosure, 1);
  complete->invocation = g_object_ref (invocation);
  complete->wait_thing = g_object_ref (self);
  complete->wait_name = g_strdup (arg_name);

  /* Wait for the job to finish */
  g_signal_connect (job, "completed", G_CALLBACK (on_create_complete), complete);

  /* Wait for the object to appear */
  complete->wait_sig = g_signal_connect_data (daemon,
                                              "published::StorageLogicalVolume",
                                              G_CALLBACK (on_create_logical_volume),
                                              complete, complete_closure_free, 0);

  g_ptr_array_free (argv, TRUE);
  return TRUE;
}
Exemple #7
0
static gboolean
handle_delete (LvmVolumeGroup *group,
               GDBusMethodInvocation *invocation,
               gboolean arg_wipe,
               GVariant *arg_options)
{
  StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group);
  VolumeGroupDeleteJobData *data;
  StorageDaemon *daemon;
  StorageJob *job;
  GList *l;

  daemon = storage_daemon_get ();

  data = g_new0 (VolumeGroupDeleteJobData, 1);
  data->vgname = g_strdup (storage_volume_group_get_name (self));

  /* Find physical volumes to wipe. */
  if (arg_wipe)
    {
      GPtrArray *devices = g_ptr_array_new ();
      GList *blocks = storage_manager_get_blocks (storage_daemon_get_manager (daemon));
      for (l = blocks; l; l = l->next)
        {
          LvmPhysicalVolumeBlock *physical_volume;
          physical_volume = storage_block_get_physical_volume_block (l->data);
          if (physical_volume
              && g_strcmp0 (lvm_physical_volume_block_get_volume_group (physical_volume),
                            storage_volume_group_get_object_path (self)) == 0)
            g_ptr_array_add (devices, g_strdup (storage_block_get_device (l->data)));
        }
      g_list_free_full (blocks, g_object_unref);
      g_ptr_array_add (devices, NULL);
      data->devices = (gchar **)g_ptr_array_free (devices, FALSE);
    }

  job = storage_daemon_launch_threaded_job (daemon, self,
                                            "lvm-vg-delete",
                                            storage_invocation_get_caller_uid (invocation),
                                            volume_group_delete_job_thread,
                                            data,
                                            volume_group_delete_job_free,
                                            NULL);

  g_signal_connect_data (job, "completed", G_CALLBACK (on_delete_complete),
                         g_object_ref (invocation), (GClosureNotify)g_object_unref, 0);

  return TRUE;
}
Exemple #8
0
static void
on_rename_complete (UDisksJob *job,
                    gboolean success,
                    gchar *message,
                    gpointer user_data)
{
  CompleteClosure *complete = user_data;

  if (success)
    return;

  g_dbus_method_invocation_return_error (complete->invocation, UDISKS_ERROR,
                                         UDISKS_ERROR_FAILED, "Error renaming volume group: %s", message);
  g_signal_handler_disconnect (storage_daemon_get (), complete->wait_sig);
}
Exemple #9
0
static void
poll_now (StorageVolumeGroup *self)
{
  const gchar *args[] = {
      STORAGED_HELPER_EXEC_NAME,
      "-b", "show", self->name, NULL
  };

  self->poll_timeout_id = g_timeout_add (5000, poll_timeout, g_object_ref (self));

  if (self->poll_pid)
    kill (self->poll_pid, SIGINT);

  self->poll_pid = storage_daemon_spawn_for_variant (storage_daemon_get (), args, G_VARIANT_TYPE ("a{sv}"),
                                                     poll_with_variant, g_object_ref (self));
}
Exemple #10
0
static gboolean
handle_remove_device (LvmVolumeGroup *group,
                      GDBusMethodInvocation *invocation,
                      const gchar *member_device_objpath,
                      gboolean wipe,
                      GVariant *options)
{
  StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group);
  VolumeGroupRemdevJobData *data;
  StorageDaemon *daemon;
  StorageManager *manager;
  StorageBlock *member_device;
  StorageJob *job;

  daemon = storage_daemon_get ();
  manager = storage_daemon_get_manager (daemon);

  member_device = storage_manager_find_block (manager, member_device_objpath);
  if (member_device == NULL)
    {
      g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
                                             "The given object is not a valid block");
      return TRUE;
    }

  data = g_new0 (VolumeGroupRemdevJobData, 1);
  data->wipe = wipe;
  data->vgname = g_strdup (storage_volume_group_get_name (self));
  data->pvname = g_strdup (storage_block_get_device (member_device));

  job = storage_daemon_launch_threaded_job (daemon, self,
                                            "lvm-vg-rem-device",
                                            storage_invocation_get_caller_uid (invocation),
                                            volume_group_remdev_job_thread,
                                            data,
                                            volume_group_remdev_job_free,
                                            NULL);

  g_signal_connect_data (job, "completed", G_CALLBACK (on_remdev_complete),
                         g_object_ref (invocation), (GClosureNotify)g_object_unref, 0);

  g_object_unref (member_device);
  return TRUE; /* returning TRUE means that we handled the method invocation */
}
Exemple #11
0
static gboolean
handle_empty_device (LvmVolumeGroup *group,
                     GDBusMethodInvocation *invocation,
                     const gchar *member_device_objpath,
                     GVariant *options)
{
  StorageJob *job;
  StorageDaemon *daemon;
  StorageManager *manager;
  const gchar *member_device_file = NULL;
  StorageBlock *member_device = NULL;

  daemon = storage_daemon_get ();
  manager = storage_daemon_get_manager (daemon);

  member_device = storage_manager_find_block (manager, member_device_objpath);
  if (member_device == NULL)
    {
      g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
                                             "The given object is not a valid block");
      return TRUE;
    }

  member_device_file = storage_block_get_device (member_device);

  job = storage_daemon_launch_spawned_job (daemon, member_device,
                                           "lvm-vg-empty-device",
                                           storage_invocation_get_caller_uid (invocation),
                                           NULL, /* GCancellable */
                                           0,    /* uid_t run_as_uid */
                                           0,    /* uid_t run_as_euid */
                                           NULL,  /* input_string */
                                           "pvmove", member_device_file,
                                           NULL);

  g_signal_connect_data (job, "completed", G_CALLBACK (on_empty_complete),
                         g_object_ref (invocation), (GClosureNotify)g_object_unref, 0);

  g_object_unref (member_device);
  return TRUE; /* returning TRUE means that we handled the method invocation */
}
Exemple #12
0
static gboolean
handle_rename (LvmVolumeGroup *group,
               GDBusMethodInvocation *invocation,
               const gchar *new_name,
               GVariant *options)
{
  StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group);
  CompleteClosure *complete;
  StorageJob *job;
  StorageDaemon *daemon;

  daemon = storage_daemon_get ();

  job = storage_daemon_launch_spawned_job (daemon, self,
                                           "lvm-vg-rename",
                                           storage_invocation_get_caller_uid (invocation),
                                           NULL, /* GCancellable */
                                           0,    /* uid_t run_as_uid */
                                           0,    /* uid_t run_as_euid */
                                           NULL,  /* input_string */
                                           "vgrename",
                                           storage_volume_group_get_name (self),
                                           new_name,
                                           NULL);

  complete = g_new0 (CompleteClosure, 1);
  complete->invocation = g_object_ref (invocation);
  complete->wait_name = g_strdup (new_name);

  /* Wait for the job to finish */
  g_signal_connect (job, "completed", G_CALLBACK (on_rename_complete), complete);

  /* Wait for the object to appear */
  complete->wait_sig = g_signal_connect_data (daemon,
                                              "published::StorageVolumeGroup",
                                              G_CALLBACK (on_rename_volume_group),
                                              complete, complete_closure_free, 0);

  return TRUE;
}
Exemple #13
0
void
storage_block_update_lv (StorageBlock *self,
                         StorageLogicalVolume *lv)
{
  const gchar *logical_volume_path;
  StorageDaemon *daemon;

  g_return_if_fail (STORAGE_IS_BLOCK (self));

  daemon = storage_daemon_get ();

  if (lv == NULL)
    {
      if (self->iface_logical_volume)
        {
          storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_logical_volume);
          g_object_unref (self->iface_logical_volume);
          self->iface_logical_volume = NULL;
        }
    }
  else
    {
      logical_volume_path = storage_logical_volume_get_object_path (lv);
      if (self->iface_logical_volume)
        {
          lvm_logical_volume_block_set_logical_volume (self->iface_logical_volume,
                                                       logical_volume_path);
        }
      else
        {
          self->iface_logical_volume = lvm_logical_volume_block_skeleton_new ();
          lvm_logical_volume_block_set_logical_volume (self->iface_logical_volume,
                                                       logical_volume_path);
          storage_daemon_publish (daemon, storage_block_get_object_path (self), FALSE, self->iface_logical_volume);
        }
    }
}
Exemple #14
0
static void
storage_block_dispose (GObject *object)
{
  StorageBlock *self = STORAGE_BLOCK (object);
  StorageDaemon *daemon;

  daemon = storage_daemon_get ();

  if (self->iface_physical_volume)
    {
      storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_physical_volume);
      g_object_unref (self->iface_physical_volume);
      self->iface_physical_volume = NULL;
    }

  if (self->iface_logical_volume)
    {
      storage_daemon_unpublish (daemon, storage_block_get_object_path (self), self->iface_logical_volume);
      g_object_unref (self->iface_logical_volume);
      self->iface_logical_volume = NULL;
    }

  G_OBJECT_CLASS (storage_block_parent_class)->dispose (object);
}
Exemple #15
0
static void
update_with_variant (GPid pid,
                     GVariant *info,
                     GError *error,
                     gpointer user_data)
{
  struct UpdateData *data = user_data;
  StorageVolumeGroup *self = data->self;
  GVariantIter *iter;
  GHashTableIter volume_iter;
  gpointer key, value;
  GHashTable *new_lvs;
  gboolean needs_polling = FALSE;
  StorageDaemon *daemon;
  gchar *path;

  daemon = storage_daemon_get ();

  if (!error)
      volume_group_update_props (self, info, &needs_polling);

  /* After basic props, publish group, if not already done */
  if (self->need_publish)
    {
      self->need_publish = FALSE;
      path = storage_util_build_object_path ("/org/freedesktop/UDisks2/lvm",
                                        storage_volume_group_get_name (self), NULL);
      storage_daemon_publish (daemon, path, FALSE, self);
      g_free (path);
    }

  if (error)
    {
      g_message ("Failed to update LVM volume group %s: %s",
                 storage_volume_group_get_name (self), error->message);
      g_object_unref (self);
      return;
    }

  if (self->info && g_variant_equal (self->info, info))
    {
      g_debug ("%s updated without changes", self->name);
      g_object_unref (self);
      return;
    }

  if (self->info)
    g_variant_unref (self->info);
  self->info = g_variant_ref (info);

  new_lvs = g_hash_table_new (g_str_hash, g_str_equal);

  if (g_variant_lookup (info, "lvs", "aa{sv}", &iter))
    {
      GVariant *lv_info = NULL;
      while (g_variant_iter_loop (iter, "@a{sv}", &lv_info))
        {
          const gchar *name;
          StorageLogicalVolume *volume;

          g_variant_lookup (lv_info, "name", "&s", &name);

          update_operations (name, lv_info, &needs_polling);

          if (lv_is_pvmove_volume (name))
            needs_polling = TRUE;

          if (!lv_is_visible (name))
            continue;

          volume = g_hash_table_lookup (self->logical_volumes, name);
          if (volume == NULL)
            {
              volume = storage_logical_volume_new (self, name);
              storage_logical_volume_update (volume, self, lv_info, &needs_polling);

              g_hash_table_insert (self->logical_volumes, g_strdup (name), g_object_ref (volume));
            }
          else
            storage_logical_volume_update (volume, self, lv_info, &needs_polling);

          g_hash_table_insert (new_lvs, (gchar *)name, volume);
        }
      g_variant_iter_free (iter);
    }

  g_hash_table_iter_init (&volume_iter, self->logical_volumes);
  while (g_hash_table_iter_next (&volume_iter, &key, &value))
    {
      const gchar *name = key;
      StorageLogicalVolume *volume = value;

      if (!g_hash_table_contains (new_lvs, name))
        {
          /* Volume unpublishes itself */
          g_object_run_dispose (G_OBJECT (volume));
          g_hash_table_iter_remove (&volume_iter);
        }
    }

  lvm_volume_group_set_needs_polling (LVM_VOLUME_GROUP (self), needs_polling);

  /* Update physical volumes. */

  g_hash_table_remove_all (self->physical_volumes);

  if (g_variant_lookup (info, "pvs", "aa{sv}", &iter))
    {
      const gchar *name;
      GVariant *pv_info;
      while (g_variant_iter_next (iter, "@a{sv}", &pv_info))
        {
          if (g_variant_lookup (pv_info, "device", "&s", &name))
            g_hash_table_insert (self->physical_volumes, g_strdup (name), pv_info);
          else
            g_variant_unref (pv_info);
        }
    }

  /* Make sure above is published before updating blocks to point at volume group */
  update_all_blocks (self);

  if (data->done)
    data->done (self, data->done_user_data);

  g_hash_table_destroy (new_lvs);
  g_object_unref (self);
  g_free (data);
}
Exemple #16
0
static void
update_progress_for_device (const gchar *operation,
                            const gchar *dev,
                            double progress)
{
  StorageDaemon *daemon;
  StorageManager *manager;
  GList *jobs, *l;

  daemon = storage_daemon_get ();
  manager = storage_daemon_get_manager (daemon);
  jobs = storage_daemon_get_jobs (daemon);

  for (l = jobs; l; l = g_list_next (l))
    {
      UDisksJob *job = l->data;
      const gchar *const *job_objects;
      int i;

      if (g_strcmp0 (udisks_job_get_operation (job), operation) != 0)
        continue;

      job_objects = udisks_job_get_objects (job);
      for (i = 0; job_objects[i]; i++)
        {
          StorageBlock *block;
          gboolean found = FALSE;

          block = storage_manager_find_block (manager, job_objects[i]);
          if (block)
            {
              if (g_strcmp0 (storage_block_get_device (block), dev) == 0)
                {
                  found = TRUE;
                }
              else
                {
                  const gchar **symlinks;
                  int j;

                  symlinks = storage_block_get_symlinks (block);
                  for (j = 0; symlinks[j]; j++)
                    {
                      if (g_strcmp0 (symlinks[j], dev) == 0)
                        {
                          found = TRUE;
                          break;
                        }
                    }
                }
            }

          if (found)
            {
              udisks_job_set_progress (job, progress);
              udisks_job_set_progress_valid (job, TRUE);
            }
        }
    }

  g_list_free_full (jobs, g_object_unref);
}