[gnome-disk-utility] First cut add creating LVM2 Logical Volumes
- From: David Zeuthen <davidz src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] First cut add creating LVM2 Logical Volumes
- Date: Tue, 12 Jan 2010 21:04:19 +0000 (UTC)
commit 019aab391ec9918ff649f85df569d38b8fd8e291
Author: David Zeuthen <davidz redhat com>
Date: Tue Jan 12 16:01:43 2010 -0500
First cut add creating LVM2 Logical Volumes
Still need support for setting up striping and mirroring.
src/gdu-gtk/Makefile.am | 2 +
src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.c | 230 +++++++++++++++++++++
src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.h | 65 ++++++
src/gdu-gtk/gdu-gtk-types.h | 59 +++---
src/gdu/gdu-callbacks.h | 5 +
src/gdu/gdu-linux-lvm2-volume-group.c | 69 ++++++
src/gdu/gdu-linux-lvm2-volume-group.h | 2 +
src/gdu/gdu-pool.c | 82 +++++++-
src/gdu/gdu-pool.h | 14 ++
src/palimpsest/gdu-section-volumes.c | 180 +++++++++++++++--
10 files changed, 662 insertions(+), 46 deletions(-)
---
diff --git a/src/gdu-gtk/Makefile.am b/src/gdu-gtk/Makefile.am
index 2002b02..4cb665b 100644
--- a/src/gdu-gtk/Makefile.am
+++ b/src/gdu-gtk/Makefile.am
@@ -49,6 +49,7 @@ libgdu_gtkinclude_HEADERS = \
gdu-format-dialog.h \
gdu-partition-dialog.h \
gdu-create-partition-dialog.h \
+ gdu-create-linux-lvm2-volume-dialog.h \
gdu-edit-name-dialog.h \
gdu-disk-selection-widget.h \
gdu-add-component-linux-md-dialog.h \
@@ -81,6 +82,7 @@ libgdu_gtk_la_SOURCES = \
gdu-format-dialog.h gdu-format-dialog.c \
gdu-partition-dialog.h gdu-partition-dialog.c \
gdu-create-partition-dialog.h gdu-create-partition-dialog.c \
+ gdu-create-linux-lvm2-volume-dialog.h gdu-create-linux-lvm2-volume-dialog.c \
gdu-edit-name-dialog.h gdu-edit-name-dialog.c \
gdu-disk-selection-widget.h gdu-disk-selection-widget.c \
gdu-add-component-linux-md-dialog.h gdu-add-component-linux-md-dialog.c \
diff --git a/src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.c b/src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.c
new file mode 100644
index 0000000..3a197db
--- /dev/null
+++ b/src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.c
@@ -0,0 +1,230 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Tomas Bzatek <tbzatek redhat com>
+ * David Zeuthen <davidz redhat com>
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <gdu/gdu.h>
+#include <gdu-gtk/gdu-gtk.h>
+
+#include "gdu-create-linux-lvm2-volume-dialog.h"
+
+struct GduCreateLinuxLvm2VolumeDialogPrivate
+{
+ guint64 max_size;
+ GtkWidget *size_widget;
+ GduPresentable *drive;
+};
+
+enum
+{
+ PROP_0,
+ PROP_SIZE,
+ PROP_MAX_SIZE,
+ PROP_DRIVE
+};
+
+static void gdu_create_linux_lvm2_volume_dialog_constructed (GObject *object);
+
+G_DEFINE_TYPE (GduCreateLinuxLvm2VolumeDialog, gdu_create_linux_lvm2_volume_dialog, GDU_TYPE_FORMAT_DIALOG)
+
+static void
+gdu_create_linux_lvm2_volume_dialog_finalize (GObject *object)
+{
+ //GduCreateLinuxLvm2VolumeDialog *dialog = GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG (object);
+
+ if (G_OBJECT_CLASS (gdu_create_linux_lvm2_volume_dialog_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (gdu_create_linux_lvm2_volume_dialog_parent_class)->finalize (object);
+}
+
+static void
+gdu_create_linux_lvm2_volume_dialog_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GduCreateLinuxLvm2VolumeDialog *dialog = GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG (object);
+
+ switch (property_id) {
+ case PROP_SIZE:
+ g_value_set_uint64 (value, gdu_create_linux_lvm2_volume_dialog_get_size (dialog));
+ break;
+
+ case PROP_MAX_SIZE:
+ g_value_set_uint64 (value, dialog->priv->max_size);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_create_linux_lvm2_volume_dialog_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GduCreateLinuxLvm2VolumeDialog *dialog = GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG (object);
+
+ switch (property_id) {
+ case PROP_MAX_SIZE:
+ dialog->priv->max_size = g_value_get_uint64 (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_create_linux_lvm2_volume_dialog_class_init (GduCreateLinuxLvm2VolumeDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GduCreateLinuxLvm2VolumeDialogPrivate));
+
+ object_class->get_property = gdu_create_linux_lvm2_volume_dialog_get_property;
+ object_class->set_property = gdu_create_linux_lvm2_volume_dialog_set_property;
+ object_class->constructed = gdu_create_linux_lvm2_volume_dialog_constructed;
+ object_class->finalize = gdu_create_linux_lvm2_volume_dialog_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_MAX_SIZE,
+ g_param_spec_uint64 ("max-size",
+ _("Maximum Logical Volume Size"),
+ _("The maximum possible logical volume size"),
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ g_object_class_install_property (object_class,
+ PROP_SIZE,
+ g_param_spec_uint64 ("size",
+ _("Logical Volume Size"),
+ _("The requested Logical Volume size"),
+ 0,
+ G_MAXUINT64,
+ 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+static void
+gdu_create_linux_lvm2_volume_dialog_init (GduCreateLinuxLvm2VolumeDialog *dialog)
+{
+ dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
+ GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG,
+ GduCreateLinuxLvm2VolumeDialogPrivate);
+}
+
+GtkWidget *
+gdu_create_linux_lvm2_volume_dialog_new (GtkWindow *parent,
+ GduPresentable *presentable,
+ guint64 max_size,
+ GduFormatDialogFlags flags)
+{
+ return GTK_WIDGET (g_object_new (GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG,
+ "transient-for", parent,
+ "presentable", presentable,
+ "max-size", max_size,
+ "affirmative-button-mnemonic", _("C_reate"),
+ "flags", flags,
+ NULL));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+guint64
+gdu_create_linux_lvm2_volume_dialog_get_size (GduCreateLinuxLvm2VolumeDialog *dialog)
+{
+ g_return_val_if_fail (GDU_IS_CREATE_LINUX_LVM2_VOLUME_DIALOG (dialog), 0);
+ return gdu_size_widget_get_size (GDU_SIZE_WIDGET (dialog->priv->size_widget));
+}
+
+guint64
+gdu_create_linux_lvm2_volume_dialog_get_max_size (GduCreateLinuxLvm2VolumeDialog *dialog)
+{
+ g_return_val_if_fail (GDU_IS_CREATE_LINUX_LVM2_VOLUME_DIALOG (dialog), 0);
+ return dialog->priv->max_size;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_create_linux_lvm2_volume_dialog_constructed (GObject *object)
+{
+ GduCreateLinuxLvm2VolumeDialog *dialog = GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG (object);
+ gchar *s;
+ gchar *s2;
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *size_widget;
+ guint row;
+
+ table = gdu_format_dialog_get_table (GDU_FORMAT_DIALOG (dialog));
+ g_object_get (table,
+ "n-rows", &row,
+ NULL);
+
+ /* add Logical Volume size widget before other widgets in the GduFormatDialog */
+ label = gtk_label_new (NULL);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), _("_Size:"));
+ gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+ size_widget = gdu_size_widget_new (0, 0, dialog->priv->max_size);
+ gdu_size_widget_set_size (GDU_SIZE_WIDGET (size_widget), dialog->priv->max_size);
+ gtk_table_attach (GTK_TABLE (table), size_widget, 1, 2, row, row + 1,
+ GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 2);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), size_widget);
+ dialog->priv->size_widget = size_widget;
+ row++;
+
+ /* run constructed() for parent class (GduFormatDialog) */
+ if (G_OBJECT_CLASS (gdu_create_linux_lvm2_volume_dialog_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (gdu_create_linux_lvm2_volume_dialog_parent_class)->constructed (object);
+
+ /* adjust window title */
+ s2 = gdu_presentable_get_vpd_name (gdu_dialog_get_presentable (GDU_DIALOG (dialog)));
+
+ /* Translators: The %s is the name of the volume group */
+ s = g_strdup_printf (_("Create Logical Volume on %s"), s2);
+ gtk_window_set_title (GTK_WINDOW (dialog), s);
+ g_free (s);
+
+
+ g_free (s2);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.h b/src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.h
new file mode 100644
index 0000000..f69ae8c
--- /dev/null
+++ b/src/gdu-gtk/gdu-create-linux-lvm2-volume-dialog.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ *
+ */
+
+#ifndef __GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG_H
+#define __GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG_H
+
+#include <gtk/gtk.h>
+#include <gdu-gtk/gdu-gtk.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG gdu_create_linux_lvm2_volume_dialog_get_type()
+#define GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG, GduCreateLinuxLvm2VolumeDialog))
+#define GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG, GduCreateLinuxLvm2VolumeDialogClass))
+#define GDU_IS_CREATE_LINUX_LVM2_VOLUME_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG))
+#define GDU_IS_CREATE_LINUX_LVM2_VOLUME_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG))
+#define GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDU_TYPE_CREATE_LINUX_LVM2_VOLUME_DIALOG, GduCreateLinuxLvm2VolumeDialogClass))
+
+typedef struct GduCreateLinuxLvm2VolumeDialogClass GduCreateLinuxLvm2VolumeDialogClass;
+typedef struct GduCreateLinuxLvm2VolumeDialogPrivate GduCreateLinuxLvm2VolumeDialogPrivate;
+
+struct GduCreateLinuxLvm2VolumeDialog
+{
+ GduFormatDialog parent;
+
+ /*< private >*/
+ GduCreateLinuxLvm2VolumeDialogPrivate *priv;
+};
+
+struct GduCreateLinuxLvm2VolumeDialogClass
+{
+ GduFormatDialogClass parent_class;
+};
+
+GType gdu_create_linux_lvm2_volume_dialog_get_type (void) G_GNUC_CONST;
+GtkWidget *gdu_create_linux_lvm2_volume_dialog_new (GtkWindow *parent,
+ GduPresentable *presentable,
+ guint64 max_size,
+ GduFormatDialogFlags flags);
+guint64 gdu_create_linux_lvm2_volume_dialog_get_size (GduCreateLinuxLvm2VolumeDialog *dialog);
+guint64 gdu_create_linux_lvm2_volume_dialog_get_max_size (GduCreateLinuxLvm2VolumeDialog *dialog);
+
+G_END_DECLS
+
+#endif /* __GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG_H */
+
diff --git a/src/gdu-gtk/gdu-gtk-types.h b/src/gdu-gtk/gdu-gtk-types.h
index f10d032..d0845ab 100644
--- a/src/gdu-gtk/gdu-gtk-types.h
+++ b/src/gdu-gtk/gdu-gtk-types.h
@@ -33,35 +33,36 @@
G_BEGIN_DECLS
-typedef struct GduSample GduSample;
-typedef struct GduColor GduColor;
-typedef struct GduCurve GduCurve;
-typedef struct GduGraph GduGraph;
-typedef struct GduTimeLabel GduTimeLabel;
-typedef struct GduAtaSmartDialog GduAtaSmartDialog;
-typedef struct GduSpinner GduSpinner;
-typedef struct GduPoolTreeModel GduPoolTreeModel;
-typedef struct GduPoolTreeView GduPoolTreeView;
-typedef struct GduCreateLinuxMdDialog GduCreateLinuxMdDialog;
-typedef struct GduSizeWidget GduSizeWidget;
-typedef struct GduVolumeGrid GduVolumeGrid;
-typedef struct GduDetailsTable GduDetailsTable;
-typedef struct GduDetailsElement GduDetailsElement;
-typedef struct GduErrorDialog GduErrorDialog;
-typedef struct GduConfirmationDialog GduConfirmationDialog;
-typedef struct GduButtonElement GduButtonElement;
-typedef struct GduButtonTable GduButtonTable;
-typedef struct GduDialog GduDialog;
-typedef struct GduEditPartitionDialog GduEditPartitionDialog;
-typedef struct GduFormatDialog GduFormatDialog;
-typedef struct GduPartitionDialog GduPartitionDialog;
-typedef struct GduCreatePartitionDialog GduCreatePartitionDialog;
-typedef struct GduEditNameDialog GduEditNameDialog;
-typedef struct GduDiskSelectionWidget GduDiskSelectionWidget;
-typedef struct GduAddComponentLinuxMdDialog GduAddComponentLinuxMdDialog;
-typedef struct GduEditLinuxMdDialog GduEditLinuxMdDialog;
-typedef struct GduDriveBenchmarkDialog GduDriveBenchmarkDialog;
-typedef struct GduConnectToServerDialog GduConnectToServerDialog;
+typedef struct GduSample GduSample;
+typedef struct GduColor GduColor;
+typedef struct GduCurve GduCurve;
+typedef struct GduGraph GduGraph;
+typedef struct GduTimeLabel GduTimeLabel;
+typedef struct GduAtaSmartDialog GduAtaSmartDialog;
+typedef struct GduSpinner GduSpinner;
+typedef struct GduPoolTreeModel GduPoolTreeModel;
+typedef struct GduPoolTreeView GduPoolTreeView;
+typedef struct GduCreateLinuxMdDialog GduCreateLinuxMdDialog;
+typedef struct GduSizeWidget GduSizeWidget;
+typedef struct GduVolumeGrid GduVolumeGrid;
+typedef struct GduDetailsTable GduDetailsTable;
+typedef struct GduDetailsElement GduDetailsElement;
+typedef struct GduErrorDialog GduErrorDialog;
+typedef struct GduConfirmationDialog GduConfirmationDialog;
+typedef struct GduButtonElement GduButtonElement;
+typedef struct GduButtonTable GduButtonTable;
+typedef struct GduDialog GduDialog;
+typedef struct GduEditPartitionDialog GduEditPartitionDialog;
+typedef struct GduFormatDialog GduFormatDialog;
+typedef struct GduPartitionDialog GduPartitionDialog;
+typedef struct GduCreatePartitionDialog GduCreatePartitionDialog;
+typedef struct GduCreateLinuxLvm2VolumeDialog GduCreateLinuxLvm2VolumeDialog;
+typedef struct GduEditNameDialog GduEditNameDialog;
+typedef struct GduDiskSelectionWidget GduDiskSelectionWidget;
+typedef struct GduAddComponentLinuxMdDialog GduAddComponentLinuxMdDialog;
+typedef struct GduEditLinuxMdDialog GduEditLinuxMdDialog;
+typedef struct GduDriveBenchmarkDialog GduDriveBenchmarkDialog;
+typedef struct GduConnectToServerDialog GduConnectToServerDialog;
G_END_DECLS
diff --git a/src/gdu/gdu-callbacks.h b/src/gdu/gdu-callbacks.h
index ffd34b9..f77af80 100644
--- a/src/gdu/gdu-callbacks.h
+++ b/src/gdu/gdu-callbacks.h
@@ -188,6 +188,11 @@ typedef void (*GduPoolLinuxLvm2LVRemoveCompletedFunc) (GduPool *pool,
GError *error,
gpointer user_data);
+typedef void (*GduPoolLinuxLvm2LVCreateCompletedFunc) (GduPool *pool,
+ char *create_logical_volume_object_path,
+ GError *error,
+ gpointer user_data);
+
/* ---------------------------------------------------------------------------------------------------- */
/* GduDrive */
diff --git a/src/gdu/gdu-linux-lvm2-volume-group.c b/src/gdu/gdu-linux-lvm2-volume-group.c
index 8b94917..430b703 100644
--- a/src/gdu/gdu-linux-lvm2-volume-group.c
+++ b/src/gdu/gdu-linux-lvm2-volume-group.c
@@ -560,6 +560,26 @@ gdu_linux_lvm2_volume_group_get_uuid (GduLinuxLvm2VolumeGroup *vg)
return vg->priv->uuid;
}
+guint
+gdu_linux_lvm2_volume_group_get_num_lvs (GduLinuxLvm2VolumeGroup *vg)
+{
+ guint ret;
+ gchar **lvs;
+
+ ret = 0;
+
+ if (vg->priv->pv == NULL)
+ goto out;
+
+ lvs = gdu_device_linux_lvm2_pv_get_group_logical_volumes (vg->priv->pv);
+
+ if (lvs != NULL)
+ ret = g_strv_length (lvs);
+
+ out:
+ return ret;
+}
+
gboolean
gdu_linux_lvm2_volume_group_get_lv_info (GduLinuxLvm2VolumeGroup *vg,
const gchar *lv_uuid,
@@ -625,3 +645,52 @@ gdu_linux_lvm2_volume_group_get_lv_info (GduLinuxLvm2VolumeGroup *vg,
}
return ret;
}
+
+static gboolean
+lv_name_exists (GduLinuxLvm2VolumeGroup *vg, const gchar *name)
+{
+ gboolean ret;
+ gchar **lvs;
+ guint n;
+
+ ret = FALSE;
+
+ if (vg->priv->pv == NULL)
+ goto out;
+
+ lvs = gdu_device_linux_lvm2_pv_get_group_logical_volumes (vg->priv->pv);
+ for (n = 0; lvs != NULL && lvs[n] != NULL; n++) {
+ gchar **tokens;
+ guint m;
+
+ tokens = g_strsplit (lvs[n], ";", 0);
+
+ for (m = 0; tokens[m] != NULL; m++) {
+ /* TODO: we need to unescape values */
+ if (g_str_has_prefix (tokens[m], "name=") && g_strcmp0 (tokens[m] + 5, name) == 0) {
+ g_strfreev (tokens);
+ ret = TRUE;
+ goto out;
+ }
+ }
+ g_strfreev (tokens);
+ }
+
+ out:
+ return ret;
+}
+
+/* Computes the next available Logical Volume name */
+gchar *
+gdu_linux_lvm2_volume_group_get_compute_new_lv_name (GduLinuxLvm2VolumeGroup *vg)
+{
+ GString *s;
+
+ s = g_string_new (NULL);
+ g_string_append_printf (s, "Logical_Volume_%02d", gdu_linux_lvm2_volume_group_get_num_lvs (vg));
+
+ while (lv_name_exists (vg, s->str))
+ g_string_append_c (s, '_');
+
+ return g_string_free (s, FALSE);
+}
diff --git a/src/gdu/gdu-linux-lvm2-volume-group.h b/src/gdu/gdu-linux-lvm2-volume-group.h
index db48b98..b065fb6 100644
--- a/src/gdu/gdu-linux-lvm2-volume-group.h
+++ b/src/gdu/gdu-linux-lvm2-volume-group.h
@@ -64,11 +64,13 @@ 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);
+guint gdu_linux_lvm2_volume_group_get_num_lvs (GduLinuxLvm2VolumeGroup *vg);
gboolean gdu_linux_lvm2_volume_group_get_lv_info (GduLinuxLvm2VolumeGroup *vg,
const gchar *lv_uuid,
guint *out_position,
gchar **out_name,
guint64 *out_size);
+gchar *gdu_linux_lvm2_volume_group_get_compute_new_lv_name (GduLinuxLvm2VolumeGroup *vg);
G_END_DECLS
diff --git a/src/gdu/gdu-pool.c b/src/gdu/gdu-pool.c
index 217cfed..4000fee 100644
--- a/src/gdu/gdu-pool.c
+++ b/src/gdu/gdu-pool.c
@@ -2984,15 +2984,15 @@ void
gdu_pool_op_linux_lvm2_lv_remove (GduPool *pool,
const gchar *group_uuid,
const gchar *uuid,
- GduPoolLinuxLvm2LVSetNameCompletedFunc callback,
+ GduPoolLinuxLvm2LVRemoveCompletedFunc callback,
gpointer user_data)
{
- LinuxLvm2LVSetNameData *data;
+ LinuxLvm2LVRemoveData *data;
char *options[16];
options[0] = NULL;
- data = g_new0 (LinuxLvm2LVSetNameData, 1);
+ data = g_new0 (LinuxLvm2LVRemoveData, 1);
data->pool = g_object_ref (pool);
data->callback = callback;
data->user_data = user_data;
@@ -3007,6 +3007,82 @@ gdu_pool_op_linux_lvm2_lv_remove (GduPool *pool,
/* ---------------------------------------------------------------------------------------------------- */
+typedef struct {
+ GduPool *pool;
+ GduPoolLinuxLvm2LVCreateCompletedFunc callback;
+ gpointer user_data;
+} LinuxLvm2LVCreateData;
+
+static void
+op_linux_lvm2_lv_create_cb (DBusGProxy *proxy,
+ char *create_logical_volume_object_path,
+ GError *error,
+ gpointer user_data)
+{
+ LinuxLvm2LVCreateData *data = user_data;
+ _gdu_error_fixup (error);
+ if (data->callback != NULL)
+ data->callback (data->pool, create_logical_volume_object_path, error, data->user_data);
+ g_object_unref (data->pool);
+ g_free (data);
+}
+
+void
+gdu_pool_op_linux_lvm2_lv_create (GduPool *pool,
+ const gchar *group_uuid,
+ const gchar *name,
+ guint64 size,
+ guint num_stripes,
+ guint64 stripe_size,
+ guint num_mirrors,
+ const char *fstype,
+ const char *fslabel,
+ const char *encrypt_passphrase,
+ gboolean fs_take_ownership,
+ GduPoolLinuxLvm2LVCreateCompletedFunc callback,
+ gpointer user_data)
+{
+ LinuxLvm2LVCreateData *data;
+ char *options[16];
+ char *fsoptions[16];
+ guint n;
+
+ data = g_new0 (LinuxLvm2LVCreateData, 1);
+ data->pool = g_object_ref (pool);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ options[0] = NULL;
+
+ n = 0;
+ if (fslabel != NULL && strlen (fslabel) > 0) {
+ fsoptions[n++] = g_strdup_printf ("label=%s", fslabel);
+ }
+ if (encrypt_passphrase != NULL && strlen (encrypt_passphrase) > 0) {
+ fsoptions[n++] = g_strdup_printf ("luks_encrypt=%s", encrypt_passphrase);
+ }
+ if (fs_take_ownership) {
+ fsoptions[n++] = g_strdup_printf ("take_ownership_uid=%d", getuid ());
+ fsoptions[n++] = g_strdup_printf ("take_ownership_gid=%d", getgid ());
+ }
+ fsoptions[n] = NULL;
+
+ org_freedesktop_UDisks_linux_lvm2_lv_create_async (pool->priv->proxy,
+ group_uuid,
+ name,
+ size,
+ num_stripes,
+ stripe_size,
+ num_mirrors,
+ (const char **) options,
+ fstype,
+ (const char **) fsoptions,
+ op_linux_lvm2_lv_create_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 b93c1fb..132be60 100644
--- a/src/gdu/gdu-pool.h
+++ b/src/gdu/gdu-pool.h
@@ -168,6 +168,20 @@ void gdu_pool_op_linux_lvm2_lv_remove (GduPool *pool,
GduPoolLinuxLvm2LVRemoveCompletedFunc callback,
gpointer user_data);
+void gdu_pool_op_linux_lvm2_lv_create (GduPool *pool,
+ const gchar *group_uuid,
+ const gchar *name,
+ guint64 size,
+ guint num_stripes,
+ guint64 stripe_size,
+ guint num_mirrors,
+ const char *fstype,
+ const char *fslabel,
+ const char *encrypt_passphrase,
+ gboolean fs_take_ownership,
+ GduPoolLinuxLvm2LVCreateCompletedFunc callback,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __GDU_POOL_H */
diff --git a/src/palimpsest/gdu-section-volumes.c b/src/palimpsest/gdu-section-volumes.c
index 04b170b..72f87e3 100644
--- a/src/palimpsest/gdu-section-volumes.c
+++ b/src/palimpsest/gdu-section-volumes.c
@@ -1392,26 +1392,178 @@ on_fs_mount_point_element_activated (GduDetailsElement *element,
/* ---------------------------------------------------------------------------------------------------- */
+typedef struct {
+ GduShell *shell;
+ GduPresentable *presentable;
+ char *encrypt_passphrase;
+ gboolean save_in_keyring;
+ gboolean save_in_keyring_session;
+} CreateLinuxLvm2LVData;
+
+static void
+create_linux_lvm2_lv_data_free (CreateLinuxLvm2LVData *data)
+{
+ if (data->shell != NULL)
+ g_object_unref (data->shell);
+ if (data->presentable != NULL)
+ g_object_unref (data->presentable);
+ if (data->encrypt_passphrase != NULL) {
+ memset (data->encrypt_passphrase, '\0', strlen (data->encrypt_passphrase));
+ g_free (data->encrypt_passphrase);
+ }
+ g_free (data);
+}
+
+static void
+lvm2_lv_create_op_callback (GduPool *pool,
+ gchar *created_device_object_path,
+ GError *error,
+ gpointer user_data)
+{
+ CreateLinuxLvm2LVData *data = user_data;
+
+ if (error != NULL) {
+ GtkWidget *dialog;
+ dialog = gdu_error_dialog_new (GTK_WINDOW (gdu_shell_get_toplevel (data->shell)),
+ data->presentable,
+ _("Error creating 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);
+ } else {
+ if (data->encrypt_passphrase != NULL) {
+ GduDevice *cleartext_device;
+
+ cleartext_device = gdu_pool_get_by_object_path (pool, created_device_object_path);
+ if (cleartext_device != NULL) {
+ const gchar *cryptotext_device_object_path;
+
+ cryptotext_device_object_path = gdu_device_luks_cleartext_get_slave (cleartext_device);
+ if (cryptotext_device_object_path != NULL) {
+ GduDevice *cryptotext_device;
+
+ cryptotext_device = gdu_pool_get_by_object_path (pool,
+ cryptotext_device_object_path);
+ if (cryptotext_device != NULL) {
+ /* now set the passphrase if requested */
+ if (data->save_in_keyring || data->save_in_keyring_session) {
+ gdu_util_save_secret (cryptotext_device,
+ data->encrypt_passphrase,
+ data->save_in_keyring_session);
+ }
+ g_object_unref (cryptotext_device);
+ }
+ }
+ g_object_unref (cleartext_device);
+ }
+ }
+ g_free (created_device_object_path);
+ }
+
+ if (data != NULL)
+ create_linux_lvm2_lv_data_free (data);
+}
+
static void
on_lvm2_create_lv_button_clicked (GduButtonElement *button_element,
gpointer user_data)
{
GduSectionVolumes *section = GDU_SECTION_VOLUMES (user_data);
+ GduPresentable *v;
+ GduPresentable *vg;
+ GduPool *pool;
+ GtkWindow *toplevel;
GtkWidget *dialog;
- GError *error;
+ gint response;
+ GduFormatDialogFlags flags;
+ const gchar *vg_uuid;
+
+ v = NULL;
+ pool = NULL;
+ dialog = NULL;
- 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);
+ v = gdu_volume_grid_get_selected (GDU_VOLUME_GRID (section->priv->grid));
+ if (v == NULL || !GDU_IS_VOLUME_HOLE (v))
+ goto out;
+
+ vg = gdu_section_get_presentable (GDU_SECTION (section));
+ vg_uuid = gdu_linux_lvm2_volume_group_get_uuid (GDU_LINUX_LVM2_VOLUME_GROUP (vg));
+
+ pool = gdu_presentable_get_pool (v);
+
+ flags = GDU_FORMAT_DIALOG_FLAGS_NONE;
+
+ toplevel = GTK_WINDOW (gdu_shell_get_toplevel (gdu_section_get_shell (GDU_SECTION (section))));
+ dialog = gdu_create_linux_lvm2_volume_dialog_new (toplevel,
+ vg,
+ gdu_presentable_get_size (v),
+ flags);
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);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_hide (dialog);
+ if (response == GTK_RESPONSE_OK) {
+ CreateLinuxLvm2LVData *data;
+ gchar *volume_name;
+ gchar *fs_type;
+ gchar *fs_label;
+ gboolean fs_take_ownership;
+ guint64 size;
+
+ data = g_new0 (CreateLinuxLvm2LVData, 1);
+ data->shell = g_object_ref (gdu_section_get_shell (GDU_SECTION (section)));
+ data->presentable = g_object_ref (vg);
+
+ if (gdu_format_dialog_get_encrypt (GDU_FORMAT_DIALOG (dialog))) {
+ data->encrypt_passphrase = gdu_util_dialog_ask_for_new_secret (GTK_WIDGET (toplevel),
+ &data->save_in_keyring,
+ &data->save_in_keyring_session);
+ if (data->encrypt_passphrase == NULL) {
+ create_linux_lvm2_lv_data_free (data);
+ goto out;
+ }
+ }
+
+ /* For now, just use a generic LV name - maybe we should include a GtkEntry widget in
+ * the GduCreateLinuxLvm2LVDialog, maybe not.
+ */
+ volume_name = gdu_linux_lvm2_volume_group_get_compute_new_lv_name (GDU_LINUX_LVM2_VOLUME_GROUP (vg));
+
+ fs_type = gdu_format_dialog_get_fs_type (GDU_FORMAT_DIALOG (dialog));
+ fs_label = gdu_format_dialog_get_fs_label (GDU_FORMAT_DIALOG (dialog));
+ fs_take_ownership = gdu_format_dialog_get_take_ownership (GDU_FORMAT_DIALOG (dialog));
+
+ size = gdu_create_linux_lvm2_volume_dialog_get_size (GDU_CREATE_LINUX_LVM2_VOLUME_DIALOG (dialog));
+
+ /* TODO: include widgets for configuring striping and mirroring */
+
+ gdu_pool_op_linux_lvm2_lv_create (pool,
+ vg_uuid,
+ volume_name,
+ size,
+ 0, /* num_stripes */
+ 0, /* stripe_size */
+ 0, /* num_mirrors */
+ fs_type,
+ fs_label,
+ data->encrypt_passphrase,
+ fs_take_ownership,
+ lvm2_lv_create_op_callback,
+ data);
+
+ g_free (fs_type);
+ g_free (fs_label);
+ g_free (volume_name);
+ }
+ out:
+ if (dialog != NULL)
+ gtk_widget_destroy (dialog);
+ if (v != NULL)
+ g_object_unref (v);
+ if (pool != NULL)
+ g_object_unref (pool);
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -2166,7 +2318,7 @@ gdu_section_volumes_constructed (GObject *object)
section->priv->fs_mount_button = button_element;
button_element = gdu_button_element_new ("gdu-unmount",
- _("_Unmount Volume"),
+ _("Un_mount Volume"),
_("Unmount the volume"));
g_signal_connect (button_element,
"clicked",
@@ -2247,7 +2399,7 @@ gdu_section_volumes_constructed (GObject *object)
section->priv->luks_lock_button = button_element;
button_element = gdu_button_element_new ("gdu-encrypted-unlock",
- _("_Unlock Volume"),
+ _("Un_lock Volume"),
_("Make encrypted data available"));
g_signal_connect (button_element,
"clicked",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]