2014-06-11 19:36:28 +08:00
|
|
|
# Copyright (C) 2008, 2013, 2014 Red Hat, Inc.
|
2008-08-15 23:22:20 +08:00
|
|
|
# Copyright (C) 2008 Cole Robinson <crobinso@redhat.com>
|
|
|
|
#
|
2018-04-04 21:35:41 +08:00
|
|
|
# This work is licensed under the GNU GPLv2 or later.
|
2018-03-21 03:00:02 +08:00
|
|
|
# See the COPYING file in the top-level directory.
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-06-11 20:23:59 +08:00
|
|
|
import os
|
2016-06-07 23:33:21 +08:00
|
|
|
|
2012-05-14 21:24:56 +08:00
|
|
|
from gi.repository import Gdk
|
2015-04-10 02:42:25 +08:00
|
|
|
from gi.repository import Gtk
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-06-17 09:12:39 +08:00
|
|
|
from virtinst import log
|
2016-12-14 01:36:49 +08:00
|
|
|
from virtinst import StoragePool
|
|
|
|
|
2019-06-17 10:19:17 +08:00
|
|
|
from .lib import uiutil
|
2019-05-05 03:03:36 +08:00
|
|
|
from .asyncjob import vmmAsyncJob
|
|
|
|
from .baseclass import vmmGObjectUI
|
2019-07-03 04:29:16 +08:00
|
|
|
from .object.storagepool import vmmStoragePool
|
2019-05-05 03:03:36 +08:00
|
|
|
from .xmleditor import vmmXMLEditor
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2013-04-14 02:34:52 +08:00
|
|
|
|
2010-12-09 06:26:19 +08:00
|
|
|
class vmmCreatePool(vmmGObjectUI):
|
2015-04-10 02:42:25 +08:00
|
|
|
__gsignals__ = {
|
2018-03-15 20:10:09 +08:00
|
|
|
"pool-created": (vmmGObjectUI.RUN_FIRST, None, [str]),
|
2015-04-10 02:42:25 +08:00
|
|
|
}
|
|
|
|
|
2010-12-09 06:26:19 +08:00
|
|
|
def __init__(self, conn):
|
2013-09-23 04:10:16 +08:00
|
|
|
vmmGObjectUI.__init__(self, "createpool.ui", "vmm-create-pool")
|
2008-08-15 23:22:20 +08:00
|
|
|
self.conn = conn
|
|
|
|
|
2019-05-05 03:03:36 +08:00
|
|
|
self._xmleditor = vmmXMLEditor(self.builder, self.topwin,
|
|
|
|
self.widget("pool-details-align"),
|
|
|
|
self.widget("pool-details"))
|
|
|
|
self._xmleditor.connect("xml-requested",
|
|
|
|
self._xmleditor_xml_requested_cb)
|
|
|
|
|
2013-02-17 02:31:46 +08:00
|
|
|
self.builder.connect_signals({
|
2017-08-05 14:39:32 +08:00
|
|
|
"on_pool_cancel_clicked": self.close,
|
|
|
|
"on_vmm_create_pool_delete_event": self.close,
|
2019-05-05 02:37:56 +08:00
|
|
|
"on_pool_finish_clicked": self._finish_clicked_cb,
|
2019-05-05 01:08:06 +08:00
|
|
|
"on_pool_type_changed": self._pool_type_changed_cb,
|
2013-09-28 00:13:01 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
"on_pool_source_button_clicked": self._browse_source_cb,
|
|
|
|
"on_pool_target_button_clicked": self._browse_target_cb,
|
2009-01-26 04:41:44 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
"on_pool_hostname_activate": self._hostname_changed_cb,
|
|
|
|
"on_pool_iqn_chk_toggled": self._iqn_toggled_cb,
|
2008-08-15 23:22:20 +08:00
|
|
|
})
|
2011-04-18 23:25:28 +08:00
|
|
|
self.bind_escape_key_close()
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
self._init_ui()
|
|
|
|
|
|
|
|
|
|
|
|
#######################
|
|
|
|
# Standard UI methods #
|
|
|
|
#######################
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2011-04-14 20:47:42 +08:00
|
|
|
def show(self, parent):
|
2019-06-17 09:12:39 +08:00
|
|
|
log.debug("Showing new pool wizard")
|
2019-05-05 02:37:56 +08:00
|
|
|
self._reset_state()
|
2011-04-14 20:47:42 +08:00
|
|
|
self.topwin.set_transient_for(parent)
|
2008-08-15 23:22:20 +08:00
|
|
|
self.topwin.present()
|
|
|
|
|
|
|
|
def close(self, ignore1=None, ignore2=None):
|
2019-06-17 09:12:39 +08:00
|
|
|
log.debug("Closing new pool wizard")
|
2008-08-15 23:22:20 +08:00
|
|
|
self.topwin.hide()
|
|
|
|
return 1
|
|
|
|
|
2011-07-24 09:16:54 +08:00
|
|
|
def _cleanup(self):
|
2011-04-13 21:27:02 +08:00
|
|
|
self.conn = None
|
2019-05-05 03:03:36 +08:00
|
|
|
self._xmleditor.cleanup()
|
|
|
|
self._xmleditor = None
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
|
|
|
|
###########
|
|
|
|
# UI init #
|
|
|
|
###########
|
2011-04-13 21:27:02 +08:00
|
|
|
|
2019-05-05 01:08:06 +08:00
|
|
|
def _build_pool_type_list(self):
|
|
|
|
# [pool type, label]
|
|
|
|
model = Gtk.ListStore(str, str)
|
|
|
|
type_list = self.widget("pool-type")
|
|
|
|
type_list.set_model(model)
|
|
|
|
uiutil.init_combo_text_column(type_list, 1)
|
|
|
|
|
2019-07-03 04:29:16 +08:00
|
|
|
for typ in vmmStoragePool.list_types():
|
|
|
|
desc = vmmStoragePool.pretty_type(typ)
|
2019-05-05 01:08:06 +08:00
|
|
|
model.append([typ, "%s: %s" % (typ, desc)])
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _init_ui(self):
|
2013-09-28 00:13:01 +08:00
|
|
|
blue = Gdk.Color.parse("#0072A8")[1]
|
|
|
|
self.widget("header").modify_bg(Gtk.StateType.NORMAL, blue)
|
|
|
|
|
2011-07-15 01:13:13 +08:00
|
|
|
format_list = self.widget("pool-format")
|
2012-05-14 21:24:56 +08:00
|
|
|
format_model = Gtk.ListStore(str, str)
|
2008-08-15 23:22:20 +08:00
|
|
|
format_list.set_model(format_model)
|
2015-04-11 01:04:02 +08:00
|
|
|
uiutil.init_combo_text_column(format_list, 1)
|
2018-09-06 08:24:23 +08:00
|
|
|
for f in ["auto"]:
|
|
|
|
format_model.append([f, f])
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2009-10-21 09:12:35 +08:00
|
|
|
# Target path combo box entry
|
2011-07-15 01:13:13 +08:00
|
|
|
target_list = self.widget("pool-target-path")
|
2009-10-21 09:12:35 +08:00
|
|
|
# target_path, Label, pool class instance
|
2012-05-14 21:24:56 +08:00
|
|
|
target_model = Gtk.ListStore(str, str, object)
|
|
|
|
target_model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
|
2009-10-21 09:12:35 +08:00
|
|
|
target_list.set_model(target_model)
|
2013-01-13 05:13:53 +08:00
|
|
|
target_list.set_entry_text_column(0)
|
2009-10-21 09:12:35 +08:00
|
|
|
|
2009-10-20 03:55:19 +08:00
|
|
|
# Source path combo box entry
|
2011-07-15 01:13:13 +08:00
|
|
|
source_list = self.widget("pool-source-path")
|
2009-10-21 08:20:59 +08:00
|
|
|
# source_path, Label, pool class instance
|
2012-05-14 21:24:56 +08:00
|
|
|
source_model = Gtk.ListStore(str, str, object)
|
|
|
|
source_model.set_sort_column_id(0, Gtk.SortType.ASCENDING)
|
2009-10-20 03:55:19 +08:00
|
|
|
source_list.set_model(source_model)
|
2013-01-13 05:13:53 +08:00
|
|
|
source_list.set_entry_text_column(0)
|
2009-10-20 03:55:19 +08:00
|
|
|
|
2019-05-05 01:08:06 +08:00
|
|
|
self._build_pool_type_list()
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _reset_state(self):
|
2019-05-05 03:03:36 +08:00
|
|
|
self._xmleditor.reset_state()
|
|
|
|
|
2019-05-05 01:08:06 +08:00
|
|
|
defaultname = StoragePool.find_free_name(
|
|
|
|
self.conn.get_backend(), "pool")
|
|
|
|
self.widget("pool-name").set_text(defaultname)
|
2011-07-15 01:13:13 +08:00
|
|
|
self.widget("pool-name").grab_focus()
|
2012-05-14 21:24:56 +08:00
|
|
|
self.widget("pool-target-path").get_child().set_text("")
|
|
|
|
self.widget("pool-source-path").get_child().set_text("")
|
2011-07-15 01:13:13 +08:00
|
|
|
self.widget("pool-hostname").set_text("")
|
2011-07-24 07:42:41 +08:00
|
|
|
self.widget("pool-iqn-chk").set_active(False)
|
|
|
|
self.widget("pool-iqn-chk").toggled()
|
|
|
|
self.widget("pool-iqn").set_text("")
|
2018-09-06 08:24:23 +08:00
|
|
|
self.widget("pool-format").set_active(0)
|
2011-07-15 01:13:13 +08:00
|
|
|
self.widget("pool-build").set_sensitive(True)
|
|
|
|
self.widget("pool-build").set_active(False)
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 01:08:06 +08:00
|
|
|
uiutil.set_list_selection(self.widget("pool-type"), 0)
|
2019-05-05 02:37:56 +08:00
|
|
|
self._show_options_by_pool()
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2009-10-21 21:48:12 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
#################
|
|
|
|
# UI populating #
|
|
|
|
#################
|
2011-07-24 07:42:41 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _populate_pool_sources(self):
|
|
|
|
pooltype = self._get_config_pool_type()
|
2011-07-15 01:13:13 +08:00
|
|
|
source_list = self.widget("pool-source-path")
|
2009-10-21 09:12:35 +08:00
|
|
|
source_model = source_list.get_model()
|
|
|
|
source_model.clear()
|
|
|
|
|
2011-07-15 01:13:13 +08:00
|
|
|
target_list = self.widget("pool-target-path")
|
2009-10-21 09:12:35 +08:00
|
|
|
target_model = target_list.get_model()
|
|
|
|
target_model.clear()
|
2009-10-20 03:55:19 +08:00
|
|
|
|
2009-10-21 09:12:35 +08:00
|
|
|
use_list = source_list
|
|
|
|
use_model = source_model
|
2009-10-20 03:55:19 +08:00
|
|
|
entry_list = []
|
2019-05-05 02:37:56 +08:00
|
|
|
if pooltype == StoragePool.TYPE_SCSI:
|
|
|
|
entry_list = self._list_scsi_adapters()
|
2009-10-21 09:12:35 +08:00
|
|
|
use_list = source_list
|
|
|
|
use_model = source_model
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
elif pooltype == StoragePool.TYPE_LOGICAL:
|
|
|
|
pool_list = self._list_pool_sources(pooltype)
|
2013-04-12 04:32:00 +08:00
|
|
|
entry_list = [[p.target_path, p.target_path, p]
|
2019-05-22 06:19:05 +08:00
|
|
|
for p in pool_list if p.target_path]
|
2009-10-21 09:12:35 +08:00
|
|
|
use_list = target_list
|
|
|
|
use_model = target_model
|
2009-10-20 03:55:19 +08:00
|
|
|
|
|
|
|
for e in entry_list:
|
2009-10-21 09:12:35 +08:00
|
|
|
use_model.append(e)
|
2009-10-20 03:55:19 +08:00
|
|
|
|
|
|
|
if entry_list:
|
2009-10-21 09:12:35 +08:00
|
|
|
use_list.set_active(0)
|
2009-10-20 03:55:19 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _list_scsi_adapters(self):
|
2015-04-10 21:37:03 +08:00
|
|
|
scsi_hosts = self.conn.filter_nodedevs("scsi_host")
|
2015-04-08 02:12:00 +08:00
|
|
|
host_list = [dev.xmlobj.host for dev in scsi_hosts]
|
2009-10-20 03:55:19 +08:00
|
|
|
|
|
|
|
clean_list = []
|
|
|
|
for h in host_list:
|
|
|
|
name = "host%s" % h
|
2013-09-20 08:18:12 +08:00
|
|
|
tmppool = self._make_stub_pool()
|
2009-10-21 08:20:59 +08:00
|
|
|
tmppool.source_path = name
|
|
|
|
|
2013-09-20 08:18:12 +08:00
|
|
|
entry = [name, name, tmppool]
|
2013-04-12 04:32:00 +08:00
|
|
|
if name not in [l[0] for l in clean_list]:
|
2009-10-20 03:55:19 +08:00
|
|
|
clean_list.append(entry)
|
|
|
|
|
|
|
|
return clean_list
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _list_pool_sources(self, pool_type, host=None):
|
2009-10-21 09:12:35 +08:00
|
|
|
plist = []
|
|
|
|
try:
|
2013-09-20 08:18:12 +08:00
|
|
|
plist = StoragePool.pool_list_from_sources(
|
2013-07-05 20:59:58 +08:00
|
|
|
self.conn.get_backend(),
|
2013-09-20 08:18:12 +08:00
|
|
|
pool_type,
|
2013-07-05 20:59:58 +08:00
|
|
|
host=host)
|
2009-10-29 08:35:13 +08:00
|
|
|
except Exception:
|
2019-06-17 09:12:39 +08:00
|
|
|
log.exception("Pool enumeration failed")
|
2009-10-21 09:12:35 +08:00
|
|
|
|
|
|
|
return plist
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_build_default(self, pooltype):
|
|
|
|
""" Return (default value, whether build option can be changed)"""
|
|
|
|
if not pooltype:
|
|
|
|
return (False, False)
|
|
|
|
|
|
|
|
if pooltype in [StoragePool.TYPE_DIR,
|
|
|
|
StoragePool.TYPE_FS,
|
|
|
|
StoragePool.TYPE_NETFS]:
|
|
|
|
# Building for these simply entails creating a directory
|
|
|
|
return (True, False)
|
|
|
|
elif pooltype in [StoragePool.TYPE_LOGICAL,
|
|
|
|
StoragePool.TYPE_DISK]:
|
|
|
|
# This is a dangerous operation, anything (False, True)
|
|
|
|
# should be assumed to be one.
|
|
|
|
return (False, True)
|
|
|
|
|
|
|
|
return (False, False)
|
|
|
|
|
|
|
|
def _show_options_by_pool(self):
|
2011-07-24 04:22:02 +08:00
|
|
|
def show_row(base, do_show):
|
2013-09-28 00:13:01 +08:00
|
|
|
widget = self.widget(base + "-label")
|
2014-01-27 07:15:50 +08:00
|
|
|
uiutil.set_grid_row_visible(widget, do_show)
|
2011-07-24 04:22:02 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
pool = self._make_stub_pool()
|
2019-07-03 05:03:39 +08:00
|
|
|
src = pool.supports_source_path()
|
2013-09-20 08:18:12 +08:00
|
|
|
src_b = src and not self.conn.is_remote()
|
2019-07-03 05:03:39 +08:00
|
|
|
tgt = pool.supports_target_path()
|
2013-09-20 08:18:12 +08:00
|
|
|
tgt_b = tgt and not self.conn.is_remote()
|
2019-07-03 05:03:39 +08:00
|
|
|
host = pool.supports_hosts()
|
|
|
|
fmt = pool.supports_format()
|
|
|
|
iqn = pool.supports_iqn()
|
2019-05-05 02:37:56 +08:00
|
|
|
builddef, buildsens = self._get_build_default(pool.type)
|
2009-10-21 04:53:13 +08:00
|
|
|
|
2014-12-10 05:05:02 +08:00
|
|
|
# We don't show source_name for logical pools, since we use
|
|
|
|
# pool-sources to avoid the need for it
|
2019-07-03 05:03:39 +08:00
|
|
|
src_name = (pool.supports_source_name() and
|
2019-05-05 02:37:56 +08:00
|
|
|
pool.type != pool.TYPE_LOGICAL)
|
2014-12-10 05:05:02 +08:00
|
|
|
|
2014-06-11 19:36:28 +08:00
|
|
|
# Source path browsing is meaningless for net pools
|
2019-05-05 02:37:56 +08:00
|
|
|
if pool.type in [StoragePool.TYPE_NETFS,
|
2013-09-20 08:18:12 +08:00
|
|
|
StoragePool.TYPE_ISCSI,
|
2014-12-10 05:05:02 +08:00
|
|
|
StoragePool.TYPE_SCSI,
|
|
|
|
StoragePool.TYPE_GLUSTER]:
|
2009-10-21 04:53:13 +08:00
|
|
|
src_b = False
|
|
|
|
|
2011-07-24 04:22:02 +08:00
|
|
|
show_row("pool-target", tgt)
|
|
|
|
show_row("pool-source", src)
|
|
|
|
show_row("pool-hostname", host)
|
|
|
|
show_row("pool-format", fmt)
|
|
|
|
show_row("pool-build", buildsens)
|
2011-07-24 07:42:41 +08:00
|
|
|
show_row("pool-iqn", iqn)
|
2014-02-12 18:52:46 +08:00
|
|
|
show_row("pool-source-name", src_name)
|
2011-07-24 04:22:02 +08:00
|
|
|
|
2014-04-03 23:19:03 +08:00
|
|
|
if iqn:
|
|
|
|
self.widget("pool-source-label").set_label(_("_Source IQN:"))
|
|
|
|
else:
|
|
|
|
self.widget("pool-source-label").set_label(_("_Source Path:"))
|
|
|
|
|
2014-02-12 17:29:22 +08:00
|
|
|
if tgt:
|
|
|
|
self.widget("pool-target-path").get_child().set_text(
|
2019-05-05 02:37:56 +08:00
|
|
|
pool.default_target_path() or "")
|
2014-02-12 17:29:22 +08:00
|
|
|
|
2011-07-15 01:13:13 +08:00
|
|
|
self.widget("pool-target-button").set_sensitive(tgt_b)
|
|
|
|
self.widget("pool-source-button").set_sensitive(src_b)
|
2011-07-24 04:22:02 +08:00
|
|
|
self.widget("pool-build").set_active(builddef)
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2014-02-12 18:52:46 +08:00
|
|
|
if src_name:
|
2018-09-03 02:47:34 +08:00
|
|
|
self.widget("pool-source-name").set_text(
|
2019-05-22 06:19:05 +08:00
|
|
|
pool.default_source_name() or "")
|
2014-02-12 18:52:46 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
self._populate_pool_sources()
|
2009-10-20 03:55:19 +08:00
|
|
|
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
################
|
|
|
|
# UI accessors #
|
|
|
|
################
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_config_pool_type(self):
|
|
|
|
return uiutil.get_list_selection(self.widget("pool-type"))
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_config_target_path(self):
|
2011-07-15 01:13:13 +08:00
|
|
|
src = self.widget("pool-target-path")
|
2012-11-09 19:13:22 +08:00
|
|
|
if not src.get_sensitive():
|
2009-10-21 09:12:35 +08:00
|
|
|
return None
|
|
|
|
|
2015-05-20 05:17:53 +08:00
|
|
|
ret = uiutil.get_list_selection(src, column=1)
|
2014-01-27 09:21:12 +08:00
|
|
|
if ret is not None:
|
|
|
|
return ret
|
2012-05-14 21:24:56 +08:00
|
|
|
return src.get_child().get_text()
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_config_source_path(self):
|
2011-07-15 01:13:13 +08:00
|
|
|
src = self.widget("pool-source-path")
|
2012-11-09 19:13:22 +08:00
|
|
|
if not src.get_sensitive():
|
2009-10-20 03:55:19 +08:00
|
|
|
return None
|
|
|
|
|
2015-05-20 05:17:53 +08:00
|
|
|
ret = uiutil.get_list_selection(src, column=1)
|
2014-01-27 09:21:12 +08:00
|
|
|
if ret is not None:
|
|
|
|
return ret
|
2012-05-14 21:24:56 +08:00
|
|
|
return src.get_child().get_text().strip()
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_config_host(self):
|
2011-07-15 01:13:13 +08:00
|
|
|
host = self.widget("pool-hostname")
|
2012-11-09 19:13:22 +08:00
|
|
|
if host.get_sensitive():
|
2011-02-03 00:47:01 +08:00
|
|
|
return host.get_text().strip()
|
2008-08-15 23:22:20 +08:00
|
|
|
return None
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_config_source_name(self):
|
2014-02-12 18:52:46 +08:00
|
|
|
name = self.widget("pool-source-name")
|
|
|
|
if name.get_sensitive():
|
|
|
|
return name.get_text().strip()
|
|
|
|
return None
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_config_format(self):
|
2015-05-20 05:17:53 +08:00
|
|
|
return uiutil.get_list_selection(self.widget("pool-format"))
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_config_iqn(self):
|
2011-07-24 07:42:41 +08:00
|
|
|
iqn = self.widget("pool-iqn")
|
2013-09-09 23:02:34 +08:00
|
|
|
if iqn.get_sensitive() and iqn.get_visible():
|
2011-07-24 07:42:41 +08:00
|
|
|
return iqn.get_text().strip()
|
|
|
|
return None
|
|
|
|
|
2013-09-28 00:13:01 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
###################
|
|
|
|
# Object building #
|
|
|
|
###################
|
2013-11-27 23:10:34 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _get_pool_from_sourcelist(self):
|
2009-10-21 08:20:59 +08:00
|
|
|
"""
|
2019-05-05 02:37:56 +08:00
|
|
|
If an enumerated pool source was selected, use that as the
|
|
|
|
basis for our pool object
|
2009-10-21 08:20:59 +08:00
|
|
|
"""
|
2011-07-15 01:13:13 +08:00
|
|
|
source_list = self.widget("pool-source-path")
|
|
|
|
target_list = self.widget("pool-target-path")
|
2009-10-21 08:20:59 +08:00
|
|
|
|
2015-06-22 03:47:31 +08:00
|
|
|
pool = uiutil.get_list_selection(source_list, column=2,
|
|
|
|
check_entry=False)
|
2014-01-27 09:21:12 +08:00
|
|
|
if pool is None:
|
2015-06-22 03:47:31 +08:00
|
|
|
pool = uiutil.get_list_selection(target_list, column=2,
|
|
|
|
check_entry=False)
|
2009-10-21 08:20:59 +08:00
|
|
|
|
|
|
|
return pool
|
|
|
|
|
2019-05-05 03:03:36 +08:00
|
|
|
def _build_xmlobj_from_xmleditor(self):
|
|
|
|
xml = self._xmleditor.get_xml()
|
2019-06-17 09:12:39 +08:00
|
|
|
log.debug("Using XML from xmleditor:\n%s", xml)
|
2019-05-05 03:03:36 +08:00
|
|
|
return StoragePool(self.conn.get_backend(), parsexml=xml)
|
|
|
|
|
2013-09-20 08:18:12 +08:00
|
|
|
def _make_stub_pool(self):
|
2019-05-05 02:37:56 +08:00
|
|
|
pool = self._get_pool_from_sourcelist()
|
|
|
|
if not pool:
|
|
|
|
pool = StoragePool(self.conn.get_backend())
|
|
|
|
pool.type = self._get_config_pool_type()
|
|
|
|
pool.name = self.widget("pool-name").get_text()
|
2013-09-20 08:18:12 +08:00
|
|
|
return pool
|
2008-08-15 23:22:20 +08:00
|
|
|
|
2019-05-05 03:03:36 +08:00
|
|
|
def _build_xmlobj_from_ui(self):
|
2019-05-05 02:37:56 +08:00
|
|
|
target = self._get_config_target_path()
|
|
|
|
host = self._get_config_host()
|
|
|
|
source = self._get_config_source_path()
|
|
|
|
fmt = self._get_config_format()
|
|
|
|
iqn = self._get_config_iqn()
|
|
|
|
source_name = self._get_config_source_name()
|
2013-09-20 08:18:12 +08:00
|
|
|
|
2019-05-05 03:03:36 +08:00
|
|
|
pool = self._make_stub_pool()
|
|
|
|
|
|
|
|
pool.target_path = target
|
|
|
|
if host:
|
|
|
|
hostobj = pool.hosts.add_new()
|
|
|
|
hostobj.name = host
|
|
|
|
if source:
|
|
|
|
pool.source_path = source
|
2019-07-03 05:03:39 +08:00
|
|
|
if fmt and pool.supports_format():
|
2019-05-05 03:03:36 +08:00
|
|
|
pool.format = fmt
|
|
|
|
if iqn:
|
|
|
|
pool.iqn = iqn
|
|
|
|
if source_name:
|
|
|
|
pool.source_name = source_name
|
|
|
|
return pool
|
|
|
|
|
|
|
|
def _build_xmlobj(self, check_xmleditor):
|
2013-09-20 08:18:12 +08:00
|
|
|
try:
|
2019-05-05 03:03:36 +08:00
|
|
|
xmlobj = self._build_xmlobj_from_ui()
|
|
|
|
if check_xmleditor and self._xmleditor.is_xml_selected():
|
|
|
|
xmlobj = self._build_xmlobj_from_xmleditor()
|
|
|
|
return xmlobj
|
|
|
|
except Exception as e:
|
|
|
|
self.err.show_err(_("Error building XML: %s") % str(e))
|
2019-05-05 01:08:06 +08:00
|
|
|
|
2019-05-05 03:03:36 +08:00
|
|
|
def _validate(self, pool):
|
|
|
|
pool.validate()
|
2013-09-20 08:18:12 +08:00
|
|
|
|
|
|
|
buildval = self.widget("pool-build").get_active()
|
|
|
|
buildsen = (self.widget("pool-build").get_sensitive() and
|
2013-09-28 00:13:01 +08:00
|
|
|
self.widget("pool-build").get_visible())
|
2013-09-20 08:18:12 +08:00
|
|
|
if buildsen and buildval:
|
|
|
|
ret = self.err.yes_no(_("Building a pool of this type will "
|
|
|
|
"format the source device. Are you "
|
|
|
|
"sure you want to 'build' this pool?"))
|
|
|
|
if not ret:
|
|
|
|
return ret
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
|
|
|
|
##################
|
|
|
|
# Object install #
|
|
|
|
##################
|
2013-09-20 08:18:12 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _pool_added_cb(self, src, connkey, created_name):
|
|
|
|
if connkey == created_name:
|
|
|
|
self.emit("pool-created", connkey)
|
|
|
|
|
|
|
|
def _finish_cb(self, error, details, pool):
|
|
|
|
self.reset_finish_cursor()
|
|
|
|
|
|
|
|
if error:
|
|
|
|
error = _("Error creating pool: %s") % error
|
|
|
|
self.err.show_err(error,
|
|
|
|
details=details)
|
|
|
|
else:
|
|
|
|
self.conn.connect_once("pool-added", self._pool_added_cb,
|
|
|
|
pool.name)
|
|
|
|
self.conn.schedule_priority_tick(pollpool=True)
|
|
|
|
self.close()
|
2009-03-09 03:14:00 +08:00
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _async_pool_create(self, asyncjob, pool, build):
|
|
|
|
meter = asyncjob.get_meter()
|
|
|
|
|
2019-06-17 09:12:39 +08:00
|
|
|
log.debug("Starting background pool creation.")
|
2019-05-05 02:37:56 +08:00
|
|
|
poolobj = pool.install(create=True, meter=meter, build=build)
|
|
|
|
poolobj.setAutostart(True)
|
2019-06-17 09:12:39 +08:00
|
|
|
log.debug("Pool creation succeeded")
|
2019-05-05 02:37:56 +08:00
|
|
|
|
|
|
|
def _finish(self):
|
2019-05-05 03:03:36 +08:00
|
|
|
pool = self._build_xmlobj(check_xmleditor=True)
|
|
|
|
if not pool:
|
|
|
|
return
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
try:
|
2019-05-05 03:03:36 +08:00
|
|
|
if self._validate(pool) is False:
|
2019-05-05 02:37:56 +08:00
|
|
|
return
|
|
|
|
except Exception as e:
|
2019-05-05 03:03:36 +08:00
|
|
|
return self.err.show_err(
|
|
|
|
_("Error validating pool: %s") % e)
|
2019-05-05 02:37:56 +08:00
|
|
|
|
|
|
|
self.reset_finish_cursor()
|
|
|
|
|
|
|
|
build = self.widget("pool-build").get_active()
|
|
|
|
progWin = vmmAsyncJob(self._async_pool_create, [pool, build],
|
|
|
|
self._finish_cb, [pool],
|
|
|
|
_("Creating storage pool..."),
|
|
|
|
_("Creating the storage pool may take a "
|
|
|
|
"while..."),
|
|
|
|
self.topwin)
|
|
|
|
progWin.run()
|
|
|
|
|
|
|
|
|
|
|
|
################
|
|
|
|
# UI listeners #
|
|
|
|
################
|
|
|
|
|
2019-05-05 03:03:36 +08:00
|
|
|
def _xmleditor_xml_requested_cb(self, src):
|
|
|
|
xmlobj = self._build_xmlobj(check_xmleditor=False)
|
|
|
|
self._xmleditor.set_xml(xmlobj and xmlobj.get_xml() or "")
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
def _finish_clicked_cb(self, src):
|
|
|
|
self._finish()
|
|
|
|
|
|
|
|
def _pool_type_changed_cb(self, src):
|
|
|
|
self._show_options_by_pool()
|
|
|
|
|
|
|
|
def _browse_source_cb(self, src):
|
|
|
|
source = self.err.browse_local(self.conn,
|
|
|
|
_("Choose source path"),
|
|
|
|
dialog_type=Gtk.FileChooserAction.OPEN,
|
|
|
|
start_folder="/dev")
|
|
|
|
if source:
|
|
|
|
self.widget("pool-source-path").get_child().set_text(source)
|
|
|
|
|
|
|
|
def _browse_target_cb(self, src):
|
2019-06-11 20:23:59 +08:00
|
|
|
current = self.widget("pool-target-path").get_child().get_text()
|
|
|
|
startfolder = None
|
|
|
|
if current:
|
|
|
|
startfolder = os.path.dirname(current)
|
|
|
|
|
2019-05-05 02:37:56 +08:00
|
|
|
target = self.err.browse_local(self.conn,
|
|
|
|
_("Choose target directory"),
|
|
|
|
dialog_type=Gtk.FileChooserAction.SELECT_FOLDER,
|
|
|
|
start_folder=startfolder)
|
|
|
|
if target:
|
|
|
|
self.widget("pool-target-path").get_child().set_text(target)
|
|
|
|
|
|
|
|
def _hostname_changed_cb(self, src):
|
|
|
|
# If a hostname was entered, try to lookup valid pool sources.
|
|
|
|
self._populate_pool_sources()
|
|
|
|
|
|
|
|
def _iqn_toggled_cb(self, src):
|
|
|
|
self.widget("pool-iqn").set_sensitive(src.get_active())
|