[gnome-disk-utility] First cut at LVM2 support
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] First cut at LVM2 support
- Date: Mon, 11 Jan 2010 23:00:05 +0000 (UTC)
commit 32d5198c223dd7a9aa48daa8a0a27918dafdad80
Author: David Zeuthen <davidz redhat com>
Date: Mon Jan 11 17:58:53 2010 -0500
First cut at LVM2 support
src/gdu-gtk/gdu-volume-grid.c | 128 ++-
src/gdu/Makefile.am | 5 +
src/gdu/gdu-callbacks.h | 17 +
src/gdu/gdu-device.c | 1125 ++++++++++++--------
src/gdu/gdu-device.h | 23 +
src/gdu/gdu-linux-lvm2-volume-group.c | 561 ++++++++++
src/gdu/gdu-linux-lvm2-volume-group.h | 70 ++
src/gdu/gdu-linux-lvm2-volume-hole.c | 331 ++++++
src/gdu/gdu-linux-lvm2-volume-hole.h | 61 ++
src/gdu/gdu-linux-lvm2-volume.c | 430 ++++++++
src/gdu/gdu-linux-lvm2-volume.h | 63 ++
src/gdu/gdu-pool.c | 240 +++++-
src/gdu/gdu-pool.h | 16 +
src/gdu/gdu-private.h | 23 +
src/gdu/gdu-types.h | 3 +
src/gdu/gdu-volume-hole.c | 3 +-
src/gdu/gdu.h | 3 +
src/palimpsest/Makefile.am | 1 +
.../gdu-section-linux-lvm2-volume-group.c | 383 +++++++
.../gdu-section-linux-lvm2-volume-group.h | 58 +
src/palimpsest/gdu-section-volumes.c | 210 ++++-
src/palimpsest/gdu-shell.c | 5 +
22 files changed, 3248 insertions(+), 511 deletions(-)
---
diff --git a/src/gdu-gtk/gdu-volume-grid.c b/src/gdu-gtk/gdu-volume-grid.c
index de72344..ecaebc4 100644
--- a/src/gdu-gtk/gdu-volume-grid.c
+++ b/src/gdu-gtk/gdu-volume-grid.c
@@ -1211,18 +1211,20 @@ render_element (GduVolumeGrid *grid,
cairo_show_text (cr, text);
} else { /* render descriptive text + icons for the presentable */
- gchar *s;
- gchar *s1;
+ GString *str;
cairo_text_extents_t te;
- cairo_text_extents_t te1;
GduDevice *d;
gdouble text_height;
+ gdouble y;
gboolean render_padlock_closed;
gboolean render_padlock_open;
gboolean render_job_in_progress;
GPtrArray *pixbufs_to_render;
guint icon_offset;
guint n;
+ guint64 size;
+ gchar *size_str;
+ gchar **lines;
render_padlock_closed = FALSE;
render_padlock_open = FALSE;
@@ -1233,37 +1235,47 @@ render_element (GduVolumeGrid *grid,
if (d != NULL && gdu_device_job_in_progress (d))
render_job_in_progress = TRUE;
- s = NULL;
- s1 = NULL;
+ str = g_string_new (NULL);
+
+ size = gdu_presentable_get_size (element->presentable);
+ size_str = gdu_util_get_size_for_display (size,
+ FALSE,
+ FALSE);
+
if (d != NULL && g_strcmp0 (gdu_device_id_get_usage (d), "filesystem") == 0) {
gchar *fstype_str;
gchar *size_str;
- s = g_strdup (gdu_device_id_get_label (d));
fstype_str = gdu_util_get_fstype_for_display (gdu_device_id_get_type (d),
gdu_device_id_get_version (d),
FALSE);
size_str = gdu_util_get_size_for_display (gdu_device_get_size (d),
FALSE,
FALSE);
- s1 = g_strdup_printf ("%s %s", size_str, fstype_str);
+
+ g_string_append_printf (str, "%s\n", gdu_device_id_get_label (d));
+ g_string_append_printf (str, "%s %s", size_str, fstype_str);
+
g_free (fstype_str);
- g_free (size_str);
} else if (d != NULL && gdu_device_is_partition (d) &&
(g_strcmp0 (gdu_device_partition_get_type (d), "0x05") == 0 ||
g_strcmp0 (gdu_device_partition_get_type (d), "0x0f") == 0 ||
g_strcmp0 (gdu_device_partition_get_type (d), "0x85") == 0)) {
- /* Translators: shown in the grid for an extended MS-DOS partition */
- s = g_strdup (_("Extended"));
- s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->presentable),
- FALSE,
- FALSE);
+
+ g_string_append_printf (str,
+ "%s\n%s",
+ /* Translators: shown in the grid for an extended MS-DOS partition */
+ _("Extended"),
+ size_str);
+
} else if (d != NULL && g_strcmp0 (gdu_device_id_get_usage (d), "crypto") == 0) {
- /* Translators: shown in the grid for an encrypted LUKS volume */
- s = g_strdup (_("Encrypted"));
- s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->presentable),
- FALSE,
- FALSE);
+
+ g_string_append_printf (str,
+ "%s\n%s",
+ /* Translators: shown in the grid for an encrypted LUKS volume */
+ _("Encrypted"),
+ size_str);
+
if (g_strcmp0 (gdu_device_luks_get_holder (d), "/") == 0) {
render_padlock_closed = TRUE;
} else {
@@ -1271,25 +1283,42 @@ render_element (GduVolumeGrid *grid,
}
} else if (d != NULL && g_strcmp0 (gdu_device_id_get_usage (d), "raid") == 0 &&
gdu_device_is_linux_md_component (d)) {
- s1 = g_strdup (gdu_device_linux_md_component_get_name (d));
+
+ g_string_append_printf (str,
+ "%s\n%s",
+ /* Translators: shown in the grid for an RAID Component */
+ _("RAID Component"),
+ gdu_device_linux_md_component_get_name (d));
+
} else if (!gdu_presentable_is_allocated (element->presentable)) {
- /* Translators: shown in the grid for space that is not claimed by any partition */
- s = g_strdup (_("Free"));
- s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->presentable),
- FALSE,
- FALSE);
+
+ g_string_append_printf (str,
+ "%s\n%s",
+ /* Translators: shown for free/unallocated space */
+ _("Free"),
+ size_str);
+
} else if (!gdu_presentable_is_recognized (element->presentable)) {
- /* Translators: shown in the grid when we don't know the purpose/usage of the partition */
- s = g_strdup (_("Unknown"));
- s1 = gdu_util_get_size_for_display (gdu_presentable_get_size (element->presentable),
- FALSE,
- FALSE);
+
+ g_string_append_printf (str,
+ "%s\n%s",
+ /* Translators: shown when we don't know contents of the volume */
+ _("Unknown"),
+ size_str);
+ } else {
+ gchar *presentable_name;
+
+ /* FALLBACK */
+ presentable_name = gdu_presentable_get_name (element->presentable);
+ if (size > 0) {
+ g_string_append_printf (str, "%s\n%s", presentable_name, size_str);
+ } else {
+ g_string_append (str, presentable_name);
+ }
+ g_free (presentable_name);
}
+ g_free (size_str);
- if (s == NULL)
- s = gdu_presentable_get_name (element->presentable);
- if (s1 == NULL)
- s1 = g_strdup ("");
if (is_selected) {
if (is_grid_focused) {
@@ -1311,21 +1340,28 @@ render_element (GduVolumeGrid *grid,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, 8.0);
- cairo_text_extents (cr, s, &te);
- cairo_text_extents (cr, s1, &te1);
+ lines = g_strsplit (str->str, "\n", 0);
+ g_string_free (str, TRUE);
+ text_height = 0.0;
+ for (n = 0; lines[n] != NULL; n++) {
+ const gchar *line = lines[n];
+ cairo_text_extents (cr, line, &te);
+ text_height += te.height + 4;
+ }
- text_height = te.height + te1.height;
+ y = element->y + element->height/2.0 - text_height/2.0;
+ for (n = 0; lines[n] != NULL; n++) {
+ const gchar *line = lines[n];
+ cairo_text_extents (cr, line, &te);
+ cairo_move_to (cr,
+ ceil (element->x + element->width / 2 - te.width/2 - te.x_bearing),
+ ceil (y - te.y_bearing));
+ cairo_show_text (cr, line);
- cairo_move_to (cr,
- ceil (element->x + element->width / 2 - te.width/2 - te.x_bearing),
- ceil (element->y + element->height / 2 - 2 - text_height/2 - te.y_bearing));
- cairo_show_text (cr, s);
- cairo_move_to (cr,
- ceil (element->x + element->width / 2 - te1.width/2 - te1.x_bearing),
- ceil (element->y + element->height / 2 + 2 - te1.y_bearing));
- cairo_show_text (cr, s1);
- g_free (s);
- g_free (s1);
+ y += te.height + 4;
+ }
+
+ g_strfreev (lines);
/* OK, done with the text - now render spinner and icons */
icon_offset = 0;
diff --git a/src/gdu/Makefile.am b/src/gdu/Makefile.am
index 7c4f404..d9dcbb1 100644
--- a/src/gdu/Makefile.am
+++ b/src/gdu/Makefile.am
@@ -43,6 +43,8 @@ libgduinclude_HEADERS = \
gdu-port.h \
gdu-drive.h \
gdu-linux-md-drive.h \
+ gdu-linux-lvm2-volume-group.h \
+ gdu-linux-lvm2-volume.h \
gdu-error.h \
gdu-known-filesystem.h \
gdu-pool.h \
@@ -67,6 +69,9 @@ libgdu_la_SOURCES = \
gdu-port.c gdu-port.h \
gdu-drive.c gdu-drive.h \
gdu-linux-md-drive.c gdu-linux-md-drive.h \
+ gdu-linux-lvm2-volume-group.c gdu-linux-lvm2-volume-group.h \
+ gdu-linux-lvm2-volume.c gdu-linux-lvm2-volume.h \
+ gdu-linux-lvm2-volume-hole.c gdu-linux-lvm2-volume-hole.h \
gdu-volume.c gdu-volume.h \
gdu-presentable.c gdu-presentable.h \
gdu-volume-hole.c gdu-volume-hole.h \
diff --git a/src/gdu/gdu-callbacks.h b/src/gdu/gdu-callbacks.h
index 4217806..e5dcd36 100644
--- a/src/gdu/gdu-callbacks.h
+++ b/src/gdu/gdu-callbacks.h
@@ -147,6 +147,10 @@ typedef void (*GduDeviceDriveBenchmarkCompletedFunc) (GduDevice *device,
GError *error,
gpointer user_data);
+typedef void (*GduDeviceLinuxLvm2LVStopCompletedFunc) (GduDevice *device,
+ GError *error,
+ gpointer user_data);
+
/* ---------------------------------------------------------------------------------------------------- */
/* GduPool */
@@ -160,6 +164,18 @@ typedef void (*GduPoolLinuxMdCreateCompletedFunc) (GduPool *pool,
GError *error,
gpointer user_data);
+typedef void (*GduPoolLinuxLvm2VGStartCompletedFunc) (GduPool *pool,
+ GError *error,
+ gpointer user_data);
+
+typedef void (*GduPoolLinuxLvm2VGStopCompletedFunc) (GduPool *pool,
+ GError *error,
+ gpointer user_data);
+
+typedef void (*GduPoolLinuxLvm2LVStartCompletedFunc) (GduPool *pool,
+ GError *error,
+ gpointer user_data);
+
/* ---------------------------------------------------------------------------------------------------- */
/* GduDrive */
@@ -172,6 +188,7 @@ typedef void (*GduDriveDeactivateFunc) (GduDrive *drive,
GError *error,
gpointer user_data);
+
/* ---------------------------------------------------------------------------------------------------- */
G_END_DECLS
diff --git a/src/gdu/gdu-device.c b/src/gdu/gdu-device.c
index 970c63d..c906440 100644
--- a/src/gdu/gdu-device.c
+++ b/src/gdu/gdu-device.c
@@ -44,483 +44,550 @@
typedef struct
{
- char *native_path;
-
- guint64 device_detection_time;
- guint64 device_media_detection_time;
- gint64 device_major;
- gint64 device_minor;
- char *device_file;
- char **device_file_by_id;
- char **device_file_by_path;
- gboolean device_is_system_internal;
- gboolean device_is_partition;
- gboolean device_is_partition_table;
- gboolean device_is_removable;
- gboolean device_is_media_available;
- gboolean device_is_media_change_detected;
- gboolean device_is_media_change_detection_polling;
- gboolean device_is_media_change_detection_inhibitable;
- gboolean device_is_media_change_detection_inhibited;
- gboolean device_is_read_only;
- gboolean device_is_drive;
- gboolean device_is_optical_disc;
- gboolean device_is_luks;
- gboolean device_is_luks_cleartext;
- gboolean device_is_mounted;
- gboolean device_is_linux_md_component;
- gboolean device_is_linux_md;
- char **device_mount_paths;
- uid_t device_mounted_by_uid;
- gboolean device_presentation_hide;
- gboolean device_presentation_nopolicy;
- char *device_presentation_name;
- char *device_presentation_icon_name;
- guint64 device_size;
- guint64 device_block_size;
-
- gboolean job_in_progress;
- char *job_id;
- uid_t job_initiated_by_uid;
- gboolean job_is_cancellable;
- double job_percentage;
-
- char *id_usage;
- char *id_type;
- char *id_version;
- char *id_uuid;
- char *id_label;
-
- char *partition_slave;
- char *partition_scheme;
- int partition_number;
- char *partition_type;
- char *partition_label;
- char *partition_uuid;
- char **partition_flags;
- guint64 partition_offset;
- guint64 partition_size;
-
- char *partition_table_scheme;
- int partition_table_count;
-
- char *luks_holder;
-
- char *luks_cleartext_slave;
- uid_t luks_cleartext_unlocked_by_uid;
-
- char *drive_vendor;
- char *drive_model;
- char *drive_revision;
- char *drive_serial;
- char *drive_wwn;
- char *drive_connection_interface;
- guint64 drive_connection_speed;
- char **drive_media_compatibility;
- char *drive_media;
- gboolean drive_is_media_ejectable;
- gboolean drive_can_detach;
- gboolean drive_can_spindown;
- gboolean drive_is_rotational;
- guint drive_rotation_rate;
- char *drive_write_cache;
- char *drive_adapter;
- char **drive_ports;
-
- gboolean optical_disc_is_blank;
- gboolean optical_disc_is_appendable;
- gboolean optical_disc_is_closed;
- guint optical_disc_num_tracks;
- guint optical_disc_num_audio_tracks;
- guint optical_disc_num_sessions;
-
- gboolean drive_ata_smart_is_available;
- guint64 drive_ata_smart_time_collected;
- gchar *drive_ata_smart_status;
- gchar *drive_ata_smart_blob;
- gsize drive_ata_smart_blob_size;
-
- char *linux_md_component_level;
- int linux_md_component_position;
- int linux_md_component_num_raid_devices;
- char *linux_md_component_uuid;
- char *linux_md_component_home_host;
- char *linux_md_component_name;
- char *linux_md_component_version;
- char *linux_md_component_holder;
- char **linux_md_component_state;
-
- char *linux_md_state;
- char *linux_md_level;
- int linux_md_num_raid_devices;
- char *linux_md_uuid;
- char *linux_md_home_host;
- char *linux_md_name;
- char *linux_md_version;
- char **linux_md_slaves;
- gboolean linux_md_is_degraded;
- char *linux_md_sync_action;
- double linux_md_sync_percentage;
- guint64 linux_md_sync_speed;
+ char *native_path;
+
+ guint64 device_detection_time;
+ guint64 device_media_detection_time;
+ gint64 device_major;
+ gint64 device_minor;
+ char *device_file;
+ char **device_file_by_id;
+ char **device_file_by_path;
+ gboolean device_is_system_internal;
+ gboolean device_is_partition;
+ gboolean device_is_partition_table;
+ gboolean device_is_removable;
+ gboolean device_is_media_available;
+ gboolean device_is_media_change_detected;
+ gboolean device_is_media_change_detection_polling;
+ gboolean device_is_media_change_detection_inhibitable;
+ gboolean device_is_media_change_detection_inhibited;
+ gboolean device_is_read_only;
+ gboolean device_is_drive;
+ gboolean device_is_optical_disc;
+ gboolean device_is_luks;
+ gboolean device_is_luks_cleartext;
+ gboolean device_is_mounted;
+ gboolean device_is_linux_md_component;
+ gboolean device_is_linux_md;
+ gboolean device_is_linux_lvm2_lv;
+ gboolean device_is_linux_lvm2_pv;
+ char **device_mount_paths;
+ uid_t device_mounted_by_uid;
+ gboolean device_presentation_hide;
+ gboolean device_presentation_nopolicy;
+ char *device_presentation_name;
+ char *device_presentation_icon_name;
+ guint64 device_size;
+ guint64 device_block_size;
+
+ gboolean job_in_progress;
+ char *job_id;
+ uid_t job_initiated_by_uid;
+ gboolean job_is_cancellable;
+ double job_percentage;
+
+ char *id_usage;
+ char *id_type;
+ char *id_version;
+ char *id_uuid;
+ char *id_label;
+
+ char *partition_slave;
+ char *partition_scheme;
+ int partition_number;
+ char *partition_type;
+ char *partition_label;
+ char *partition_uuid;
+ char **partition_flags;
+ guint64 partition_offset;
+ guint64 partition_size;
+
+ char *partition_table_scheme;
+ int partition_table_count;
+
+ char *luks_holder;
+
+ char *luks_cleartext_slave;
+ uid_t luks_cleartext_unlocked_by_uid;
+
+ char *drive_vendor;
+ char *drive_model;
+ char *drive_revision;
+ char *drive_serial;
+ char *drive_wwn;
+ char *drive_connection_interface;
+ guint64 drive_connection_speed;
+ char **drive_media_compatibility;
+ char *drive_media;
+ gboolean drive_is_media_ejectable;
+ gboolean drive_can_detach;
+ gboolean drive_can_spindown;
+ gboolean drive_is_rotational;
+ guint drive_rotation_rate;
+ char *drive_write_cache;
+ char *drive_adapter;
+ char **drive_ports;
+
+ gboolean optical_disc_is_blank;
+ gboolean optical_disc_is_appendable;
+ gboolean optical_disc_is_closed;
+ guint optical_disc_num_tracks;
+ guint optical_disc_num_audio_tracks;
+ guint optical_disc_num_sessions;
+
+ gboolean drive_ata_smart_is_available;
+ guint64 drive_ata_smart_time_collected;
+ gchar *drive_ata_smart_status;
+ gchar *drive_ata_smart_blob;
+ gsize drive_ata_smart_blob_size;
+
+ char *linux_md_component_level;
+ int linux_md_component_position;
+ int linux_md_component_num_raid_devices;
+ char *linux_md_component_uuid;
+ char *linux_md_component_home_host;
+ char *linux_md_component_name;
+ char *linux_md_component_version;
+ char *linux_md_component_holder;
+ char **linux_md_component_state;
+
+ char *linux_md_state;
+ char *linux_md_level;
+ int linux_md_num_raid_devices;
+ char *linux_md_uuid;
+ char *linux_md_home_host;
+ char *linux_md_name;
+ char *linux_md_version;
+ char **linux_md_slaves;
+ gboolean linux_md_is_degraded;
+ char *linux_md_sync_action;
+ double linux_md_sync_percentage;
+ guint64 linux_md_sync_speed;
+
+ gchar *linux_lvm2_lv_name;
+ gchar *linux_lvm2_lv_uuid;
+ gchar *linux_lvm2_lv_group_name;
+ gchar *linux_lvm2_lv_group_uuid;
+
+ gchar *linux_lvm2_pv_uuid;
+ guint linux_lvm2_pv_num_metadata_areas;
+ gchar *linux_lvm2_pv_group_name;
+ gchar *linux_lvm2_pv_group_uuid;
+ guint64 linux_lvm2_pv_group_size;
+ guint64 linux_lvm2_pv_group_unallocated_size;
+ guint64 linux_lvm2_pv_group_sequence_number;
+ guint64 linux_lvm2_pv_group_extent_size;
+ char **linux_lvm2_pv_group_physical_volumes;
+ char **linux_lvm2_pv_group_logical_volumes;
} DeviceProperties;
static void
-collect_props (const char *key, const GValue *value, DeviceProperties *props)
-{
- gboolean handled = TRUE;
-
- if (strcmp (key, "NativePath") == 0)
- props->native_path = g_strdup (g_value_get_string (value));
-
- else if (strcmp (key, "DeviceDetectionTime") == 0)
- props->device_detection_time = g_value_get_uint64 (value);
- else if (strcmp (key, "DeviceMediaDetectionTime") == 0)
- props->device_media_detection_time = g_value_get_uint64 (value);
- else if (strcmp (key, "DeviceMajor") == 0)
- props->device_major = g_value_get_int64 (value);
- else if (strcmp (key, "DeviceMinor") == 0)
- props->device_minor = g_value_get_int64 (value);
- else if (strcmp (key, "DeviceFile") == 0)
- props->device_file = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DeviceFileById") == 0)
- props->device_file_by_id = g_strdupv (g_value_get_boxed (value));
- else if (strcmp (key, "DeviceFileByPath") == 0)
- props->device_file_by_path = g_strdupv (g_value_get_boxed (value));
- else if (strcmp (key, "DeviceIsSystemInternal") == 0)
- props->device_is_system_internal = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsPartition") == 0)
- props->device_is_partition = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsPartitionTable") == 0)
- props->device_is_partition_table = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsRemovable") == 0)
- props->device_is_removable = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsMediaAvailable") == 0)
- props->device_is_media_available = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsMediaChangeDetected") == 0)
- props->device_is_media_change_detected = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsMediaChangeDetectionPolling") == 0)
- props->device_is_media_change_detection_polling = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsMediaChangeDetectionInhibitable") == 0)
- props->device_is_media_change_detection_inhibitable = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsMediaChangeDetectionInhibited") == 0)
- props->device_is_media_change_detection_inhibited = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsReadOnly") == 0)
- props->device_is_read_only = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsDrive") == 0)
- props->device_is_drive = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsOpticalDisc") == 0)
- props->device_is_optical_disc = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsLuks") == 0)
- props->device_is_luks = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsLuksCleartext") == 0)
- props->device_is_luks_cleartext = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsLinuxMdComponent") == 0)
- props->device_is_linux_md_component = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsLinuxMd") == 0)
- props->device_is_linux_md = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceIsMounted") == 0)
- props->device_is_mounted = g_value_get_boolean (value);
- else if (strcmp (key, "DeviceMountPaths") == 0)
- props->device_mount_paths = g_strdupv (g_value_get_boxed (value));
- else if (strcmp (key, "DeviceMountedByUid") == 0)
- props->device_mounted_by_uid = g_value_get_uint (value);
- else if (strcmp (key, "DevicePresentationHide") == 0)
- props->device_presentation_hide = g_value_get_boolean (value);
- else if (strcmp (key, "DevicePresentationNopolicy") == 0)
- props->device_presentation_nopolicy = g_value_get_boolean (value);
- else if (strcmp (key, "DevicePresentationName") == 0)
- props->device_presentation_name = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DevicePresentationIconName") == 0)
- props->device_presentation_icon_name = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DeviceSize") == 0)
- props->device_size = g_value_get_uint64 (value);
- else if (strcmp (key, "DeviceBlockSize") == 0)
- props->device_block_size = g_value_get_uint64 (value);
-
- else if (strcmp (key, "JobInProgress") == 0)
- props->job_in_progress = g_value_get_boolean (value);
- else if (strcmp (key, "JobId") == 0)
- props->job_id = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "JobInitiatedByUid") == 0)
- props->job_initiated_by_uid = g_value_get_uint (value);
- else if (strcmp (key, "JobIsCancellable") == 0)
- props->job_is_cancellable = g_value_get_boolean (value);
- else if (strcmp (key, "JobPercentage") == 0)
- props->job_percentage = g_value_get_double (value);
-
- else if (strcmp (key, "IdUsage") == 0)
- props->id_usage = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "IdType") == 0)
- props->id_type = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "IdVersion") == 0)
- props->id_version = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "IdUuid") == 0)
- props->id_uuid = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "IdLabel") == 0)
- props->id_label = g_strdup (g_value_get_string (value));
-
- else if (strcmp (key, "PartitionSlave") == 0)
- props->partition_slave = g_strdup (g_value_get_boxed (value));
- else if (strcmp (key, "PartitionScheme") == 0)
- props->partition_scheme = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "PartitionNumber") == 0)
- props->partition_number = g_value_get_int (value);
- else if (strcmp (key, "PartitionType") == 0)
- props->partition_type = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "PartitionLabel") == 0)
- props->partition_label = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "PartitionUuid") == 0)
- props->partition_uuid = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "PartitionFlags") == 0)
- props->partition_flags = g_strdupv (g_value_get_boxed (value));
- else if (strcmp (key, "PartitionOffset") == 0)
- props->partition_offset = g_value_get_uint64 (value);
- else if (strcmp (key, "PartitionSize") == 0)
- props->partition_size = g_value_get_uint64 (value);
-
- else if (strcmp (key, "PartitionTableScheme") == 0)
- props->partition_table_scheme = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "PartitionTableCount") == 0)
- props->partition_table_count = g_value_get_int (value);
-
- else if (strcmp (key, "LuksHolder") == 0)
- props->luks_holder = g_strdup (g_value_get_boxed (value));
-
- else if (strcmp (key, "LuksCleartextSlave") == 0)
- props->luks_cleartext_slave = g_strdup (g_value_get_boxed (value));
- else if (strcmp (key, "LuksCleartextUnlockedByUid") == 0)
- props->luks_cleartext_unlocked_by_uid = g_value_get_uint (value);
-
- else if (strcmp (key, "DriveVendor") == 0)
- props->drive_vendor = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveModel") == 0)
- props->drive_model = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveRevision") == 0)
- props->drive_revision = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveSerial") == 0)
- props->drive_serial = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveWwn") == 0)
- props->drive_wwn = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveConnectionInterface") == 0)
- props->drive_connection_interface = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveConnectionSpeed") == 0)
- props->drive_connection_speed = g_value_get_uint64 (value);
- else if (strcmp (key, "DriveMediaCompatibility") == 0)
- props->drive_media_compatibility = g_strdupv (g_value_get_boxed (value));
- else if (strcmp (key, "DriveMedia") == 0)
- props->drive_media = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveIsMediaEjectable") == 0)
- props->drive_is_media_ejectable = g_value_get_boolean (value);
- else if (strcmp (key, "DriveCanDetach") == 0)
- props->drive_can_detach = g_value_get_boolean (value);
- else if (strcmp (key, "DriveCanSpindown") == 0)
- props->drive_can_spindown = g_value_get_boolean (value);
- else if (strcmp (key, "DriveIsRotational") == 0)
- props->drive_is_rotational = g_value_get_boolean (value);
- else if (strcmp (key, "DriveRotationRate") == 0)
- props->drive_rotation_rate = g_value_get_uint (value);
- else if (strcmp (key, "DriveWriteCache") == 0)
- props->drive_write_cache = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveAdapter") == 0)
- props->drive_adapter = g_strdup (g_value_get_boxed (value));
- else if (strcmp (key, "DrivePorts") == 0) {
- guint n;
- GPtrArray *object_paths;
-
- object_paths = g_value_get_boxed (value);
-
- props->drive_ports = g_new0 (char *, object_paths->len + 1);
- for (n = 0; n < object_paths->len; n++)
- props->drive_ports[n] = g_strdup (object_paths->pdata[n]);
- props->drive_ports[n] = NULL;
- }
-
- else if (strcmp (key, "OpticalDiscIsBlank") == 0)
- props->optical_disc_is_blank = g_value_get_boolean (value);
- else if (strcmp (key, "OpticalDiscIsAppendable") == 0)
- props->optical_disc_is_appendable = g_value_get_boolean (value);
- else if (strcmp (key, "OpticalDiscIsClosed") == 0)
- props->optical_disc_is_closed = g_value_get_boolean (value);
- else if (strcmp (key, "OpticalDiscNumTracks") == 0)
- props->optical_disc_num_tracks = g_value_get_uint (value);
- else if (strcmp (key, "OpticalDiscNumAudioTracks") == 0)
- props->optical_disc_num_audio_tracks = g_value_get_uint (value);
- else if (strcmp (key, "OpticalDiscNumSessions") == 0)
- props->optical_disc_num_sessions = g_value_get_uint (value);
-
- else if (strcmp (key, "DriveAtaSmartIsAvailable") == 0)
- props->drive_ata_smart_is_available = g_value_get_boolean (value);
- else if (strcmp (key, "DriveAtaSmartTimeCollected") == 0)
- props->drive_ata_smart_time_collected = g_value_get_uint64 (value);
- else if (strcmp (key, "DriveAtaSmartStatus") == 0)
- props->drive_ata_smart_status = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "DriveAtaSmartBlob") == 0) {
- GArray *a = g_value_get_boxed (value);
- g_free (props->drive_ata_smart_blob);
- props->drive_ata_smart_blob = g_memdup (a->data, a->len);
- props->drive_ata_smart_blob_size = a->len;
- }
-
- else if (strcmp (key, "LinuxMdComponentLevel") == 0)
- props->linux_md_component_level = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdComponentPosition") == 0)
- props->linux_md_component_position = g_value_get_int (value);
- else if (strcmp (key, "LinuxMdComponentNumRaidDevices") == 0)
- props->linux_md_component_num_raid_devices = g_value_get_int (value);
- else if (strcmp (key, "LinuxMdComponentUuid") == 0)
- props->linux_md_component_uuid = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdComponentHomeHost") == 0)
- props->linux_md_component_home_host = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdComponentName") == 0)
- props->linux_md_component_name = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdComponentVersion") == 0)
- props->linux_md_component_version = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdComponentHolder") == 0)
- props->linux_md_component_holder = g_strdup (g_value_get_boxed (value));
- else if (strcmp (key, "LinuxMdComponentState") == 0)
- props->linux_md_component_state = g_strdupv (g_value_get_boxed (value));
-
- else if (strcmp (key, "LinuxMdState") == 0)
- props->linux_md_state = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdLevel") == 0)
- props->linux_md_level = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdNumRaidDevices") == 0)
- props->linux_md_num_raid_devices = g_value_get_int (value);
- else if (strcmp (key, "LinuxMdUuid") == 0)
- props->linux_md_uuid = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdHomeHost") == 0)
- props->linux_md_home_host = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdName") == 0)
- props->linux_md_name = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdVersion") == 0)
- props->linux_md_version = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdSlaves") == 0) {
- guint n;
- GPtrArray *object_paths;
-
- object_paths = g_value_get_boxed (value);
-
- props->linux_md_slaves = g_new0 (char *, object_paths->len + 1);
- for (n = 0; n < object_paths->len; n++)
- props->linux_md_slaves[n] = g_strdup (object_paths->pdata[n]);
- props->linux_md_slaves[n] = NULL;
- }
- else if (strcmp (key, "LinuxMdIsDegraded") == 0)
- props->linux_md_is_degraded = g_value_get_boolean (value);
- else if (strcmp (key, "LinuxMdSyncAction") == 0)
- props->linux_md_sync_action = g_strdup (g_value_get_string (value));
- else if (strcmp (key, "LinuxMdSyncPercentage") == 0)
- props->linux_md_sync_percentage = g_value_get_double (value);
- else if (strcmp (key, "LinuxMdSyncSpeed") == 0)
- props->linux_md_sync_speed = g_value_get_uint64 (value);
-
- else
- handled = FALSE;
-
- if (!handled)
- g_debug ("unhandled property '%s'", key);
+collect_props (const char *key,
+ const GValue *value,
+ DeviceProperties *props)
+{
+ gboolean handled = TRUE;
+
+ if (strcmp (key, "NativePath") == 0)
+ props->native_path = g_strdup (g_value_get_string (value));
+
+ else if (strcmp (key, "DeviceDetectionTime") == 0)
+ props->device_detection_time = g_value_get_uint64 (value);
+ else if (strcmp (key, "DeviceMediaDetectionTime") == 0)
+ props->device_media_detection_time = g_value_get_uint64 (value);
+ else if (strcmp (key, "DeviceMajor") == 0)
+ props->device_major = g_value_get_int64 (value);
+ else if (strcmp (key, "DeviceMinor") == 0)
+ props->device_minor = g_value_get_int64 (value);
+ else if (strcmp (key, "DeviceFile") == 0)
+ props->device_file = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DeviceFileById") == 0)
+ props->device_file_by_id = g_strdupv (g_value_get_boxed (value));
+ else if (strcmp (key, "DeviceFileByPath") == 0)
+ props->device_file_by_path = g_strdupv (g_value_get_boxed (value));
+ else if (strcmp (key, "DeviceIsSystemInternal") == 0)
+ props->device_is_system_internal = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsPartition") == 0)
+ props->device_is_partition = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsPartitionTable") == 0)
+ props->device_is_partition_table = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsRemovable") == 0)
+ props->device_is_removable = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsMediaAvailable") == 0)
+ props->device_is_media_available = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsMediaChangeDetected") == 0)
+ props->device_is_media_change_detected = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsMediaChangeDetectionPolling") == 0)
+ props->device_is_media_change_detection_polling = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsMediaChangeDetectionInhibitable") == 0)
+ props->device_is_media_change_detection_inhibitable = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsMediaChangeDetectionInhibited") == 0)
+ props->device_is_media_change_detection_inhibited = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsReadOnly") == 0)
+ props->device_is_read_only = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsDrive") == 0)
+ props->device_is_drive = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsOpticalDisc") == 0)
+ props->device_is_optical_disc = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLuks") == 0)
+ props->device_is_luks = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLuksCleartext") == 0)
+ props->device_is_luks_cleartext = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLinuxMdComponent") == 0)
+ props->device_is_linux_md_component = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLinuxMd") == 0)
+ props->device_is_linux_md = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLinuxLvm2LV") == 0)
+ props->device_is_linux_lvm2_lv = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLinuxLvm2PV") == 0)
+ props->device_is_linux_lvm2_pv = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsMounted") == 0)
+ props->device_is_mounted = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceMountPaths") == 0)
+ props->device_mount_paths = g_strdupv (g_value_get_boxed (value));
+ else if (strcmp (key, "DeviceMountedByUid") == 0)
+ props->device_mounted_by_uid = g_value_get_uint (value);
+ else if (strcmp (key, "DevicePresentationHide") == 0)
+ props->device_presentation_hide = g_value_get_boolean (value);
+ else if (strcmp (key, "DevicePresentationNopolicy") == 0)
+ props->device_presentation_nopolicy = g_value_get_boolean (value);
+ else if (strcmp (key, "DevicePresentationName") == 0)
+ props->device_presentation_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DevicePresentationIconName") == 0)
+ props->device_presentation_icon_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DeviceSize") == 0)
+ props->device_size = g_value_get_uint64 (value);
+ else if (strcmp (key, "DeviceBlockSize") == 0)
+ props->device_block_size = g_value_get_uint64 (value);
+
+ else if (strcmp (key, "JobInProgress") == 0)
+ props->job_in_progress = g_value_get_boolean (value);
+ else if (strcmp (key, "JobId") == 0)
+ props->job_id = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "JobInitiatedByUid") == 0)
+ props->job_initiated_by_uid = g_value_get_uint (value);
+ else if (strcmp (key, "JobIsCancellable") == 0)
+ props->job_is_cancellable = g_value_get_boolean (value);
+ else if (strcmp (key, "JobPercentage") == 0)
+ props->job_percentage = g_value_get_double (value);
+
+ else if (strcmp (key, "IdUsage") == 0)
+ props->id_usage = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "IdType") == 0)
+ props->id_type = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "IdVersion") == 0)
+ props->id_version = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "IdUuid") == 0)
+ props->id_uuid = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "IdLabel") == 0)
+ props->id_label = g_strdup (g_value_get_string (value));
+
+ else if (strcmp (key, "PartitionSlave") == 0)
+ props->partition_slave = g_strdup (g_value_get_boxed (value));
+ else if (strcmp (key, "PartitionScheme") == 0)
+ props->partition_scheme = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "PartitionNumber") == 0)
+ props->partition_number = g_value_get_int (value);
+ else if (strcmp (key, "PartitionType") == 0)
+ props->partition_type = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "PartitionLabel") == 0)
+ props->partition_label = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "PartitionUuid") == 0)
+ props->partition_uuid = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "PartitionFlags") == 0)
+ props->partition_flags = g_strdupv (g_value_get_boxed (value));
+ else if (strcmp (key, "PartitionOffset") == 0)
+ props->partition_offset = g_value_get_uint64 (value);
+ else if (strcmp (key, "PartitionSize") == 0)
+ props->partition_size = g_value_get_uint64 (value);
+
+ else if (strcmp (key, "PartitionTableScheme") == 0)
+ props->partition_table_scheme = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "PartitionTableCount") == 0)
+ props->partition_table_count = g_value_get_int (value);
+
+ else if (strcmp (key, "LuksHolder") == 0)
+ props->luks_holder = g_strdup (g_value_get_boxed (value));
+
+ else if (strcmp (key, "LuksCleartextSlave") == 0)
+ props->luks_cleartext_slave = g_strdup (g_value_get_boxed (value));
+ else if (strcmp (key, "LuksCleartextUnlockedByUid") == 0)
+ props->luks_cleartext_unlocked_by_uid = g_value_get_uint (value);
+
+ else if (strcmp (key, "DriveVendor") == 0)
+ props->drive_vendor = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveModel") == 0)
+ props->drive_model = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveRevision") == 0)
+ props->drive_revision = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveSerial") == 0)
+ props->drive_serial = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveWwn") == 0)
+ props->drive_wwn = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveConnectionInterface") == 0)
+ props->drive_connection_interface = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveConnectionSpeed") == 0)
+ props->drive_connection_speed = g_value_get_uint64 (value);
+ else if (strcmp (key, "DriveMediaCompatibility") == 0)
+ props->drive_media_compatibility = g_strdupv (g_value_get_boxed (value));
+ else if (strcmp (key, "DriveMedia") == 0)
+ props->drive_media = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveIsMediaEjectable") == 0)
+ props->drive_is_media_ejectable = g_value_get_boolean (value);
+ else if (strcmp (key, "DriveCanDetach") == 0)
+ props->drive_can_detach = g_value_get_boolean (value);
+ else if (strcmp (key, "DriveCanSpindown") == 0)
+ props->drive_can_spindown = g_value_get_boolean (value);
+ else if (strcmp (key, "DriveIsRotational") == 0)
+ props->drive_is_rotational = g_value_get_boolean (value);
+ else if (strcmp (key, "DriveRotationRate") == 0)
+ props->drive_rotation_rate = g_value_get_uint (value);
+ else if (strcmp (key, "DriveWriteCache") == 0)
+ props->drive_write_cache = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveAdapter") == 0)
+ props->drive_adapter = g_strdup (g_value_get_boxed (value));
+ else if (strcmp (key, "DrivePorts") == 0)
+ {
+ guint n;
+ GPtrArray *object_paths;
+
+ object_paths = g_value_get_boxed (value);
+
+ props->drive_ports = g_new0 (char *, object_paths->len + 1);
+ for (n = 0; n < object_paths->len; n++)
+ props->drive_ports[n] = g_strdup (object_paths->pdata[n]);
+ props->drive_ports[n] = NULL;
+ }
+
+ else if (strcmp (key, "OpticalDiscIsBlank") == 0)
+ props->optical_disc_is_blank = g_value_get_boolean (value);
+ else if (strcmp (key, "OpticalDiscIsAppendable") == 0)
+ props->optical_disc_is_appendable = g_value_get_boolean (value);
+ else if (strcmp (key, "OpticalDiscIsClosed") == 0)
+ props->optical_disc_is_closed = g_value_get_boolean (value);
+ else if (strcmp (key, "OpticalDiscNumTracks") == 0)
+ props->optical_disc_num_tracks = g_value_get_uint (value);
+ else if (strcmp (key, "OpticalDiscNumAudioTracks") == 0)
+ props->optical_disc_num_audio_tracks = g_value_get_uint (value);
+ else if (strcmp (key, "OpticalDiscNumSessions") == 0)
+ props->optical_disc_num_sessions = g_value_get_uint (value);
+
+ else if (strcmp (key, "DriveAtaSmartIsAvailable") == 0)
+ props->drive_ata_smart_is_available = g_value_get_boolean (value);
+ else if (strcmp (key, "DriveAtaSmartTimeCollected") == 0)
+ props->drive_ata_smart_time_collected = g_value_get_uint64 (value);
+ else if (strcmp (key, "DriveAtaSmartStatus") == 0)
+ props->drive_ata_smart_status = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DriveAtaSmartBlob") == 0)
+ {
+ GArray *a = g_value_get_boxed (value);
+ g_free (props->drive_ata_smart_blob);
+ props->drive_ata_smart_blob = g_memdup (a->data, a->len);
+ props->drive_ata_smart_blob_size = a->len;
+ }
+
+ else if (strcmp (key, "LinuxMdComponentLevel") == 0)
+ props->linux_md_component_level = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdComponentPosition") == 0)
+ props->linux_md_component_position = g_value_get_int (value);
+ else if (strcmp (key, "LinuxMdComponentNumRaidDevices") == 0)
+ props->linux_md_component_num_raid_devices = g_value_get_int (value);
+ else if (strcmp (key, "LinuxMdComponentUuid") == 0)
+ props->linux_md_component_uuid = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdComponentHomeHost") == 0)
+ props->linux_md_component_home_host = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdComponentName") == 0)
+ props->linux_md_component_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdComponentVersion") == 0)
+ props->linux_md_component_version = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdComponentHolder") == 0)
+ props->linux_md_component_holder = g_strdup (g_value_get_boxed (value));
+ else if (strcmp (key, "LinuxMdComponentState") == 0)
+ props->linux_md_component_state = g_strdupv (g_value_get_boxed (value));
+
+ else if (strcmp (key, "LinuxMdState") == 0)
+ props->linux_md_state = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdLevel") == 0)
+ props->linux_md_level = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdNumRaidDevices") == 0)
+ props->linux_md_num_raid_devices = g_value_get_int (value);
+ else if (strcmp (key, "LinuxMdUuid") == 0)
+ props->linux_md_uuid = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdHomeHost") == 0)
+ props->linux_md_home_host = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdName") == 0)
+ props->linux_md_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdVersion") == 0)
+ props->linux_md_version = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdSlaves") == 0)
+ {
+ guint n;
+ GPtrArray *object_paths;
+
+ object_paths = g_value_get_boxed (value);
+
+ props->linux_md_slaves = g_new0 (char *, object_paths->len + 1);
+ for (n = 0; n < object_paths->len; n++)
+ props->linux_md_slaves[n] = g_strdup (object_paths->pdata[n]);
+ props->linux_md_slaves[n] = NULL;
+ }
+ else if (strcmp (key, "LinuxMdIsDegraded") == 0)
+ props->linux_md_is_degraded = g_value_get_boolean (value);
+ else if (strcmp (key, "LinuxMdSyncAction") == 0)
+ props->linux_md_sync_action = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxMdSyncPercentage") == 0)
+ props->linux_md_sync_percentage = g_value_get_double (value);
+ else if (strcmp (key, "LinuxMdSyncSpeed") == 0)
+ props->linux_md_sync_speed = g_value_get_uint64 (value);
+
+ else if (strcmp (key, "LinuxLvm2LVName") == 0)
+ props->linux_lvm2_lv_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxLvm2LVUuid") == 0)
+ props->linux_lvm2_lv_uuid = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxLvm2LVGroupName") == 0)
+ props->linux_lvm2_lv_group_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxLvm2LVGroupUuid") == 0)
+ props->linux_lvm2_lv_group_uuid = g_strdup (g_value_get_string (value));
+
+ else if (strcmp (key, "LinuxLvm2PVUuid") == 0)
+ props->linux_lvm2_pv_uuid = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxLvm2PVNumMetadataAreas") == 0)
+ props->linux_lvm2_pv_num_metadata_areas = g_value_get_uint (value);
+ else if (strcmp (key, "LinuxLvm2PVGroupName") == 0)
+ props->linux_lvm2_pv_group_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxLvm2PVGroupUuid") == 0)
+ props->linux_lvm2_pv_group_uuid = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxLvm2PVGroupSize") == 0)
+ props->linux_lvm2_pv_group_size = g_value_get_uint64 (value);
+ else if (strcmp (key, "LinuxLvm2PVGroupUnallocatedSize") == 0)
+ props->linux_lvm2_pv_group_unallocated_size = g_value_get_uint64 (value);
+ else if (strcmp (key, "LinuxLvm2PVGroupSequenceNumber") == 0)
+ props->linux_lvm2_pv_group_sequence_number = g_value_get_uint64 (value);
+ else if (strcmp (key, "LinuxLvm2PVGroupExtentSize") == 0)
+ props->linux_lvm2_pv_group_extent_size = g_value_get_uint64 (value);
+ else if (strcmp (key, "LinuxLvm2PVGroupPhysicalVolumes") == 0)
+ props->linux_lvm2_pv_group_physical_volumes = g_strdupv (g_value_get_boxed (value));
+ else if (strcmp (key, "LinuxLvm2PVGroupLogicalVolumes") == 0)
+ props->linux_lvm2_pv_group_logical_volumes = g_strdupv (g_value_get_boxed (value));
+
+ else
+ handled = FALSE;
+
+ if (!handled)
+ g_warning ("unhandled property '%s'", key);
}
static void
device_properties_free (DeviceProperties *props)
{
- g_free (props->native_path);
- g_free (props->device_file);
- g_strfreev (props->device_file_by_id);
- g_strfreev (props->device_file_by_path);
- g_strfreev (props->device_mount_paths);
- g_free (props->device_presentation_name);
- g_free (props->device_presentation_icon_name);
- g_free (props->job_id);
- g_free (props->id_usage);
- g_free (props->id_type);
- g_free (props->id_version);
- g_free (props->id_uuid);
- g_free (props->id_label);
- g_free (props->partition_slave);
- g_free (props->partition_type);
- g_free (props->partition_label);
- g_free (props->partition_uuid);
- g_strfreev (props->partition_flags);
- g_free (props->partition_table_scheme);
- g_free (props->luks_holder);
- g_free (props->luks_cleartext_slave);
- g_free (props->drive_model);
- g_free (props->drive_vendor);
- g_free (props->drive_revision);
- g_free (props->drive_serial);
- g_free (props->drive_wwn);
- g_free (props->drive_connection_interface);
- g_strfreev (props->drive_media_compatibility);
- g_free (props->drive_media);
- g_free (props->drive_write_cache);
- g_free (props->drive_adapter);
- g_strfreev (props->drive_ports);
-
- g_free (props->drive_ata_smart_status);
- g_free (props->drive_ata_smart_blob);
-
- g_free (props->linux_md_component_level);
- g_free (props->linux_md_component_uuid);
- g_free (props->linux_md_component_home_host);
- g_free (props->linux_md_component_name);
- g_free (props->linux_md_component_version);
- g_free (props->linux_md_component_holder);
- g_strfreev (props->linux_md_component_state);
-
- g_free (props->linux_md_state);
- g_free (props->linux_md_level);
- g_free (props->linux_md_uuid);
- g_free (props->linux_md_home_host);
- g_free (props->linux_md_name);
- g_free (props->linux_md_version);
- g_strfreev (props->linux_md_slaves);
- g_free (props->linux_md_sync_action);
- g_free (props);
+ g_free (props->native_path);
+ g_free (props->device_file);
+ g_strfreev (props->device_file_by_id);
+ g_strfreev (props->device_file_by_path);
+ g_strfreev (props->device_mount_paths);
+ g_free (props->device_presentation_name);
+ g_free (props->device_presentation_icon_name);
+ g_free (props->job_id);
+ g_free (props->id_usage);
+ g_free (props->id_type);
+ g_free (props->id_version);
+ g_free (props->id_uuid);
+ g_free (props->id_label);
+ g_free (props->partition_slave);
+ g_free (props->partition_type);
+ g_free (props->partition_label);
+ g_free (props->partition_uuid);
+ g_strfreev (props->partition_flags);
+ g_free (props->partition_table_scheme);
+ g_free (props->luks_holder);
+ g_free (props->luks_cleartext_slave);
+ g_free (props->drive_model);
+ g_free (props->drive_vendor);
+ g_free (props->drive_revision);
+ g_free (props->drive_serial);
+ g_free (props->drive_wwn);
+ g_free (props->drive_connection_interface);
+ g_strfreev (props->drive_media_compatibility);
+ g_free (props->drive_media);
+ g_free (props->drive_write_cache);
+ g_free (props->drive_adapter);
+ g_strfreev (props->drive_ports);
+
+ g_free (props->drive_ata_smart_status);
+ g_free (props->drive_ata_smart_blob);
+
+ g_free (props->linux_md_component_level);
+ g_free (props->linux_md_component_uuid);
+ g_free (props->linux_md_component_home_host);
+ g_free (props->linux_md_component_name);
+ g_free (props->linux_md_component_version);
+ g_free (props->linux_md_component_holder);
+ g_strfreev (props->linux_md_component_state);
+
+ g_free (props->linux_md_state);
+ g_free (props->linux_md_level);
+ g_free (props->linux_md_uuid);
+ g_free (props->linux_md_home_host);
+ g_free (props->linux_md_name);
+ g_free (props->linux_md_version);
+ g_strfreev (props->linux_md_slaves);
+ g_free (props->linux_md_sync_action);
+
+ g_free (props->linux_lvm2_lv_name);
+ g_free (props->linux_lvm2_lv_uuid);
+ g_free (props->linux_lvm2_lv_group_name);
+ g_free (props->linux_lvm2_lv_group_uuid);
+
+ g_free (props->linux_lvm2_pv_uuid);
+ g_free (props->linux_lvm2_pv_group_name);
+ g_free (props->linux_lvm2_pv_group_uuid);
+ g_strfreev (props->linux_lvm2_pv_group_physical_volumes);
+ g_strfreev (props->linux_lvm2_pv_group_logical_volumes);
+
+ g_free (props);
}
static DeviceProperties *
device_properties_get (DBusGConnection *bus,
const char *object_path)
{
- DeviceProperties *props;
- GError *error;
- GHashTable *hash_table;
- DBusGProxy *prop_proxy;
- const char *ifname = "org.freedesktop.UDisks.Device";
-
- props = g_new0 (DeviceProperties, 1);
-
- prop_proxy = dbus_g_proxy_new_for_name (bus,
- "org.freedesktop.UDisks",
- object_path,
- "org.freedesktop.DBus.Properties");
- error = NULL;
- if (!dbus_g_proxy_call (prop_proxy,
- "GetAll",
- &error,
- G_TYPE_STRING,
- ifname,
- G_TYPE_INVALID,
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
- &hash_table,
- G_TYPE_INVALID)) {
- g_debug ("Error calling GetAll() when retrieving properties for %s: %s", object_path, error->message);
- g_error_free (error);
-
- device_properties_free (props);
- props = NULL;
- goto out;
- }
- g_debug ("yay, got props for %s", object_path);
+ DeviceProperties *props;
+ GError *error;
+ GHashTable *hash_table;
+ DBusGProxy *prop_proxy;
+ const char *ifname = "org.freedesktop.UDisks.Device";
- g_hash_table_foreach (hash_table, (GHFunc) collect_props, props);
+ props = g_new0 (DeviceProperties, 1);
- g_hash_table_unref (hash_table);
+ prop_proxy
+ = dbus_g_proxy_new_for_name (bus, "org.freedesktop.UDisks", object_path, "org.freedesktop.DBus.Properties");
+ error = NULL;
+ if (!dbus_g_proxy_call (prop_proxy,
+ "GetAll",
+ &error,
+ G_TYPE_STRING,
+ ifname,
+ G_TYPE_INVALID,
+ dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ &hash_table,
+ G_TYPE_INVALID))
+ {
+ g_warning ("Couldn't call GetAll() to get properties for %s: %s", object_path, error->message);
+ g_error_free (error);
-out:
- g_object_unref (prop_proxy);
- return props;
+ device_properties_free (props);
+ props = NULL;
+ goto out;
+ }
+
+ g_hash_table_foreach (hash_table, (GHFunc) collect_props, props);
+
+ g_hash_table_unref (hash_table);
+
+ out:
+ g_object_unref (prop_proxy);
+ return props;
}
/* --- SUCKY CODE END --- */
@@ -849,6 +916,18 @@ gdu_device_is_linux_md (GduDevice *device)
}
gboolean
+gdu_device_is_linux_lvm2_lv (GduDevice *device)
+{
+ return device->priv->props->device_is_linux_lvm2_lv;
+}
+
+gboolean
+gdu_device_is_linux_lvm2_pv (GduDevice *device)
+{
+ return device->priv->props->device_is_linux_lvm2_pv;
+}
+
+gboolean
gdu_device_is_mounted (GduDevice *device)
{
return device->priv->props->device_is_mounted;
@@ -1302,6 +1381,92 @@ gdu_device_linux_md_get_sync_speed (GduDevice *device)
return device->priv->props->linux_md_sync_speed;
}
+const char *
+gdu_device_linux_lvm2_lv_get_name (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_lv_name;
+}
+
+const char *
+gdu_device_linux_lvm2_lv_get_uuid (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_lv_uuid;
+}
+
+const char *
+gdu_device_linux_lvm2_lv_get_group_name (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_lv_group_name;
+}
+
+const char *
+gdu_device_linux_lvm2_lv_get_group_uuid (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_lv_group_uuid;
+}
+
+
+const char *
+gdu_device_linux_lvm2_pv_get_uuid (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_uuid;
+}
+
+guint
+gdu_device_linux_lvm2_pv_get_num_metadata_areas (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_num_metadata_areas;
+}
+
+const char *
+gdu_device_linux_lvm2_pv_get_group_name (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_name;
+}
+
+const char *
+gdu_device_linux_lvm2_pv_get_group_uuid (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_uuid;
+}
+
+guint64
+gdu_device_linux_lvm2_pv_get_group_size (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_size;
+}
+
+guint64
+gdu_device_linux_lvm2_pv_get_group_unallocated_size (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_unallocated_size;
+}
+
+guint64
+gdu_device_linux_lvm2_pv_get_group_extent_size (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_extent_size;
+}
+
+guint64
+gdu_device_linux_lvm2_pv_get_group_sequence_number (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_sequence_number;
+}
+
+gchar **
+gdu_device_linux_lvm2_pv_get_group_physical_volumes (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_physical_volumes;
+}
+
+gchar **
+gdu_device_linux_lvm2_pv_get_group_logical_volumes (GduDevice *device)
+{
+ return device->priv->props->linux_lvm2_pv_group_logical_volumes;
+}
+
+
/* ---------------------------------------------------------------------------------------------------- */
gboolean
@@ -2445,3 +2610,43 @@ void gdu_device_op_drive_benchmark (GduDevice *devic
/* -------------------------------------------------------------------------------- */
+
+typedef struct {
+ GduDevice *device;
+ GduDeviceLinuxLvm2LVStopCompletedFunc callback;
+ gpointer user_data;
+} LinuxLvm2LVStopData;
+
+static void
+op_stop_linux_lvm2_lv_array_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+ LinuxLvm2LVStopData *data = user_data;
+ _gdu_error_fixup (error);
+ if (data->callback != NULL)
+ data->callback (data->device, error, data->user_data);
+ g_object_unref (data->device);
+ g_free (data);
+}
+
+void
+gdu_device_op_linux_lvm2_lv_stop (GduDevice *device,
+ GduDeviceLinuxLvm2LVStopCompletedFunc callback,
+ gpointer user_data)
+{
+ char *options[16];
+ LinuxLvm2LVStopData *data;
+
+ data = g_new0 (LinuxLvm2LVStopData, 1);
+ data->device = g_object_ref (device);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ options[0] = NULL;
+
+ org_freedesktop_UDisks_Device_linux_lvm2_lv_stop_async (device->priv->proxy,
+ (const char **) options,
+ op_stop_linux_lvm2_lv_array_cb,
+ data);
+}
+
+/* -------------------------------------------------------------------------------- */
diff --git a/src/gdu/gdu-device.h b/src/gdu/gdu-device.h
index 5cebf67..f3e5291 100644
--- a/src/gdu/gdu-device.h
+++ b/src/gdu/gdu-device.h
@@ -89,6 +89,8 @@ gboolean gdu_device_is_luks (GduDevice *device);
gboolean gdu_device_is_luks_cleartext (GduDevice *device);
gboolean gdu_device_is_linux_md_component (GduDevice *device);
gboolean gdu_device_is_linux_md (GduDevice *device);
+gboolean gdu_device_is_linux_lvm2_lv (GduDevice *device);
+gboolean gdu_device_is_linux_lvm2_pv (GduDevice *device);
gboolean gdu_device_is_mounted (GduDevice *device);
const char *gdu_device_get_mount_path (GduDevice *device);
char **gdu_device_get_mount_paths (GduDevice *device);
@@ -177,6 +179,21 @@ const char *gdu_device_linux_md_get_sync_action (GduDevice *device);
double gdu_device_linux_md_get_sync_percentage (GduDevice *device);
guint64 gdu_device_linux_md_get_sync_speed (GduDevice *device);
+const char *gdu_device_linux_lvm2_lv_get_name (GduDevice *device);
+const char *gdu_device_linux_lvm2_lv_get_uuid (GduDevice *device);
+const char *gdu_device_linux_lvm2_lv_get_group_name (GduDevice *device);
+const char *gdu_device_linux_lvm2_lv_get_group_uuid (GduDevice *device);
+
+const char *gdu_device_linux_lvm2_pv_get_uuid (GduDevice *device);
+guint gdu_device_linux_lvm2_pv_get_num_metadata_areas (GduDevice *device);
+const char *gdu_device_linux_lvm2_pv_get_group_name (GduDevice *device);
+const char *gdu_device_linux_lvm2_pv_get_group_uuid (GduDevice *device);
+guint64 gdu_device_linux_lvm2_pv_get_group_size (GduDevice *device);
+guint64 gdu_device_linux_lvm2_pv_get_group_unallocated_size (GduDevice *device);
+guint64 gdu_device_linux_lvm2_pv_get_group_extent_size (GduDevice *device);
+guint64 gdu_device_linux_lvm2_pv_get_group_sequence_number (GduDevice *device);
+gchar **gdu_device_linux_lvm2_pv_get_group_physical_volumes (GduDevice *device);
+gchar **gdu_device_linux_lvm2_pv_get_group_logical_volumes (GduDevice *device);
gboolean gdu_device_drive_ata_smart_get_is_available (GduDevice *device);
guint64 gdu_device_drive_ata_smart_get_time_collected (GduDevice *device);
@@ -358,6 +375,12 @@ void gdu_device_op_drive_benchmark (GduDevice *devic
GduDeviceDriveBenchmarkCompletedFunc callback,
gpointer user_data);
+/* ---------------------------------------------------------------------------------------------------- */
+
+void gdu_device_op_linux_lvm2_lv_stop (GduDevice *device,
+ GduDeviceLinuxLvm2LVStopCompletedFunc callback,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __GDU_DEVICE_H */
diff --git a/src/gdu/gdu-linux-lvm2-volume-group.c b/src/gdu/gdu-linux-lvm2-volume-group.c
new file mode 100644
index 0000000..a88b9ac
--- /dev/null
+++ b/src/gdu/gdu-linux-lvm2-volume-group.c
@@ -0,0 +1,561 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2010 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+#include <dbus/dbus-glib.h>
+
+#include "gdu-private.h"
+#include "gdu-util.h"
+#include "gdu-pool.h"
+#include "gdu-device.h"
+#include "gdu-linux-lvm2-volume-group.h"
+#include "gdu-linux-lvm2-volume.h"
+#include "gdu-presentable.h"
+
+struct _GduLinuxLvm2VolumeGroupPrivate
+{
+ GList *slaves;
+
+ GduPool *pool;
+
+ gchar *uuid;
+
+ /* list of PV GduDevice objects that makes up this VG */
+ GList *pv_devices;
+ /* the PV for which we get VG data from (highest seqnum) */
+ GduDevice *pv;
+
+ gchar *id;
+
+ GduPresentable *enclosing_presentable;
+};
+
+static GObjectClass *parent_class = NULL;
+
+static void gdu_linux_lvm2_volume_group_presentable_iface_init (GduPresentableIface *iface);
+
+static gboolean gdu_linux_lvm2_volume_group_is_active (GduDrive *drive);
+static gboolean gdu_linux_lvm2_volume_group_is_activatable (GduDrive *drive);
+static gboolean gdu_linux_lvm2_volume_group_can_deactivate (GduDrive *drive);
+static gboolean gdu_linux_lvm2_volume_group_can_activate (GduDrive *drive, gboolean *out_degraded);
+
+static void on_device_added (GduPool *pool, GduDevice *device, gpointer user_data);
+static void on_device_removed (GduPool *pool, GduDevice *device, gpointer user_data);
+static void on_device_changed (GduPool *pool, GduDevice *device, gpointer user_data);
+
+G_DEFINE_TYPE_WITH_CODE (GduLinuxLvm2VolumeGroup, gdu_linux_lvm2_volume_group, GDU_TYPE_DRIVE,
+ G_IMPLEMENT_INTERFACE (GDU_TYPE_PRESENTABLE,
+ gdu_linux_lvm2_volume_group_presentable_iface_init))
+
+static void
+gdu_linux_lvm2_volume_group_finalize (GObject *object)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (object);
+
+ //g_debug ("##### finalized linux-lvm2 volume group '%s' %p", vg->priv->id, vg);
+
+ if (vg->priv->pool != NULL) {
+ g_signal_handlers_disconnect_by_func (vg->priv->pool, on_device_added, vg);
+ g_signal_handlers_disconnect_by_func (vg->priv->pool, on_device_removed, vg);
+ g_signal_handlers_disconnect_by_func (vg->priv->pool, on_device_changed, vg);
+ g_object_unref (vg->priv->pool);
+ }
+
+ g_free (vg->priv->id);
+ g_free (vg->priv->uuid);
+
+ if (vg->priv->enclosing_presentable != NULL)
+ g_object_unref (vg->priv->enclosing_presentable);
+
+ g_list_foreach (vg->priv->pv_devices, (GFunc) g_object_unref, NULL);
+ g_list_free (vg->priv->pv_devices);
+ if (vg->priv->pv != NULL)
+ g_object_unref (vg->priv->pv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (G_OBJECT (vg));
+}
+
+static void
+gdu_linux_lvm2_volume_group_class_init (GduLinuxLvm2VolumeGroupClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GduDriveClass *drive_class = (GduDriveClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gdu_linux_lvm2_volume_group_finalize;
+
+ g_type_class_add_private (klass, sizeof (GduLinuxLvm2VolumeGroupPrivate));
+
+ drive_class->is_active = gdu_linux_lvm2_volume_group_is_active;
+ drive_class->is_activatable = gdu_linux_lvm2_volume_group_is_activatable;
+ drive_class->can_deactivate = gdu_linux_lvm2_volume_group_can_deactivate;
+ drive_class->can_activate = gdu_linux_lvm2_volume_group_can_activate;
+}
+
+static void
+gdu_linux_lvm2_volume_group_init (GduLinuxLvm2VolumeGroup *vg)
+{
+ vg->priv = G_TYPE_INSTANCE_GET_PRIVATE (vg, GDU_TYPE_LINUX_LVM2_VOLUME_GROUP, GduLinuxLvm2VolumeGroupPrivate);
+}
+
+static void
+emit_changed (GduLinuxLvm2VolumeGroup *vg)
+{
+ //g_debug ("emitting changed for uuid '%s'", vg->priv->uuid);
+ g_signal_emit_by_name (vg, "changed");
+ g_signal_emit_by_name (vg->priv->pool, "presentable-changed", vg);
+}
+
+static gboolean
+find_pvs (GduLinuxLvm2VolumeGroup *vg)
+{
+ GList *devices;
+ GList *l;
+ guint64 seq_num;
+ GduDevice *pv_to_use;
+ gboolean emitted_changed;
+
+ emitted_changed = FALSE;
+
+ /* TODO: do incremental list management instead of recomputing on
+ * each add/remove/change event
+ */
+
+ /* out with the old.. */
+ g_list_foreach (vg->priv->pv_devices, (GFunc) g_object_unref, NULL);
+ g_list_free (vg->priv->pv_devices);
+ vg->priv->pv_devices = NULL;
+
+ /* find all GduDevice objects for LVs that are part of this VG */
+ devices = gdu_pool_get_devices (vg->priv->pool);
+ for (l = devices; l != NULL; l = l->next) {
+ GduDevice *d = GDU_DEVICE (l->data);
+ if (gdu_device_is_linux_lvm2_pv (d) &&
+ g_strcmp0 (gdu_device_linux_lvm2_pv_get_group_uuid (d), vg->priv->uuid) == 0) {
+ vg->priv->pv_devices = g_list_prepend (vg->priv->pv_devices, g_object_ref (d));
+ }
+ }
+ g_list_foreach (devices, (GFunc) g_object_unref, NULL);
+ g_list_free (devices);
+
+ /* Find the PV with the highest sequence number and use that */
+ seq_num = 0;
+ pv_to_use = NULL;
+ for (l = vg->priv->pv_devices; l != NULL; l = l->next) {
+ GduDevice *d = GDU_DEVICE (l->data);
+ if (pv_to_use == NULL || gdu_device_linux_lvm2_pv_get_group_sequence_number (d) > seq_num) {
+ pv_to_use = d;
+ }
+ }
+
+ if (pv_to_use == NULL) {
+ /* ok, switch to the new LV */
+ if (vg->priv->pv != NULL)
+ g_object_unref (vg->priv->pv);
+ vg->priv->pv = NULL;
+
+ /* emit changed since data might have changed */
+ emit_changed (vg);
+ emitted_changed = TRUE;
+
+ } else if (vg->priv->pv == NULL ||
+ (gdu_device_linux_lvm2_pv_get_group_sequence_number (pv_to_use) >
+ gdu_device_linux_lvm2_pv_get_group_sequence_number (vg->priv->pv))) {
+ /* ok, switch to the new PV */
+ if (vg->priv->pv != NULL)
+ g_object_unref (vg->priv->pv);
+ vg->priv->pv = g_object_ref (pv_to_use);
+
+ /* emit changed since data might have changed */
+ emit_changed (vg);
+ emitted_changed = TRUE;
+ }
+
+ return emitted_changed;
+}
+
+static void
+on_device_added (GduPool *pool, GduDevice *device, gpointer user_data)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (user_data);
+ find_pvs (vg);
+}
+
+static void
+on_device_removed (GduPool *pool, GduDevice *device, gpointer user_data)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (user_data);
+ find_pvs (vg);
+}
+
+static void
+on_device_changed (GduPool *pool, GduDevice *device, gpointer user_data)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (user_data);
+ gboolean emitted_changed;
+
+ emitted_changed = find_pvs (vg);
+
+ /* propagate change events from LVs and PVs as change events on the VG */
+ if (!emitted_changed) {
+ if ((gdu_device_is_linux_lvm2_pv (device) &&
+ g_strcmp0 (gdu_device_linux_lvm2_pv_get_group_uuid (device), vg->priv->uuid) == 0) ||
+ (gdu_device_is_linux_lvm2_lv (device) &&
+ g_strcmp0 (gdu_device_linux_lvm2_lv_get_group_uuid (device), vg->priv->uuid) == 0)) {
+
+ emit_changed (vg);
+ }
+ }
+}
+
+/**
+ * _gdu_linux_lvm2_volume_group_new:
+ * @pool: A #GduPool.
+ * @uuid: The UUID for the volume group.
+ * @enclosing_presentable: The enclosing presentable
+ *
+ * Creates a new #GduLinuxLvm2VolumeGroup. Note that only one of @uuid and
+ * @device_file may be %NULL.
+ */
+GduLinuxLvm2VolumeGroup *
+_gdu_linux_lvm2_volume_group_new (GduPool *pool,
+ const gchar *uuid,
+ GduPresentable *enclosing_presentable)
+{
+ GduLinuxLvm2VolumeGroup *vg;
+
+ vg = GDU_LINUX_LVM2_VOLUME_GROUP (g_object_new (GDU_TYPE_LINUX_LVM2_VOLUME_GROUP, NULL));
+ vg->priv->pool = g_object_ref (pool);
+ vg->priv->uuid = g_strdup (uuid);
+
+ vg->priv->id = g_strdup_printf ("linux_lvm2_volume_group_%s_enclosed_by_%s",
+ uuid,
+ enclosing_presentable != NULL ? gdu_presentable_get_id (enclosing_presentable) : "(none)");
+
+ vg->priv->enclosing_presentable =
+ enclosing_presentable != NULL ? g_object_ref (enclosing_presentable) : NULL;
+
+ g_signal_connect (vg->priv->pool, "device-added", G_CALLBACK (on_device_added), vg);
+ g_signal_connect (vg->priv->pool, "device-removed", G_CALLBACK (on_device_removed), vg);
+ g_signal_connect (vg->priv->pool, "device-changed", G_CALLBACK (on_device_changed), vg);
+ find_pvs (vg);
+
+ return vg;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* GduPresentable methods */
+
+static const gchar *
+gdu_linux_lvm2_volume_group_get_id (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (presentable);
+
+ return vg->priv->id;
+}
+
+static GduDevice *
+gdu_linux_lvm2_volume_group_get_device (GduPresentable *presentable)
+{
+ return NULL;
+}
+
+static GduPresentable *
+gdu_linux_lvm2_volume_group_get_enclosing_presentable (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (presentable);
+ if (vg->priv->enclosing_presentable != NULL)
+ return g_object_ref (vg->priv->enclosing_presentable);
+ return NULL;
+}
+
+static gchar *
+get_names_and_desc (GduPresentable *presentable,
+ gchar **out_vpd_name,
+ gchar **out_desc)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (presentable);
+ gchar *ret;
+ gchar *ret_desc;
+ gchar *ret_vpd;
+ guint64 size;
+ gchar *size_str;
+
+ ret = NULL;
+ ret_desc = NULL;
+ ret_vpd = NULL;
+ size = 0;
+ size_str = NULL;
+
+ if (vg->priv->pv != NULL) {
+ ret = g_strdup (gdu_device_linux_lvm2_pv_get_group_name (vg->priv->pv));
+ size = gdu_device_linux_lvm2_pv_get_group_size (vg->priv->pv);
+ size_str = gdu_util_get_size_for_display (size, FALSE, FALSE);
+ } else {
+ ret = g_strdup (_("Volume Group"));
+ }
+
+ /* Translators: Description */
+ ret_desc = g_strdup (_("Volume Group"));
+
+ if (size_str != NULL) {
+ /* Translators: VPD name - first %s is the size e.g. '45 GB' */
+ ret_vpd = g_strdup_printf (_("%s LVM2 Volume Group"), size_str);
+ } else {
+ /* Translators: VPD name when size is not known */
+ ret_vpd = g_strdup (_("LVM2 Volume Group"));
+ }
+
+ if (out_desc != NULL)
+ *out_desc = ret_desc;
+ else
+ g_free (ret_desc);
+
+ if (out_vpd_name != NULL)
+ *out_vpd_name = ret_vpd;
+ else
+ g_free (ret_vpd);
+
+ g_free (size_str);
+
+ return ret;
+}
+
+static char *
+gdu_linux_lvm2_volume_group_get_name (GduPresentable *presentable)
+{
+ return get_names_and_desc (presentable, NULL, NULL);
+}
+
+static gchar *
+gdu_linux_lvm2_volume_group_get_description (GduPresentable *presentable)
+{
+ gchar *desc;
+ gchar *name;
+
+ name = get_names_and_desc (presentable, NULL, &desc);
+ g_free (name);
+
+ return desc;
+}
+
+static gchar *
+gdu_linux_lvm2_volume_group_get_vpd_name (GduPresentable *presentable)
+{
+ gchar *vpd_name;
+ gchar *name;
+
+ name = get_names_and_desc (presentable, &vpd_name, NULL);
+ g_free (name);
+
+ return vpd_name;
+}
+
+static GIcon *
+gdu_linux_lvm2_volume_group_get_icon (GduPresentable *presentable)
+{
+ return g_themed_icon_new_with_default_fallbacks ("gdu-raid-array");
+}
+
+static guint64
+gdu_linux_lvm2_volume_group_get_offset (GduPresentable *presentable)
+{
+ return 0;
+}
+
+static guint64
+gdu_linux_lvm2_volume_group_get_size (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (presentable);
+ guint64 ret;
+
+ if (vg->priv->pv != NULL) {
+ ret = gdu_device_linux_lvm2_pv_get_group_size (vg->priv->pv);
+ } else {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static GduPool *
+gdu_linux_lvm2_volume_group_get_pool (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeGroup *vg = GDU_LINUX_LVM2_VOLUME_GROUP (presentable);
+ return g_object_ref (vg->priv->pool);
+}
+
+static gboolean
+gdu_linux_lvm2_volume_group_is_allocated (GduPresentable *presentable)
+{
+ return TRUE;
+}
+
+static gboolean
+gdu_linux_lvm2_volume_group_is_recognized (GduPresentable *presentable)
+{
+ /* TODO: maybe we need to return FALSE sometimes */
+ return TRUE;
+}
+
+static void
+gdu_linux_lvm2_volume_group_presentable_iface_init (GduPresentableIface *iface)
+{
+ iface->get_id = gdu_linux_lvm2_volume_group_get_id;
+ iface->get_device = gdu_linux_lvm2_volume_group_get_device;
+ iface->get_enclosing_presentable = gdu_linux_lvm2_volume_group_get_enclosing_presentable;
+ iface->get_name = gdu_linux_lvm2_volume_group_get_name;
+ iface->get_description = gdu_linux_lvm2_volume_group_get_description;
+ iface->get_vpd_name = gdu_linux_lvm2_volume_group_get_vpd_name;
+ iface->get_icon = gdu_linux_lvm2_volume_group_get_icon;
+ iface->get_offset = gdu_linux_lvm2_volume_group_get_offset;
+ iface->get_size = gdu_linux_lvm2_volume_group_get_size;
+ iface->get_pool = gdu_linux_lvm2_volume_group_get_pool;
+ iface->is_allocated = gdu_linux_lvm2_volume_group_is_allocated;
+ iface->is_recognized = gdu_linux_lvm2_volume_group_is_recognized;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+void
+_gdu_linux_lvm2_volume_group_rewrite_enclosing_presentable (GduLinuxLvm2VolumeGroup *vg)
+{
+ if (vg->priv->enclosing_presentable != NULL) {
+ const gchar *enclosing_presentable_id;
+ GduPresentable *new_enclosing_presentable;
+
+ enclosing_presentable_id = gdu_presentable_get_id (vg->priv->enclosing_presentable);
+
+ new_enclosing_presentable = gdu_pool_get_presentable_by_id (vg->priv->pool,
+ enclosing_presentable_id);
+ if (new_enclosing_presentable == NULL) {
+ g_warning ("Error rewriting enclosing_presentable for %s, no such id %s",
+ vg->priv->id,
+ enclosing_presentable_id);
+ goto out;
+ }
+
+ g_object_unref (vg->priv->enclosing_presentable);
+ vg->priv->enclosing_presentable = new_enclosing_presentable;
+ }
+
+ out:
+ ;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* GduDrive virtual method overrides */
+
+static gboolean
+gdu_linux_lvm2_volume_group_is_active (GduDrive *drive)
+{
+ return TRUE;
+}
+
+static gboolean
+gdu_linux_lvm2_volume_group_is_activatable (GduDrive *drive)
+{
+ return FALSE;
+}
+
+static gboolean
+gdu_linux_lvm2_volume_group_can_deactivate (GduDrive *drive)
+{
+ return FALSE;
+}
+
+static gboolean
+gdu_linux_lvm2_volume_group_can_activate (GduDrive *drive,
+ gboolean *out_degraded)
+{
+ return FALSE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * gdu_linux_lvm2_volume_group_get_lv_device:
+ * @vg: A #GduLinuxLvm2VolumeGroup.
+ *
+ * Returns a #GduDevice for a PV in @vg with the most up to date volume group info.
+ *
+ * Returns: A #GduDevice (free with g_object_unref()) or %NULL if not found.
+ */
+GduDevice *
+gdu_linux_lvm2_volume_group_get_pv_device (GduLinuxLvm2VolumeGroup *vg)
+{
+ if (vg->priv->pv != NULL) {
+ return g_object_ref (vg->priv->pv);
+ } else {
+ return NULL;
+ }
+}
+
+GduLinuxLvm2VolumeGroupState
+gdu_linux_lvm2_volume_group_get_state (GduLinuxLvm2VolumeGroup *vg)
+{
+ GList *lvs;
+ GList *l;
+ guint num_lvs;
+ guint num_running_lvs;
+ GduLinuxLvm2VolumeGroupState ret;
+
+ lvs = gdu_pool_get_enclosed_presentables (vg->priv->pool, GDU_PRESENTABLE (vg));
+ num_lvs = 0;
+ num_running_lvs = 0;
+ for (l = lvs; l != NULL; l = l->next) {
+ GduPresentable *p = GDU_PRESENTABLE (l->data);
+
+ if (GDU_IS_LINUX_LVM2_VOLUME (p)) {
+ GduDevice *d;
+
+ d = gdu_presentable_get_device (p);
+ if (d != NULL) {
+ num_running_lvs++;
+ g_object_unref (d);
+ }
+ num_lvs++;
+ }
+ }
+ g_list_foreach (lvs, (GFunc) g_object_unref, NULL);
+ g_list_free (lvs);
+
+ if (num_running_lvs == 0)
+ ret = GDU_LINUX_LVM2_VOLUME_GROUP_STATE_NOT_RUNNING;
+ else if (num_running_lvs == num_lvs)
+ ret = GDU_LINUX_LVM2_VOLUME_GROUP_STATE_RUNNING;
+ else
+ ret = GDU_LINUX_LVM2_VOLUME_GROUP_STATE_PARTIALLY_RUNNING;
+
+ return ret;
+}
+
+const gchar *
+gdu_linux_lvm2_volume_group_get_uuid (GduLinuxLvm2VolumeGroup *vg)
+{
+ return vg->priv->uuid;
+}
diff --git a/src/gdu/gdu-linux-lvm2-volume-group.h b/src/gdu/gdu-linux-lvm2-volume-group.h
new file mode 100644
index 0000000..824f23d
--- /dev/null
+++ b/src/gdu/gdu-linux-lvm2-volume-group.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2010 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined (__GDU_INSIDE_GDU_H) && !defined (GDU_COMPILATION)
+#error "Only <gdu/gdu.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __GDU_LINUX_LVM2_VOLUME_GROUP_H
+#define __GDU_LINUX_LVM2_VOLUME_GROUP_H
+
+#include <gdu/gdu-types.h>
+#include <gdu/gdu-callbacks.h>
+#include <gdu/gdu-drive.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_LINUX_LVM2_VOLUME_GROUP (gdu_linux_lvm2_volume_group_get_type ())
+#define GDU_LINUX_LVM2_VOLUME_GROUP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_LINUX_LVM2_VOLUME_GROUP, GduLinuxLvm2VolumeGroup))
+#define GDU_LINUX_LVM2_VOLUME_GROUP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_LINUX_LVM2_VOLUME_GROUP, GduLinuxLvm2VolumeGroupClass))
+#define GDU_IS_LINUX_LVM2_VOLUME_GROUP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_LINUX_LVM2_VOLUME_GROUP))
+#define GDU_IS_LINUX_LVM2_VOLUME_GROUP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_LINUX_LVM2_VOLUME_GROUP))
+#define GDU_LINUX_LVM2_VOLUME_GROUP_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), GDU_TYPE_LINUX_LVM2_VOLUME_GROUP, GduLinuxLvm2VolumeGroupClass))
+
+typedef struct _GduLinuxLvm2VolumeGroupClass GduLinuxLvm2VolumeGroupClass;
+typedef struct _GduLinuxLvm2VolumeGroupPrivate GduLinuxLvm2VolumeGroupPrivate;
+
+struct _GduLinuxLvm2VolumeGroup
+{
+ GduDrive parent;
+
+ /*< private >*/
+ GduLinuxLvm2VolumeGroupPrivate *priv;
+};
+
+struct _GduLinuxLvm2VolumeGroupClass
+{
+ GduDriveClass parent_class;
+};
+
+typedef enum {
+ GDU_LINUX_LVM2_VOLUME_GROUP_STATE_NOT_RUNNING,
+ GDU_LINUX_LVM2_VOLUME_GROUP_STATE_PARTIALLY_RUNNING,
+ GDU_LINUX_LVM2_VOLUME_GROUP_STATE_RUNNING,
+} GduLinuxLvm2VolumeGroupState;
+
+GType gdu_linux_lvm2_volume_group_get_type (void);
+const gchar *gdu_linux_lvm2_volume_group_get_uuid (GduLinuxLvm2VolumeGroup *vg);
+GduLinuxLvm2VolumeGroupState gdu_linux_lvm2_volume_group_get_state (GduLinuxLvm2VolumeGroup *vg);
+GduDevice *gdu_linux_lvm2_volume_group_get_pv_device (GduLinuxLvm2VolumeGroup *vg);
+
+G_END_DECLS
+
+#endif /* __GDU_LINUX_LVM2_VOLUME_GROUP_H */
diff --git a/src/gdu/gdu-linux-lvm2-volume-hole.c b/src/gdu/gdu-linux-lvm2-volume-hole.c
new file mode 100644
index 0000000..298c821
--- /dev/null
+++ b/src/gdu/gdu-linux-lvm2-volume-hole.c
@@ -0,0 +1,331 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2010 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+#include <dbus/dbus-glib.h>
+
+#include "gdu-private.h"
+#include "gdu-util.h"
+#include "gdu-pool.h"
+#include "gdu-device.h"
+#include "gdu-linux-lvm2-volume-group.h"
+#include "gdu-linux-lvm2-volume-hole.h"
+#include "gdu-presentable.h"
+
+struct _GduLinuxLvm2VolumeHolePrivate
+{
+ GduPool *pool;
+
+ gchar *id;
+
+ GduPresentable *enclosing_presentable;
+};
+
+static GObjectClass *parent_class = NULL;
+
+static void gdu_linux_lvm2_volume_hole_presentable_iface_init (GduPresentableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GduLinuxLvm2VolumeHole, gdu_linux_lvm2_volume_hole, GDU_TYPE_VOLUME_HOLE,
+ G_IMPLEMENT_INTERFACE (GDU_TYPE_PRESENTABLE,
+ gdu_linux_lvm2_volume_hole_presentable_iface_init))
+
+static void on_presentable_changed (GduPresentable *presentable, gpointer user_data);
+
+static void
+gdu_linux_lvm2_volume_hole_finalize (GObject *object)
+{
+ GduLinuxLvm2VolumeHole *volume_hole = GDU_LINUX_LVM2_VOLUME_HOLE (object);
+
+ //g_debug ("##### finalized linux-lvm2 volume_hole '%s' %p", volume_hole->priv->id, lv);
+
+ g_free (volume_hole->priv->id);
+
+ if (volume_hole->priv->enclosing_presentable != NULL) {
+ g_signal_handlers_disconnect_by_func (volume_hole->priv->enclosing_presentable,
+ on_presentable_changed,
+ volume_hole);
+ g_object_unref (volume_hole->priv->enclosing_presentable);
+ }
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+static void
+gdu_linux_lvm2_volume_hole_class_init (GduLinuxLvm2VolumeHoleClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gdu_linux_lvm2_volume_hole_finalize;
+
+ g_type_class_add_private (klass, sizeof (GduLinuxLvm2VolumeHolePrivate));
+}
+
+static void
+gdu_linux_lvm2_volume_hole_init (GduLinuxLvm2VolumeHole *volume_hole)
+{
+ volume_hole->priv = G_TYPE_INSTANCE_GET_PRIVATE (volume_hole, GDU_TYPE_LINUX_LVM2_VOLUME_HOLE, GduLinuxLvm2VolumeHolePrivate);
+}
+
+/**
+ * _gdu_linux_lvm2_volume_hole_new:
+ * @pool: A #GduPool.
+ * @enclosing_presentable: The enclosing presentable.
+ *
+ * Creates a new #GduLinuxLvm2VolumeHole.
+ */
+GduLinuxLvm2VolumeHole *
+_gdu_linux_lvm2_volume_hole_new (GduPool *pool,
+ GduPresentable *enclosing_presentable)
+{
+ GduLinuxLvm2VolumeHole *volume_hole;
+
+ volume_hole = GDU_LINUX_LVM2_VOLUME_HOLE (g_object_new (GDU_TYPE_LINUX_LVM2_VOLUME_HOLE, NULL));
+ volume_hole->priv->pool = g_object_ref (pool);
+
+ volume_hole->priv->id = g_strdup_printf ("linux_lvm2_volume_hole_enclosed_by_%s",
+ enclosing_presentable != NULL ? gdu_presentable_get_id (enclosing_presentable) : "(none)");
+
+ volume_hole->priv->enclosing_presentable =
+ enclosing_presentable != NULL ? g_object_ref (enclosing_presentable) : NULL;
+
+ /* Track the VG since we get the amount of free space from there */
+ if (volume_hole->priv->enclosing_presentable != NULL) {
+ g_signal_connect (volume_hole->priv->enclosing_presentable,
+ "changed",
+ G_CALLBACK (on_presentable_changed),
+ volume_hole);
+ }
+
+ return volume_hole;
+}
+
+static void
+on_presentable_changed (GduPresentable *presentable, gpointer user_data)
+{
+ GduLinuxLvm2VolumeHole *volume_hole = GDU_LINUX_LVM2_VOLUME_HOLE (user_data);
+
+ g_signal_emit_by_name (volume_hole, "changed");
+ g_signal_emit_by_name (volume_hole->priv->pool, "presentable-changed", volume_hole);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* GduPresentable methods */
+
+static const gchar *
+gdu_linux_lvm2_volume_hole_get_id (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeHole *volume_hole = GDU_LINUX_LVM2_VOLUME_HOLE (presentable);
+
+ return volume_hole->priv->id;
+}
+
+static GduDevice *
+gdu_linux_lvm2_volume_hole_get_device (GduPresentable *presentable)
+{
+ return NULL;
+}
+
+static GduPresentable *
+gdu_linux_lvm2_volume_hole_get_enclosing_presentable (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeHole *volume_hole = GDU_LINUX_LVM2_VOLUME_HOLE (presentable);
+
+ if (volume_hole->priv->enclosing_presentable != NULL)
+ return g_object_ref (volume_hole->priv->enclosing_presentable);
+ return NULL;
+}
+
+static guint64
+gdu_linux_lvm2_volume_hole_get_size (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeHole *volume_hole = GDU_LINUX_LVM2_VOLUME_HOLE (presentable);
+ GduDevice *pv_device;
+ guint64 ret;
+
+ ret = 0;
+
+ pv_device = gdu_linux_lvm2_volume_group_get_pv_device (GDU_LINUX_LVM2_VOLUME_GROUP (volume_hole->priv->enclosing_presentable));
+ if (pv_device != NULL) {
+ ret = gdu_device_linux_lvm2_pv_get_group_unallocated_size (pv_device);
+ g_object_unref (pv_device);
+ }
+
+ return ret;
+}
+
+static gchar *
+get_names_and_desc (GduPresentable *presentable,
+ gchar **out_vpd_name,
+ gchar **out_desc)
+{
+ gchar *ret;
+ gchar *ret_desc;
+ gchar *ret_vpd;
+ guint64 size;
+ gchar *strsize;
+
+ ret = NULL;
+ ret_desc = NULL;
+ ret_vpd = NULL;
+
+ size = gdu_linux_lvm2_volume_hole_get_size (presentable);
+ strsize = gdu_util_get_size_for_display (size, FALSE, FALSE);
+
+ /* Translators: label for an unallocated space in a LVM2 volume group.
+ * %s is the size, formatted like '45 GB'
+ */
+ ret = g_strdup_printf (_("%s Free"), strsize);
+ g_free (strsize);
+
+ /* Translators: Description */
+ ret_desc = g_strdup (_("Unallocated Space"));
+
+ /* Translators: VPD name */
+ ret_vpd = g_strdup (_("LVM2 VG Unallocated Space"));
+
+ if (out_desc != NULL)
+ *out_desc = ret_desc;
+ else
+ g_free (ret_desc);
+
+ if (out_vpd_name != NULL)
+ *out_vpd_name = ret_vpd;
+ else
+ g_free (ret_vpd);
+
+ return ret;
+}
+
+static char *
+gdu_linux_lvm2_volume_hole_get_name (GduPresentable *presentable)
+{
+ return get_names_and_desc (presentable, NULL, NULL);
+}
+
+static gchar *
+gdu_linux_lvm2_volume_hole_get_description (GduPresentable *presentable)
+{
+ gchar *desc;
+ gchar *name;
+
+ name = get_names_and_desc (presentable, NULL, &desc);
+ g_free (name);
+
+ return desc;
+}
+
+static gchar *
+gdu_linux_lvm2_volume_hole_get_vpd_name (GduPresentable *presentable)
+{
+ gchar *vpd_name;
+ gchar *name;
+
+ name = get_names_and_desc (presentable, &vpd_name, NULL);
+ g_free (name);
+
+ return vpd_name;
+}
+
+static GIcon *
+gdu_linux_lvm2_volume_hole_get_icon (GduPresentable *presentable)
+{
+ return g_themed_icon_new_with_default_fallbacks ("gdu-raid-array");
+}
+
+static guint64
+gdu_linux_lvm2_volume_hole_get_offset (GduPresentable *presentable)
+{
+ /* Halfway to G_MAXUINT64 - should guarantee that we're always at the end... */
+ return G_MAXINT64;
+}
+
+static GduPool *
+gdu_linux_lvm2_volume_hole_get_pool (GduPresentable *presentable)
+{
+ GduLinuxLvm2VolumeHole *volume_hole = GDU_LINUX_LVM2_VOLUME_HOLE (presentable);
+ return g_object_ref (volume_hole->priv->pool);
+}
+
+static gboolean
+gdu_linux_lvm2_volume_hole_is_allocated (GduPresentable *presentable)
+{
+ return FALSE;
+}
+
+static gboolean
+gdu_linux_lvm2_volume_hole_is_recognized (GduPresentable *presentable)
+{
+ /* TODO: maybe we need to return FALSE sometimes */
+ return TRUE;
+}
+
+static void
+gdu_linux_lvm2_volume_hole_presentable_iface_init (GduPresentableIface *iface)
+{
+ iface->get_id = gdu_linux_lvm2_volume_hole_get_id;
+ iface->get_device = gdu_linux_lvm2_volume_hole_get_device;
+ iface->get_enclosing_presentable = gdu_linux_lvm2_volume_hole_get_enclosing_presentable;
+ iface->get_name = gdu_linux_lvm2_volume_hole_get_name;
+ iface->get_description = gdu_linux_lvm2_volume_hole_get_description;
+ iface->get_vpd_name = gdu_linux_lvm2_volume_hole_get_vpd_name;
+ iface->get_icon = gdu_linux_lvm2_volume_hole_get_icon;
+ iface->get_offset = gdu_linux_lvm2_volume_hole_get_offset;
+ iface->get_size = gdu_linux_lvm2_volume_hole_get_size;
+ iface->get_pool = gdu_linux_lvm2_volume_hole_get_pool;
+ iface->is_allocated = gdu_linux_lvm2_volume_hole_is_allocated;
+ iface->is_recognized = gdu_linux_lvm2_volume_hole_is_recognized;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+void
+_gdu_linux_lvm2_volume_hole_rewrite_enclosing_presentable (GduLinuxLvm2VolumeHole *volume_hole)
+{
+ if (volume_hole->priv->enclosing_presentable != NULL) {
+ const gchar *enclosing_presentable_id;
+ GduPresentable *new_enclosing_presentable;
+
+ enclosing_presentable_id = gdu_presentable_get_id (volume_hole->priv->enclosing_presentable);
+
+ new_enclosing_presentable = gdu_pool_get_presentable_by_id (volume_hole->priv->pool,
+ enclosing_presentable_id);
+ if (new_enclosing_presentable == NULL) {
+ g_warning ("Error rewriting enclosing_presentable for %s, no such id %s",
+ volume_hole->priv->id,
+ enclosing_presentable_id);
+ goto out;
+ }
+
+ g_object_unref (volume_hole->priv->enclosing_presentable);
+ volume_hole->priv->enclosing_presentable = new_enclosing_presentable;
+ }
+
+ out:
+ ;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/gdu/gdu-linux-lvm2-volume-hole.h b/src/gdu/gdu-linux-lvm2-volume-hole.h
new file mode 100644
index 0000000..b2ed174
--- /dev/null
+++ b/src/gdu/gdu-linux-lvm2-volume-hole.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2010 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined (__GDU_INSIDE_GDU_H) && !defined (GDU_COMPILATION)
+#error "Only <gdu/gdu.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __GDU_LINUX_LVM2_VOLUME_HOLE_H
+#define __GDU_LINUX_LVM2_VOLUME_HOLE_H
+
+#include <gdu/gdu-types.h>
+#include <gdu/gdu-callbacks.h>
+#include <gdu/gdu-volume-hole.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_LINUX_LVM2_VOLUME_HOLE (gdu_linux_lvm2_volume_hole_get_type ())
+#define GDU_LINUX_LVM2_VOLUME_HOLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_LINUX_LVM2_VOLUME_HOLE, GduLinuxLvm2VolumeHole))
+#define GDU_LINUX_LVM2_VOLUME_HOLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_LINUX_LVM2_VOLUME_HOLE, GduLinuxLvm2VolumeHoleClass))
+#define GDU_IS_LINUX_LVM2_VOLUME_HOLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_LINUX_LVM2_VOLUME_HOLE))
+#define GDU_IS_LINUX_LVM2_VOLUME_HOLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_LINUX_LVM2_VOLUME_HOLE))
+#define GDU_LINUX_LVM2_VOLUME_HOLE_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), GDU_TYPE_LINUX_LVM2_VOLUME_HOLE, GduLinuxLvm2VolumeHoleClass))
+
+typedef struct _GduLinuxLvm2VolumeHoleClass GduLinuxLvm2VolumeHoleClass;
+typedef struct _GduLinuxLvm2VolumeHolePrivate GduLinuxLvm2VolumeHolePrivate;
+
+struct _GduLinuxLvm2VolumeHole
+{
+ GduVolumeHole parent;
+
+ /*< private >*/
+ GduLinuxLvm2VolumeHolePrivate *priv;
+};
+
+struct _GduLinuxLvm2VolumeHoleClass
+{
+ GduVolumeHoleClass parent_class;
+};
+
+GType gdu_linux_lvm2_volume_hole_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDU_LINUX_LVM2_VOLUME_HOLE_H */
diff --git a/src/gdu/gdu-linux-lvm2-volume.c b/src/gdu/gdu-linux-lvm2-volume.c
new file mode 100644
index 0000000..e483c38
--- /dev/null
+++ b/src/gdu/gdu-linux-lvm2-volume.c
@@ -0,0 +1,430 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2010 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+#include <dbus/dbus-glib.h>
+
+#include "gdu-private.h"
+#include "gdu-util.h"
+#include "gdu-pool.h"
+#include "gdu-device.h"
+#include "gdu-linux-lvm2-volume.h"
+#include "gdu-presentable.h"
+
+struct _GduLinuxLvm2VolumePrivate
+{
+ GduPool *pool;
+
+ gchar *name;
+
+ gchar *group_uuid;
+ gchar *uuid;
+
+ guint64 offset;
+ guint64 size;
+
+ /* the GduDevice for the LV / mapped device (if activated) */
+ GduDevice *lv;
+
+ gchar *id;
+
+ GduPresentable *enclosing_presentable;
+};
+
+static GObjectClass *parent_class = NULL;
+
+static void gdu_linux_lvm2_volume_presentable_iface_init (GduPresentableIface *iface);
+
+static void on_device_added (GduPool *pool, GduDevice *device, gpointer user_data);
+static void on_device_removed (GduPool *pool, GduDevice *device, gpointer user_data);
+static void on_device_changed (GduPool *pool, GduDevice *device, gpointer user_data);
+
+G_DEFINE_TYPE_WITH_CODE (GduLinuxLvm2Volume, gdu_linux_lvm2_volume, GDU_TYPE_VOLUME,
+ G_IMPLEMENT_INTERFACE (GDU_TYPE_PRESENTABLE,
+ gdu_linux_lvm2_volume_presentable_iface_init))
+
+static void
+gdu_linux_lvm2_volume_finalize (GObject *object)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (object);
+
+ //g_debug ("##### finalized linux-lvm2 volume '%s' %p", lv->priv->id, lv);
+
+ if (volume->priv->pool != NULL) {
+ g_signal_handlers_disconnect_by_func (volume->priv->pool, on_device_added, volume);
+ g_signal_handlers_disconnect_by_func (volume->priv->pool, on_device_removed, volume);
+ g_signal_handlers_disconnect_by_func (volume->priv->pool, on_device_changed, volume);
+ g_object_unref (volume->priv->pool);
+ }
+
+ g_free (volume->priv->id);
+ g_free (volume->priv->name);
+ g_free (volume->priv->group_uuid);
+ g_free (volume->priv->uuid);
+
+ if (volume->priv->enclosing_presentable != NULL)
+ g_object_unref (volume->priv->enclosing_presentable);
+
+ if (volume->priv->lv != NULL)
+ g_object_unref (volume->priv->lv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+static void
+gdu_linux_lvm2_volume_class_init (GduLinuxLvm2VolumeClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gdu_linux_lvm2_volume_finalize;
+
+ g_type_class_add_private (klass, sizeof (GduLinuxLvm2VolumePrivate));
+}
+
+static void
+gdu_linux_lvm2_volume_init (GduLinuxLvm2Volume *volume)
+{
+ volume->priv = G_TYPE_INSTANCE_GET_PRIVATE (volume, GDU_TYPE_LINUX_LVM2_VOLUME, GduLinuxLvm2VolumePrivate);
+}
+
+static void
+emit_changed (GduLinuxLvm2Volume *volume)
+{
+ //g_debug ("emitting changed for uuid '%s'", volume->priv->uuid);
+ g_signal_emit_by_name (volume, "changed");
+ g_signal_emit_by_name (volume->priv->pool, "presentable-changed", volume);
+}
+
+static gboolean
+find_lv (GduLinuxLvm2Volume *volume)
+{
+ GList *devices;
+ GList *l;
+ GduDevice *lv_to_use;
+ gboolean emitted_changed;
+
+ emitted_changed = FALSE;
+
+ /* find all GduDevice objects for LVs that are part of this VG */
+ lv_to_use = NULL;
+ devices = gdu_pool_get_devices (volume->priv->pool);
+ for (l = devices; l != NULL; l = l->next) {
+ GduDevice *d = GDU_DEVICE (l->data);
+ if (gdu_device_is_linux_lvm2_lv (d) &&
+ g_strcmp0 (gdu_device_linux_lvm2_lv_get_uuid (d), volume->priv->uuid) == 0) {
+ lv_to_use = d;
+ break;
+ }
+ }
+ g_list_foreach (devices, (GFunc) g_object_unref, NULL);
+ g_list_free (devices);
+
+ /* Find the PV with the highest sequence number and use that */
+
+ if (volume->priv->lv != lv_to_use) {
+ if (volume->priv->lv != NULL)
+ g_object_unref (volume->priv->lv);
+ volume->priv->lv = lv_to_use != NULL ? g_object_ref (lv_to_use) : NULL;
+ emit_changed (volume);
+ emitted_changed = TRUE;
+ }
+
+ return emitted_changed;
+}
+
+static void
+on_device_added (GduPool *pool, GduDevice *device, gpointer user_data)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (user_data);
+ find_lv (volume);
+}
+
+static void
+on_device_removed (GduPool *pool, GduDevice *device, gpointer user_data)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (user_data);
+ find_lv (volume);
+}
+
+static void
+on_device_changed (GduPool *pool, GduDevice *device, gpointer user_data)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (user_data);
+ gboolean emitted_changed;
+
+ emitted_changed = find_lv (volume);
+
+ if (!emitted_changed && device == volume->priv->lv)
+ emit_changed (volume);
+}
+
+/**
+ * _gdu_linux_lvm2_volume_new:
+ * @pool: A #GduPool.
+ * @name: The name of the logical volume.
+ * @group_uuid: The UUID of the group that the logical volume belongs to.
+ * @uuid: The UUID of the logical volume.
+ * @offset: The offset of the logical volume.
+ * @size: The size of the logical volume.
+ * @enclosing_presentable: The enclosing presentable.
+ *
+ * Creates a new #GduLinuxLvm2Volume.
+ *
+ * Note that @offset is only used for laying out the volumes in e.g. a grid - it doesn't really
+ * make sense to talk about the offset of a LV in LVM2.
+ */
+GduLinuxLvm2Volume *
+_gdu_linux_lvm2_volume_new (GduPool *pool,
+ const gchar *name,
+ const gchar *group_uuid,
+ const gchar *uuid,
+ guint64 offset,
+ guint64 size,
+ GduPresentable *enclosing_presentable)
+{
+ GduLinuxLvm2Volume *volume;
+
+ volume = GDU_LINUX_LVM2_VOLUME (g_object_new (GDU_TYPE_LINUX_LVM2_VOLUME, NULL));
+ volume->priv->pool = g_object_ref (pool);
+ volume->priv->name = g_strdup (name);
+ volume->priv->group_uuid = g_strdup (group_uuid);
+ volume->priv->uuid = g_strdup (uuid);
+ volume->priv->offset = offset;
+ volume->priv->size = size;
+
+ volume->priv->id = g_strdup_printf ("linux_lvm2_volume_%s_enclosed_by_%s",
+ uuid,
+ enclosing_presentable != NULL ? gdu_presentable_get_id (enclosing_presentable) : "(none)");
+
+ volume->priv->enclosing_presentable =
+ enclosing_presentable != NULL ? g_object_ref (enclosing_presentable) : NULL;
+
+ g_signal_connect (volume->priv->pool, "device-added", G_CALLBACK (on_device_added), volume);
+ g_signal_connect (volume->priv->pool, "device-removed", G_CALLBACK (on_device_removed), volume);
+ g_signal_connect (volume->priv->pool, "device-changed", G_CALLBACK (on_device_changed), volume);
+ find_lv (volume);
+
+ return volume;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* GduPresentable methods */
+
+static const gchar *
+gdu_linux_lvm2_volume_get_id (GduPresentable *presentable)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (presentable);
+
+ return volume->priv->id;
+}
+
+static GduDevice *
+gdu_linux_lvm2_volume_get_device (GduPresentable *presentable)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (presentable);
+
+ if (volume->priv->lv != NULL)
+ return g_object_ref (volume->priv->lv);
+ return NULL;
+}
+
+static GduPresentable *
+gdu_linux_lvm2_volume_get_enclosing_presentable (GduPresentable *presentable)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (presentable);
+
+ if (volume->priv->enclosing_presentable != NULL)
+ return g_object_ref (volume->priv->enclosing_presentable);
+ return NULL;
+}
+
+static gchar *
+get_names_and_desc (GduPresentable *presentable,
+ gchar **out_vpd_name,
+ gchar **out_desc)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (presentable);
+ gchar *ret;
+ gchar *ret_desc;
+ gchar *ret_vpd;
+
+ ret = NULL;
+ ret_desc = NULL;
+ ret_vpd = NULL;
+
+ ret = g_strdup (volume->priv->name);
+
+ /* Translators: Description */
+ ret_desc = g_strdup (_("Logical Volume"));
+
+ /* Translators: VPD name */
+ ret_vpd = g_strdup (_("LVM2 Logical Volume"));
+
+ if (out_desc != NULL)
+ *out_desc = ret_desc;
+ else
+ g_free (ret_desc);
+
+ if (out_vpd_name != NULL)
+ *out_vpd_name = ret_vpd;
+ else
+ g_free (ret_vpd);
+
+ return ret;
+}
+
+static char *
+gdu_linux_lvm2_volume_get_name (GduPresentable *presentable)
+{
+ return get_names_and_desc (presentable, NULL, NULL);
+}
+
+static gchar *
+gdu_linux_lvm2_volume_get_description (GduPresentable *presentable)
+{
+ gchar *desc;
+ gchar *name;
+
+ name = get_names_and_desc (presentable, NULL, &desc);
+ g_free (name);
+
+ return desc;
+}
+
+static gchar *
+gdu_linux_lvm2_volume_get_vpd_name (GduPresentable *presentable)
+{
+ gchar *vpd_name;
+ gchar *name;
+
+ name = get_names_and_desc (presentable, &vpd_name, NULL);
+ g_free (name);
+
+ return vpd_name;
+}
+
+static GIcon *
+gdu_linux_lvm2_volume_get_icon (GduPresentable *presentable)
+{
+ return g_themed_icon_new_with_default_fallbacks ("gdu-raid-array");
+}
+
+static guint64
+gdu_linux_lvm2_volume_get_offset (GduPresentable *presentable)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (presentable);
+
+ return volume->priv->offset;
+}
+
+static guint64
+gdu_linux_lvm2_volume_get_size (GduPresentable *presentable)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (presentable);
+
+ return volume->priv->size;
+}
+
+static GduPool *
+gdu_linux_lvm2_volume_get_pool (GduPresentable *presentable)
+{
+ GduLinuxLvm2Volume *volume = GDU_LINUX_LVM2_VOLUME (presentable);
+ return g_object_ref (volume->priv->pool);
+}
+
+static gboolean
+gdu_linux_lvm2_volume_is_allocated (GduPresentable *presentable)
+{
+ return TRUE;
+}
+
+static gboolean
+gdu_linux_lvm2_volume_is_recognized (GduPresentable *presentable)
+{
+ /* TODO: maybe we need to return FALSE sometimes */
+ return TRUE;
+}
+
+static void
+gdu_linux_lvm2_volume_presentable_iface_init (GduPresentableIface *iface)
+{
+ iface->get_id = gdu_linux_lvm2_volume_get_id;
+ iface->get_device = gdu_linux_lvm2_volume_get_device;
+ iface->get_enclosing_presentable = gdu_linux_lvm2_volume_get_enclosing_presentable;
+ iface->get_name = gdu_linux_lvm2_volume_get_name;
+ iface->get_description = gdu_linux_lvm2_volume_get_description;
+ iface->get_vpd_name = gdu_linux_lvm2_volume_get_vpd_name;
+ iface->get_icon = gdu_linux_lvm2_volume_get_icon;
+ iface->get_offset = gdu_linux_lvm2_volume_get_offset;
+ iface->get_size = gdu_linux_lvm2_volume_get_size;
+ iface->get_pool = gdu_linux_lvm2_volume_get_pool;
+ iface->is_allocated = gdu_linux_lvm2_volume_is_allocated;
+ iface->is_recognized = gdu_linux_lvm2_volume_is_recognized;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+void
+_gdu_linux_lvm2_volume_rewrite_enclosing_presentable (GduLinuxLvm2Volume *volume)
+{
+ if (volume->priv->enclosing_presentable != NULL) {
+ const gchar *enclosing_presentable_id;
+ GduPresentable *new_enclosing_presentable;
+
+ enclosing_presentable_id = gdu_presentable_get_id (volume->priv->enclosing_presentable);
+
+ new_enclosing_presentable = gdu_pool_get_presentable_by_id (volume->priv->pool,
+ enclosing_presentable_id);
+ if (new_enclosing_presentable == NULL) {
+ g_warning ("Error rewriting enclosing_presentable for %s, no such id %s",
+ volume->priv->id,
+ enclosing_presentable_id);
+ goto out;
+ }
+
+ g_object_unref (volume->priv->enclosing_presentable);
+ volume->priv->enclosing_presentable = new_enclosing_presentable;
+ }
+
+ out:
+ ;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+const gchar *
+gdu_linux_lvm2_volume_get_uuid (GduLinuxLvm2Volume *volume)
+{
+ return volume->priv->uuid;
+}
+
+const gchar *
+gdu_linux_lvm2_volume_get_group_uuid (GduLinuxLvm2Volume *volume)
+{
+ return volume->priv->group_uuid;
+}
+
diff --git a/src/gdu/gdu-linux-lvm2-volume.h b/src/gdu/gdu-linux-lvm2-volume.h
new file mode 100644
index 0000000..018a6d9
--- /dev/null
+++ b/src/gdu/gdu-linux-lvm2-volume.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2010 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#if !defined (__GDU_INSIDE_GDU_H) && !defined (GDU_COMPILATION)
+#error "Only <gdu/gdu.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __GDU_LINUX_LVM2_VOLUME_H
+#define __GDU_LINUX_LVM2_VOLUME_H
+
+#include <gdu/gdu-types.h>
+#include <gdu/gdu-callbacks.h>
+#include <gdu/gdu-volume.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_LINUX_LVM2_VOLUME (gdu_linux_lvm2_volume_get_type ())
+#define GDU_LINUX_LVM2_VOLUME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_LINUX_LVM2_VOLUME, GduLinuxLvm2Volume))
+#define GDU_LINUX_LVM2_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GDU_LINUX_LVM2_VOLUME, GduLinuxLvm2VolumeClass))
+#define GDU_IS_LINUX_LVM2_VOLUME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_LINUX_LVM2_VOLUME))
+#define GDU_IS_LINUX_LVM2_VOLUME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDU_TYPE_LINUX_LVM2_VOLUME))
+#define GDU_LINUX_LVM2_VOLUME_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((k), GDU_TYPE_LINUX_LVM2_VOLUME, GduLinuxLvm2VolumeClass))
+
+typedef struct _GduLinuxLvm2VolumeClass GduLinuxLvm2VolumeClass;
+typedef struct _GduLinuxLvm2VolumePrivate GduLinuxLvm2VolumePrivate;
+
+struct _GduLinuxLvm2Volume
+{
+ GduVolume parent;
+
+ /*< private >*/
+ GduLinuxLvm2VolumePrivate *priv;
+};
+
+struct _GduLinuxLvm2VolumeClass
+{
+ GduVolumeClass parent_class;
+};
+
+GType gdu_linux_lvm2_volume_get_type (void);
+const gchar *gdu_linux_lvm2_volume_get_uuid (GduLinuxLvm2Volume *volume);
+const gchar *gdu_linux_lvm2_volume_get_group_uuid (GduLinuxLvm2Volume *volume);
+
+G_END_DECLS
+
+#endif /* __GDU_LINUX_LVM2_VOLUME_H */
diff --git a/src/gdu/gdu-pool.c b/src/gdu/gdu-pool.c
index fb8e858..2c57c51 100644
--- a/src/gdu/gdu-pool.c
+++ b/src/gdu/gdu-pool.c
@@ -39,6 +39,9 @@
#include "gdu-hub.h"
#include "gdu-known-filesystem.h"
#include "gdu-private.h"
+#include "gdu-linux-lvm2-volume-group.h"
+#include "gdu-linux-lvm2-volume.h"
+#include "gdu-linux-lvm2-volume-hole.h"
#include "gdu-ssh-bridge.h"
#include "gdu-error.h"
@@ -838,6 +841,7 @@ get_holes_for_drive (GduPool *pool,
return ret;
}
+
static void
recompute_presentables (GduPool *pool)
{
@@ -851,6 +855,7 @@ recompute_presentables (GduPool *pool)
GList *removed_presentables;
GHashTable *hash_map_from_drive_to_extended_partition;
GHashTable *hash_map_from_linux_md_uuid_to_drive;
+ GHashTable *hash_map_from_linux_lvm2_group_uuid_to_vg;
GHashTable *hash_map_from_adapter_objpath_to_hub;
GHashTable *hash_map_from_expander_objpath_to_hub;
@@ -879,6 +884,11 @@ recompute_presentables (GduPool *pool)
NULL,
NULL);
+ hash_map_from_linux_lvm2_group_uuid_to_vg = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ NULL,
+ NULL);
+
hash_map_from_adapter_objpath_to_hub = g_hash_table_new_full (g_str_hash,
g_str_equal,
NULL,
@@ -1135,11 +1145,100 @@ recompute_presentables (GduPool *pool)
volume = _gdu_volume_new_from_device (pool, device, enclosing_luks_device);
new_presentables = g_list_prepend (new_presentables, volume);
+ } else if (gdu_device_is_linux_lvm2_lv (device)) {
+
+ /* Do nothing - this is handled when creating the Lvm2VolumeGroup object below */
+
} else {
- g_debug ("Don't know how to handle device %s", gdu_device_get_device_file (device));
+ g_warning ("Don't know how to handle device %s", gdu_device_get_device_file (device));
+ }
+
+ /* Ensure we have a GduLinuxLvm2VolumeGroup even if the volume group isn't running */
+ if (gdu_device_is_linux_lvm2_pv (device)) {
+ GduLinuxLvm2VolumeGroup *vg;
+ const gchar *vg_uuid;
+
+ vg_uuid = gdu_device_linux_lvm2_pv_get_group_uuid (device);
+
+ /* First, see if we have a volume group for this UUID already */
+ vg = g_hash_table_lookup (hash_map_from_linux_lvm2_group_uuid_to_vg, vg_uuid);
+ if (vg == NULL) {
+ gchar **lvs;
+ guint n;
+ guint64 offset;
+ guint64 unallocated_size;
+
+ /* otherwise create one */
+ vg = _gdu_linux_lvm2_volume_group_new (pool, vg_uuid, pool->priv->machine);
+ g_hash_table_insert (hash_map_from_linux_lvm2_group_uuid_to_vg, (gpointer) vg_uuid, vg);
+ new_presentables = g_list_prepend (new_presentables, vg);
+
+ /* and create logical volume objects as well */
+ lvs = gdu_device_linux_lvm2_pv_get_group_logical_volumes (device);
+ offset = 0;
+ for (n = 0; lvs != NULL && lvs[n] != NULL; n++) {
+ const gchar *lv_desc = lvs[n];
+ gchar **tokens;
+ gchar *name;
+ gchar *uuid;
+ guint64 size;
+ guint m;
+
+ tokens = g_strsplit (lv_desc, ";", 0);
+ for (m = 0; tokens[m] != NULL; m++) {
+ /* TODO: we need to unescape values */
+
+ if (g_str_has_prefix (tokens[m], "name="))
+ name = g_strdup (tokens[m] + 5);
+ else if (g_str_has_prefix (tokens[m], "uuid="))
+ uuid = g_strdup (tokens[m] + 5);
+ else if (g_str_has_prefix (tokens[m], "size="))
+ size = g_ascii_strtoull (tokens[m] + 5, NULL, 10);
+ }
+
+ if (name != NULL && uuid != NULL && size > 0) {
+ GduLinuxLvm2Volume *volume;
+
+ volume = _gdu_linux_lvm2_volume_new (pool,
+ name,
+ vg_uuid,
+ uuid,
+ offset,
+ size,
+ GDU_PRESENTABLE (vg));
+ new_presentables = g_list_prepend (new_presentables, volume);
+
+ offset += size;
+
+ } else {
+ g_warning ("Malformed LMV2 LV in group with UUID %s: "
+ "pos=%d name=%s uuid=%s size=%" G_GUINT64_FORMAT,
+ vg_uuid,
+ n,
+ name,
+ uuid,
+ size);
+ }
+
+ g_free (name);
+ g_free (uuid);
+ g_strfreev (tokens);
+ } /* foreach LV in VG */
+
+ /* Create a GduLinuxLvm2VolumeHole for unallocated space - TODO: use 1% or
+ * something based on extent size... instead of 1MB
+ */
+ unallocated_size = gdu_device_linux_lvm2_pv_get_group_unallocated_size (device);
+ if (unallocated_size >= 1000 * 1000) {
+ GduLinuxLvm2VolumeHole *volume_hole;
+ volume_hole = _gdu_linux_lvm2_volume_hole_new (pool,
+ GDU_PRESENTABLE (vg));
+ new_presentables = g_list_prepend (new_presentables, volume_hole);
+ }
+ }
}
- /* Ensure we have a GduLinuxMdDrive for non-running arrays */
+ /* Ensure we have a GduLinuxMdDrive for each non-running arrays */
if (gdu_device_is_linux_md_component (device)) {
const gchar *uuid;
@@ -1180,6 +1279,7 @@ recompute_presentables (GduPool *pool)
g_list_free (new_partitioned_drives);
g_hash_table_unref (hash_map_from_drive_to_extended_partition);
g_hash_table_unref (hash_map_from_linux_md_uuid_to_drive);
+ g_hash_table_unref (hash_map_from_linux_lvm2_group_uuid_to_vg);
g_hash_table_unref (hash_map_from_adapter_objpath_to_hub);
g_hash_table_unref (hash_map_from_expander_objpath_to_hub);
@@ -1224,6 +1324,12 @@ recompute_presentables (GduPool *pool)
_gdu_volume_rewrite_enclosing_presentable (GDU_VOLUME (p));
else if (GDU_IS_VOLUME_HOLE (p))
_gdu_volume_hole_rewrite_enclosing_presentable (GDU_VOLUME_HOLE (p));
+ else if (GDU_IS_LINUX_LVM2_VOLUME_GROUP (p))
+ _gdu_linux_lvm2_volume_group_rewrite_enclosing_presentable (GDU_LINUX_LVM2_VOLUME_GROUP (p));
+ else if (GDU_IS_LINUX_LVM2_VOLUME (p))
+ _gdu_linux_lvm2_volume_rewrite_enclosing_presentable (GDU_LINUX_LVM2_VOLUME (p));
+ else if (GDU_IS_LINUX_LVM2_VOLUME_HOLE (p))
+ _gdu_linux_lvm2_volume_hole_rewrite_enclosing_presentable (GDU_LINUX_LVM2_VOLUME_HOLE (p));
g_debug ("Added presentable %s %p", gdu_presentable_get_id (p), p);
@@ -2653,6 +2759,136 @@ gdu_pool_op_linux_md_create (GduPool *pool,
/* ---------------------------------------------------------------------------------------------------- */
+typedef struct {
+ GduPool *pool;
+ GduPoolLinuxLvm2VGStartCompletedFunc callback;
+ gpointer user_data;
+} LinuxLvm2VGStartData;
+
+static void
+op_linux_lvm2_vg_start_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+ LinuxLvm2VGStartData *data = user_data;
+ _gdu_error_fixup (error);
+ if (data->callback != NULL)
+ data->callback (data->pool, error, data->user_data);
+ g_object_unref (data->pool);
+ g_free (data);
+}
+
+void
+gdu_pool_op_linux_lvm2_vg_start (GduPool *pool,
+ const gchar *uuid,
+ GduPoolLinuxLvm2VGStartCompletedFunc callback,
+ gpointer user_data)
+{
+ LinuxLvm2VGStartData *data;
+ char *options[16];
+
+ options[0] = NULL;
+
+ data = g_new0 (LinuxLvm2VGStartData, 1);
+ data->pool = g_object_ref (pool);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ org_freedesktop_UDisks_linux_lvm2_vg_start_async (pool->priv->proxy,
+ uuid,
+ (const char **) options,
+ op_linux_lvm2_vg_start_cb,
+ data);
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct {
+ GduPool *pool;
+ GduPoolLinuxLvm2VGStopCompletedFunc callback;
+ gpointer user_data;
+} LinuxLvm2VGStopData;
+
+static void
+op_linux_lvm2_vg_stop_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+ LinuxLvm2VGStopData *data = user_data;
+ _gdu_error_fixup (error);
+ if (data->callback != NULL)
+ data->callback (data->pool, error, data->user_data);
+ g_object_unref (data->pool);
+ g_free (data);
+}
+
+void
+gdu_pool_op_linux_lvm2_vg_stop (GduPool *pool,
+ const gchar *uuid,
+ GduPoolLinuxLvm2VGStopCompletedFunc callback,
+ gpointer user_data)
+{
+ LinuxLvm2VGStopData *data;
+ char *options[16];
+
+ options[0] = NULL;
+
+ data = g_new0 (LinuxLvm2VGStopData, 1);
+ data->pool = g_object_ref (pool);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ org_freedesktop_UDisks_linux_lvm2_vg_stop_async (pool->priv->proxy,
+ uuid,
+ (const char **) options,
+ op_linux_lvm2_vg_stop_cb,
+ data);
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct {
+ GduPool *pool;
+ GduPoolLinuxLvm2LVStartCompletedFunc callback;
+ gpointer user_data;
+} LinuxLvm2LVStartData;
+
+static void
+op_linux_lvm2_lv_start_cb (DBusGProxy *proxy, GError *error, gpointer user_data)
+{
+ LinuxLvm2LVStartData *data = user_data;
+ _gdu_error_fixup (error);
+ if (data->callback != NULL)
+ data->callback (data->pool, error, data->user_data);
+ g_object_unref (data->pool);
+ g_free (data);
+}
+
+void
+gdu_pool_op_linux_lvm2_lv_start (GduPool *pool,
+ const gchar *group_uuid,
+ const gchar *uuid,
+ GduPoolLinuxLvm2LVStartCompletedFunc callback,
+ gpointer user_data)
+{
+ LinuxLvm2LVStartData *data;
+ char *options[16];
+
+ options[0] = NULL;
+
+ data = g_new0 (LinuxLvm2LVStartData, 1);
+ data->pool = g_object_ref (pool);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ org_freedesktop_UDisks_linux_lvm2_lv_start_async (pool->priv->proxy,
+ group_uuid,
+ uuid,
+ (const char **) options,
+ op_linux_lvm2_lv_start_cb,
+ data);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
/**
* gdu_pool_get_daemon_version:
* @pool: A #GduPool.
diff --git a/src/gdu/gdu-pool.h b/src/gdu/gdu-pool.h
index 9605402..c9135e3 100644
--- a/src/gdu/gdu-pool.h
+++ b/src/gdu/gdu-pool.h
@@ -133,6 +133,22 @@ void gdu_pool_op_linux_md_create (GduPool *pool,
GduPoolLinuxMdCreateCompletedFunc callback,
gpointer user_data);
+void gdu_pool_op_linux_lvm2_vg_start (GduPool *pool,
+ const gchar *uuid,
+ GduPoolLinuxLvm2VGStartCompletedFunc callback,
+ gpointer user_data);
+
+void gdu_pool_op_linux_lvm2_vg_stop (GduPool *pool,
+ const gchar *uuid,
+ GduPoolLinuxLvm2VGStopCompletedFunc callback,
+ gpointer user_data);
+
+void gdu_pool_op_linux_lvm2_lv_start (GduPool *pool,
+ const gchar *group_uuid,
+ const gchar *uuid,
+ GduPoolLinuxLvm2VGStartCompletedFunc callback,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __GDU_POOL_H */
diff --git a/src/gdu/gdu-private.h b/src/gdu/gdu-private.h
index ac5a2c0..406ba2d 100644
--- a/src/gdu/gdu-private.h
+++ b/src/gdu/gdu-private.h
@@ -123,6 +123,29 @@ gboolean _gdu_port_changed (GduPort *port);
GduMachine *_gdu_machine_new (GduPool *pool);
+GduLinuxLvm2VolumeGroup *
+_gdu_linux_lvm2_volume_group_new (GduPool *pool,
+ const gchar *vg_uuid,
+ GduPresentable *enclosing_presentable);
+
+void _gdu_linux_lvm2_volume_group_rewrite_enclosing_presentable (GduLinuxLvm2VolumeGroup *vg);
+
+GduLinuxLvm2Volume *_gdu_linux_lvm2_volume_new (GduPool *pool,
+ const gchar *name,
+ const gchar *group_uuid,
+ const gchar *uuid,
+ guint64 offset,
+ guint64 size,
+ GduPresentable *enclosing_presentable);
+
+void _gdu_linux_lvm2_volume_rewrite_enclosing_presentable (GduLinuxLvm2Volume *volume);
+
+GduLinuxLvm2VolumeHole *_gdu_linux_lvm2_volume_hole_new (GduPool *pool,
+ GduPresentable *enclosing_presentable);
+
+void _gdu_linux_lvm2_volume_hole_rewrite_enclosing_presentable (GduLinuxLvm2VolumeHole *volume_hole);
+
+
void _gdu_hub_rewrite_enclosing_presentable (GduHub *hub);
void _gdu_drive_rewrite_enclosing_presentable (GduDrive *drive);
void _gdu_linux_md_drive_rewrite_enclosing_presentable (GduLinuxMdDrive *drive);
diff --git a/src/gdu/gdu-types.h b/src/gdu/gdu-types.h
index 8de117f..7a768f4 100644
--- a/src/gdu/gdu-types.h
+++ b/src/gdu/gdu-types.h
@@ -43,8 +43,11 @@ typedef struct _GduPresentable GduPresentable; /* Dummy typedef */
typedef struct _GduDrive GduDrive;
typedef struct _GduLinuxMdDrive GduLinuxMdDrive;
+typedef struct _GduLinuxLvm2VolumeGroup GduLinuxLvm2VolumeGroup;
typedef struct _GduVolume GduVolume;
typedef struct _GduVolumeHole GduVolumeHole;
+typedef struct _GduLinuxLvm2Volume GduLinuxLvm2Volume;
+typedef struct _GduLinuxLvm2VolumeHole GduLinuxLvm2VolumeHole;
typedef struct _GduHub GduHub;
typedef struct _GduMachine GduMachine;
diff --git a/src/gdu/gdu-volume-hole.c b/src/gdu/gdu-volume-hole.c
index b3c5dfe..c4425cf 100644
--- a/src/gdu/gdu-volume-hole.c
+++ b/src/gdu/gdu-volume-hole.c
@@ -66,7 +66,8 @@ gdu_volume_hole_finalize (GduVolumeHole *volume_hole)
{
//g_debug ("finalized volume_hole '%s' %p", volume_hole->priv->id, volume_hole);
- g_object_unref (volume_hole->priv->pool);
+ if (volume_hole->priv->pool != NULL)
+ g_object_unref (volume_hole->priv->pool);
if (volume_hole->priv->enclosing_presentable != NULL)
g_object_unref (volume_hole->priv->enclosing_presentable);
diff --git a/src/gdu/gdu.h b/src/gdu/gdu.h
index 8c805ec..f642059 100644
--- a/src/gdu/gdu.h
+++ b/src/gdu/gdu.h
@@ -30,6 +30,9 @@
#include <gdu/gdu-types.h>
#include <gdu/gdu-linux-md-drive.h>
+#include <gdu/gdu-linux-lvm2-volume-group.h>
+#include <gdu/gdu-linux-lvm2-volume.h>
+#include <gdu/gdu-linux-lvm2-volume-hole.h>
#include <gdu/gdu-device.h>
#include <gdu/gdu-adapter.h>
#include <gdu/gdu-expander.h>
diff --git a/src/palimpsest/Makefile.am b/src/palimpsest/Makefile.am
index eb4a9c0..95baa9b 100644
--- a/src/palimpsest/Makefile.am
+++ b/src/palimpsest/Makefile.am
@@ -8,6 +8,7 @@ palimpsest_SOURCES = \
gdu-shell.h gdu-shell.c \
gdu-section.h gdu-section.c \
gdu-section-linux-md-drive.h gdu-section-linux-md-drive.c \
+ gdu-section-linux-lvm2-volume-group.h gdu-section-linux-lvm2-volume-group.c \
gdu-section-drive.h gdu-section-drive.c \
gdu-section-volumes.h gdu-section-volumes.c \
gdu-section-hub.h gdu-section-hub.c \
diff --git a/src/palimpsest/gdu-section-linux-lvm2-volume-group.c b/src/palimpsest/gdu-section-linux-lvm2-volume-group.c
new file mode 100644
index 0000000..fa501be
--- /dev/null
+++ b/src/palimpsest/gdu-section-linux-lvm2-volume-group.c
@@ -0,0 +1,383 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-section-linux-md-drive.c
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <glib/gi18n.h>
+
+#include <string.h>
+#include <dbus/dbus-glib.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <gdu/gdu.h>
+#include <gdu-gtk/gdu-gtk.h>
+
+#include "gdu-section-drive.h"
+#include "gdu-section-linux-lvm2-volume-group.h"
+
+struct _GduSectionLinuxLvm2VolumeGroupPrivate
+{
+ GduDetailsElement *name_element;
+ GduDetailsElement *state_element;
+ GduDetailsElement *capacity_element;
+ GduDetailsElement *extent_size_element;
+ GduDetailsElement *unallocated_size_element;
+ GduDetailsElement *num_pvs_element;
+
+ GduButtonElement *vg_start_button;
+ GduButtonElement *vg_stop_button;
+};
+
+G_DEFINE_TYPE (GduSectionLinuxLvm2VolumeGroup, gdu_section_linux_lvm2_volume_group, GDU_TYPE_SECTION)
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_section_linux_lvm2_volume_group_finalize (GObject *object)
+{
+ //GduSectionLinuxLvm2VolumeGroup *section = GDU_SECTION_LINUX_LVM2_VOLUME_GROUP (object);
+
+ if (G_OBJECT_CLASS (gdu_section_linux_lvm2_volume_group_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (gdu_section_linux_lvm2_volume_group_parent_class)->finalize (object);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+lvm2_vg_start_op_callback (GduPool *pool,
+ GError *error,
+ gpointer user_data)
+{
+ GduShell *shell = GDU_SHELL (user_data);
+
+ if (error != NULL) {
+ GtkWidget *dialog;
+ dialog = gdu_error_dialog_new (GTK_WINDOW (gdu_shell_get_toplevel (shell)),
+ NULL,
+ _("Error starting Volume Group"),
+ error);
+ gtk_widget_show_all (dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+ }
+ g_object_unref (shell);
+}
+
+static void
+on_lvm2_vg_start_button_clicked (GduButtonElement *button_element,
+ gpointer user_data)
+{
+ GduSectionLinuxLvm2VolumeGroup *section = GDU_SECTION_LINUX_LVM2_VOLUME_GROUP (user_data);
+ GduLinuxLvm2VolumeGroup *vg;
+ GduPool *pool;
+ const gchar *uuid;
+
+ vg = GDU_LINUX_LVM2_VOLUME_GROUP (gdu_section_get_presentable (GDU_SECTION (section)));
+ pool = gdu_presentable_get_pool (GDU_PRESENTABLE (vg));
+
+ uuid = gdu_linux_lvm2_volume_group_get_uuid (vg);
+
+ gdu_pool_op_linux_lvm2_vg_start (pool,
+ uuid,
+ lvm2_vg_start_op_callback,
+ g_object_ref (gdu_section_get_shell (GDU_SECTION (section))));
+
+ g_object_unref (pool);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+lvm2_vg_stop_op_callback (GduPool *pool,
+ GError *error,
+ gpointer user_data)
+{
+ GduShell *shell = GDU_SHELL (user_data);
+
+ if (error != NULL) {
+ GtkWidget *dialog;
+ dialog = gdu_error_dialog_new (GTK_WINDOW (gdu_shell_get_toplevel (shell)),
+ NULL,
+ _("Error stopping Volume Group"),
+ error);
+ gtk_widget_show_all (dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+ }
+ g_object_unref (shell);
+}
+
+static void
+on_lvm2_vg_stop_button_clicked (GduButtonElement *button_element,
+ gpointer user_data)
+{
+ GduSectionLinuxLvm2VolumeGroup *section = GDU_SECTION_LINUX_LVM2_VOLUME_GROUP (user_data);
+ GduLinuxLvm2VolumeGroup *vg;
+ GduPool *pool;
+ const gchar *uuid;
+
+ vg = GDU_LINUX_LVM2_VOLUME_GROUP (gdu_section_get_presentable (GDU_SECTION (section)));
+ pool = gdu_presentable_get_pool (GDU_PRESENTABLE (vg));
+
+ uuid = gdu_linux_lvm2_volume_group_get_uuid (vg);
+
+ gdu_pool_op_linux_lvm2_vg_stop (pool,
+ uuid,
+ lvm2_vg_stop_op_callback,
+ g_object_ref (gdu_section_get_shell (GDU_SECTION (section))));
+
+ g_object_unref (pool);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_section_linux_lvm2_volume_group_update (GduSection *_section)
+{
+ GduSectionLinuxLvm2VolumeGroup *section = GDU_SECTION_LINUX_LVM2_VOLUME_GROUP (_section);
+ GduPresentable *p;
+ GduLinuxLvm2VolumeGroup *vg;
+ GduDevice *pv_device;
+ const gchar *name;
+ guint64 size;
+ guint64 unallocated_size;
+ guint64 extent_size;
+ gchar **pvs;
+ gchar *s;
+ GduLinuxLvm2VolumeGroupState state;
+ gchar *state_str;
+ gboolean show_vg_start_button;
+ gboolean show_vg_stop_button;
+
+ show_vg_start_button = FALSE;
+ show_vg_stop_button = FALSE;
+
+ state_str = NULL;
+
+ p = gdu_section_get_presentable (_section);
+ vg = GDU_LINUX_LVM2_VOLUME_GROUP (p);
+
+ pv_device = gdu_linux_lvm2_volume_group_get_pv_device (vg);
+ if (pv_device == NULL)
+ goto out;
+
+ name = gdu_device_linux_lvm2_pv_get_group_name (pv_device);
+ size = gdu_device_linux_lvm2_pv_get_group_size (pv_device);
+ unallocated_size = gdu_device_linux_lvm2_pv_get_group_unallocated_size (pv_device);
+ extent_size = gdu_device_linux_lvm2_pv_get_group_extent_size (pv_device);
+ pvs = gdu_device_linux_lvm2_pv_get_group_physical_volumes (pv_device);
+
+ gdu_details_element_set_text (section->priv->name_element, name);
+ s = gdu_util_get_size_for_display (size, FALSE, TRUE);
+ gdu_details_element_set_text (section->priv->capacity_element, s);
+ g_free (s);
+ s = gdu_util_get_size_for_display (unallocated_size, FALSE, TRUE);
+ gdu_details_element_set_text (section->priv->unallocated_size_element, s);
+ g_free (s);
+ /* Use the nerd units here (MiB) since that's what LVM defaults to (divisble by sector size etc.) */
+ s = gdu_util_get_size_for_display (extent_size, TRUE, TRUE);
+ gdu_details_element_set_text (section->priv->extent_size_element, s);
+ g_free (s);
+ s = g_strdup_printf ("%d", g_strv_length (pvs));
+ gdu_details_element_set_text (section->priv->num_pvs_element, s);
+ g_free (s);
+
+ state = gdu_linux_lvm2_volume_group_get_state (vg);
+
+ switch (state) {
+ case GDU_LINUX_LVM2_VOLUME_GROUP_STATE_NOT_RUNNING:
+ state_str = g_strdup (_("Not Running"));
+ show_vg_start_button = TRUE;
+ break;
+ case GDU_LINUX_LVM2_VOLUME_GROUP_STATE_PARTIALLY_RUNNING:
+ state_str = g_strdup (_("Partially Running"));
+ show_vg_start_button = TRUE;
+ show_vg_stop_button = TRUE;
+ break;
+ case GDU_LINUX_LVM2_VOLUME_GROUP_STATE_RUNNING:
+ state_str = g_strdup (_("Running"));
+ show_vg_stop_button = TRUE;
+ break;
+ default:
+ state_str = g_strdup_printf (_("Unknown (%d)"), state);
+ show_vg_start_button = TRUE;
+ show_vg_stop_button = TRUE;
+ break;
+ }
+ gdu_details_element_set_text (section->priv->state_element, state_str);
+
+
+ out:
+ gdu_button_element_set_visible (section->priv->vg_start_button, show_vg_start_button);
+ gdu_button_element_set_visible (section->priv->vg_stop_button, show_vg_stop_button);
+
+ if (pv_device != NULL)
+ g_object_unref (pv_device);
+ g_free (state_str);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_section_linux_lvm2_volume_group_constructed (GObject *object)
+{
+ GduSectionLinuxLvm2VolumeGroup *section = GDU_SECTION_LINUX_LVM2_VOLUME_GROUP (object);
+ GtkWidget *align;
+ GtkWidget *label;
+ GtkWidget *table;
+ GtkWidget *vbox;
+ gchar *s;
+ GduPresentable *p;
+ GduDevice *d;
+ GPtrArray *elements;
+ GduDetailsElement *element;
+ GduButtonElement *button_element;
+
+ p = gdu_section_get_presentable (GDU_SECTION (section));
+ d = gdu_presentable_get_device (p);
+
+ gtk_box_set_spacing (GTK_BOX (section), 12);
+
+ /*------------------------------------- */
+
+ label = gtk_label_new (NULL);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ s = g_strconcat ("<b>", _("Volume Group"), "</b>", NULL);
+ gtk_label_set_markup (GTK_LABEL (label), s);
+ g_free (s);
+ gtk_box_pack_start (GTK_BOX (section), label, FALSE, FALSE, 0);
+
+ align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 12, 0);
+ gtk_box_pack_start (GTK_BOX (section), align, FALSE, FALSE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (align), vbox);
+
+ elements = g_ptr_array_new_with_free_func (g_object_unref);
+
+ element = gdu_details_element_new (_("Name:"), NULL, NULL);
+ g_ptr_array_add (elements, element);
+ section->priv->name_element = element;
+
+ element = gdu_details_element_new (_("Extent Size:"), NULL, NULL);
+ g_ptr_array_add (elements, element);
+ section->priv->extent_size_element = element;
+
+ element = gdu_details_element_new (_("Physical Volumes:"), NULL, NULL);
+ g_ptr_array_add (elements, element);
+ section->priv->num_pvs_element = element;
+
+ element = gdu_details_element_new (_("Capacity:"), NULL, NULL);
+ g_ptr_array_add (elements, element);
+ section->priv->capacity_element = element;
+
+ element = gdu_details_element_new (_("State:"), NULL, NULL);
+ g_ptr_array_add (elements, element);
+ section->priv->state_element = element;
+
+ element = gdu_details_element_new (_("Unallocated:"), NULL, NULL);
+ g_ptr_array_add (elements, element);
+ section->priv->unallocated_size_element = element;
+
+ table = gdu_details_table_new (2, elements);
+ g_ptr_array_unref (elements);
+ gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+
+ /* -------------------------------------------------------------------------------- */
+
+ align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 12, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
+
+ table = gdu_button_table_new (2, NULL);
+ gtk_container_add (GTK_CONTAINER (align), table);
+ elements = g_ptr_array_new_with_free_func (g_object_unref);
+
+ button_element = gdu_button_element_new ("gdu-raid-array-start",
+ _("St_art Volume Group"),
+ _("Activate all LVs in the VG"));
+ g_signal_connect (button_element,
+ "clicked",
+ G_CALLBACK (on_lvm2_vg_start_button_clicked),
+ section);
+ section->priv->vg_start_button = button_element;
+ g_ptr_array_add (elements, button_element);
+
+ button_element = gdu_button_element_new ("gdu-raid-array-stop",
+ _("St_op Volume Group"),
+ _("Deactivate all LVs in the VG"));
+ g_signal_connect (button_element,
+ "clicked",
+ G_CALLBACK (on_lvm2_vg_stop_button_clicked),
+ section);
+ section->priv->vg_stop_button = button_element;
+ g_ptr_array_add (elements, button_element);
+
+ gdu_button_table_set_elements (GDU_BUTTON_TABLE (table), elements);
+ g_ptr_array_unref (elements);
+
+ /* -------------------------------------------------------------------------------- */
+
+ gtk_widget_show_all (GTK_WIDGET (section));
+
+ if (d != NULL)
+ g_object_unref (d);
+
+ if (G_OBJECT_CLASS (gdu_section_linux_lvm2_volume_group_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (gdu_section_linux_lvm2_volume_group_parent_class)->constructed (object);
+}
+
+static void
+gdu_section_linux_lvm2_volume_group_class_init (GduSectionLinuxLvm2VolumeGroupClass *klass)
+{
+ GObjectClass *gobject_class;
+ GduSectionClass *section_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ section_class = GDU_SECTION_CLASS (klass);
+
+ gobject_class->finalize = gdu_section_linux_lvm2_volume_group_finalize;
+ gobject_class->constructed = gdu_section_linux_lvm2_volume_group_constructed;
+ section_class->update = gdu_section_linux_lvm2_volume_group_update;
+
+ g_type_class_add_private (klass, sizeof (GduSectionLinuxLvm2VolumeGroupPrivate));
+}
+
+static void
+gdu_section_linux_lvm2_volume_group_init (GduSectionLinuxLvm2VolumeGroup *section)
+{
+ section->priv = G_TYPE_INSTANCE_GET_PRIVATE (section, GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP, GduSectionLinuxLvm2VolumeGroupPrivate);
+}
+
+GtkWidget *
+gdu_section_linux_lvm2_volume_group_new (GduShell *shell,
+ GduPresentable *presentable)
+{
+ return GTK_WIDGET (g_object_new (GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP,
+ "shell", shell,
+ "presentable", presentable,
+ NULL));
+}
diff --git a/src/palimpsest/gdu-section-linux-lvm2-volume-group.h b/src/palimpsest/gdu-section-linux-lvm2-volume-group.h
new file mode 100644
index 0000000..8511c04
--- /dev/null
+++ b/src/palimpsest/gdu-section-linux-lvm2-volume-group.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* gdu-section-linux-md-drive.h
+ *
+ * Copyright (C) 2007 David Zeuthen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+#include "gdu-section.h"
+
+#ifndef GDU_SECTION_LINUX_LVM2_VOLUME_GROUP_H
+#define GDU_SECTION_LINUX_LVM2_VOLUME_GROUP_H
+
+#define GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP (gdu_section_linux_lvm2_volume_group_get_type ())
+#define GDU_SECTION_LINUX_LVM2_VOLUME_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP, GduSectionLinuxLvm2VolumeGroup))
+#define GDU_SECTION_LINUX_LVM2_VOLUME_GROUP_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GDU_SECTION_LINUX_LVM2_VOLUME_GROUP, GduSectionLinuxLvm2VolumeGroupClass))
+#define GDU_IS_SECTION_LINUX_LVM2_VOLUME_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP))
+#define GDU_IS_SECTION_LINUX_LVM2_VOLUME_GROUP_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP))
+#define GDU_SECTION_LINUX_LVM2_VOLUME_GROUP_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP, GduSectionLinuxLvm2VolumeGroupClass))
+
+typedef struct _GduSectionLinuxLvm2VolumeGroupClass GduSectionLinuxLvm2VolumeGroupClass;
+typedef struct _GduSectionLinuxLvm2VolumeGroup GduSectionLinuxLvm2VolumeGroup;
+
+struct _GduSectionLinuxLvm2VolumeGroupPrivate;
+typedef struct _GduSectionLinuxLvm2VolumeGroupPrivate GduSectionLinuxLvm2VolumeGroupPrivate;
+
+struct _GduSectionLinuxLvm2VolumeGroup
+{
+ GduSection parent;
+
+ /* private */
+ GduSectionLinuxLvm2VolumeGroupPrivate *priv;
+};
+
+struct _GduSectionLinuxLvm2VolumeGroupClass
+{
+ GduSectionClass parent_class;
+};
+
+GType gdu_section_linux_lvm2_volume_group_get_type (void);
+GtkWidget *gdu_section_linux_lvm2_volume_group_new (GduShell *shell,
+ GduPresentable *presentable);
+
+#endif /* GDU_SECTION_LINUX_LVM2_VOLUME_GROUP_H */
diff --git a/src/palimpsest/gdu-section-volumes.c b/src/palimpsest/gdu-section-volumes.c
index 35d56f4..ff33248 100644
--- a/src/palimpsest/gdu-section-volumes.c
+++ b/src/palimpsest/gdu-section-volumes.c
@@ -38,6 +38,10 @@ struct _GduSectionVolumesPrivate
GtkWidget *details_table;
GtkWidget *button_table;
+ /* elements for LVM2 Logical Volumes */
+ GduDetailsElement *lvm2_name_element;
+ GduDetailsElement *lvm2_state_element;
+
/* shared between all volume types */
GduDetailsElement *usage_element;
GduDetailsElement *capacity_element;
@@ -64,6 +68,9 @@ struct _GduSectionVolumesPrivate
GduButtonElement *luks_unlock_button;
GduButtonElement *luks_forget_passphrase_button;
GduButtonElement *luks_change_passphrase_button;
+ GduButtonElement *lvm2_create_lv_button;
+ GduButtonElement *lvm2_lv_start_button;
+ GduButtonElement *lvm2_lv_stop_button;
};
G_DEFINE_TYPE (GduSectionVolumes, gdu_section_volumes, GDU_TYPE_SECTION)
@@ -1357,6 +1364,125 @@ on_fs_mount_point_element_activated (GduDetailsElement *element,
/* ---------------------------------------------------------------------------------------------------- */
static void
+on_lvm2_create_lv_button_clicked (GduButtonElement *button_element,
+ gpointer user_data)
+{
+ GduSectionVolumes *section = GDU_SECTION_VOLUMES (user_data);
+ GtkWidget *dialog;
+ GError *error;
+
+ error = g_error_new (GDU_ERROR,
+ GDU_ERROR_NOT_SUPPORTED,
+ _("Not yet implemented"));
+ dialog = gdu_error_dialog_new (GTK_WINDOW (gdu_shell_get_toplevel (gdu_section_get_shell (GDU_SECTION (section)))),
+ gdu_section_get_presentable (GDU_SECTION (section)),
+ _("There was an error creating a Logical Volume"),
+ error);
+ gtk_widget_show_all (dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+lvm2_lv_stop_op_callback (GduDevice *device,
+ GError *error,
+ gpointer user_data)
+{
+ GduShell *shell = GDU_SHELL (user_data);
+
+ if (error != NULL) {
+ GtkWidget *dialog;
+ dialog = gdu_error_dialog_new_for_volume (GTK_WINDOW (gdu_shell_get_toplevel (shell)),
+ device,
+ _("Error stopping Logical Volume"),
+ error);
+ gtk_widget_show_all (dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+ }
+ g_object_unref (shell);
+}
+
+static void
+on_lvm2_lv_stop_button_clicked (GduButtonElement *button_element,
+ gpointer user_data)
+{
+ GduSectionVolumes *section = GDU_SECTION_VOLUMES (user_data);
+ GduLinuxLvm2Volume *volume;
+ GduDevice *d;
+
+ volume = GDU_LINUX_LVM2_VOLUME (gdu_volume_grid_get_selected (GDU_VOLUME_GRID (section->priv->grid)));
+ d = gdu_presentable_get_device (GDU_PRESENTABLE (volume));
+ if (d == NULL)
+ goto out;
+
+ gdu_device_op_linux_lvm2_lv_stop (d,
+ lvm2_lv_stop_op_callback,
+ g_object_ref (gdu_section_get_shell (GDU_SECTION (section))));
+
+ out:
+ if (d != NULL)
+ g_object_unref (d);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+lvm2_lv_start_op_callback (GduPool *pool,
+ GError *error,
+ gpointer user_data)
+{
+ GduShell *shell = GDU_SHELL (user_data);
+
+ if (error != NULL) {
+ GtkWidget *dialog;
+ dialog = gdu_error_dialog_new (GTK_WINDOW (gdu_shell_get_toplevel (shell)),
+ NULL,
+ _("Error starting Logical Volume"),
+ error);
+ gtk_widget_show_all (dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+ }
+ g_object_unref (shell);
+}
+
+static void
+on_lvm2_lv_start_button_clicked (GduButtonElement *button_element,
+ gpointer user_data)
+{
+ GduSectionVolumes *section = GDU_SECTION_VOLUMES (user_data);
+ GduLinuxLvm2Volume *volume;
+ GduPool *pool;
+ const gchar *group_uuid;
+ const gchar *uuid;
+
+ volume = GDU_LINUX_LVM2_VOLUME (gdu_volume_grid_get_selected (GDU_VOLUME_GRID (section->priv->grid)));
+ pool = gdu_presentable_get_pool (GDU_PRESENTABLE (volume));
+
+ group_uuid = gdu_linux_lvm2_volume_get_group_uuid (volume);
+ uuid = gdu_linux_lvm2_volume_get_uuid (volume);
+
+ gdu_pool_op_linux_lvm2_lv_start (pool,
+ group_uuid,
+ uuid,
+ lvm2_lv_start_op_callback,
+ g_object_ref (gdu_section_get_shell (GDU_SECTION (section))));
+
+ g_object_unref (pool);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
gdu_section_volumes_update (GduSection *_section)
{
GduSectionVolumes *section = GDU_SECTION_VOLUMES (_section);
@@ -1378,6 +1504,9 @@ gdu_section_volumes_update (GduSection *_section)
gboolean show_luks_unlock_button;
gboolean show_luks_forget_passphrase_button;
gboolean show_luks_change_passphrase_button;
+ gboolean show_lvm2_create_lv_button;
+ gboolean show_lvm2_lv_start_button;
+ gboolean show_lvm2_lv_stop_button;
GduKnownFilesystem *kfs;
GPtrArray *elements;
@@ -1398,6 +1527,9 @@ gdu_section_volumes_update (GduSection *_section)
show_luks_unlock_button = FALSE;
show_luks_forget_passphrase_button = FALSE;
show_luks_change_passphrase_button = FALSE;
+ show_lvm2_create_lv_button = FALSE;
+ show_lvm2_lv_start_button = FALSE;
+ show_lvm2_lv_stop_button = FALSE;
v = gdu_volume_grid_get_selected (GDU_VOLUME_GRID (section->priv->grid));
@@ -1423,6 +1555,8 @@ gdu_section_volumes_update (GduSection *_section)
g_object_unref (section->priv->cur_volume);
section->priv->cur_volume = v != NULL ? g_object_ref (v) : NULL;
+ section->priv->lvm2_name_element = NULL;
+ section->priv->lvm2_state_element = NULL;
section->priv->usage_element = NULL;
section->priv->capacity_element = NULL;
section->priv->partition_type_element = NULL;
@@ -1436,6 +1570,13 @@ gdu_section_volumes_update (GduSection *_section)
elements = g_ptr_array_new_with_free_func (g_object_unref);
+ if (GDU_IS_LINUX_LVM2_VOLUME (v)) {
+ section->priv->lvm2_name_element = gdu_details_element_new (_("Volume Name:"), NULL, NULL);
+ g_ptr_array_add (elements, section->priv->lvm2_name_element);
+ section->priv->lvm2_state_element = gdu_details_element_new (_("State:"), NULL, NULL);
+ g_ptr_array_add (elements, section->priv->lvm2_state_element);
+ }
+
section->priv->usage_element = gdu_details_element_new (_("Usage:"), NULL, NULL);
g_ptr_array_add (elements, section->priv->usage_element);
g_signal_connect (section->priv->usage_element,
@@ -1484,6 +1625,21 @@ gdu_section_volumes_update (GduSection *_section)
/* ---------------------------------------------------------------------------------------------------- */
/* reset all elements */
+ if (GDU_IS_LINUX_LVM2_VOLUME (v)) {
+ gchar *lv_name;
+ lv_name = gdu_presentable_get_name (v);
+ gdu_details_element_set_text (section->priv->lvm2_name_element, lv_name);
+ g_free (lv_name);
+ gdu_details_element_set_text (section->priv->lvm2_state_element,
+ d != NULL ?
+ C_("LVM2 LV State", "Running") :
+ C_("LVM2 LV State", "Not Running"));
+ if (d != NULL)
+ show_lvm2_lv_stop_button = TRUE;
+ else
+ show_lvm2_lv_start_button = TRUE;
+ }
+
if (section->priv->usage_element != NULL) {
gdu_details_element_set_text (section->priv->usage_element, "â??");
gdu_details_element_set_action_text (section->priv->usage_element, NULL);
@@ -1594,7 +1750,9 @@ gdu_section_volumes_update (GduSection *_section)
/* ---------------------------------------------------------------------------------------------------- */
/* populate according to usage */
- show_format_button = TRUE;
+ if (d != NULL)
+ show_format_button = TRUE;
+
if (g_strcmp0 (id_usage, "filesystem") == 0) {
const gchar *label;
@@ -1690,6 +1848,13 @@ gdu_section_volumes_update (GduSection *_section)
gdu_details_element_set_text (section->priv->usage_element, _("Container for Logical Partitions"));
show_format_button = FALSE;
+
+ } else if (GDU_IS_LINUX_LVM2_VOLUME_HOLE (v)) {
+ gdu_details_element_set_text (section->priv->usage_element, _("Unallocated Space"));
+ gdu_details_element_set_text (section->priv->device_element, "â??");
+ show_lvm2_create_lv_button = TRUE;
+ show_format_button = FALSE;
+
} else if (GDU_IS_VOLUME_HOLE (v)) {
GduDevice *drive_device;
gdu_details_element_set_text (section->priv->usage_element, _("Unallocated Space"));
@@ -1728,6 +1893,10 @@ gdu_section_volumes_update (GduSection *_section)
gdu_button_element_set_visible (section->priv->luks_unlock_button, show_luks_unlock_button);
gdu_button_element_set_visible (section->priv->luks_forget_passphrase_button, show_luks_forget_passphrase_button);
gdu_button_element_set_visible (section->priv->luks_change_passphrase_button, show_luks_change_passphrase_button);
+ gdu_button_element_set_visible (section->priv->lvm2_create_lv_button, show_lvm2_create_lv_button);
+ gdu_button_element_set_visible (section->priv->lvm2_lv_start_button, show_lvm2_lv_start_button);
+ gdu_button_element_set_visible (section->priv->lvm2_lv_stop_button, show_lvm2_lv_stop_button);
+
if (d != NULL)
g_object_unref (d);
@@ -1754,6 +1923,7 @@ static void
gdu_section_volumes_constructed (GObject *object)
{
GduSectionVolumes *section = GDU_SECTION_VOLUMES (object);
+ GduPresentable *presentable;
GPtrArray *button_elements;
GduButtonElement *button_element;
GtkWidget *grid;
@@ -1767,9 +1937,15 @@ gdu_section_volumes_constructed (GObject *object)
/*------------------------------------- */
+ presentable = gdu_section_get_presentable (GDU_SECTION (section));
+
label = gtk_label_new (NULL);
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- s = g_strconcat ("<b>", _("_Volumes"), "</b>", NULL);
+ if (GDU_IS_LINUX_LVM2_VOLUME_GROUP (presentable)) {
+ s = g_strconcat ("<b>", _("Logical _Volumes"), "</b>", NULL);
+ } else {
+ s = g_strconcat ("<b>", _("_Volumes"), "</b>", NULL);
+ }
gtk_label_set_markup (GTK_LABEL (label), s);
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
g_free (s);
@@ -1930,6 +2106,36 @@ gdu_section_volumes_constructed (GObject *object)
g_ptr_array_add (button_elements, button_element);
section->priv->luks_change_passphrase_button = button_element;
+ button_element = gdu_button_element_new (GTK_STOCK_ADD,
+ _("_Create Logical Volume"),
+ _("Create a new logical volume"));
+ g_signal_connect (button_element,
+ "clicked",
+ G_CALLBACK (on_lvm2_create_lv_button_clicked),
+ section);
+ g_ptr_array_add (button_elements, button_element);
+ section->priv->lvm2_create_lv_button = button_element;
+
+ button_element = gdu_button_element_new ("gdu-raid-array-start",
+ _("S_tart Volume"),
+ _("Activate the Logical Volume"));
+ g_signal_connect (button_element,
+ "clicked",
+ G_CALLBACK (on_lvm2_lv_start_button_clicked),
+ section);
+ section->priv->lvm2_lv_start_button = button_element;
+ g_ptr_array_add (button_elements, button_element);
+
+ button_element = gdu_button_element_new ("gdu-raid-array-stop",
+ _("Sto_p Volume"),
+ _("Deactivate the Logical Volume"));
+ g_signal_connect (button_element,
+ "clicked",
+ G_CALLBACK (on_lvm2_lv_stop_button_clicked),
+ section);
+ section->priv->lvm2_lv_stop_button = button_element;
+ g_ptr_array_add (button_elements, button_element);
+
gdu_button_table_set_elements (GDU_BUTTON_TABLE (section->priv->button_table), button_elements);
g_ptr_array_unref (button_elements);
diff --git a/src/palimpsest/gdu-shell.c b/src/palimpsest/gdu-shell.c
index c1da1d7..17d9cbd 100644
--- a/src/palimpsest/gdu-shell.c
+++ b/src/palimpsest/gdu-shell.c
@@ -36,6 +36,7 @@
#include "gdu-shell.h"
#include "gdu-section-linux-md-drive.h"
+#include "gdu-section-linux-lvm2-volume-group.h"
#include "gdu-section-drive.h"
#include "gdu-section-volumes.h"
#include "gdu-section-hub.h"
@@ -232,6 +233,10 @@ compute_sections_to_show (GduShell *shell)
sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_LINUX_MD_DRIVE);
sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_VOLUMES);
+ } else if (GDU_IS_LINUX_LVM2_VOLUME_GROUP (shell->priv->presentable_now_showing)) {
+
+ sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_LINUX_LVM2_VOLUME_GROUP);
+ sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_VOLUMES);
} else if (GDU_IS_DRIVE (shell->priv->presentable_now_showing)) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]