[gnome-disk-utility/udisks2-port] Preliminary iSCSI support
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility/udisks2-port] Preliminary iSCSI support
- Date: Mon, 28 Mar 2011 11:12:47 +0000 (UTC)
commit cae1204e431b77c48da684839db777839fea8328
Author: David Zeuthen <davidz redhat com>
Date: Fri Mar 25 18:18:58 2011 -0400
Preliminary iSCSI support
Signed-off-by: David Zeuthen <davidz redhat com>
data/ui/palimpsest.ui | 275 ++++++++++++++--
src/palimpsest/Makefile.am | 1 +
src/palimpsest/gdudevicetreemodel.c | 282 +++++++++++++++-
src/palimpsest/gduiscsipathmodel.c | 332 ++++++++++++++++++
src/palimpsest/gduiscsipathmodel.h | 55 +++
src/palimpsest/gdutypes.h | 3 +
src/palimpsest/gduwindow.c | 645 +++++++++++++++++++++++++++++------
7 files changed, 1462 insertions(+), 131 deletions(-)
---
diff --git a/data/ui/palimpsest.ui b/data/ui/palimpsest.ui
index 1a1d5fe..e139cb3 100644
--- a/data/ui/palimpsest.ui
+++ b/data/ui/palimpsest.ui
@@ -863,12 +863,6 @@
</packing>
</child>
<child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
<object class="GtkLabel" id="devtab-compat-media-label">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -905,6 +899,12 @@
<property name="y_padding">4</property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="expand">True</property>
@@ -947,13 +947,241 @@
</packing>
</child>
<child>
- <placeholder/>
+ <object class="GtkVBox" id="iscsitab_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkTable" id="iscsitab-table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="iscsitab-alias-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Alias</property>
+ <attributes>
+ <attribute name="foreground" value="#555555555555"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="y_padding">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="iscsitab-name-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Name</property>
+ <attributes>
+ <attribute name="foreground" value="#555555555555"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="y_padding">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="iscsitab-alias-value-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="selectable">True</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="y_padding">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="iscsitab-name-value-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="xalign">0</property>
+ <property name="selectable">True</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="y_padding">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="iscsitab-connection-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Connection</property>
+ <property name="use_underline">True</property>
+ <attributes>
+ <attribute name="foreground" value="#555555555555"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="y_padding">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="iscsitab-connection-hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="y_padding">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="iscsitab-main-label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><b>C_onnections</b></property>
+ <property name="use_markup">True</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">iscsi-connections-treeview</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkScrolledWindow" id="iscsitab-scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="iscsi-connections-treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_expanders">False</property>
+ <property name="level_indentation">12</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="iscsitab-toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="icon_size">1</property>
+ <child>
+ <object class="GtkToolButton" id="iscsitab-add-toolbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="icon_name">list-add-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="iscsitab-remove-toolbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="icon_name">list-remove-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
</child>
<child type="tab">
- <object class="GtkLabel" id="newtab_label">
+ <object class="GtkLabel" id="iscsitab_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">new</property>
+ <property name="label" translatable="yes">iscsi</property>
</object>
<packing>
<property name="position">2</property>
@@ -961,29 +1189,28 @@
</packing>
</child>
<child>
- <placeholder/>
+ <object class="GtkVBox" id="newtab_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
</child>
<child type="tab">
- <placeholder/>
- </child>
- <child>
- <object class="GtkVBox" id="newtab_vbox">
+ <object class="GtkLabel" id="newtab_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
+ <property name="label" translatable="yes">new</property>
</object>
<packing>
- <property name="position">2</property>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
<child type="tab">
<placeholder/>
</child>
diff --git a/src/palimpsest/Makefile.am b/src/palimpsest/Makefile.am
index 9019a68..6cca8ca 100644
--- a/src/palimpsest/Makefile.am
+++ b/src/palimpsest/Makefile.am
@@ -27,6 +27,7 @@ palimpsest_SOURCES = \
gdu.h \
gduapplication.h gduapplication.c \
gdudevicetreemodel.h gdudevicetreemodel.c \
+ gduiscsipathmodel.h gduiscsipathmodel.c \
gdutypes.h \
gduutils.h gduutils.c \
gduvolumegrid.h gduvolumegrid.c \
diff --git a/src/palimpsest/gdudevicetreemodel.c b/src/palimpsest/gdudevicetreemodel.c
index 8d18119..a7eb9a6 100644
--- a/src/palimpsest/gdudevicetreemodel.c
+++ b/src/palimpsest/gdudevicetreemodel.c
@@ -39,6 +39,10 @@ struct _GduDeviceTreeModel
GList *current_blocks;
GtkTreeIter block_iter;
gboolean block_iter_valid;
+
+ GList *current_iscsi_targets_and_luns;
+ GtkTreeIter iscsi_targets_iter;
+ gboolean iscsi_targets_iter_valid;
};
typedef struct
@@ -156,9 +160,12 @@ gdu_device_tree_model_set_property (GObject *object,
}
}
+/* ---------------------------------------------------------------------------------------------------- */
+
typedef struct
{
GDBusObject *object;
+ const gchar *object_path;
GtkTreeIter iter;
gboolean found;
} FindIterData;
@@ -188,6 +195,14 @@ find_iter_for_object_cb (GtkTreeModel *model,
goto out;
}
+ if (g_strcmp0 (g_dbus_object_get_object_path (iter_object), data->object_path) == 0)
+ {
+ data->iter = *iter;
+ data->found = TRUE;
+ goto out;
+ }
+
+
out:
if (iter_object != NULL)
g_object_unref (iter_object);
@@ -216,6 +231,28 @@ find_iter_for_object (GduDeviceTreeModel *model,
return data.found;
}
+static gboolean
+find_iter_for_object_path (GduDeviceTreeModel *model,
+ const gchar *object_path,
+ GtkTreeIter *out_iter)
+{
+ FindIterData data;
+
+ memset (&data, 0, sizeof (data));
+ data.object_path = object_path;
+ data.found = FALSE;
+ gtk_tree_model_foreach (GTK_TREE_MODEL (model),
+ find_iter_for_object_cb,
+ &data);
+ if (data.found)
+ {
+ if (out_iter != NULL)
+ *out_iter = data.iter;
+ }
+
+ return data.found;
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static void
@@ -488,6 +525,27 @@ remove_lun (GduDeviceTreeModel *model,
;
}
+static gboolean
+should_include_lun (GDBusObject *object,
+ gboolean allow_iscsi)
+{
+ UDisksLun *lun;
+ gboolean ret;
+
+ ret = FALSE;
+
+ lun = UDISKS_PEEK_LUN (object);
+
+ /* unless specificlly allowed, don't show LUNs paired with an iSCSI target */
+ if (!allow_iscsi && g_strcmp0 (udisks_lun_get_iscsi_target (lun), "/") != 0)
+ goto out;
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
static void
update_luns (GduDeviceTreeModel *model)
{
@@ -511,7 +569,8 @@ update_luns (GduDeviceTreeModel *model)
if (lun == NULL)
continue;
- luns = g_list_prepend (luns, g_object_ref (object));
+ if (should_include_lun (object, FALSE))
+ luns = g_list_prepend (luns, g_object_ref (object));
}
luns = g_list_sort (luns, (GCompareFunc) _g_dbus_object_compare);
@@ -789,12 +848,233 @@ update_blocks (GduDeviceTreeModel *model)
/* ---------------------------------------------------------------------------------------------------- */
+static GtkTreeIter *
+get_iscsi_header_iter (GduDeviceTreeModel *model)
+{
+ gchar *s;
+
+ if (model->iscsi_targets_iter_valid)
+ goto out;
+
+ s = g_strdup_printf ("<small><span foreground=\"#555555\">%s</span></small>",
+ _("iSCSI Targets"));
+ gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
+ &model->iscsi_targets_iter,
+ NULL, /* GtkTreeIter *parent */
+ 0,
+ GDU_DEVICE_TREE_MODEL_COLUMN_IS_HEADING, TRUE,
+ GDU_DEVICE_TREE_MODEL_COLUMN_HEADING_TEXT, s,
+ GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY, "02_iscsi",
+ -1);
+ g_free (s);
+
+ model->iscsi_targets_iter_valid = TRUE;
+
+ out:
+ return &model->iscsi_targets_iter;
+}
+
+static void
+nuke_iscsi_targets_header (GduDeviceTreeModel *model)
+{
+ if (model->iscsi_targets_iter_valid)
+ {
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &model->iscsi_targets_iter);
+ model->iscsi_targets_iter_valid = FALSE;
+ }
+}
+
+static void
+add_iscsi_target (GduDeviceTreeModel *model,
+ GDBusObject *object,
+ GtkTreeIter *parent)
+{
+ UDisksIScsiTarget *target;
+ GIcon *icon;
+ gchar *s;
+ gchar *sort_key;
+ GtkTreeIter iter;
+
+ target = UDISKS_PEEK_ISCSI_TARGET (object);
+
+#if 0
+ GIcon *base_icon;
+ GIcon *emblem_icon;
+ GEmblem *emblem;
+ emblem_icon = g_themed_icon_new_with_default_fallbacks ("emblem-web");
+ emblem = g_emblem_new (emblem_icon);
+ base_icon = g_themed_icon_new_with_default_fallbacks ("drive-harddisk");
+ icon = g_emblemed_icon_new (base_icon, emblem);
+ g_object_unref (emblem);
+ g_object_unref (base_icon);
+ g_object_unref (emblem_icon);
+#endif
+ icon = g_themed_icon_new_with_default_fallbacks ("network-server");
+
+ s = g_strdup_printf ("%s\n"
+ "<small><span foreground=\"#555555\">%s</span></small>",
+ "Remote iSCSI Target", /* TODO: alias */
+ udisks_iscsi_target_get_name (target));
+
+ sort_key = g_strdup (g_dbus_object_get_object_path (object)); /* for now */
+ gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
+ &iter,
+ parent,
+ 0,
+ GDU_DEVICE_TREE_MODEL_COLUMN_ICON, icon,
+ GDU_DEVICE_TREE_MODEL_COLUMN_NAME, s,
+ GDU_DEVICE_TREE_MODEL_COLUMN_SORT_KEY, sort_key,
+ GDU_DEVICE_TREE_MODEL_COLUMN_OBJECT, object,
+ -1);
+ g_object_unref (icon);
+ g_free (sort_key);
+ g_free (s);
+}
+
+static void
+remove_iscsi_target (GduDeviceTreeModel *model,
+ GDBusObject *object)
+{
+ GtkTreeIter iter;
+
+ if (!find_iter_for_object (model,
+ object,
+ &iter))
+ {
+ g_warning ("Error finding iter for object at %s",
+ g_dbus_object_get_object_path (object));
+ goto out;
+ }
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
+
+ out:
+ ;
+}
+
+static gboolean
+should_include_iscsi_target (GDBusObject *object)
+{
+ /* for now, just include all of them */
+ return TRUE;
+}
+
+static void
+update_iscsi_targets (GduDeviceTreeModel *model)
+{
+ GDBusObjectManager *object_manager;
+ GList *objects;
+ GList *iscsi_targets_and_luns;
+ GList *added;
+ GList *removed;
+ GList *l;
+
+ object_manager = udisks_client_get_object_manager (model->client);
+ objects = g_dbus_object_manager_get_objects (object_manager);
+
+ iscsi_targets_and_luns = NULL;
+ for (l = objects; l != NULL; l = l->next)
+ {
+ GDBusObject *object = G_DBUS_OBJECT (l->data);
+ UDisksIScsiTarget *target;
+
+ target = UDISKS_PEEK_ISCSI_TARGET (object);
+ if (target == NULL)
+ continue;
+
+ if (should_include_iscsi_target (object))
+ {
+ GList *ll;
+ const gchar *target_object_path;
+
+ iscsi_targets_and_luns = g_list_prepend (iscsi_targets_and_luns, g_object_ref (object));
+
+ /* also include the LUNs that are associated with this target */
+ target_object_path = g_dbus_object_get_object_path (object);
+ for (ll = objects; ll != NULL; ll = ll->next)
+ {
+ GDBusObject *lun_object = G_DBUS_OBJECT (ll->data);
+ UDisksLun *lun;
+ lun = UDISKS_PEEK_LUN (lun_object);
+ if (lun != NULL)
+ {
+ if (g_strcmp0 (udisks_lun_get_iscsi_target (lun), target_object_path) == 0)
+ {
+ if (should_include_lun (lun_object, TRUE))
+ iscsi_targets_and_luns = g_list_prepend (iscsi_targets_and_luns, g_object_ref (lun_object));
+ }
+ }
+ }
+ }
+ }
+
+ iscsi_targets_and_luns = g_list_sort (iscsi_targets_and_luns, (GCompareFunc) _g_dbus_object_compare);
+ model->current_iscsi_targets_and_luns = g_list_sort (model->current_iscsi_targets_and_luns, (GCompareFunc) _g_dbus_object_compare);
+ diff_sorted_lists (model->current_iscsi_targets_and_luns,
+ iscsi_targets_and_luns,
+ (GCompareFunc) _g_dbus_object_compare,
+ &added,
+ &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ GDBusObject *object = G_DBUS_OBJECT (l->data);
+
+ g_assert (g_list_find (model->current_iscsi_targets_and_luns, object) != NULL);
+
+ model->current_iscsi_targets_and_luns = g_list_remove (model->current_iscsi_targets_and_luns, object);
+ remove_iscsi_target (model, object);
+ g_object_unref (object);
+ }
+
+ /* Two passes: first add the iSCSI targets ... */
+ for (l = added; l != NULL; l = l->next)
+ {
+ GDBusObject *object = G_DBUS_OBJECT (l->data);
+ if (UDISKS_PEEK_ISCSI_TARGET (object) != NULL)
+ {
+ model->current_iscsi_targets_and_luns = g_list_prepend (model->current_iscsi_targets_and_luns,
+ g_object_ref (object));
+ add_iscsi_target (model, object, get_iscsi_header_iter (model));
+ }
+ }
+ /* ... and then the LUNs */
+ for (l = added; l != NULL; l = l->next)
+ {
+ GDBusObject *object = G_DBUS_OBJECT (l->data);
+ if (UDISKS_PEEK_LUN (object) != NULL)
+ {
+ GtkTreeIter iter;
+ model->current_iscsi_targets_and_luns = g_list_prepend (model->current_iscsi_targets_and_luns,
+ g_object_ref (object));
+ g_warn_if_fail (find_iter_for_object_path (model,
+ udisks_lun_get_iscsi_target (UDISKS_PEEK_LUN (object)),
+ &iter));
+ add_lun (model, object, &iter);
+ }
+ }
+
+ if (g_list_length (model->current_iscsi_targets_and_luns) == 0)
+ nuke_iscsi_targets_header (model);
+
+ g_list_free (added);
+ g_list_free (removed);
+ g_list_foreach (iscsi_targets_and_luns, (GFunc) g_object_unref, NULL);
+ g_list_free (iscsi_targets_and_luns);
+
+ g_list_foreach (objects, (GFunc) g_object_unref, NULL);
+ g_list_free (objects);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
update_all (GduDeviceTreeModel *model)
{
/* TODO: if this is CPU intensive we could coalesce all updates / schedule timeouts */
update_luns (model);
update_blocks (model);
+ update_iscsi_targets (model);
}
static void
diff --git a/src/palimpsest/gduiscsipathmodel.c b/src/palimpsest/gduiscsipathmodel.c
new file mode 100644
index 0000000..9b554e6
--- /dev/null
+++ b/src/palimpsest/gduiscsipathmodel.c
@@ -0,0 +1,332 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2011 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+#include <glib/gi18n.h>
+
+#include "gduiscsipathmodel.h"
+#include "gduutils.h"
+
+struct _GduIScsiPathModel
+{
+ GtkListStore parent_instance;
+
+ UDisksClient *client;
+
+ UDisksIScsiTarget *iscsi_target;
+ GDBusObject *object;
+};
+
+typedef struct
+{
+ GtkListStoreClass parent_class;
+} GduIScsiPathModelClass;
+
+enum
+{
+ PROP_0,
+ PROP_CLIENT,
+ PROP_OBJECT
+};
+
+static void update_all (GduIScsiPathModel *model);
+static void on_notify_for_iscsi_target (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data);
+
+G_DEFINE_TYPE (GduIScsiPathModel, gdu_iscsi_path_model, GTK_TYPE_LIST_STORE);
+
+static void
+gdu_iscsi_path_model_finalize (GObject *object)
+{
+ GduIScsiPathModel *model = GDU_ISCSI_PATH_MODEL (object);
+
+ g_signal_handlers_disconnect_by_func (model->iscsi_target,
+ G_CALLBACK (on_notify_for_iscsi_target),
+ model);
+ g_object_unref (model->iscsi_target);
+ g_object_unref (model->client);
+
+ G_OBJECT_CLASS (gdu_iscsi_path_model_parent_class)->finalize (object);
+}
+
+static void
+gdu_iscsi_path_model_init (GduIScsiPathModel *model)
+{
+}
+
+static void
+gdu_iscsi_path_model_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GduIScsiPathModel *model = GDU_ISCSI_PATH_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_CLIENT:
+ g_value_set_object (value, gdu_iscsi_path_model_get_client (model));
+ break;
+
+ case PROP_OBJECT:
+ g_value_set_object (value, gdu_iscsi_path_model_get_object (model));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gdu_iscsi_path_model_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GduIScsiPathModel *model = GDU_ISCSI_PATH_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_CLIENT:
+ model->client = g_value_dup_object (value);
+ break;
+
+ case PROP_OBJECT:
+ model->object = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+gdu_iscsi_path_model_constructed (GObject *object)
+{
+ GduIScsiPathModel *model = GDU_ISCSI_PATH_MODEL (object);
+ GType types[GDU_ISCSI_PATH_MODEL_N_COLUMNS];
+ /* GDBusObjectManager *object_manager; */
+
+ model->iscsi_target = UDISKS_GET_ISCSI_TARGET (model->object);
+ g_assert (model->iscsi_target != NULL);
+
+ types[0] = G_TYPE_BOOLEAN;
+ types[1] = G_TYPE_STRING;
+ types[2] = G_TYPE_INT;
+ types[3] = G_TYPE_INT;
+ types[4] = G_TYPE_STRING;
+ types[5] = G_TYPE_STRING;
+ G_STATIC_ASSERT (6 == GDU_ISCSI_PATH_MODEL_N_COLUMNS);
+ gtk_list_store_set_column_types (GTK_LIST_STORE (model),
+ GDU_ISCSI_PATH_MODEL_N_COLUMNS,
+ types);
+
+ update_all (model);
+ g_signal_connect (model->iscsi_target,
+ "notify",
+ G_CALLBACK (on_notify_for_iscsi_target),
+ model);
+
+ if (G_OBJECT_CLASS (gdu_iscsi_path_model_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (gdu_iscsi_path_model_parent_class)->constructed (object);
+}
+
+static void
+gdu_iscsi_path_model_class_init (GduIScsiPathModelClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = gdu_iscsi_path_model_finalize;
+ gobject_class->constructed = gdu_iscsi_path_model_constructed;
+ gobject_class->get_property = gdu_iscsi_path_model_get_property;
+ gobject_class->set_property = gdu_iscsi_path_model_set_property;
+
+ /**
+ * GduIScsiPathModel:client:
+ *
+ * The #UDisksClient used by the #GduIScsiPathModel instance.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_CLIENT,
+ g_param_spec_object ("client",
+ "Client",
+ "The client used by the tree model",
+ UDISKS_TYPE_CLIENT,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GduIScsiPathModel:object:
+ *
+ * The #GDBusObject that is a iSCSI target.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_OBJECT,
+ g_param_spec_object ("object",
+ "Object",
+ "The iSCSI target",
+ G_TYPE_DBUS_OBJECT,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * gdu_iscsi_path_model_new:
+ * @client: A #UDisksClient.
+ * @object: A #GDBusObject.
+ *
+ * Creates a new #GduIScsiPathModel for viewing the paths on the iSCSI
+ * target on @object.
+ *
+ * Returns: A #GduIScsiPathModel. Free with g_object_unref().
+ */
+GduIScsiPathModel *
+gdu_iscsi_path_model_new (UDisksClient *client,
+ GDBusObject *object)
+{
+ return GDU_ISCSI_PATH_MODEL (g_object_new (GDU_TYPE_ISCSI_PATH_MODEL,
+ "client", client,
+ "object", object,
+ NULL));
+}
+
+/**
+ * gdu_iscsi_path_model_get_client:
+ * @model: A #GduIScsiPathModel.
+ *
+ * Gets the #UDisksClient used by @model.
+ *
+ * Returns: (transfer none): A #UDisksClient. Do not free, the object
+ * belongs to @model.
+ */
+UDisksClient *
+gdu_iscsi_path_model_get_client (GduIScsiPathModel *model)
+{
+ g_return_val_if_fail (GDU_IS_ISCSI_PATH_MODEL (model), NULL);
+ return model->client;
+}
+
+/**
+ * gdu_iscsi_path_model_get_object:
+ * @model: A #GduIScsiPathModel.
+ *
+ * Gets the #GDBusObject used by @model.
+ *
+ * Returns: (transfer none): A #GDBusObject. Do not free, the object
+ * belongs to @model.
+ */
+GDBusObject *
+gdu_iscsi_path_model_get_object (GduIScsiPathModel *model)
+{
+ g_return_val_if_fail (GDU_IS_ISCSI_PATH_MODEL (model), NULL);
+ return model->object;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+update_all (GduIScsiPathModel *model)
+{
+ GVariant *portals_and_interfaces;
+ GVariantIter portal_iter;
+ const gchar *portal_name;
+ gint port;
+ gint group;
+ GVariantIter *iface_iter;
+
+ gtk_list_store_clear (GTK_LIST_STORE (model));
+
+ portals_and_interfaces = udisks_iscsi_target_get_portals_and_interfaces (model->iscsi_target);
+ g_variant_iter_init (&portal_iter, portals_and_interfaces);
+
+ while (g_variant_iter_next (&portal_iter,
+ "(^&ayiia(ays))",
+ &portal_name,
+ &port,
+ &group,
+ &iface_iter))
+ {
+ const gchar *iface_name;
+ const gchar *state;
+
+ while (g_variant_iter_next (iface_iter,
+ "(^&ays)",
+ &iface_name,
+ &state))
+ {
+ gchar *status;
+ gboolean active;
+ if (g_strcmp0 (state, "LOGGED_IN") == 0)
+ {
+ active = TRUE;
+ status = g_strdup (_("Logged In"));
+ }
+ else if (g_strcmp0 (state, "FAILED") == 0)
+ {
+ active = TRUE;
+ status = g_strdup_printf ("<span foreground=\"#ff0000\"><b>%s</b></span>", _("FAILED"));
+ }
+ else if (g_strcmp0 (state, "") == 0)
+ {
+ active = FALSE;
+ status = g_strdup (_("Not Logged In"));
+ }
+ else
+ {
+ active = TRUE;
+ status = g_strdup (state);
+ }
+
+ gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
+ NULL, /* GtkTreeIter *out */
+ G_MAXINT, /* position */
+ GDU_ISCSI_PATH_MODEL_COLUMN_ACTIVE, active,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_ADDRESS, portal_name,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_PORT, port,
+ GDU_ISCSI_PATH_MODEL_COLUMN_TPGT, group,
+ GDU_ISCSI_PATH_MODEL_COLUMN_INTERFACE, iface_name,
+ GDU_ISCSI_PATH_MODEL_COLUMN_STATUS, status,
+ -1);
+ g_free (status);
+ }
+ g_variant_iter_free (iface_iter);
+ }
+}
+
+static void
+on_notify_for_iscsi_target (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GduIScsiPathModel *model = GDU_ISCSI_PATH_MODEL (user_data);
+ update_all (model);
+}
diff --git a/src/palimpsest/gduiscsipathmodel.h b/src/palimpsest/gduiscsipathmodel.h
new file mode 100644
index 0000000..a1eca25
--- /dev/null
+++ b/src/palimpsest/gduiscsipathmodel.h
@@ -0,0 +1,55 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2008-2011 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#ifndef __GDU_ISCSI_PATH_MODEL_H__
+#define __GDU_ISCSI_PATH_MODEL_H__
+
+#include <gtk/gtk.h>
+#include "gdutypes.h"
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_ISCSI_PATH_MODEL (gdu_iscsi_path_model_get_type ())
+#define GDU_ISCSI_PATH_MODEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_ISCSI_PATH_MODEL, GduIScsiPathModel))
+#define GDU_IS_ISCSI_PATH_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_ISCSI_PATH_MODEL))
+
+enum
+{
+ GDU_ISCSI_PATH_MODEL_COLUMN_ACTIVE,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_ADDRESS,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_PORT,
+ GDU_ISCSI_PATH_MODEL_COLUMN_TPGT,
+ GDU_ISCSI_PATH_MODEL_COLUMN_INTERFACE,
+ GDU_ISCSI_PATH_MODEL_COLUMN_STATUS,
+ GDU_ISCSI_PATH_MODEL_N_COLUMNS
+};
+
+GType gdu_iscsi_path_model_get_type (void) G_GNUC_CONST;
+GduIScsiPathModel *gdu_iscsi_path_model_new (UDisksClient *client,
+ GDBusObject *object);
+UDisksClient *gdu_iscsi_path_model_get_client (GduIScsiPathModel *model);
+GDBusObject *gdu_iscsi_path_model_get_object (GduIScsiPathModel *model);
+
+
+G_END_DECLS
+
+#endif /* __GDU_ISCSI_PATH_MODEL_H__ */
diff --git a/src/palimpsest/gdutypes.h b/src/palimpsest/gdutypes.h
index dd70775..4cdae4e 100644
--- a/src/palimpsest/gdutypes.h
+++ b/src/palimpsest/gdutypes.h
@@ -43,6 +43,9 @@ typedef struct _GduWindow GduWindow;
struct _GduVolumeGrid;
typedef struct _GduVolumeGrid GduVolumeGrid;
+struct _GduIScsiPathModel;
+typedef struct _GduIScsiPathModel GduIScsiPathModel;
+
G_END_DECLS
#endif /* __GDU_TYPES_H__ */
diff --git a/src/palimpsest/gduwindow.c b/src/palimpsest/gduwindow.c
index f0f8149..e8668a8 100644
--- a/src/palimpsest/gduwindow.c
+++ b/src/palimpsest/gduwindow.c
@@ -31,12 +31,14 @@
#include "gdudevicetreemodel.h"
#include "gduutils.h"
#include "gduvolumegrid.h"
+#include "gduiscsipathmodel.h"
/* Keep in sync with tabs in palimpsest.ui file */
typedef enum
{
DETAILS_PAGE_NOT_SELECTED,
DETAILS_PAGE_DEVICE,
+ DETAILS_PAGE_ISCSI_TARGET,
} DetailsPage;
struct _GduWindow
@@ -54,6 +56,7 @@ struct _GduWindow
GtkWidget *volume_grid;
GtkWidget *write_cache_switch;
+ GtkWidget *iscsi_connection_switch;
GHashTable *label_connections;
};
@@ -70,9 +73,25 @@ enum
PROP_CLIENT
};
+static void gdu_window_show_error (GduWindow *window,
+ const gchar *message,
+ GError *orig_error);
+
+static void setup_device_page (GduWindow *window, GDBusObject *object);
+static void update_device_page (GduWindow *window);
+static void teardown_device_page (GduWindow *window);
+
+static void setup_iscsi_target_page (GduWindow *window, GDBusObject *object);
+static void update_iscsi_target_page (GduWindow *window);
+static void teardown_iscsi_target_page (GduWindow *window);
+
static void on_volume_grid_changed (GduVolumeGrid *grid,
gpointer user_data);
+static void iscsi_connection_switch_on_notify_active (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data);
+
G_DEFINE_TYPE (GduWindow, gdu_window, GTK_TYPE_WINDOW);
static void
@@ -190,6 +209,10 @@ set_selected_object (GduWindow *window,
{
select_details_page (window, object, DETAILS_PAGE_DEVICE);
}
+ else if (UDISKS_PEEK_ISCSI_TARGET (object) != NULL)
+ {
+ select_details_page (window, object, DETAILS_PAGE_ISCSI_TARGET);
+ }
else
{
g_assert_not_reached ();
@@ -274,6 +297,13 @@ gdu_window_constructed (GObject *object)
context = gtk_widget_get_style_context (gdu_window_get_widget (window, "device-tree-scrolledwindow"));
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
context = gtk_widget_get_style_context (gdu_window_get_widget (window, "device-tree-add-remove-toolbar"));
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
+ gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+
+ context = gtk_widget_get_style_context (gdu_window_get_widget (window, "iscsitab-scrolledwindow"));
+ gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+ context = gtk_widget_get_style_context (gdu_window_get_widget (window, "iscsitab-toolbar"));
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
window->model = gdu_device_tree_model_new (window->client);
@@ -321,7 +351,7 @@ gdu_window_constructed (GObject *object)
NULL);
renderer = gtk_cell_renderer_text_new ();
g_object_set (G_OBJECT (renderer),
- "ellipsize", PANGO_ELLIPSIZE_END,
+ "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
NULL);
gtk_tree_view_column_pack_start (column, renderer, FALSE);
gtk_tree_view_column_set_attributes (column,
@@ -371,12 +401,25 @@ gdu_window_constructed (GObject *object)
G_CALLBACK (on_volume_grid_changed),
window);
+ /* devtab's Write Cache switch */
window->write_cache_switch = gtk_switch_new ();
gtk_box_pack_start (GTK_BOX (gdu_window_get_widget (window, "devtab-write-cache-hbox")),
window->write_cache_switch,
FALSE, TRUE, 0);
gtk_label_set_mnemonic_widget (GTK_LABEL (gdu_window_get_widget (window, "devtab-write-cache-label")),
window->write_cache_switch);
+
+ /* iSCSI tab's Connection switch */
+ window->iscsi_connection_switch = gtk_switch_new ();
+ g_signal_connect (window->iscsi_connection_switch,
+ "notify::active",
+ G_CALLBACK (iscsi_connection_switch_on_notify_active),
+ window);
+ gtk_box_pack_start (GTK_BOX (gdu_window_get_widget (window, "iscsitab-connection-hbox")),
+ window->iscsi_connection_switch,
+ FALSE, TRUE, 0);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (gdu_window_get_widget (window, "iscsitab-connection-label")),
+ window->iscsi_connection_switch);
}
static void
@@ -507,7 +550,7 @@ gdu_window_get_widget (GduWindow *window,
static void
teardown_details_page (GduWindow *window,
GDBusObject *object,
- gint page)
+ DetailsPage page)
{
//g_debug ("teardown for %s, page %d",
// object != NULL ? g_dbus_object_get_object_path (object) : "<none>",
@@ -516,8 +559,13 @@ teardown_details_page (GduWindow *window,
{
case DETAILS_PAGE_NOT_SELECTED:
break;
+
case DETAILS_PAGE_DEVICE:
- gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), NULL);
+ teardown_device_page (window);
+ break;
+
+ case DETAILS_PAGE_ISCSI_TARGET:
+ teardown_iscsi_target_page (window);
break;
}
}
@@ -642,84 +690,9 @@ block_device_compare_on_preferred (GDBusObject *a,
/* ---------------------------------------------------------------------------------------------------- */
static void
-setup_device_page (GduWindow *window,
- GDBusObject *object)
-{
- UDisksLun *lun;
- UDisksBlockDevice *block;
- GList *children;
- GList *l;
-
- children = gtk_container_get_children (GTK_CONTAINER (gdu_window_get_widget (window, "devtab-table")));
- for (l = children; l != NULL; l = l->next)
- {
- GtkWidget *child = GTK_WIDGET (l->data);
- gtk_widget_hide (child);
- }
- g_list_free (children);
-
- lun = UDISKS_PEEK_LUN (object);
- block = UDISKS_PEEK_BLOCK_DEVICE (object);
-
- if (lun != NULL)
- {
- GList *block_devices;
- gchar *lun_name;
- gchar *lun_desc;
- GIcon *lun_icon;
- GIcon *lun_media_icon;
-
- /* TODO: for multipath, ensure e.g. mpathk is before sda, sdb */
- block_devices = get_top_level_block_devices_for_lun (window, g_dbus_object_get_object_path (object));
- block_devices = g_list_sort (block_devices, (GCompareFunc) block_device_compare_on_preferred);
-
- udisks_util_get_lun_info (lun,
- &lun_name,
- &lun_desc,
- &lun_icon,
- &lun_media_icon);
- gdu_volume_grid_set_container_icon (GDU_VOLUME_GRID (window->volume_grid),
- lun_icon);
-
- gdu_volume_grid_set_container_visible (GDU_VOLUME_GRID (window->volume_grid), TRUE);
- if (block_devices != NULL)
- gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), block_devices->data);
- else
- gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), NULL);
-
- g_free (lun_name);
- g_free (lun_desc);
- g_object_unref (lun_icon);
- g_object_unref (lun_media_icon);
-
- g_list_foreach (block_devices, (GFunc) g_object_unref, NULL);
- g_list_free (block_devices);
- }
- else if (block != NULL)
- {
- gdu_volume_grid_set_container_visible (GDU_VOLUME_GRID (window->volume_grid), FALSE);
- gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), object);
- }
- else
- {
- g_assert_not_reached ();
- }
-}
-
-static void update_devtab (GduWindow *window);
-
-static void
-update_device_page (GduWindow *window)
-{
- update_devtab (window);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
setup_details_page (GduWindow *window,
GDBusObject *object,
- gint page)
+ DetailsPage page)
{
//g_debug ("setup for %s, page %d",
// object != NULL ? g_dbus_object_get_object_path (object) : "<none>",
@@ -733,12 +706,16 @@ setup_details_page (GduWindow *window,
case DETAILS_PAGE_DEVICE:
setup_device_page (window, object);
break;
+
+ case DETAILS_PAGE_ISCSI_TARGET:
+ setup_iscsi_target_page (window, object);
+ break;
}
}
static void
-update_details_page (GduWindow *window,
- gint page)
+update_details_page (GduWindow *window,
+ DetailsPage page)
{
//g_debug ("update for %s, page %d",
// object != NULL ? g_dbus_object_get_object_path (object) : "<none>",
@@ -752,6 +729,10 @@ update_details_page (GduWindow *window,
case DETAILS_PAGE_DEVICE:
update_device_page (window);
break;
+
+ case DETAILS_PAGE_ISCSI_TARGET:
+ update_iscsi_target_page (window);
+ break;
}
}
@@ -799,6 +780,14 @@ update_all (GduWindow *window,
update_details_page (window, window->current_page);
}
break;
+
+ case DETAILS_PAGE_ISCSI_TARGET:
+ if (object == window->current_object)
+ {
+ update_details_page (window, window->current_page);
+ }
+ /* Nothing to update */
+ break;
}
}
@@ -852,10 +841,77 @@ on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager,
update_all (window, G_DBUS_OBJECT (object_proxy));
}
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
-update_devtab_for_lun (GduWindow *window,
- GDBusObject *object,
- UDisksLun *lun)
+setup_device_page (GduWindow *window,
+ GDBusObject *object)
+{
+ UDisksLun *lun;
+ UDisksBlockDevice *block;
+ GList *children;
+ GList *l;
+
+ children = gtk_container_get_children (GTK_CONTAINER (gdu_window_get_widget (window, "devtab-table")));
+ for (l = children; l != NULL; l = l->next)
+ {
+ GtkWidget *child = GTK_WIDGET (l->data);
+ gtk_widget_hide (child);
+ }
+ g_list_free (children);
+
+ lun = UDISKS_PEEK_LUN (object);
+ block = UDISKS_PEEK_BLOCK_DEVICE (object);
+
+ if (lun != NULL)
+ {
+ GList *block_devices;
+ gchar *lun_name;
+ gchar *lun_desc;
+ GIcon *lun_icon;
+ GIcon *lun_media_icon;
+
+ /* TODO: for multipath, ensure e.g. mpathk is before sda, sdb */
+ block_devices = get_top_level_block_devices_for_lun (window, g_dbus_object_get_object_path (object));
+ block_devices = g_list_sort (block_devices, (GCompareFunc) block_device_compare_on_preferred);
+
+ udisks_util_get_lun_info (lun,
+ &lun_name,
+ &lun_desc,
+ &lun_icon,
+ &lun_media_icon);
+ gdu_volume_grid_set_container_icon (GDU_VOLUME_GRID (window->volume_grid),
+ lun_icon);
+
+ gdu_volume_grid_set_container_visible (GDU_VOLUME_GRID (window->volume_grid), TRUE);
+ if (block_devices != NULL)
+ gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), block_devices->data);
+ else
+ gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), NULL);
+
+ g_free (lun_name);
+ g_free (lun_desc);
+ g_object_unref (lun_icon);
+ g_object_unref (lun_media_icon);
+
+ g_list_foreach (block_devices, (GFunc) g_object_unref, NULL);
+ g_list_free (block_devices);
+ }
+ else if (block != NULL)
+ {
+ gdu_volume_grid_set_container_visible (GDU_VOLUME_GRID (window->volume_grid), FALSE);
+ gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), object);
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+}
+
+static void
+update_device_page_for_lun (GduWindow *window,
+ GDBusObject *object,
+ UDisksLun *lun)
{
gchar *s;
GList *block_devices;
@@ -866,7 +922,7 @@ update_devtab_for_lun (GduWindow *window,
const gchar* const *lun_media_compat;
gchar *media_compat_for_display;
- //g_debug ("In update_devtab_for_lun() - selected=%s",
+ //g_debug ("In update_device_page_for_lun() - selected=%s",
// object != NULL ? g_dbus_object_get_object_path (object) : "<nothing>");
/* TODO: for multipath, ensure e.g. mpathk is before sda, sdb */
@@ -936,10 +992,10 @@ update_devtab_for_lun (GduWindow *window,
}
static void
-update_devtab_for_block (GduWindow *window,
- GDBusObject *object,
- UDisksBlockDevice *block,
- guint64 size)
+update_device_page_for_block (GduWindow *window,
+ GDBusObject *object,
+ UDisksBlockDevice *block,
+ guint64 size)
{
const gchar *backing_file;
const gchar *usage;
@@ -948,7 +1004,7 @@ update_devtab_for_block (GduWindow *window,
gint partition_type;
gchar *type_for_display;
- //g_debug ("In update_devtab_for_block() - size=%" G_GUINT64_FORMAT " selected=%s",
+ //g_debug ("In update_device_page_for_block() - size=%" G_GUINT64_FORMAT " selected=%s",
// size,
// object != NULL ? g_dbus_object_get_object_path (object) : "<nothing>");
@@ -1026,21 +1082,21 @@ update_devtab_for_block (GduWindow *window,
}
static void
-update_devtab_for_no_media (GduWindow *window,
- GDBusObject *object,
- UDisksBlockDevice *block)
+update_device_page_for_no_media (GduWindow *window,
+ GDBusObject *object,
+ UDisksBlockDevice *block)
{
- //g_debug ("In update_devtab_for_no_media() - selected=%s",
+ //g_debug ("In update_device_page_for_no_media() - selected=%s",
// object != NULL ? g_dbus_object_get_object_path (object) : "<nothing>");
}
static void
-update_devtab_for_free_space (GduWindow *window,
- GDBusObject *object,
- UDisksBlockDevice *block,
- guint64 size)
+update_device_page_for_free_space (GduWindow *window,
+ GDBusObject *object,
+ UDisksBlockDevice *block,
+ guint64 size)
{
- //g_debug ("In update_devtab_for_free_space() - size=%" G_GUINT64_FORMAT " selected=%s",
+ //g_debug ("In update_device_page_for_free_space() - size=%" G_GUINT64_FORMAT " selected=%s",
// size,
// object != NULL ? g_dbus_object_get_object_path (object) : "<nothing>");
@@ -1060,7 +1116,7 @@ update_devtab_for_free_space (GduWindow *window,
}
static void
-update_devtab (GduWindow *window)
+update_device_page (GduWindow *window)
{
GDBusObject *object;
GList *children;
@@ -1088,9 +1144,9 @@ update_devtab (GduWindow *window)
if (type == GDU_VOLUME_GRID_ELEMENT_TYPE_CONTAINER)
{
if (lun != NULL)
- update_devtab_for_lun (window, object, lun);
+ update_device_page_for_lun (window, object, lun);
else if (block != NULL)
- update_devtab_for_block (window, object, block, size);
+ update_device_page_for_block (window, object, block, size);
}
else
{
@@ -1107,15 +1163,15 @@ update_devtab (GduWindow *window)
break;
case GDU_VOLUME_GRID_ELEMENT_TYPE_DEVICE:
- update_devtab_for_block (window, object, block, size);
+ update_device_page_for_block (window, object, block, size);
break;
case GDU_VOLUME_GRID_ELEMENT_TYPE_NO_MEDIA:
- update_devtab_for_no_media (window, object, block);
+ update_device_page_for_no_media (window, object, block);
break;
case GDU_VOLUME_GRID_ELEMENT_TYPE_FREE_SPACE:
- update_devtab_for_free_space (window, object, block, size);
+ update_device_page_for_free_space (window, object, block, size);
break;
}
}
@@ -1123,11 +1179,388 @@ update_devtab (GduWindow *window)
}
static void
+teardown_device_page (GduWindow *window)
+{
+ gdu_volume_grid_set_block_device (GDU_VOLUME_GRID (window->volume_grid), NULL);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+iscsi_target_format_portal_address (GtkCellLayout *cell_layout,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ /* GduWindow *window = GDU_WINDOW (user_data); */
+ gchar *portal_address;
+ gint portal_port;
+ gchar *markup;
+
+ gtk_tree_model_get (tree_model,
+ iter,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_ADDRESS, &portal_address,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_PORT, &portal_port,
+ -1);
+
+ /* only show port if it is non-standard */
+ if (portal_port != 3260)
+ markup = g_strdup_printf ("%s:%d", portal_address, portal_port);
+ else
+ markup = g_strdup (portal_address);
+
+ g_object_set (renderer,
+ "markup", markup,
+ NULL);
+
+ g_free (markup);
+ g_free (portal_address);
+}
+
+static void
+iscsi_target_login_cb (UDisksIScsiTarget *target,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ GError *error;
+ error = NULL;
+ if (!udisks_iscsi_target_call_login_finish (target, res, &error))
+ {
+ gdu_window_show_error (window,
+ _("Error logging in to iSCSI target"),
+ error);
+ g_error_free (error);
+ }
+ g_object_unref (window);
+}
+
+static void
+iscsi_target_logout_cb (UDisksIScsiTarget *target,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ GError *error;
+ error = NULL;
+ if (!udisks_iscsi_target_call_logout_finish (target, res, &error))
+ {
+ gdu_window_show_error (window,
+ _("Error logging out of iSCSI target"),
+ error);
+ g_error_free (error);
+ }
+ g_object_unref (window);
+}
+
+static void
+on_iscsi_active_toggled (GtkCellRendererToggle *renderer,
+ gchar *path,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ gboolean is_active;
+ GtkTreeView *tree_view;
+ GtkTreeModel *tree_model;
+ GtkTreeIter iter;
+ gchar *portal_address;
+ gchar *iface_name;
+ gint portal_port;
+ UDisksIScsiTarget *target;
+
+ portal_address = NULL;
+ iface_name = NULL;
+
+ tree_view = GTK_TREE_VIEW (gdu_window_get_widget (window, "iscsi-connections-treeview"));
+ tree_model = gtk_tree_view_get_model (tree_view);
+
+ target = UDISKS_PEEK_ISCSI_TARGET (window->current_object);
+ if (target == NULL)
+ {
+ g_warning ("Expected selected object to be an iSCSI target");
+ goto out;
+ }
+
+ if (!gtk_tree_model_get_iter_from_string (tree_model,
+ &iter,
+ path))
+ {
+ g_warning ("Unable to get tree iter");
+ goto out;
+ }
+
+ gtk_tree_model_get (tree_model,
+ &iter,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_ADDRESS, &portal_address,
+ GDU_ISCSI_PATH_MODEL_COLUMN_PORTAL_PORT, &portal_port,
+ GDU_ISCSI_PATH_MODEL_COLUMN_INTERFACE, &iface_name,
+ -1);
+
+ is_active = gtk_cell_renderer_toggle_get_active (renderer);
+ if (is_active)
+ {
+ const gchar *options[] = {NULL};
+ udisks_iscsi_target_call_logout (target,
+ options,
+ portal_address,
+ portal_port,
+ iface_name,
+ NULL, /* GCancellable* */
+ (GAsyncReadyCallback) iscsi_target_login_cb,
+ g_object_ref (window));
+ }
+ else
+ {
+ const gchar *options[] = {NULL};
+ udisks_iscsi_target_call_login (target,
+ options,
+ portal_address,
+ portal_port,
+ iface_name,
+ NULL, /* GCancellable* */
+ (GAsyncReadyCallback) iscsi_target_login_cb,
+ g_object_ref (window));
+ }
+
+ out:
+ g_free (portal_address);
+ g_free (iface_name);
+}
+
+static void
+init_iscsi_target_page (GduWindow *window)
+{
+ static volatile gsize init_val = 0;
+ GtkTreeView *tree_view;
+ /* GtkTreeSelection *selection; */
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ if (!g_once_init_enter (&init_val))
+ goto out;
+
+ tree_view = GTK_TREE_VIEW (gdu_window_get_widget (window, "iscsi-connections-treeview"));
+ gtk_tree_view_set_rules_hint (tree_view, TRUE);
+#if 0
+ selection = gtk_tree_view_get_selection (tree_view);
+ gtk_tree_selection_set_select_function (selection, dont_select_headings, NULL, NULL);
+ g_signal_connect (selection,
+ "changed",
+ G_CALLBACK (on_tree_selection_changed),
+ window);
+#endif
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column (tree_view, column);
+ renderer = gtk_cell_renderer_toggle_new ();
+ gtk_tree_view_column_pack_end (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "active", GDU_ISCSI_PATH_MODEL_COLUMN_ACTIVE, NULL);
+ g_signal_connect (renderer,
+ "toggled",
+ G_CALLBACK (on_iscsi_active_toggled),
+ window);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Portal"));
+ gtk_tree_view_append_column (tree_view, column);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_alignment (column, 0.0);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (column),
+ renderer,
+ iscsi_target_format_portal_address,
+ window,
+ NULL);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Network Interface"));
+ gtk_tree_view_append_column (tree_view, column);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "markup", GDU_ISCSI_PATH_MODEL_COLUMN_INTERFACE, NULL);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("TPGT"));
+ gtk_tree_view_append_column (tree_view, column);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "markup", GDU_ISCSI_PATH_MODEL_COLUMN_TPGT, NULL);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Status"));
+ gtk_tree_view_append_column (tree_view, column);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "markup", GDU_ISCSI_PATH_MODEL_COLUMN_STATUS, NULL);
+
+ g_once_init_leave (&init_val, 1);
+ out:
+ ;
+}
+
+static gboolean
+iscsi_target_has_active_connections (UDisksIScsiTarget *target)
+{
+ GVariant *portals_and_interfaces;
+ GVariantIter portal_iter;
+ GVariantIter *iface_iter;
+ gboolean ret;
+
+ ret = FALSE;
+ portals_and_interfaces = udisks_iscsi_target_get_portals_and_interfaces (target);
+ g_variant_iter_init (&portal_iter, portals_and_interfaces);
+ while (g_variant_iter_next (&portal_iter,
+ "(^&ayiia(ays))",
+ NULL, /* &portal_adress */
+ NULL, /* &port */
+ NULL, /* &tpgt */
+ &iface_iter))
+ {
+ const gchar *state;
+ while (g_variant_iter_next (iface_iter,
+ "(^&ays)",
+ NULL, /* &iface_name */
+ &state))
+ {
+ if (g_strcmp0 (state, "LOGGED_IN") == 0)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ }
+ }
+ out:
+ return ret;
+}
+
+
+static void
+update_iscsi_target_page (GduWindow *window)
+{
+ GList *children;
+ GList *l;
+ UDisksIScsiTarget *target;
+
+ /* first hide everything */
+ children = gtk_container_get_children (GTK_CONTAINER (gdu_window_get_widget (window, "iscsitab-table")));
+ for (l = children; l != NULL; l = l->next)
+ {
+ GtkWidget *child = GTK_WIDGET (l->data);
+ gtk_widget_hide (child);
+ }
+ g_list_free (children);
+
+ target = UDISKS_PEEK_ISCSI_TARGET (window->current_object);
+ /* TODO: get Alias from somewhere */
+ set_markup (window,
+ "iscsitab-alias-label",
+ "iscsitab-alias-value-label",
+ "", SET_MARKUP_FLAGS_HYPHEN_IF_EMPTY);
+ set_markup (window,
+ "iscsitab-name-label",
+ "iscsitab-name-value-label",
+ udisks_iscsi_target_get_name (target), SET_MARKUP_FLAGS_NONE);
+
+ gtk_switch_set_active (GTK_SWITCH (window->iscsi_connection_switch),
+ iscsi_target_has_active_connections (target));
+ gtk_widget_show (gdu_window_get_widget (window, "iscsitab-connection-label"));
+ gtk_widget_show_all (gdu_window_get_widget (window, "iscsitab-connection-hbox"));
+
+}
+
+static void
+iscsi_connection_switch_on_notify_active (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GduWindow *window = GDU_WINDOW (user_data);
+ gboolean active;
+ gboolean has_connections;
+ UDisksIScsiTarget *target;
+
+ target = UDISKS_PEEK_ISCSI_TARGET (window->current_object);
+ if (target == NULL)
+ {
+ g_warning ("Expected selected object to be an iSCSI target");
+ goto out;
+ }
+
+ active = !! gtk_switch_get_active (GTK_SWITCH (window->iscsi_connection_switch));
+ has_connections = !! iscsi_target_has_active_connections (target);
+ if (active != has_connections)
+ {
+ if (!has_connections)
+ {
+ const gchar *options[] = {NULL};
+ udisks_iscsi_target_call_login (target,
+ options,
+ "", /* portal_address */
+ 0, /* portal_port */
+ "", /* interface_name */
+ NULL, /* GCancellable* */
+ (GAsyncReadyCallback) iscsi_target_login_cb,
+ g_object_ref (window));
+ }
+ else
+ {
+ const gchar *options[] = {NULL};
+ udisks_iscsi_target_call_logout (target,
+ options,
+ "", /* portal_address */
+ 0, /* portal_port */
+ "", /* interface_name */
+ NULL, /* GCancellable* */
+ (GAsyncReadyCallback) iscsi_target_logout_cb,
+ g_object_ref (window));
+ }
+ }
+ gtk_switch_set_active (GTK_SWITCH (window->iscsi_connection_switch), has_connections);
+
+ out:
+ ;
+}
+
+static void
+setup_iscsi_target_page (GduWindow *window,
+ GDBusObject *object)
+{
+ GtkTreeView *tree_view;
+ GduIScsiPathModel *model;
+ GtkTreeIter first_iter;
+
+ init_iscsi_target_page (window);
+
+ tree_view = GTK_TREE_VIEW (gdu_window_get_widget (window, "iscsi-connections-treeview"));
+ model = gdu_iscsi_path_model_new (window->client, object);
+ gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (model));
+ /* select the first row */
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &first_iter))
+ gtk_tree_selection_select_iter (gtk_tree_view_get_selection (tree_view), &first_iter);
+ g_object_unref (model);
+}
+
+static void
+teardown_iscsi_target_page (GduWindow *window)
+{
+ GtkTreeView *tree_view;
+
+ tree_view = GTK_TREE_VIEW (gdu_window_get_widget (window, "iscsi-connections-treeview"));
+ gtk_tree_view_set_model (tree_view, NULL);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
on_volume_grid_changed (GduVolumeGrid *grid,
gpointer user_data)
{
GduWindow *window = GDU_WINDOW (user_data);
- update_devtab (window);
+ update_device_page (window);
}
/* ---------------------------------------------------------------------------------------------------- */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]