static gboolean handle_delete (CockpitStorageVolumeGroup *object, GDBusMethodInvocation *invocation) { StorageVolumeGroup *group = STORAGE_VOLUME_GROUP(object); StorageProvider *provider = storage_object_get_provider (group->object); GError *error = NULL; if (!auth_check_sender_role (invocation, COCKPIT_ROLE_STORAGE_ADMIN)) return TRUE; if (!storage_cleanup_volume_group (provider, group->lvm_volume_group, &error) || !lvm_volume_group_call_delete_sync (group->lvm_volume_group, TRUE, null_asv (), NULL, &error)) { g_dbus_error_strip_remote_error (error); g_dbus_method_invocation_return_error (invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "%s", error->message); g_error_free (error); } else cockpit_storage_volume_group_complete_delete (object, invocation); return TRUE; }
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); }
static void storage_volume_group_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (obj); switch (prop_id) { case PROP_NAME: g_free (self->name); self->name = g_value_dup_string (value); break; case PROP_MANAGER: g_assert (self->manager == NULL); self->manager = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; } }
static gboolean handle_create_thin_pool_volume (CockpitStorageVolumeGroup *object, GDBusMethodInvocation *invocation, const gchar *arg_name, guint64 arg_size) { StorageVolumeGroup *group = STORAGE_VOLUME_GROUP(object); GError *error = NULL; gs_free gchar *result = NULL; if (!auth_check_sender_role (invocation, COCKPIT_ROLE_STORAGE_ADMIN)) return TRUE; if (!lvm_volume_group_call_create_thin_pool_volume_sync (group->lvm_volume_group, arg_name, arg_size, null_asv (), &result, NULL, &error)) { g_dbus_error_strip_remote_error (error); g_dbus_method_invocation_return_error (invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "%s", error->message); g_error_free (error); } else cockpit_storage_volume_group_complete_create_thin_pool_volume (object, invocation); return TRUE; }
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; }
static void on_lvm_volume_group_notify (GObject *object, GParamSpec *pspec, gpointer user_data) { StorageVolumeGroup *volume_group = STORAGE_VOLUME_GROUP (user_data); storage_volume_group_update (volume_group); }
static void storage_volume_group_finalize (GObject *obj) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (obj); g_hash_table_unref (self->logical_volumes); g_free (self->name); G_OBJECT_CLASS (storage_volume_group_parent_class)->finalize (obj); }
static gboolean handle_poll (LvmVolumeGroup *group, GDBusMethodInvocation *invocation) { StorageVolumeGroup *self = STORAGE_VOLUME_GROUP (group); storage_volume_group_poll (self); lvm_volume_group_complete_poll (group, invocation); return TRUE; }
static void storage_volume_group_finalize (GObject *object) { StorageVolumeGroup *volume_group = STORAGE_VOLUME_GROUP (object); g_signal_handlers_disconnect_by_func (volume_group->lvm_volume_group, G_CALLBACK (on_lvm_volume_group_notify), volume_group); g_object_unref (volume_group->lvm_volume_group); G_OBJECT_CLASS (storage_volume_group_parent_class)->finalize (object); }
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; }
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 */ }
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; }
static gboolean handle_empty_device (CockpitStorageVolumeGroup *object, GDBusMethodInvocation *invocation, const gchar *arg_objpath) { StorageVolumeGroup *group = STORAGE_VOLUME_GROUP(object); GError *error = NULL; const gchar *block_path = "/"; if (!auth_check_sender_role (invocation, COCKPIT_ROLE_STORAGE_ADMIN)) return TRUE; StorageProvider *provider = storage_object_get_provider (group->object); Daemon *daemon = storage_provider_get_daemon (provider); GDBusObjectManagerServer *object_manager_server = daemon_get_object_manager (daemon); GDBusObjectManager *object_manager = G_DBUS_OBJECT_MANAGER (object_manager_server); StorageObject *block_object = STORAGE_OBJECT (g_dbus_object_manager_get_object (object_manager, arg_objpath)); UDisksBlock *udisks_block = storage_object_get_udisks_block (block_object); if (udisks_block) block_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (udisks_block)); g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (group->lvm_volume_group), G_MAXINT); if (!lvm_volume_group_call_empty_device_sync (group->lvm_volume_group, block_path, null_asv (), NULL, &error)) { g_dbus_error_strip_remote_error (error); g_dbus_method_invocation_return_error (invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "%s", error->message); g_error_free (error); } else cockpit_storage_volume_group_complete_empty_device (object, invocation); g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (group->lvm_volume_group), -1); return TRUE; }
static gboolean handle_create_thin_volume (CockpitStorageVolumeGroup *object, GDBusMethodInvocation *invocation, const gchar *arg_name, guint64 arg_size, const gchar *arg_pool) { StorageVolumeGroup *group = STORAGE_VOLUME_GROUP(object); GError *error = NULL; gs_free gchar *result = NULL; const gchar *pool_path = "/"; if (!auth_check_sender_role (invocation, COCKPIT_ROLE_STORAGE_ADMIN)) return TRUE; StorageProvider *provider = storage_object_get_provider (group->object); Daemon *daemon = storage_provider_get_daemon (provider); GDBusObjectManagerServer *object_manager_server = daemon_get_object_manager (daemon); GDBusObjectManager *object_manager = G_DBUS_OBJECT_MANAGER (object_manager_server); StorageObject *pool_object = STORAGE_OBJECT (g_dbus_object_manager_get_object (object_manager, arg_pool)); LvmLogicalVolume *lvm_pool_lvol = storage_object_get_lvm_logical_volume (pool_object); if (lvm_pool_lvol) pool_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (lvm_pool_lvol)); if (!lvm_volume_group_call_create_thin_volume_sync (group->lvm_volume_group, arg_name, arg_size, pool_path, null_asv (), &result, NULL, &error)) { g_dbus_error_strip_remote_error (error); g_dbus_method_invocation_return_error (invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "%s", error->message); g_error_free (error); } else cockpit_storage_volume_group_complete_create_thin_pool_volume (object, invocation); return TRUE; }
static void storage_volume_group_constructed (GObject *object) { StorageVolumeGroup *volume_group = STORAGE_VOLUME_GROUP (object); volume_group->lvm_volume_group = g_object_ref (storage_object_get_lvm_volume_group (volume_group->object)); g_signal_connect (volume_group->lvm_volume_group, "notify", G_CALLBACK (on_lvm_volume_group_notify), volume_group); storage_volume_group_update (volume_group); if (G_OBJECT_CLASS (storage_volume_group_parent_class)->constructed != NULL) G_OBJECT_CLASS (storage_volume_group_parent_class)->constructed (object); }
static void on_create_logical_volume (StorageDaemon *daemon, StorageLogicalVolume *volume, gpointer user_data) { CompleteClosure *complete = user_data; if (g_str_equal (storage_logical_volume_get_name (volume), complete->wait_name) && storage_logical_volume_get_volume_group (volume) == STORAGE_VOLUME_GROUP (complete->wait_thing)) { /* All creates have the same signature */ lvm_volume_group_complete_create_plain_volume (NULL, complete->invocation, storage_logical_volume_get_object_path (volume)); g_signal_handler_disconnect (daemon, complete->wait_sig); } }
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 */ }
static void storage_volume_group_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { StorageVolumeGroup *volume_group = STORAGE_VOLUME_GROUP (object); switch (prop_id) { case PROP_OBJECT: g_value_set_object (value, volume_group->object); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
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; }
static gboolean handle_poll (CockpitStorageVolumeGroup *object, GDBusMethodInvocation *invocation) { StorageVolumeGroup *group = STORAGE_VOLUME_GROUP(object); GError *error = NULL; if (!lvm_volume_group_call_poll_sync (group->lvm_volume_group, NULL, &error)) { g_dbus_error_strip_remote_error (error); g_dbus_method_invocation_return_error (invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "%s", error->message); g_error_free (error); } else cockpit_storage_volume_group_complete_poll (object, invocation); return TRUE; }