static gboolean logical_volume_is_unused_walker (GDBusObjectManager *objman, LvmLogicalVolume *logical_volume, gpointer user_data, GError **error) { StorageProvider *provider = user_data; UDisksBlock *block = lvm_util_peek_block_for_logical_volume (storage_provider_get_lvm_object_manager (provider), storage_provider_get_udisks_client (provider), logical_volume); if (block) return block_is_unused (storage_provider_get_udisks_client (provider), block, error); else return TRUE; }
static gboolean cleanup_logical_volume_walker (GDBusObjectManager *objman, LvmLogicalVolume *logical_volume, gpointer user_data, GError **error) { StorageProvider *provider = user_data; UDisksBlock *block = lvm_util_peek_block_for_logical_volume (storage_provider_get_lvm_object_manager (provider), storage_provider_get_udisks_client (provider), logical_volume); if (block) { /* The logical volume is active, let's clean it up by walking the tree of block devices hanging off of it. */ return cleanup_block (provider, block, error); } else { /* The logical volume is inactive, let's clean it up by removing the remembered configs from its children. */ LvmObject *object = LVM_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (logical_volume))); GList *remembered_configs = storage_provider_get_and_forget_remembered_configs (provider, g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); for (GList *l = remembered_configs; l; l = l->next) { GVariant *config = l->data; storage_remove_config (provider, NULL, config); } g_list_free_full (remembered_configs, (GDestroyNotify)g_variant_unref); return TRUE; } }
static gboolean handle_delete (CockpitStorageMDRaid *object, GDBusMethodInvocation *invocation) { StorageMDRaid *mdraid = STORAGE_MDRAID(object); StorageProvider *provider = storage_object_get_provider (mdraid->object); UDisksClient *udisks_client = storage_provider_get_udisks_client (provider); gs_unref_object UDisksBlock *block = NULL; GList *members = NULL; GError *error = NULL; /* Delete is Stop followed by wiping of all member devices. */ block = udisks_client_get_block_for_mdraid (udisks_client, mdraid->udisks_mdraid); if (block) { if (!storage_cleanup_block (provider, block, &error)) goto out; } GVariantBuilder options; g_variant_builder_init (&options, G_VARIANT_TYPE("a{sv}")); if (!udisks_mdraid_call_stop_sync (mdraid->udisks_mdraid, g_variant_builder_end (&options), NULL, &error)) goto out; members = udisks_client_get_members_for_mdraid (udisks_client, mdraid->udisks_mdraid); for (GList *m = members; m; m = m->next) { UDisksBlock *block = m->data; GVariantBuilder options; g_variant_builder_init (&options, G_VARIANT_TYPE("a{sv}")); udisks_block_call_format_sync (block, "empty", g_variant_builder_end (&options), NULL, error ? NULL : &error); } out: if (error) { g_dbus_error_strip_remote_error (error); g_dbus_method_invocation_return_error (invocation, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "%s", error->message); } else cockpit_storage_mdraid_complete_stop (object, invocation); g_list_free_full (members, g_object_unref); g_clear_error (&error); return TRUE; }
static void start_format_and_configure_block (StorageProvider *provider, UDisksBlock *block, GDBusMethodInvocation *invocation, const gchar *type, const gchar *erase, const gchar *label, const gchar *passphrase, const gchar *mount_point, const gchar *mount_options, const gchar *crypto_passphrase, const gchar *crypto_options) { GError *error = NULL; if (!storage_cleanup_block (provider, block, &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); return; } FormatData *data = g_new0(FormatData, 1); data->block = g_object_ref (block); data->invocation = g_object_ref (invocation); data->mount_point = g_strdup (mount_point); data->mount_options = g_strdup (mount_options); data->crypto_passphrase = g_strdup (crypto_passphrase); data->crypto_options = g_strdup (crypto_options); data->udisks_object_manager = udisks_client_get_object_manager (storage_provider_get_udisks_client (provider)); data->object_added_handler_id = g_signal_connect (data->udisks_object_manager, "object-added", G_CALLBACK (on_udisks_object_added), data); GVariantBuilder options; g_variant_builder_init (&options, G_VARIANT_TYPE("a{sv}")); if (erase && strcmp (erase, "no") != 0) g_variant_builder_add (&options, "{sv}", "erase", g_variant_new_string (erase)); if (label && *label) g_variant_builder_add (&options, "{sv}", "label", g_variant_new_string (label)); if (passphrase && *passphrase) g_variant_builder_add (&options, "{sv}", "encrypt.passphrase", g_variant_new_string (passphrase)); udisks_block_call_format (block, type, g_variant_builder_end (&options), NULL, on_format_done, data); }
void storage_mdraid_update (StorageMDRaid *mdraid) { UDisksMDRaid *udisks_mdraid = mdraid->udisks_mdraid; CockpitStorageMDRaid *iface = COCKPIT_STORAGE_MDRAID (mdraid); StorageProvider *provider = storage_object_get_provider (mdraid->object); UDisksClient *udisks_client = storage_provider_get_udisks_client (provider); cockpit_storage_mdraid_set_uuid (iface, udisks_mdraid_get_uuid (udisks_mdraid)); cockpit_storage_mdraid_set_name (iface, udisks_mdraid_get_name (udisks_mdraid)); cockpit_storage_mdraid_set_level (iface, udisks_mdraid_get_level (udisks_mdraid)); cockpit_storage_mdraid_set_num_devices (iface, udisks_mdraid_get_num_devices (udisks_mdraid)); cockpit_storage_mdraid_set_size (iface, udisks_mdraid_get_size (udisks_mdraid)); cockpit_storage_mdraid_set_sync_action (iface, udisks_mdraid_get_sync_action (udisks_mdraid)); cockpit_storage_mdraid_set_sync_completed (iface, udisks_mdraid_get_sync_completed (udisks_mdraid)); cockpit_storage_mdraid_set_sync_rate (iface, udisks_mdraid_get_sync_rate (udisks_mdraid)); cockpit_storage_mdraid_set_sync_remaining_time (iface, udisks_mdraid_get_sync_remaining_time (udisks_mdraid)); cockpit_storage_mdraid_set_degraded (iface, udisks_mdraid_get_degraded (udisks_mdraid)); { gs_free gchar *loc = g_locale_to_utf8 (udisks_mdraid_get_bitmap_location (udisks_mdraid), -1, NULL, NULL, NULL); cockpit_storage_mdraid_set_bitmap_location (iface, loc); } cockpit_storage_mdraid_set_chunk_size (iface, udisks_mdraid_get_chunk_size (udisks_mdraid)); GVariantBuilder devices; g_variant_builder_init (&devices, G_VARIANT_TYPE("a(oiast)")); GVariantIter iter; gint disk_slot; const gchar *disk_block_objpath; gs_unref_variant GVariant *disk_states = NULL; guint64 disk_num_errors; g_variant_iter_init (&iter, udisks_mdraid_get_active_devices (udisks_mdraid)); while (g_variant_iter_next (&iter, "(&oi@asta{sv})", &disk_block_objpath, &disk_slot, &disk_states, &disk_num_errors, NULL)) { UDisksObject *udisks_object; UDisksBlock *udisks_block; StorageObject *object; if ((udisks_object = udisks_client_peek_object (udisks_client, disk_block_objpath)) && (udisks_block = udisks_object_peek_block (udisks_object)) && (object = storage_provider_lookup_for_udisks_block (provider, udisks_block))) { g_variant_builder_add (&devices, "(oi@ast)", g_dbus_object_get_object_path (G_DBUS_OBJECT(object)), disk_slot, disk_states, disk_num_errors); } } cockpit_storage_mdraid_set_active_devices (iface, g_variant_builder_end (&devices)); }
gboolean storage_cleanup_block (StorageProvider *provider, UDisksBlock *block, GError **error) { return (block_is_unused (storage_provider_get_udisks_client (provider), block, error) && cleanup_block (provider, block, error) && reload_systemd (error)); }
static void storage_remove_config (StorageProvider *provider, UDisksBlock *block, GVariant *config) { GVariantIter iter; GVariant *item; GError *error = NULL; gs_unref_object UDisksBlock *block_to_use = NULL; if (block == NULL) { /* Any block can be used to add/remove any configuration item. Let's hope we have at least one... XXX - UDisks should offer a method for manipulating fstab and crypttab on the Manager. */ UDisksClient *client = storage_provider_get_udisks_client (provider); GDBusObjectManager *manager = udisks_client_get_object_manager (client); GList *objects = g_dbus_object_manager_get_objects (manager); for (GList *l = objects; l; l = l->next) { UDisksObject *object = l->data; block_to_use = udisks_object_get_block (object); if (block_to_use) break; } g_list_free_full (objects, g_object_unref); if (block_to_use == NULL) { g_warning ("Can't remove config: no block object found."); return; } } else block_to_use = g_object_ref (block); g_variant_iter_init (&iter, config); while ((item = g_variant_iter_next_value (&iter)) != NULL) { if (!udisks_block_call_remove_configuration_item_sync (block_to_use, item, g_variant_new ("a{sv}", NULL), NULL, &error)) { gs_free gchar *config_text = g_variant_print (config, FALSE); g_warning ("Can't remove storage configuration '%s': %s", config_text, error->message); g_clear_error (&error); } } }
static gboolean cleanup_block (StorageProvider *provider, UDisksBlock *block, GError **error) { gboolean ret = walk_block (storage_provider_get_udisks_client (provider), block, cleanup_block_walker, provider, error); storage_provider_save_remembered_configs (provider); return ret; }
static UDisksBlock * create_partition (StorageBlock *block, guint64 offset, guint64 size, const gchar *type, GError **error) { UDisksObject *udisks_object = (UDisksObject *) g_dbus_interface_get_object (G_DBUS_INTERFACE (block->udisks_block)); if (udisks_object == NULL) { g_set_error (error, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "No object!?"); return NULL; } UDisksPartitionTable *table = udisks_object_peek_partition_table (udisks_object); if (table == NULL) { g_set_error (error, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "Block device has no partition table"); return NULL; } gs_free gchar *part_object_path = NULL; if (!udisks_partition_table_call_create_partition_sync (table, offset, size, type, "", g_variant_new ("a{sv}", NULL), &part_object_path, NULL, error)) return NULL; StorageProvider *provider = storage_object_get_provider (block->object); UDisksClient *client = storage_provider_get_udisks_client (provider); udisks_client_settle (client); gs_unref_object UDisksObject *partition_object = udisks_client_get_object (client, part_object_path); UDisksBlock *partition_block = udisks_object_peek_block (partition_object); if (partition_block == NULL) { g_set_error (error, COCKPIT_ERROR, COCKPIT_ERROR_FAILED, "Partition has no associated block device"); return NULL; } return partition_block; }
void storage_remember_block_configs (StorageProvider *provider, UDisksBlock *block) { GVariant *config = udisks_block_get_configuration (block); if (g_variant_n_children (config) > 0) { UDisksClient *client = storage_provider_get_udisks_client (provider); GDBusObjectManager *objman = storage_provider_get_lvm_object_manager (provider); GDBusObject *object = g_dbus_interface_get_object (G_DBUS_INTERFACE (block)); struct RememberData data; data.provider = provider; data.child_path = g_dbus_object_get_object_path (object); data.config = config; walk_block_parents (client, objman, block, remember_configs, &data, NULL); } }
void storage_block_update (StorageBlock *block) { CockpitStorageBlock *iface = COCKPIT_STORAGE_BLOCK (block); StorageProvider *provider; UDisksClient *udisks_client; UDisksObject *udisks_object; UDisksBlock *udisks_block; UDisksPartition *udisks_partition = NULL; UDisksPartitionTable *udisks_partition_table = NULL; UDisksFilesystem *udisks_filesystem = NULL; UDisksPhysicalVolume *udisks_physical_volume = NULL; provider = storage_object_get_provider (block->object); udisks_client = storage_provider_get_udisks_client (provider); udisks_block = block->udisks_block; udisks_object = (UDisksObject *)g_dbus_interface_get_object (G_DBUS_INTERFACE (udisks_block)); if (udisks_object != NULL) { udisks_partition = udisks_object_peek_partition (udisks_object); udisks_partition_table = udisks_object_peek_partition_table (udisks_object); udisks_filesystem = udisks_object_peek_filesystem (udisks_object); udisks_physical_volume = udisks_object_peek_physical_volume (udisks_object); } { gs_free gchar *d = g_filename_display_name (udisks_block_get_preferred_device (udisks_block)); cockpit_storage_block_set_device (iface, d); } cockpit_storage_block_set_size (iface, udisks_block_get_size (udisks_block)); cockpit_storage_block_set_id_usage (iface, udisks_block_get_id_usage (udisks_block)); cockpit_storage_block_set_id_type (iface, udisks_block_get_id_type (udisks_block)); cockpit_storage_block_set_id_version (iface, udisks_block_get_id_version (udisks_block)); cockpit_storage_block_set_id_label (iface, udisks_block_get_id_label (udisks_block)); cockpit_storage_block_set_id_uuid (iface, udisks_block_get_id_uuid (udisks_block)); if (udisks_partition == NULL) { cockpit_storage_block_set_partition_number (iface, 0); cockpit_storage_block_set_partition_table (iface, "/"); } else { UDisksPartitionTable *table_for_partition; const gchar *objpath = "/"; GDBusObject *o; UDisksBlock *b; StorageObject *so; table_for_partition = udisks_client_get_partition_table (udisks_client, udisks_partition); if (table_for_partition != NULL) { o = g_dbus_interface_get_object (G_DBUS_INTERFACE (table_for_partition)); if (o != NULL) { b = udisks_object_peek_block (UDISKS_OBJECT (o)); if (b != NULL) { so = storage_provider_lookup_for_udisks_block (provider, b); if (so != NULL) { objpath = g_dbus_object_get_object_path (G_DBUS_OBJECT (so)); } } } } cockpit_storage_block_set_partition_table (iface, objpath); cockpit_storage_block_set_partition_number (iface, udisks_partition_get_number (udisks_partition)); } GVariantBuilder partitions; g_variant_builder_init (&partitions, G_VARIANT_TYPE ("a(otts)")); if (udisks_partition_table != NULL) { GList *ps, *l; ps = udisks_client_get_partitions (udisks_client, udisks_partition_table); for (l = ps; l != NULL; l = l->next) { UDisksPartition *p = UDISKS_PARTITION (l->data); GDBusObject *o; UDisksBlock *b; StorageObject *so; o = g_dbus_interface_get_object (G_DBUS_INTERFACE (p)); if (o != NULL) { b = udisks_object_peek_block (UDISKS_OBJECT (o)); if (b != NULL) { so = storage_provider_lookup_for_udisks_block (provider, b); if (so != NULL) { const gchar *type = "p"; if (udisks_partition_get_is_container (p)) type = "x"; else if (udisks_partition_get_is_contained (p)) type = "l"; g_variant_builder_add (&partitions, "(otts)", g_dbus_object_get_object_path (G_DBUS_OBJECT (so)), udisks_partition_get_offset (p), udisks_partition_get_size (p), type); } } } } g_list_free_full (ps, g_object_unref); const gchar *type = udisks_partition_table_get_type_ (udisks_partition_table); if (type == NULL || type[0] == '\0') type = "unknown"; cockpit_storage_block_set_partition_table_type (iface, type); } else cockpit_storage_block_set_partition_table_type (iface, ""); cockpit_storage_block_set_partitions (iface, g_variant_builder_end (&partitions)); cockpit_storage_block_set_drive (iface, storage_provider_translate_path (provider, udisks_block_get_drive (udisks_block))); cockpit_storage_block_set_crypto_backing_device (iface, storage_provider_translate_path (provider, udisks_block_get_crypto_backing_device (udisks_block))); cockpit_storage_block_set_mdraid (iface, storage_provider_translate_path (provider, udisks_block_get_mdraid (udisks_block))); cockpit_storage_block_set_mdraid_member (iface, storage_provider_translate_path (provider, udisks_block_get_mdraid_member (udisks_block))); if (udisks_filesystem) { const gchar *const *p = udisks_filesystem_get_mount_points (udisks_filesystem); gchar *u[g_strv_length ((gchar **)p) + 1]; int i; for (i = 0; p[i]; i++) u[i] = g_filename_display_name (p[i]); u[i] = NULL; cockpit_storage_block_set_mounted_at (iface, (const gchar *const *)u); for (i = 0; u[i]; i++) g_free (u[i]); } GVariantIter iter; g_variant_iter_init (&iter, udisks_block_get_configuration (udisks_block)); const gchar *type; GVariant *details; gboolean got_fstab = FALSE, got_crypttab = FALSE; while (g_variant_iter_next (&iter, "(&s*)", &type, &details)) { if (strcmp (type, "fstab") == 0 && !got_fstab) { got_fstab = TRUE; const gchar *dir = variant_lookup (details, "dir"); if (dir) { gs_free gchar *dir_display = g_filename_display_name (dir); cockpit_storage_block_set_mount_point (iface, dir_display); } const gchar *opts = variant_lookup (details, "opts"); if (opts) { gs_free gchar *opts_locale = g_locale_to_utf8 (opts, -1, NULL, NULL, NULL); if (opts_locale) cockpit_storage_block_set_mount_options (iface, opts_locale); else g_warning ("Can't convert fstab options into UTF8"); } } else if (strcmp (type, "crypttab") == 0 && !got_crypttab) { got_crypttab = TRUE; const gchar *opts = variant_lookup (details, "options"); if (opts) { gs_free gchar *opts_locale = g_locale_to_utf8 (opts, -1, NULL, NULL, NULL); if (opts_locale) cockpit_storage_block_set_crypto_options (iface, opts_locale); else g_warning ("Can't convert crypttab options into UTF8"); } } g_variant_unref (details); } cockpit_storage_block_set_logical_volume (iface, storage_provider_translate_path (provider, udisks_block_get_logical_volume (udisks_block))); if (udisks_physical_volume) { cockpit_storage_block_set_pv_group (iface, storage_provider_translate_path (provider, udisks_physical_volume_get_volume_group (udisks_physical_volume))); cockpit_storage_block_set_pv_size (iface, udisks_physical_volume_get_size (udisks_physical_volume)); cockpit_storage_block_set_pv_free_size (iface, udisks_physical_volume_get_free_size (udisks_physical_volume)); } else cockpit_storage_block_set_pv_group (iface, "/"); }