[virt-tools-list] [PATCH v2] Virtuozzo hypervisor basic support
Mikhail Feoktistov
mfeoktistov at virtuozzo.com
Wed Feb 15 12:01:45 UTC 2017
This patch introduces virtuozzo hypervisor support.
Here we implemented only basic functionality.
User can create/start/stop/delete containers.
Also we allow to change hardware configuration (basic devices)
and connect via VNC. We are very intrested in the development of
virt-manager to support all virtuozzo features.
GUI changes:
Add virtuozzo hypervisor to connection list.
Add radio buttons for choosing VM or container virtualization type.
New wizzard window for setting template name for containers.
Creating guest:
We don't call createXML() for virtuozzo guests, because
virtuozzo driver in libvirt doesn't support transient domains.
Instead of this we call defineXML() and createDomain().
If we create container from template we generate XML which
contains only one storage device with type "template".
Virtuozzo hypervisor will create new container and filesystem for it.
After container was created we should not call the second
defineXML(final_xml) because it rewrites "devices" section in XML
and deletes container filesytem.
---
.../compare/virt-install-vz-ct-template.xml | 26 ++++
tests/clitest.py | 15 +++
tests/uitests/newvm.py | 23 ++++
tests/utils.py | 1 +
ui/create.ui | 149 ++++++++++++++++++++-
virtManager/addhardware.py | 2 +-
virtManager/connect.py | 8 +-
virtManager/connection.py | 1 +
virtManager/create.py | 58 +++++++-
virtinst/connection.py | 3 +
virtinst/guest.py | 22 ++-
virtinst/uri.py | 4 +-
12 files changed, 296 insertions(+), 16 deletions(-)
create mode 100644 tests/cli-test-xml/compare/virt-install-vz-ct-template.xml
diff --git a/tests/cli-test-xml/compare/virt-install-vz-ct-template.xml b/tests/cli-test-xml/compare/virt-install-vz-ct-template.xml
new file mode 100644
index 0000000..06fdc88
--- /dev/null
+++ b/tests/cli-test-xml/compare/virt-install-vz-ct-template.xml
@@ -0,0 +1,26 @@
+<domain type="vz">
+ <name>foobar</name>
+ <uuid>00000000-1111-2222-3333-444444444444</uuid>
+ <memory>65536</memory>
+ <currentMemory>65536</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch="x86_64">exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <filesystem type="template">
+ <source name="centos-7-x86_64"/>
+ <target dir="/"/>
+ </filesystem>
+ <interface type="network">
+ <source network="Bridged"/>
+ <mac address="00:11:22:33:44:55"/>
+ </interface>
+ <graphics type="vnc" port="-1" keymap="en-us"/>
+ <console type="pty"/>
+ </devices>
+</domain>
diff --git a/tests/clitest.py b/tests/clitest.py
index 7b4e259..ade1b81 100644
--- a/tests/clitest.py
+++ b/tests/clitest.py
@@ -81,6 +81,7 @@ test_files = {
'URI-KVM-S390X-KVMIBM' : utils.uri_kvm_s390x_KVMIBM,
'URI-XEN': utils.uri_xen,
'URI-LXC': utils.uri_lxc,
+ 'URI-VZ': utils.uri_vz,
'CLONE_DISK_XML' : "%s/clone-disk.xml" % xmldir,
'CLONE_STORAGE_XML' : "%s/clone-disk-managed.xml" % xmldir,
@@ -772,6 +773,20 @@ c.add_compare("--disk %(BLOCKVOL)s --cdrom %(EXISTIMG1)s --livecd --hvm", "xen-h
+#####################
+# VZ specific tests #
+#####################
+
+c = vinst.add_category("vz", "--connect %(URI-VZ)s --noautoconsole")
+c.add_compare(""" \
+--container \
+--filesystem type=template,source=centos-7-x86_64,target="/" \
+--network network="Bridged" \
+""", "vz-ct-template")
+
+
+
+
#####################################
# Device option back compat testing #
#####################################
diff --git a/tests/uitests/newvm.py b/tests/uitests/newvm.py
index 83b4d67..cebbdb9 100644
--- a/tests/uitests/newvm.py
+++ b/tests/uitests/newvm.py
@@ -285,6 +285,29 @@ class NewVM(unittest.TestCase):
self.assertFalse(newvm.showing)
self.app.quit()
+
+ def testNewVMContainerVZ(self):
+ """
+ Virtuozzo container install
+ """
+ self.app.uri = tests.utils.uri_vz
+
+ newvm = self._open_create_wizard()
+ uiutils.find_fuzzy(newvm, "Container", "radio").click()
+ uiutils.find_fuzzy(newvm, "Forward", "button").click()
+
+ # Set directory path
+ uiutils.find_fuzzy(newvm, None,
+ "text", "container template").text = "centos-6-x86_64"
+ uiutils.find_fuzzy(newvm, "Forward", "button").click()
+ uiutils.find_fuzzy(newvm, "Forward", "button").click()
+ uiutils.find_fuzzy(newvm, "Finish", "button").click()
+
+ uiutils.find_fuzzy(self.app.root, "container1 on", "frame")
+ self.assertFalse(newvm.showing)
+ self.app.quit()
+
+
def testNewXenPV(self):
"""
Test the create wizard with a fake xen PV install
diff --git a/tests/utils.py b/tests/utils.py
index 013b305..64dfee4 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -54,6 +54,7 @@ uri_kvm_s390x_KVMIBM = (_uri_kvm_domcaps + _capsprefix + "kvm-s390x-KVMIBM.xml")
uri_xen = uri_test + _capsprefix + "xen-rhel5.4.xml,xen"
uri_lxc = uri_test + _capsprefix + "lxc.xml,lxc"
+uri_vz = uri_test + _capsprefix + "vz.xml,vz"
def get_debug():
diff --git a/ui/create.ui b/ui/create.ui
index d271e0d..c197a97 100644
--- a/ui/create.ui
+++ b/ui/create.ui
@@ -143,6 +143,85 @@
<property name="vexpand">False</property>
<property name="row_spacing">12</property>
<child>
+ <object class="GtkVBox" id="vz-install-box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="label39">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Choose virtualization type</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">15</property>
+ <child>
+ <object class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkRadioButton" id="vz-virt-type-hvm">
+ <property name="label" translatable="yes">_Virtual machine</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_vz_virt_type_changed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="vz-virt-type-exe">
+ <property name="label" translatable="yes">_Container</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">vz-virt-type-hvm</property>
+ <signal name="toggled" handler="on_vz_virt_type_changed" swapped="no"/>
+ </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">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkVBox" id="virt-install-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -255,7 +334,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
@@ -334,7 +413,7 @@
</object>
<packing>
<property name="left_attach">0</property>
- <property name="top_attach">1</property>
+ <property name="top_attach">2</property>
</packing>
</child>
</object>
@@ -1620,6 +1699,72 @@ is not yet supported.</small></property>
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkVBox" id="vbox67">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label53">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Select _container template:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">install-container-template</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkEntry" id="install-container-template">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="label52">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">VZ templates</property>
+ </object>
+ <packing>
+ <property name="position">6</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">True</property>
diff --git a/virtManager/addhardware.py b/virtManager/addhardware.py
index e63ad3d..3ceb27c 100644
--- a/virtManager/addhardware.py
+++ b/virtManager/addhardware.py
@@ -551,7 +551,7 @@ class vmmAddHardware(vmmGObjectUI):
model.append([None, _("Hypervisor default")])
if vm.is_hvm():
mod_list = []
- if vm.get_hv_type() in ["kvm", "qemu", "test"]:
+ if vm.get_hv_type() in ["kvm", "qemu", "vz", "test"]:
mod_list.append("virtio")
mod_list.append("rtl8139")
mod_list.append("e1000")
diff --git a/virtManager/connect.py b/virtManager/connect.py
index 30add14..4cec8ca 100644
--- a/virtManager/connect.py
+++ b/virtManager/connect.py
@@ -34,7 +34,8 @@ from .baseclass import vmmGObjectUI
HV_XEN,
HV_LXC,
HV_QEMU_SESSION,
-HV_BHYVE) = range(5)
+HV_BHYVE,
+HV_VZ) = range(6)
(CONN_SSH,
CONN_TCP,
@@ -169,6 +170,7 @@ class vmmConnect(vmmGObjectUI):
_add_hv_row(HV_XEN, "xen", "Xen")
_add_hv_row(HV_LXC, "lxc", "LXC (" + _("Linux Containers") + ")")
_add_hv_row(HV_BHYVE, "bhyve", "Bhyve")
+ _add_hv_row(HV_VZ, "vz", "Virtuozzo")
combo.set_model(model)
uiutil.init_combo_text_column(combo, 1)
@@ -384,6 +386,8 @@ class vmmConnect(vmmGObjectUI):
hvstr = "qemu"
elif hv == HV_BHYVE:
hvstr = "bhyve"
+ elif hv == HV_VZ:
+ hvstr = "vz"
else:
hvstr = "lxc"
@@ -408,7 +412,7 @@ class vmmConnect(vmmGObjectUI):
hoststr += addrstr + "/"
uri = hvstr + hoststr
- if hv in (HV_QEMU, HV_BHYVE):
+ if hv in (HV_QEMU, HV_BHYVE, HV_VZ):
uri += "system"
elif hv == HV_QEMU_SESSION:
uri += "session"
diff --git a/virtManager/connection.py b/virtManager/connection.py
index 4997918..96c6a7b 100644
--- a/virtManager/connection.py
+++ b/virtManager/connection.py
@@ -348,6 +348,7 @@ class vmmConnection(vmmGObject):
is_container = property(lambda s: getattr(s, "_backend").is_container)
is_lxc = property(lambda s: getattr(s, "_backend").is_lxc)
is_openvz = property(lambda s: getattr(s, "_backend").is_openvz)
+ is_vz = property(lambda s: getattr(s, "_backend").is_vz)
is_xen = property(lambda s: getattr(s, "_backend").is_xen)
is_remote = property(lambda s: getattr(s, "_backend").is_remote)
is_qemu = property(lambda s: getattr(s, "_backend").is_qemu)
diff --git a/virtManager/create.py b/virtManager/create.py
index 7d53110..603dd7c 100644
--- a/virtManager/create.py
+++ b/virtManager/create.py
@@ -56,7 +56,8 @@ DEFAULT_MEM = 1024
INSTALL_PAGE_PXE,
INSTALL_PAGE_IMPORT,
INSTALL_PAGE_CONTAINER_APP,
- INSTALL_PAGE_CONTAINER_OS) = range(6)
+ INSTALL_PAGE_CONTAINER_OS,
+ INSTALL_PAGE_VZ_TEMPLATE) = range(7)
# Column numbers for os type/version list models
(OS_COL_ID,
@@ -156,6 +157,7 @@ class vmmCreate(vmmGObjectUI):
"on_arch_changed": self._arch_changed,
"on_virt_type_changed": self._virt_type_changed,
"on_machine_changed": self._machine_changed,
+ "on_vz_virt_type_changed": self._vz_virt_type_changed,
"on_install_cdrom_radio_toggled": self._local_media_toggled,
"on_install_iso_entry_changed": self._iso_changed,
@@ -375,6 +377,7 @@ class vmmCreate(vmmGObjectUI):
self.widget("create-conn").set_active(-1)
activeconn = self._populate_conn_list(urihint)
self.widget("arch-expander").set_expanded(False)
+ self.widget("vz-virt-type-hvm").set_active(True)
if self._set_conn(activeconn) is False:
return False
@@ -418,6 +421,9 @@ class vmmCreate(vmmGObjectUI):
# Install container OS
self.widget("install-oscontainer-fs").set_text("")
+ # Install VZ container from template
+ self.widget("install-container-template").set_text("centos-7-x86_64")
+
# Storage
self.widget("enable-storage").set_active(True)
self._addstorage.reset_state()
@@ -441,6 +447,7 @@ class vmmCreate(vmmGObjectUI):
can_storage = (is_local or is_storage_capable)
is_pv = (self._capsinfo.os_type == "xen")
is_container = self.conn.is_container()
+ is_vz = self.conn.is_vz()
can_remote_url = self.conn.get_backend().support_remote_url_install()
installable_arch = (self._capsinfo.arch in
@@ -522,6 +529,7 @@ class vmmCreate(vmmGObjectUI):
method_container_app.set_active(True)
self.widget("virt-install-box").set_visible(not is_container)
self.widget("container-install-box").set_visible(is_container)
+ self.widget("vz-install-box").set_visible(is_vz)
show_dtb = ("arm" in self._capsinfo.arch or
"microblaze" in self._capsinfo.arch or
@@ -585,6 +593,21 @@ class vmmCreate(vmmGObjectUI):
"are not loaded. Your virtual machines may perform poorly.")
self._show_startup_warning(error)
+ elif self.conn.is_vz():
+ has_hvm_guests = False
+ has_exe_guests = False
+ for g in self.conn.caps.guests:
+ if g.os_type == "hvm":
+ has_hvm_guests = True
+ if g.os_type == "exe":
+ has_exe_guests = True
+
+ self.widget("vz-virt-type-hvm").set_sensitive(has_hvm_guests)
+ self.widget("virt-install-box").set_sensitive(has_hvm_guests)
+ self.widget("vz-virt-type-exe").set_sensitive(has_exe_guests)
+ if not has_hvm_guests and has_exe_guests:
+ self.widget("vz-virt-type-exe").set_active(True)
+
# Install local
iso_option = self.widget("install-iso-radio")
cdrom_option = self.widget("install-cdrom-radio")
@@ -1073,6 +1096,8 @@ class vmmCreate(vmmGObjectUI):
install = _("Application container")
elif instmethod == INSTALL_PAGE_CONTAINER_OS:
install = _("Operating system container")
+ elif instmethod == INSTALL_PAGE_VZ_TEMPLATE:
+ install = _("Virtuozzo container")
osstr = ""
have_os = True
@@ -1109,6 +1134,9 @@ class vmmCreate(vmmGObjectUI):
check_visible=True)
def _get_config_install_page(self):
+ if self.widget("vz-install-box").get_visible():
+ if self.widget("vz-virt-type-exe").get_active():
+ return INSTALL_PAGE_VZ_TEMPLATE
if self.widget("virt-install-box").get_visible():
if self.widget("method-local").get_active():
return INSTALL_PAGE_ISO
@@ -1126,11 +1154,13 @@ class vmmCreate(vmmGObjectUI):
def _is_container_install(self):
return self._get_config_install_page() in [INSTALL_PAGE_CONTAINER_APP,
- INSTALL_PAGE_CONTAINER_OS]
+ INSTALL_PAGE_CONTAINER_OS,
+ INSTALL_PAGE_VZ_TEMPLATE]
def _should_skip_disk_page(self):
return self._get_config_install_page() in [INSTALL_PAGE_IMPORT,
INSTALL_PAGE_CONTAINER_APP,
- INSTALL_PAGE_CONTAINER_OS]
+ INSTALL_PAGE_CONTAINER_OS,
+ INSTALL_PAGE_VZ_TEMPLATE]
def _get_config_os_info(self):
drow = uiutil.get_list_selected_row(self.widget("install-os-type"))
@@ -1293,6 +1323,13 @@ class vmmCreate(vmmGObjectUI):
self._change_caps(self._capsinfo.os_type, self._capsinfo.arch, domtype)
+ def _vz_virt_type_changed(self, ignore):
+ is_hvm = self.widget("vz-virt-type-hvm").get_active()
+ self.widget("virt-install-box").set_sensitive(is_hvm)
+ if is_hvm:
+ self._change_caps("hvm")
+ else:
+ self._change_caps("exe")
# Install page listeners
def _detectable_media_widget_changed(self, widget, checkfocus=True):
@@ -1745,6 +1782,7 @@ class vmmCreate(vmmGObjectUI):
is_import = False
init = None
fs = None
+ template = None
distro, variant, valid, ignore1, ignore2 = self._get_config_os_info()
if not valid:
@@ -1802,6 +1840,12 @@ class vmmCreate(vmmGObjectUI):
if not fs:
return self.err.val_err(_("An OS directory path is required."))
+ elif instmethod == INSTALL_PAGE_VZ_TEMPLATE:
+ instclass = virtinst.ContainerInstaller
+ template = self.widget("install-container-template").get_text()
+ if not template:
+ return self.err.val_err(_("A template name is required."))
+
# Build the installer and Guest instance
try:
# Overwrite the guest
@@ -1832,6 +1876,14 @@ class vmmCreate(vmmGObjectUI):
fsdev.target = "/"
fsdev.source = fs
self._guest.add_device(fsdev)
+
+ if template:
+ fsdev = virtinst.VirtualFilesystem(self._guest.conn)
+ fsdev.target = "/"
+ fsdev.type = "template"
+ fsdev.source = template
+ self._guest.add_device(fsdev)
+
except Exception, e:
return self.err.val_err(
_("Error setting install media location."), e)
diff --git a/virtinst/connection.py b/virtinst/connection.py
index e8d2378..bdf1717 100644
--- a/virtinst/connection.py
+++ b/virtinst/connection.py
@@ -387,6 +387,9 @@ class VirtualConnection(object):
return self._uriobj.scheme.startswith("openvz")
def is_container(self):
return self.is_lxc() or self.is_openvz()
+ def is_vz(self):
+ return (self._uriobj.scheme.startswith("vz") or
+ self._uriobj.scheme.startswith("parallels"))
#########################
diff --git a/virtinst/guest.py b/virtinst/guest.py
index 7d3fb9d..9f6cbcf 100644
--- a/virtinst/guest.py
+++ b/virtinst/guest.py
@@ -358,6 +358,9 @@ class Guest(XMLBuilder):
# so use preserve
self.on_crash = "preserve"
+ if self.type == "vz":
+ self.on_crash = "destroy"
+
self._set_osxml_defaults()
self.bootloader = None
@@ -394,11 +397,16 @@ class Guest(XMLBuilder):
meter = util.ensure_meter(meter)
meter.start(size=None, text=meter_label)
- if doboot or transient or self.installer.has_install_phase():
- self.domain = self.conn.createXML(install_xml or final_xml, 0)
-
- if not transient:
+ if self.type == "vz":
self.domain = self.conn.defineXML(final_xml)
+ if doboot:
+ self.domain.create()
+ else:
+ if doboot or transient or self.installer.has_install_phase():
+ self.domain = self.conn.createXML(install_xml or final_xml, 0)
+
+ if not transient:
+ self.domain = self.conn.defineXML(final_xml)
meter.end(0)
try:
@@ -623,7 +631,7 @@ class Guest(XMLBuilder):
return
if self.get_devices("graphics"):
return
- if self.os.is_container():
+ if self.os.is_container() and not self.conn.is_vz():
return
if self.os.arch not in ["x86_64", "i686", "ppc64", "ppc64le", "ia64"]:
return
@@ -752,7 +760,7 @@ class Guest(XMLBuilder):
hyperv.present = True
def _set_emulator_defaults(self):
- if self.os.is_xenpv():
+ if self.os.is_xenpv() or self.type == "vz":
self.emulator = None
return
@@ -816,7 +824,7 @@ class Guest(XMLBuilder):
self.features.acpi = None
self.features.apic = None
self.features.pae = None
- if self._is_full_os_container():
+ if self._is_full_os_container() and self.type != "vz":
self.features.privnet = True
return
diff --git a/virtinst/uri.py b/virtinst/uri.py
index 3674726..2ea31d2 100644
--- a/virtinst/uri.py
+++ b/virtinst/uri.py
@@ -124,7 +124,7 @@ class MagicURI(object):
files in test/capabilities-xml/
* 'domcaps=%s': Points to a file with domain capabilities XML, that
will be returned in conn.getDomainCapabilities
- * qemu or xen or lxc: Fake the specified hypervisor
+ * qemu, xen, lxc or vz: Fake the specified hypervisor
See tests/utils.py for example URLs
"""
@@ -161,6 +161,8 @@ class MagicURI(object):
self.hv = "lxc"
if pop_bool("xen"):
self.hv = "xen"
+ if pop_bool("vz"):
+ self.hv = "vz"
self.conn_version = opts.pop("connver", None)
if self.conn_version:
--
2.5.5
More information about the virt-tools-list
mailing list