From 2778a41e1fdd2252bce51ef3187374c610d8ba5e Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Wed, 13 Jan 2010 17:48:17 -0500 Subject: [PATCH] Add methods for adding/removing PVs to a VG --- data/org.freedesktop.UDisks.xml | 81 ++++++++++++++ src/daemon.h | 12 ++ src/device.c | 235 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) diff --git a/data/org.freedesktop.UDisks.xml b/data/org.freedesktop.UDisks.xml index 0696070..077b381 100644 --- a/data/org.freedesktop.UDisks.xml +++ b/data/org.freedesktop.UDisks.xml @@ -402,6 +402,87 @@ + + + + The UUID of the volume group to add a physical volume to. + + + The objcet path of the device to use as a physical volume. + + + Currently unused. + + + + + + Adds a Physical volume to a Linux LVM2 Volume Group. Existing data + on the given device to use for a physical volume will be erased. + + + + The caller will need the following PolicyKit authorization: + + + org.freedesktop.udisks.linux-lvm2 + + Needed to configured Linux LVM2 devices. + + + + + + if the caller lacks the appropriate PolicyKit authorization + if one of the given components are busy + if the operation failed + if the job was cancelled + + + + + + + + + + The UUID of the volume group to remove the physical volume from. + + + The objcet path of the device to remove. + + + Currently unused. + + + + + + Removes a Physical volume from a Linux LVM2 Volume Group. + + + + The caller will need the following PolicyKit authorization: + + + org.freedesktop.udisks.linux-lvm2 + + Needed to configured Linux LVM2 devices. + + + + + + if the caller lacks the appropriate PolicyKit authorization + if one of the given components are busy + if the operation failed + if the job was cancelled + + + + + + diff --git a/src/daemon.h b/src/daemon.h index ad7177a..cc6c7df 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -265,6 +265,18 @@ gboolean daemon_linux_lvm2_lv_create (Daemon *daemon, char **fsoptions, DBusGMethodInvocation *context); +gboolean daemon_linux_lvm2_vg_add_pv (Daemon *daemon, + const gchar *uuid, + const gchar *physical_volume_object_path, + char **options, + DBusGMethodInvocation *context); + +gboolean daemon_linux_lvm2_vg_remove_pv (Daemon *daemon, + const gchar *uuid, + const gchar *physical_volume_object_path, + char **options, + DBusGMethodInvocation *context); + G_END_DECLS #endif /* __DAEMON_H__ */ diff --git a/src/device.c b/src/device.c index 28ecd79..58e10bd 100644 --- a/src/device.c +++ b/src/device.c @@ -12693,3 +12693,238 @@ daemon_linux_lvm2_lv_create (Daemon *daemon, return TRUE; } + +/*--------------------------------------------------------------------------------------------------------------*/ + +static void +linux_lvm2_vg_add_pv_completed_cb (DBusGMethodInvocation *context, + Device *device, + gboolean job_was_cancelled, + int status, + const char *stderr, + const char *stdout, + gpointer user_data) +{ + if (WEXITSTATUS (status) == 0 && !job_was_cancelled) + { + dbus_g_method_return (context); + } + else + { + if (job_was_cancelled) + { + throw_error (context, ERROR_CANCELLED, "Job was cancelled"); + } + else + { + throw_error (context, + ERROR_FAILED, + "Error adding PV for LVM2 Volume Group: vgextend exited with exit code %d: %s", + WEXITSTATUS (status), + stderr); + } + } +} + +static void +daemon_linux_lvm2_vg_add_pv_authorized_cb (Daemon *daemon, + Device *device, + DBusGMethodInvocation *context, + const gchar *action_id, + guint num_user_data, + gpointer *user_data_elements) +{ + const gchar *uuid = user_data_elements[0]; + const gchar *physical_volume = user_data_elements[1]; + /* TODO: use options: gchar **options = user_data_elements[2]; */ + const gchar *vg_name; + guint n; + gchar *argv[10]; + Device *pv; + GError *error; + + /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this + * UUID by looking at PVs + */ + + vg_name = find_lvm2_vg_name_for_uuid (daemon, uuid); + if (vg_name == NULL) + { + throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", uuid); + goto out; + } + + pv = daemon_local_find_by_object_path (daemon, physical_volume); + if (pv == NULL) + { + throw_error (context, ERROR_FAILED, "physical volume doesn't exist"); + goto out; + } + + error = NULL; + if (device_local_is_busy (pv, TRUE, &error)) + { + dbus_g_method_return_error (context, error); + g_error_free (error); + goto out; + } + + + n = 0; + argv[n++] = "vgextend"; + argv[n++] = (gchar *) vg_name; + argv[n++] = (gchar *) pv->priv->device_file; + argv[n++] = NULL; + + if (!job_new (context, "LinuxLvm2VGAddPV", TRUE, NULL, argv, NULL, linux_lvm2_vg_add_pv_completed_cb, FALSE, NULL, NULL)) + { + goto out; + } + + out: + ; +} + +gboolean +daemon_linux_lvm2_vg_add_pv (Daemon *daemon, + const gchar *uuid, + const gchar *object_path, + gchar **options, + DBusGMethodInvocation *context) +{ + daemon_local_check_auth (daemon, + NULL, + "org.freedesktop.udisks.linux-lvm2", + "LinuxLvm2VGAddPV", + TRUE, + daemon_linux_lvm2_vg_add_pv_authorized_cb, + context, + 3, + g_strdup (uuid), + g_free, + g_strdup (object_path), + g_free, + g_strdupv (options), + g_strfreev); + + return TRUE; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static void +linux_lvm2_vg_remove_pv_completed_cb (DBusGMethodInvocation *context, + Device *device, + gboolean job_was_cancelled, + int status, + const char *stderr, + const char *stdout, + gpointer user_data) +{ + if (WEXITSTATUS (status) == 0 && !job_was_cancelled) + { + dbus_g_method_return (context); + } + else + { + if (job_was_cancelled) + { + throw_error (context, ERROR_CANCELLED, "Job was cancelled"); + } + else + { + throw_error (context, + ERROR_FAILED, + "Error removing PV for LVM2 Volume Group: vgreduce exited with exit code %d: %s", + WEXITSTATUS (status), + stderr); + } + } +} + +static void +daemon_linux_lvm2_vg_remove_pv_authorized_cb (Daemon *daemon, + Device *device, + DBusGMethodInvocation *context, + const gchar *action_id, + guint num_user_data, + gpointer *user_data_elements) +{ + const gchar *uuid = user_data_elements[0]; + const gchar *physical_volume = user_data_elements[1]; + /* TODO: use options: gchar **options = user_data_elements[2]; */ + const gchar *vg_name; + guint n; + gchar *argv[10]; + Device *pv; + GError *error; + + /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this + * UUID by looking at PVs + */ + + vg_name = find_lvm2_vg_name_for_uuid (daemon, uuid); + if (vg_name == NULL) + { + throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", uuid); + goto out; + } + + pv = daemon_local_find_by_object_path (daemon, physical_volume); + if (pv == NULL) + { + throw_error (context, ERROR_FAILED, "physical volume doesn't exist"); + goto out; + } + + error = NULL; + if (device_local_is_busy (pv, TRUE, &error)) + { + dbus_g_method_return_error (context, error); + g_error_free (error); + goto out; + } + + + n = 0; + argv[n++] = "vgreduce"; + argv[n++] = (gchar *) vg_name; + argv[n++] = (gchar *) pv->priv->device_file; + argv[n++] = NULL; + + if (!job_new (context, "LinuxLvm2VGRemovePV", TRUE, NULL, argv, NULL, linux_lvm2_vg_remove_pv_completed_cb, FALSE, NULL, NULL)) + { + goto out; + } + + out: + ; +} + +gboolean +daemon_linux_lvm2_vg_remove_pv (Daemon *daemon, + const gchar *uuid, + const gchar *object_path, + gchar **options, + DBusGMethodInvocation *context) +{ + daemon_local_check_auth (daemon, + NULL, + "org.freedesktop.udisks.linux-lvm2", + "LinuxLvm2VGRemovePV", + TRUE, + daemon_linux_lvm2_vg_remove_pv_authorized_cb, + context, + 3, + g_strdup (uuid), + g_free, + g_strdup (object_path), + g_free, + g_strdupv (options), + g_strfreev); + + return TRUE; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + -- 2.7.4