Add base conn object and bump minimum libvirt version to 0.6.0
This base connection object will be used to simplify the API in various places, reduce libvirt API calls, and better share code between virtinst and virt-manager. For now it just centralizes connection opening. This also exposed various places where our handling for older libvirt was busted, so raise our minimum host version to 0.6.0, the first version that supports threaded client requests.
This commit is contained in:
parent
35758d0fb7
commit
be2d9ddcb4
|
@ -15,7 +15,6 @@
|
||||||
# MA 02110-1301 USA.
|
# MA 02110-1301 USA.
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import libvirt
|
|
||||||
import virtinst
|
import virtinst
|
||||||
import virtinst.cli
|
import virtinst.cli
|
||||||
import virtinst.ImageParser
|
import virtinst.ImageParser
|
||||||
|
@ -32,8 +31,8 @@ qemuuri = "__virtinst_test__test:///default,caps=%s/tests/capabilities-xml/capab
|
||||||
class TestImageParser(unittest.TestCase):
|
class TestImageParser(unittest.TestCase):
|
||||||
|
|
||||||
basedir = "tests/image-xml/"
|
basedir = "tests/image-xml/"
|
||||||
conn = libvirt.open("test:///default")
|
conn = utils.open_testdefault()
|
||||||
qemuconn = virtinst.cli.open_test_uri(qemuuri)
|
qemuconn = virtinst.cli.getConnection(qemuuri)
|
||||||
caps = virtinst.CapabilitiesParser.parse(conn.getCapabilities())
|
caps = virtinst.CapabilitiesParser.parse(conn.getCapabilities())
|
||||||
qemucaps = virtinst.CapabilitiesParser.parse(qemuconn.getCapabilities())
|
qemucaps = virtinst.CapabilitiesParser.parse(qemuconn.getCapabilities())
|
||||||
|
|
||||||
|
@ -107,7 +106,7 @@ class TestImageParser(unittest.TestCase):
|
||||||
utils.reset_conn()
|
utils.reset_conn()
|
||||||
|
|
||||||
def testImage2XML(self):
|
def testImage2XML(self):
|
||||||
# Build libvirt XML from the image xml
|
# Build guest XML from the image xml
|
||||||
self._image2XMLhelper("image.xml", ["image-xenpv32.xml",
|
self._image2XMLhelper("image.xml", ["image-xenpv32.xml",
|
||||||
"image-xenfv32.xml"])
|
"image-xenfv32.xml"])
|
||||||
self._image2XMLhelper("image-kernel.xml", ["image-xenpv32-kernel.xml"])
|
self._image2XMLhelper("image-kernel.xml", ["image-xenpv32-kernel.xml"])
|
||||||
|
|
|
@ -19,9 +19,8 @@ import unittest
|
||||||
|
|
||||||
import virtinst.Storage
|
import virtinst.Storage
|
||||||
from virtinst.Storage import StoragePool, StorageVolume
|
from virtinst.Storage import StoragePool, StorageVolume
|
||||||
from tests import utils
|
|
||||||
|
|
||||||
import libvirt
|
from tests import utils
|
||||||
|
|
||||||
# pylint: disable=W0212
|
# pylint: disable=W0212
|
||||||
# Access to protected member, needed to unittest stuff
|
# Access to protected member, needed to unittest stuff
|
||||||
|
@ -134,7 +133,7 @@ def createVol(poolobj, volname=None, input_vol=None, clone_vol=None):
|
||||||
class TestStorage(unittest.TestCase):
|
class TestStorage(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.conn = libvirt.open("test:///default")
|
self.conn = utils.open_testdefault()
|
||||||
|
|
||||||
def testDirPool(self):
|
def testDirPool(self):
|
||||||
poolobj = createPool(self.conn, StoragePool.TYPE_DIR, "pool-dir")
|
poolobj = createPool(self.conn, StoragePool.TYPE_DIR, "pool-dir")
|
||||||
|
|
|
@ -32,7 +32,6 @@ from virtinst.OSDistro import SLDistro
|
||||||
from virtinst.OSDistro import UbuntuDistro
|
from virtinst.OSDistro import UbuntuDistro
|
||||||
from virtinst.OSDistro import MandrivaDistro
|
from virtinst.OSDistro import MandrivaDistro
|
||||||
|
|
||||||
import libvirt
|
|
||||||
import urlgrabber.progress
|
import urlgrabber.progress
|
||||||
|
|
||||||
# pylint: disable=W0212
|
# pylint: disable=W0212
|
||||||
|
@ -224,7 +223,7 @@ urls = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
testconn = libvirt.open("test:///default")
|
testconn = utils.open_testdefault()
|
||||||
testguest = virtinst.Guest(testconn, installer=virtinst.DistroInstaller())
|
testguest = virtinst.Guest(testconn, installer=virtinst.DistroInstaller())
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,10 @@ def _make_uri(base, connver=None, libver=None):
|
||||||
return base
|
return base
|
||||||
|
|
||||||
|
|
||||||
|
def open_testdefault():
|
||||||
|
return virtinst.cli.getConnection("test:///default")
|
||||||
|
|
||||||
|
|
||||||
def open_testdriver():
|
def open_testdriver():
|
||||||
return virtinst.cli.getConnection(_testuri)
|
return virtinst.cli.getConnection(_testuri)
|
||||||
|
|
||||||
|
|
|
@ -802,7 +802,7 @@ class TestXMLConfig(unittest.TestCase):
|
||||||
self._compare(g, "boot-many-devices", False)
|
self._compare(g, "boot-many-devices", False)
|
||||||
|
|
||||||
def testCpuset(self):
|
def testCpuset(self):
|
||||||
normaltest = libvirt.open("test:///default")
|
normaltest = utils.open_testdefault()
|
||||||
utils.set_conn(normaltest)
|
utils.set_conn(normaltest)
|
||||||
g = utils.get_basic_fullyvirt_guest()
|
g = utils.get_basic_fullyvirt_guest()
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,8 @@ GObject.threads_init()
|
||||||
|
|
||||||
def _show_startup_error(msg, details):
|
def _show_startup_error(msg, details):
|
||||||
if logging_setup:
|
if logging_setup:
|
||||||
logging.exception("Error starting virt-manager")
|
logging.debug("Error starting virt-manager: %s\n%s", msg, details,
|
||||||
|
exc_info=True)
|
||||||
from virtManager.error import vmmErrorDialog
|
from virtManager.error import vmmErrorDialog
|
||||||
err = vmmErrorDialog()
|
err = vmmErrorDialog()
|
||||||
title = _("Error starting Virtual Machine Manager")
|
title = _("Error starting Virtual Machine Manager")
|
||||||
|
@ -243,6 +244,12 @@ def main():
|
||||||
cliconfig.__version__,
|
cliconfig.__version__,
|
||||||
os.path.join(cliconfig.asset_dir, "ui"),
|
os.path.join(cliconfig.asset_dir, "ui"),
|
||||||
options.testfirstrun)
|
options.testfirstrun)
|
||||||
|
|
||||||
|
if not config.support_threading:
|
||||||
|
_show_startup_error(
|
||||||
|
_("virt-manager requires libvirt 0.6.0 or later."), "")
|
||||||
|
return
|
||||||
|
|
||||||
virtManager.util.running_config = config
|
virtManager.util.running_config = config
|
||||||
config.default_qemu_user = cliconfig.default_qemu_user
|
config.default_qemu_user = cliconfig.default_qemu_user
|
||||||
config.rhel6_defaults = cliconfig.rhel_enable_unsupported_opts
|
config.rhel6_defaults = cliconfig.rhel_enable_unsupported_opts
|
||||||
|
|
|
@ -408,7 +408,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
"pci")
|
"pci")
|
||||||
add_hw_option("Video", "video-display", PAGE_VIDEO,
|
add_hw_option("Video", "video-display", PAGE_VIDEO,
|
||||||
virtinst.support.check_conn_support(
|
virtinst.support.check_conn_support(
|
||||||
self.conn.vmm,
|
self.conn.get_backend(),
|
||||||
virtinst.support.SUPPORT_CONN_DOMAIN_VIDEO),
|
virtinst.support.SUPPORT_CONN_DOMAIN_VIDEO),
|
||||||
_("Libvirt version does not support video devices."))
|
_("Libvirt version does not support video devices."))
|
||||||
add_hw_option("Watchdog", "device_pci", PAGE_WATCHDOG,
|
add_hw_option("Watchdog", "device_pci", PAGE_WATCHDOG,
|
||||||
|
@ -416,7 +416,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
_("Not supported for this guest type."))
|
_("Not supported for this guest type."))
|
||||||
add_hw_option("Filesystem", Gtk.STOCK_DIRECTORY, PAGE_FILESYSTEM,
|
add_hw_option("Filesystem", Gtk.STOCK_DIRECTORY, PAGE_FILESYSTEM,
|
||||||
virtinst.support.check_conn_hv_support(
|
virtinst.support.check_conn_hv_support(
|
||||||
self.conn.vmm,
|
self.conn.get_backend(),
|
||||||
virtinst.support.SUPPORT_CONN_HV_FILESYSTEM,
|
virtinst.support.SUPPORT_CONN_HV_FILESYSTEM,
|
||||||
self.vm.get_hv_type()),
|
self.vm.get_hv_type()),
|
||||||
_("Not supported for this hypervisor/libvirt "
|
_("Not supported for this hypervisor/libvirt "
|
||||||
|
@ -1048,7 +1048,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
return
|
return
|
||||||
|
|
||||||
devtype = src.get_model()[src.get_active()][0]
|
devtype = src.get_model()[src.get_active()][0]
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
|
|
||||||
self._dev = VirtualTPMDevice.get_dev_instance(conn,
|
self._dev = VirtualTPMDevice.get_dev_instance(conn,
|
||||||
devtype)
|
devtype)
|
||||||
|
@ -1073,7 +1073,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
|
|
||||||
chartype = self.get_char_type()
|
chartype = self.get_char_type()
|
||||||
devtype = src.get_model()[src.get_active()][0]
|
devtype = src.get_model()[src.get_active()][0]
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
|
|
||||||
self._dev = VirtualCharDevice.get_dev_instance(conn,
|
self._dev = VirtualCharDevice.get_dev_instance(conn,
|
||||||
chartype,
|
chartype,
|
||||||
|
@ -1167,13 +1167,8 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
def do_file_allocate(asyncjob, disk):
|
def do_file_allocate(asyncjob, disk):
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
||||||
# If creating disk via storage API, we need to thread
|
|
||||||
# off a new connection
|
|
||||||
if disk.vol_install:
|
|
||||||
newconn = util.dup_lib_conn(disk.conn)
|
|
||||||
disk.conn = newconn
|
|
||||||
logging.debug("Starting background file allocate process")
|
logging.debug("Starting background file allocate process")
|
||||||
disk.setup_dev(self.conn.vmm, meter=meter)
|
disk.setup_dev(self.conn.get_backend(), meter=meter)
|
||||||
logging.debug("Allocation completed")
|
logging.debug("Allocation completed")
|
||||||
|
|
||||||
progWin = vmmAsyncJob(do_file_allocate,
|
progWin = vmmAsyncJob(do_file_allocate,
|
||||||
|
@ -1190,7 +1185,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
self._dev.creating_storage()):
|
self._dev.creating_storage()):
|
||||||
return self._storage_progress()
|
return self._storage_progress()
|
||||||
|
|
||||||
return self._dev.setup_dev(self.conn.vmm)
|
return self._dev.setup_dev(self.conn.get_backend())
|
||||||
|
|
||||||
def add_device(self):
|
def add_device(self):
|
||||||
ret = self.setup_device()
|
ret = self.setup_device()
|
||||||
|
@ -1282,6 +1277,8 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
cache = self.get_config_disk_cache()
|
cache = self.get_config_disk_cache()
|
||||||
fmt = self.get_config_disk_format()
|
fmt = self.get_config_disk_format()
|
||||||
controller_model = None
|
controller_model = None
|
||||||
|
conn = self.conn.get_backend()
|
||||||
|
|
||||||
if bus == "virtio-scsi":
|
if bus == "virtio-scsi":
|
||||||
bus = "scsi"
|
bus = "scsi"
|
||||||
controller_model = "virtio-scsi"
|
controller_model = "virtio-scsi"
|
||||||
|
@ -1309,11 +1306,9 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
ret = True
|
ret = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
do_exist = virtinst.VirtualDisk.path_exists(
|
do_exist = virtinst.VirtualDisk.path_exists(conn, ideal)
|
||||||
self.conn.vmm, ideal)
|
|
||||||
|
|
||||||
ret = virtinst.VirtualDisk.path_in_use_by(self.conn.vmm,
|
ret = virtinst.VirtualDisk.path_in_use_by(conn, ideal)
|
||||||
ideal)
|
|
||||||
except:
|
except:
|
||||||
logging.exception("Error checking default path usage")
|
logging.exception("Error checking default path usage")
|
||||||
|
|
||||||
|
@ -1326,7 +1321,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
if do_use:
|
if do_use:
|
||||||
diskpath = ideal
|
diskpath = ideal
|
||||||
|
|
||||||
disk = virtinst.VirtualDisk(conn=self.conn.vmm,
|
disk = virtinst.VirtualDisk(conn=conn,
|
||||||
path=diskpath,
|
path=diskpath,
|
||||||
size=disksize,
|
size=disksize,
|
||||||
sparse=sparse,
|
sparse=sparse,
|
||||||
|
@ -1369,7 +1364,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Disk collision
|
# Disk collision
|
||||||
if disk.is_conflict_disk(self.conn.vmm):
|
if disk.is_conflict_disk(conn):
|
||||||
res = self.err.yes_no(_('Disk "%s" is already in use by another '
|
res = self.err.yes_no(_('Disk "%s" is already in use by another '
|
||||||
'guest!' % disk.path),
|
'guest!' % disk.path),
|
||||||
_("Do you really want to use the disk?"))
|
_("Do you really want to use the disk?"))
|
||||||
|
@ -1383,7 +1378,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
disk.vmm_controller = None
|
disk.vmm_controller = None
|
||||||
if (controller_model == "virtio-scsi") and (bus == "scsi"):
|
if (controller_model == "virtio-scsi") and (bus == "scsi"):
|
||||||
controllers = self.vm.get_controller_devices()
|
controllers = self.vm.get_controller_devices()
|
||||||
controller = VirtualControllerSCSI(conn=self.conn.vmm)
|
controller = VirtualControllerSCSI(conn=conn)
|
||||||
controller.set_model(controller_model)
|
controller.set_model(controller_model)
|
||||||
disk.vmm_controller = controller
|
disk.vmm_controller = controller
|
||||||
for d in controllers:
|
for d in controllers:
|
||||||
|
@ -1423,7 +1418,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
|
|
||||||
def validate_page_input(self):
|
def validate_page_input(self):
|
||||||
ignore, inp_type, inp_bus = self.get_config_input()
|
ignore, inp_type, inp_bus = self.get_config_input()
|
||||||
dev = virtinst.VirtualInputDevice(self.conn.vmm)
|
dev = virtinst.VirtualInputDevice(self.conn.get_backend())
|
||||||
dev.type = inp_type
|
dev.type = inp_type
|
||||||
dev.bus = inp_bus
|
dev.bus = inp_bus
|
||||||
|
|
||||||
|
@ -1436,7 +1431,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
"sdl": virtinst.VirtualGraphics.TYPE_SDL}[graphics]
|
"sdl": virtinst.VirtualGraphics.TYPE_SDL}[graphics]
|
||||||
|
|
||||||
self._dev = virtinst.VirtualGraphics(type=_type,
|
self._dev = virtinst.VirtualGraphics(type=_type,
|
||||||
conn=self.conn.vmm)
|
conn=self.conn.get_backend())
|
||||||
try:
|
try:
|
||||||
self._dev.port = self.get_config_graphics_port()
|
self._dev.port = self.get_config_graphics_port()
|
||||||
self._dev.tlsPort = self.get_config_graphics_tls_port()
|
self._dev.tlsPort = self.get_config_graphics_tls_port()
|
||||||
|
@ -1449,7 +1444,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
def validate_page_sound(self):
|
def validate_page_sound(self):
|
||||||
smodel = self.get_config_sound_model()
|
smodel = self.get_config_sound_model()
|
||||||
try:
|
try:
|
||||||
self._dev = virtinst.VirtualAudio(conn=self.conn.vmm,
|
self._dev = virtinst.VirtualAudio(conn=self.conn.get_backend(),
|
||||||
model=smodel)
|
model=smodel)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
return self.err.val_err(_("Sound device parameter error"), e)
|
return self.err.val_err(_("Sound device parameter error"), e)
|
||||||
|
@ -1479,7 +1474,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._dev = virtinst.VirtualHostDevice.device_from_node(
|
self._dev = virtinst.VirtualHostDevice.device_from_node(
|
||||||
conn=self.conn.vmm,
|
conn=self.conn.get_backend(),
|
||||||
name=nodedev_name,
|
name=nodedev_name,
|
||||||
nodedev=nodedev,
|
nodedev=nodedev,
|
||||||
is_dup=is_dup)
|
is_dup=is_dup)
|
||||||
|
@ -1491,7 +1486,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
modebox = self.widget("char-mode")
|
modebox = self.widget("char-mode")
|
||||||
devbox = self.widget("char-device-type")
|
devbox = self.widget("char-device-type")
|
||||||
devtype = devbox.get_model()[devbox.get_active()][0]
|
devtype = devbox.get_model()[devbox.get_active()][0]
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
|
|
||||||
devclass = VirtualCharDevice.get_dev_instance(conn, chartype, devtype)
|
devclass = VirtualCharDevice.get_dev_instance(conn, chartype, devtype)
|
||||||
|
|
||||||
|
@ -1533,7 +1528,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
chartype.capitalize(), e)
|
chartype.capitalize(), e)
|
||||||
|
|
||||||
def validate_page_video(self):
|
def validate_page_video(self):
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
model = self.get_config_video_model()
|
model = self.get_config_video_model()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1543,7 +1538,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
return self.err.val_err(_("Video device parameter error"), e)
|
return self.err.val_err(_("Video device parameter error"), e)
|
||||||
|
|
||||||
def validate_page_watchdog(self):
|
def validate_page_watchdog(self):
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
model = self.get_config_watchdog_model()
|
model = self.get_config_watchdog_model()
|
||||||
action = self.get_config_watchdog_action()
|
action = self.get_config_watchdog_action()
|
||||||
|
|
||||||
|
@ -1555,7 +1550,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
return self.err.val_err(_("Watchdog parameter error"), e)
|
return self.err.val_err(_("Watchdog parameter error"), e)
|
||||||
|
|
||||||
def validate_page_filesystem(self):
|
def validate_page_filesystem(self):
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
source = self.widget("fs-source").get_text()
|
source = self.widget("fs-source").get_text()
|
||||||
target = self.widget("fs-target").get_text()
|
target = self.widget("fs-target").get_text()
|
||||||
mode = self.get_config_fs_mode()
|
mode = self.get_config_fs_mode()
|
||||||
|
@ -1600,7 +1595,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_page_smartcard(self):
|
def validate_page_smartcard(self):
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
mode = self.get_config_smartcard_mode()
|
mode = self.get_config_smartcard_mode()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -1609,7 +1604,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
return self.err.val_err(_("Smartcard device parameter error"), e)
|
return self.err.val_err(_("Smartcard device parameter error"), e)
|
||||||
|
|
||||||
def validate_page_usbredir(self):
|
def validate_page_usbredir(self):
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
stype = self.get_config_usbredir_type()
|
stype = self.get_config_usbredir_type()
|
||||||
host = self.get_config_usbredir_host()
|
host = self.get_config_usbredir_host()
|
||||||
service = self.get_config_usbredir_service()
|
service = self.get_config_usbredir_service()
|
||||||
|
@ -1625,7 +1620,7 @@ class vmmAddHardware(vmmGObjectUI):
|
||||||
str(e))
|
str(e))
|
||||||
|
|
||||||
def validate_page_tpm(self):
|
def validate_page_tpm(self):
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
typ = self.get_config_tpm_type()
|
typ = self.get_config_tpm_type()
|
||||||
|
|
||||||
device_path = self.widget("tpm-device-path").get_text()
|
device_path = self.widget("tpm-device-path").get_text()
|
||||||
|
|
|
@ -29,7 +29,6 @@ from gi.repository import Gdk
|
||||||
from virtManager.baseclass import vmmGObjectUI
|
from virtManager.baseclass import vmmGObjectUI
|
||||||
from virtManager.asyncjob import vmmAsyncJob
|
from virtManager.asyncjob import vmmAsyncJob
|
||||||
from virtManager.storagebrowse import vmmStorageBrowser
|
from virtManager.storagebrowse import vmmStorageBrowser
|
||||||
from virtManager import util
|
|
||||||
|
|
||||||
import virtinst
|
import virtinst
|
||||||
from virtinst import Cloner
|
from virtinst import Cloner
|
||||||
|
@ -73,7 +72,8 @@ def can_we_clone(conn, vol, path):
|
||||||
|
|
||||||
elif vol:
|
elif vol:
|
||||||
# Managed storage
|
# Managed storage
|
||||||
if not virtinst.Storage.is_create_vol_from_supported(conn.vmm):
|
if not virtinst.Storage.is_create_vol_from_supported(
|
||||||
|
conn.get_backend()):
|
||||||
if conn.is_remote() or not os.access(path, os.R_OK):
|
if conn.is_remote() or not os.access(path, os.R_OK):
|
||||||
msg = _("Connection does not support managed storage cloning.")
|
msg = _("Connection does not support managed storage cloning.")
|
||||||
else:
|
else:
|
||||||
|
@ -255,7 +255,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
self.clone_design = self.build_new_clone_design()
|
self.clone_design = self.build_new_clone_design()
|
||||||
|
|
||||||
def build_new_clone_design(self, new_name=None):
|
def build_new_clone_design(self, new_name=None):
|
||||||
design = Cloner(self.conn.vmm)
|
design = Cloner(self.conn.get_backend())
|
||||||
design.original_guest = self.orig_vm.get_name()
|
design.original_guest = self.orig_vm.get_name()
|
||||||
if not new_name:
|
if not new_name:
|
||||||
new_name = design.generate_clone_name()
|
new_name = design.generate_clone_name()
|
||||||
|
@ -302,9 +302,9 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
net_type = net.type
|
net_type = net.type
|
||||||
|
|
||||||
# Generate a new MAC
|
# Generate a new MAC
|
||||||
obj = VirtualNetworkInterface(conn=self.conn.vmm,
|
obj = VirtualNetworkInterface(conn=self.conn.get_backend(),
|
||||||
type=VirtualNetworkInterface.TYPE_USER)
|
type=VirtualNetworkInterface.TYPE_USER)
|
||||||
obj.setup(self.conn.vmm)
|
obj.setup(self.conn.get_backend())
|
||||||
newmac = obj.macaddr
|
newmac = obj.macaddr
|
||||||
|
|
||||||
|
|
||||||
|
@ -676,7 +676,7 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
row = self.net_list[orig]
|
row = self.net_list[orig]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
VirtualNetworkInterface(conn=self.conn.vmm,
|
VirtualNetworkInterface(conn=self.conn.get_backend(),
|
||||||
type=VirtualNetworkInterface.TYPE_USER,
|
type=VirtualNetworkInterface.TYPE_USER,
|
||||||
macaddr=new)
|
macaddr=new)
|
||||||
row[NETWORK_INFO_NEW_MAC] = new
|
row[NETWORK_INFO_NEW_MAC] = new
|
||||||
|
@ -819,20 +819,10 @@ class vmmCloneVM(vmmGObjectUI):
|
||||||
self.conn.tick(noStatsUpdate=True)
|
self.conn.tick(noStatsUpdate=True)
|
||||||
|
|
||||||
def _async_clone(self, asyncjob):
|
def _async_clone(self, asyncjob):
|
||||||
newconn = None
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.orig_vm.set_cloning(True)
|
self.orig_vm.set_cloning(True)
|
||||||
|
|
||||||
# Open a seperate connection to install on since this is async
|
|
||||||
logging.debug("Threading off connection to clone VM.")
|
|
||||||
newconn = util.dup_conn(self.conn).vmm
|
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
||||||
self.clone_design.orig_connection = newconn
|
|
||||||
for d in self.clone_design.clone_disks:
|
|
||||||
d.conn = newconn
|
|
||||||
|
|
||||||
self.clone_design.setup()
|
self.clone_design.setup()
|
||||||
self.clone_design.start_duplicate(meter)
|
self.clone_design.start_duplicate(meter)
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -88,12 +88,10 @@ class vmmConnection(vmmGObject):
|
||||||
self.connectThread = None
|
self.connectThread = None
|
||||||
self.connectError = None
|
self.connectError = None
|
||||||
self._ticklock = threading.Lock()
|
self._ticklock = threading.Lock()
|
||||||
self.vmm = None
|
self._backend = virtinst.VirtualConnection(self._uri)
|
||||||
|
|
||||||
self._caps = None
|
self._caps = None
|
||||||
self._caps_xml = None
|
self._caps_xml = None
|
||||||
self._is_virtinst_test_uri = virtinst.cli.is_virtinst_test_uri(
|
|
||||||
self._uri)
|
|
||||||
|
|
||||||
self.network_capable = None
|
self.network_capable = None
|
||||||
self._storage_capable = None
|
self._storage_capable = None
|
||||||
|
@ -129,6 +127,7 @@ class vmmConnection(vmmGObject):
|
||||||
self.mediadev_error = ""
|
self.mediadev_error = ""
|
||||||
self.mediadev_use_libvirt = False
|
self.mediadev_use_libvirt = False
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Init routines #
|
# Init routines #
|
||||||
#################
|
#################
|
||||||
|
@ -186,6 +185,8 @@ class vmmConnection(vmmGObject):
|
||||||
|
|
||||||
def get_uri(self):
|
def get_uri(self):
|
||||||
return self._uri
|
return self._uri
|
||||||
|
def get_backend(self):
|
||||||
|
return self._backend
|
||||||
|
|
||||||
def invalidate_caps(self):
|
def invalidate_caps(self):
|
||||||
self._caps_xml = None
|
self._caps_xml = None
|
||||||
|
@ -193,7 +194,7 @@ class vmmConnection(vmmGObject):
|
||||||
|
|
||||||
def _check_caps(self):
|
def _check_caps(self):
|
||||||
if not (self._caps_xml or self._caps):
|
if not (self._caps_xml or self._caps):
|
||||||
self._caps_xml = self.vmm.getCapabilities()
|
self._caps_xml = self._backend.getCapabilities()
|
||||||
self._caps = virtinst.CapabilitiesParser.parse(self._caps_xml)
|
self._caps = virtinst.CapabilitiesParser.parse(self._caps_xml)
|
||||||
|
|
||||||
def get_capabilities_xml(self):
|
def get_capabilities_xml(self):
|
||||||
|
@ -207,33 +208,33 @@ class vmmConnection(vmmGObject):
|
||||||
return self._caps
|
return self._caps
|
||||||
|
|
||||||
def get_max_vcpus(self, _type):
|
def get_max_vcpus(self, _type):
|
||||||
return virtinst.util.get_max_vcpus(self.vmm, _type)
|
return virtinst.util.get_max_vcpus(self._backend, _type)
|
||||||
|
|
||||||
def get_host_info(self):
|
def get_host_info(self):
|
||||||
return self.hostinfo
|
return self.hostinfo
|
||||||
|
|
||||||
def pretty_host_memory_size(self):
|
def pretty_host_memory_size(self):
|
||||||
if self.vmm is None:
|
if not self._backend.is_open():
|
||||||
return ""
|
return ""
|
||||||
return util.pretty_mem(self.host_memory_size())
|
return util.pretty_mem(self.host_memory_size())
|
||||||
|
|
||||||
def host_memory_size(self):
|
def host_memory_size(self):
|
||||||
if self.vmm is None:
|
if not self._backend.is_open():
|
||||||
return 0
|
return 0
|
||||||
return self.hostinfo[1] * 1024
|
return self.hostinfo[1] * 1024
|
||||||
|
|
||||||
def host_architecture(self):
|
def host_architecture(self):
|
||||||
if self.vmm is None:
|
if not self._backend.is_open():
|
||||||
return ""
|
return ""
|
||||||
return self.hostinfo[0]
|
return self.hostinfo[0]
|
||||||
|
|
||||||
def host_active_processor_count(self):
|
def host_active_processor_count(self):
|
||||||
if self.vmm is None:
|
if not self._backend.is_open():
|
||||||
return 0
|
return 0
|
||||||
return self.hostinfo[2]
|
return self.hostinfo[2]
|
||||||
|
|
||||||
def host_maximum_processor_count(self):
|
def host_maximum_processor_count(self):
|
||||||
if self.vmm is None:
|
if not self._backend.is_open():
|
||||||
return 0
|
return 0
|
||||||
return (self.hostinfo[4] * self.hostinfo[5] *
|
return (self.hostinfo[4] * self.hostinfo[5] *
|
||||||
self.hostinfo[6] * self.hostinfo[7])
|
self.hostinfo[6] * self.hostinfo[7])
|
||||||
|
@ -258,9 +259,9 @@ class vmmConnection(vmmGObject):
|
||||||
##########################
|
##########################
|
||||||
|
|
||||||
def get_qualified_hostname(self):
|
def get_qualified_hostname(self):
|
||||||
if virtinst.support.check_conn_support(self.vmm,
|
if virtinst.support.check_conn_support(self._backend,
|
||||||
virtinst.support.SUPPORT_CONN_GETHOSTNAME):
|
virtinst.support.SUPPORT_CONN_GETHOSTNAME):
|
||||||
return self.vmm.getHostname()
|
return self._backend.getHostname()
|
||||||
|
|
||||||
uri_hostname = self.get_uri_hostname()
|
uri_hostname = self.get_uri_hostname()
|
||||||
if self.is_remote() and uri_hostname.lower() != "localhost":
|
if self.is_remote() and uri_hostname.lower() != "localhost":
|
||||||
|
@ -299,7 +300,7 @@ class vmmConnection(vmmGObject):
|
||||||
return self.is_lxc() or self.is_openvz()
|
return self.is_lxc() or self.is_openvz()
|
||||||
|
|
||||||
def is_lxc(self):
|
def is_lxc(self):
|
||||||
if self._is_virtinst_test_uri:
|
if self._backend.is_virtinst_test_uri:
|
||||||
self.get_uri().count(",lxc")
|
self.get_uri().count(",lxc")
|
||||||
|
|
||||||
return uriutil.uri_split(self.get_uri())[0].startswith("lxc")
|
return uriutil.uri_split(self.get_uri())[0].startswith("lxc")
|
||||||
|
@ -308,14 +309,14 @@ class vmmConnection(vmmGObject):
|
||||||
return uriutil.uri_split(self.get_uri())[0].startswith("openvz")
|
return uriutil.uri_split(self.get_uri())[0].startswith("openvz")
|
||||||
|
|
||||||
def is_xen(self):
|
def is_xen(self):
|
||||||
if self._is_virtinst_test_uri:
|
if self._backend.is_virtinst_test_uri:
|
||||||
return self.get_uri().count(",xen")
|
return self.get_uri().count(",xen")
|
||||||
|
|
||||||
scheme = uriutil.uri_split(self.get_uri())[0]
|
scheme = uriutil.uri_split(self.get_uri())[0]
|
||||||
return scheme.startswith("xen")
|
return scheme.startswith("xen")
|
||||||
|
|
||||||
def is_qemu(self):
|
def is_qemu(self):
|
||||||
if self._is_virtinst_test_uri:
|
if self._backend.is_virtinst_test_uri:
|
||||||
return self.get_uri().count(",qemu")
|
return self.get_uri().count(",qemu")
|
||||||
|
|
||||||
scheme = uriutil.uri_split(self.get_uri())[0]
|
scheme = uriutil.uri_split(self.get_uri())[0]
|
||||||
|
@ -465,7 +466,7 @@ class vmmConnection(vmmGObject):
|
||||||
|
|
||||||
def is_storage_capable(self):
|
def is_storage_capable(self):
|
||||||
if self._storage_capable is None:
|
if self._storage_capable is None:
|
||||||
self._storage_capable = virtinst.util.is_storage_capable(self.vmm)
|
self._storage_capable = virtinst.util.is_storage_capable(self._backend)
|
||||||
if self._storage_capable is False:
|
if self._storage_capable is False:
|
||||||
logging.debug("Connection doesn't seem to support storage "
|
logging.debug("Connection doesn't seem to support storage "
|
||||||
"APIs. Skipping all storage polling.")
|
"APIs. Skipping all storage polling.")
|
||||||
|
@ -481,7 +482,7 @@ class vmmConnection(vmmGObject):
|
||||||
def is_network_capable(self):
|
def is_network_capable(self):
|
||||||
if self.network_capable is None:
|
if self.network_capable is None:
|
||||||
self.network_capable = virtinst.support.check_conn_support(
|
self.network_capable = virtinst.support.check_conn_support(
|
||||||
self.vmm,
|
self._backend,
|
||||||
virtinst.support.SUPPORT_CONN_NETWORK)
|
virtinst.support.SUPPORT_CONN_NETWORK)
|
||||||
if self.network_capable is False:
|
if self.network_capable is False:
|
||||||
logging.debug("Connection doesn't seem to support network "
|
logging.debug("Connection doesn't seem to support network "
|
||||||
|
@ -492,7 +493,7 @@ class vmmConnection(vmmGObject):
|
||||||
def is_interface_capable(self):
|
def is_interface_capable(self):
|
||||||
if self.interface_capable is None:
|
if self.interface_capable is None:
|
||||||
self.interface_capable = virtinst.support.check_conn_support(
|
self.interface_capable = virtinst.support.check_conn_support(
|
||||||
self.vmm,
|
self._backend,
|
||||||
virtinst.support.SUPPORT_CONN_INTERFACE)
|
virtinst.support.SUPPORT_CONN_INTERFACE)
|
||||||
if self.interface_capable is False:
|
if self.interface_capable is False:
|
||||||
logging.debug("Connection doesn't seem to support interface "
|
logging.debug("Connection doesn't seem to support interface "
|
||||||
|
@ -502,7 +503,7 @@ class vmmConnection(vmmGObject):
|
||||||
|
|
||||||
def is_nodedev_capable(self):
|
def is_nodedev_capable(self):
|
||||||
if self._nodedev_capable is None:
|
if self._nodedev_capable is None:
|
||||||
self._nodedev_capable = virtinst.NodeDeviceParser.is_nodedev_capable(self.vmm)
|
self._nodedev_capable = virtinst.NodeDeviceParser.is_nodedev_capable(self._backend)
|
||||||
return self._nodedev_capable
|
return self._nodedev_capable
|
||||||
|
|
||||||
def _get_flags_helper(self, obj, key, check_func):
|
def _get_flags_helper(self, obj, key, check_func):
|
||||||
|
@ -765,7 +766,7 @@ class vmmConnection(vmmGObject):
|
||||||
|
|
||||||
def create_network(self, xml, start=True, autostart=True):
|
def create_network(self, xml, start=True, autostart=True):
|
||||||
# Define network
|
# Define network
|
||||||
net = self.vmm.networkDefineXML(xml)
|
net = self._backend.networkDefineXML(xml)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if start:
|
if start:
|
||||||
|
@ -805,12 +806,12 @@ class vmmConnection(vmmGObject):
|
||||||
domainobj.change_name_backend(newobj)
|
domainobj.change_name_backend(newobj)
|
||||||
|
|
||||||
def define_domain(self, xml):
|
def define_domain(self, xml):
|
||||||
return self.vmm.defineXML(xml)
|
return self._backend.defineXML(xml)
|
||||||
def define_interface(self, xml):
|
def define_interface(self, xml):
|
||||||
self.vmm.interfaceDefineXML(xml, 0)
|
self._backend.interfaceDefineXML(xml, 0)
|
||||||
|
|
||||||
def restore(self, frm):
|
def restore(self, frm):
|
||||||
self.vmm.restore(frm)
|
self._backend.restore(frm)
|
||||||
try:
|
try:
|
||||||
# FIXME: This isn't correct in the remote case. Why do we even
|
# FIXME: This isn't correct in the remote case. Why do we even
|
||||||
# do this? Seems like we should provide an option for this
|
# do this? Seems like we should provide an option for this
|
||||||
|
@ -879,7 +880,7 @@ class vmmConnection(vmmGObject):
|
||||||
for dev in devs.values():
|
for dev in devs.values():
|
||||||
dev.cleanup()
|
dev.cleanup()
|
||||||
|
|
||||||
self.vmm = None
|
self._backend.close()
|
||||||
self.record = []
|
self.record = []
|
||||||
|
|
||||||
cleanup(self.nodedevs)
|
cleanup(self.nodedevs)
|
||||||
|
@ -909,15 +910,6 @@ class vmmConnection(vmmGObject):
|
||||||
self.close()
|
self.close()
|
||||||
self.connectError = None
|
self.connectError = None
|
||||||
|
|
||||||
def _open_dev_conn(self, uri):
|
|
||||||
"""
|
|
||||||
Allow using virtinsts connection hacking to fake capabilities
|
|
||||||
and other reproducible/testable behavior
|
|
||||||
"""
|
|
||||||
if not self._is_virtinst_test_uri:
|
|
||||||
return
|
|
||||||
return virtinst.cli.open_test_uri(uri)
|
|
||||||
|
|
||||||
def open(self, sync=False):
|
def open(self, sync=False):
|
||||||
if self.state != self.STATE_DISCONNECTED:
|
if self.state != self.STATE_DISCONNECTED:
|
||||||
return
|
return
|
||||||
|
@ -937,18 +929,8 @@ class vmmConnection(vmmGObject):
|
||||||
self.connectThread.setDaemon(True)
|
self.connectThread.setDaemon(True)
|
||||||
self.connectThread.start()
|
self.connectThread.start()
|
||||||
|
|
||||||
def _do_creds(self, creds, cbdata):
|
def _do_creds_password(self, creds):
|
||||||
"""
|
|
||||||
Generic libvirt openAuth callback
|
|
||||||
"""
|
|
||||||
ignore = cbdata
|
|
||||||
try:
|
try:
|
||||||
for cred in creds:
|
|
||||||
if cred[0] == libvirt.VIR_CRED_EXTERNAL:
|
|
||||||
logging.debug("Don't know how to handle external cred %s",
|
|
||||||
cred[2])
|
|
||||||
return -1
|
|
||||||
|
|
||||||
return connectauth.creds_dialog(creds)
|
return connectauth.creds_dialog(creds)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
# Detailed error message, in English so it can be Googled.
|
# Detailed error message, in English so it can be Googled.
|
||||||
|
@ -957,23 +939,6 @@ class vmmConnection(vmmGObject):
|
||||||
(self.get_uri(), str(e), "".join(traceback.format_exc())))
|
(self.get_uri(), str(e), "".join(traceback.format_exc())))
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def _try_open(self):
|
|
||||||
vmm = self._open_dev_conn(self.get_uri())
|
|
||||||
if vmm:
|
|
||||||
return vmm
|
|
||||||
|
|
||||||
if virtinst.support.support_openauth():
|
|
||||||
vmm = libvirt.openAuth(self.get_uri(),
|
|
||||||
[[libvirt.VIR_CRED_AUTHNAME,
|
|
||||||
libvirt.VIR_CRED_PASSPHRASE,
|
|
||||||
libvirt.VIR_CRED_EXTERNAL],
|
|
||||||
self._do_creds, None],
|
|
||||||
flags)
|
|
||||||
else:
|
|
||||||
vmm = libvirt.open(self.get_uri())
|
|
||||||
|
|
||||||
return vmm
|
|
||||||
|
|
||||||
def _open_thread(self):
|
def _open_thread(self):
|
||||||
logging.debug("Background 'open connection' thread is running")
|
logging.debug("Background 'open connection' thread is running")
|
||||||
|
|
||||||
|
@ -983,7 +948,7 @@ class vmmConnection(vmmGObject):
|
||||||
tb = None
|
tb = None
|
||||||
warnconsole = False
|
warnconsole = False
|
||||||
try:
|
try:
|
||||||
self.vmm = self._try_open()
|
self._backend.open(self._do_creds_password)
|
||||||
except libvirt.libvirtError, libexc:
|
except libvirt.libvirtError, libexc:
|
||||||
tb = "".join(traceback.format_exc())
|
tb = "".join(traceback.format_exc())
|
||||||
except Exception, exc:
|
except Exception, exc:
|
||||||
|
@ -1123,10 +1088,10 @@ class vmmConnection(vmmGObject):
|
||||||
def _update_nets(self):
|
def _update_nets(self):
|
||||||
orig = self.nets.copy()
|
orig = self.nets.copy()
|
||||||
name = "network"
|
name = "network"
|
||||||
active_list = self.vmm.listNetworks
|
active_list = self._backend.listNetworks
|
||||||
inactive_list = self.vmm.listDefinedNetworks
|
inactive_list = self._backend.listDefinedNetworks
|
||||||
check_support = self.is_network_capable
|
check_support = self.is_network_capable
|
||||||
lookup_func = self.vmm.networkLookupByName
|
lookup_func = self._backend.networkLookupByName
|
||||||
build_class = vmmNetwork
|
build_class = vmmNetwork
|
||||||
|
|
||||||
return self._poll_helper(orig, name, check_support,
|
return self._poll_helper(orig, name, check_support,
|
||||||
|
@ -1136,10 +1101,10 @@ class vmmConnection(vmmGObject):
|
||||||
def _update_pools(self):
|
def _update_pools(self):
|
||||||
orig = self.pools.copy()
|
orig = self.pools.copy()
|
||||||
name = "pool"
|
name = "pool"
|
||||||
active_list = self.vmm.listStoragePools
|
active_list = self._backend.listStoragePools
|
||||||
inactive_list = self.vmm.listDefinedStoragePools
|
inactive_list = self._backend.listDefinedStoragePools
|
||||||
check_support = self.is_storage_capable
|
check_support = self.is_storage_capable
|
||||||
lookup_func = self.vmm.storagePoolLookupByName
|
lookup_func = self._backend.storagePoolLookupByName
|
||||||
build_class = vmmStoragePool
|
build_class = vmmStoragePool
|
||||||
|
|
||||||
return self._poll_helper(orig, name, check_support,
|
return self._poll_helper(orig, name, check_support,
|
||||||
|
@ -1149,10 +1114,10 @@ class vmmConnection(vmmGObject):
|
||||||
def _update_interfaces(self):
|
def _update_interfaces(self):
|
||||||
orig = self.interfaces.copy()
|
orig = self.interfaces.copy()
|
||||||
name = "interface"
|
name = "interface"
|
||||||
active_list = self.vmm.listInterfaces
|
active_list = self._backend.listInterfaces
|
||||||
inactive_list = self.vmm.listDefinedInterfaces
|
inactive_list = self._backend.listDefinedInterfaces
|
||||||
check_support = self.is_interface_capable
|
check_support = self.is_interface_capable
|
||||||
lookup_func = self.vmm.interfaceLookupByName
|
lookup_func = self._backend.interfaceLookupByName
|
||||||
build_class = vmmInterface
|
build_class = vmmInterface
|
||||||
|
|
||||||
return self._poll_helper(orig, name, check_support,
|
return self._poll_helper(orig, name, check_support,
|
||||||
|
@ -1163,10 +1128,10 @@ class vmmConnection(vmmGObject):
|
||||||
def _update_nodedevs(self):
|
def _update_nodedevs(self):
|
||||||
orig = self.nodedevs.copy()
|
orig = self.nodedevs.copy()
|
||||||
name = "nodedev"
|
name = "nodedev"
|
||||||
active_list = lambda: self.vmm.listDevices(None, 0)
|
active_list = lambda: self._backend.listDevices(None, 0)
|
||||||
inactive_list = lambda: []
|
inactive_list = lambda: []
|
||||||
check_support = self.is_nodedev_capable
|
check_support = self.is_nodedev_capable
|
||||||
lookup_func = self.vmm.nodeDeviceLookupByName
|
lookup_func = self._backend.nodeDeviceLookupByName
|
||||||
build_class = (lambda conn, obj, key, ignore:
|
build_class = (lambda conn, obj, key, ignore:
|
||||||
vmmNodeDevice(conn, obj, key))
|
vmmNodeDevice(conn, obj, key))
|
||||||
|
|
||||||
|
@ -1196,12 +1161,12 @@ class vmmConnection(vmmGObject):
|
||||||
oldInactiveNames[vm.get_name()] = vm
|
oldInactiveNames[vm.get_name()] = vm
|
||||||
|
|
||||||
try:
|
try:
|
||||||
newActiveIDs = self.vmm.listDomainsID()
|
newActiveIDs = self._backend.listDomainsID()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logging.debug("Unable to list active domains: %s", e)
|
logging.debug("Unable to list active domains: %s", e)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
newInactiveNames = self.vmm.listDefinedDomains()
|
newInactiveNames = self._backend.listDefinedDomains()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logging.exception("Unable to list inactive domains: %s", e)
|
logging.exception("Unable to list inactive domains: %s", e)
|
||||||
|
|
||||||
|
@ -1234,7 +1199,7 @@ class vmmConnection(vmmGObject):
|
||||||
else:
|
else:
|
||||||
# Check if domain is brand new, or old one that changed state
|
# Check if domain is brand new, or old one that changed state
|
||||||
try:
|
try:
|
||||||
vm = self.vmm.lookupByID(_id)
|
vm = self._backend.lookupByID(_id)
|
||||||
uuid = util.uuidstr(vm.UUID())
|
uuid = util.uuidstr(vm.UUID())
|
||||||
|
|
||||||
check_new(vm, uuid)
|
check_new(vm, uuid)
|
||||||
|
@ -1250,7 +1215,7 @@ class vmmConnection(vmmGObject):
|
||||||
else:
|
else:
|
||||||
# Check if domain is brand new, or old one that changed state
|
# Check if domain is brand new, or old one that changed state
|
||||||
try:
|
try:
|
||||||
vm = self.vmm.lookupByName(name)
|
vm = self._backend.lookupByName(name)
|
||||||
uuid = util.uuidstr(vm.UUID())
|
uuid = util.uuidstr(vm.UUID())
|
||||||
|
|
||||||
check_new(vm, uuid)
|
check_new(vm, uuid)
|
||||||
|
@ -1271,7 +1236,7 @@ class vmmConnection(vmmGObject):
|
||||||
if self.state != self.STATE_ACTIVE:
|
if self.state != self.STATE_ACTIVE:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.hostinfo = self.vmm.getInfo()
|
self.hostinfo = self._backend.getInfo()
|
||||||
|
|
||||||
# Poll for new virtual network objects
|
# Poll for new virtual network objects
|
||||||
(startNets, stopNets, oldNets,
|
(startNets, stopNets, oldNets,
|
||||||
|
@ -1299,7 +1264,7 @@ class vmmConnection(vmmGObject):
|
||||||
app with long tick operations.
|
app with long tick operations.
|
||||||
"""
|
"""
|
||||||
# Connection closed out from under us
|
# Connection closed out from under us
|
||||||
if not self.vmm:
|
if not self._backend.is_open():
|
||||||
return
|
return
|
||||||
|
|
||||||
# Make sure device polling is setup
|
# Make sure device polling is setup
|
||||||
|
@ -1375,7 +1340,7 @@ class vmmConnection(vmmGObject):
|
||||||
(getattr(e, "get_error_code")() ==
|
(getattr(e, "get_error_code")() ==
|
||||||
libvirt.VIR_ERR_SYSTEM_ERROR)):
|
libvirt.VIR_ERR_SYSTEM_ERROR)):
|
||||||
# Try a simple getInfo call to see if conn was dropped
|
# Try a simple getInfo call to see if conn was dropped
|
||||||
self.vmm.getInfo()
|
self._backend.getInfo()
|
||||||
logging.debug("vm tick raised system error but "
|
logging.debug("vm tick raised system error but "
|
||||||
"connection doesn't seem to have dropped. "
|
"connection doesn't seem to have dropped. "
|
||||||
"Ignoring.")
|
"Ignoring.")
|
||||||
|
@ -1391,7 +1356,7 @@ class vmmConnection(vmmGObject):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def _recalculate_stats(self, now, vms):
|
def _recalculate_stats(self, now, vms):
|
||||||
if self.vmm is None:
|
if not self._backend.is_open():
|
||||||
return
|
return
|
||||||
|
|
||||||
expected = self.config.get_stats_history_length()
|
expected = self.config.get_stats_history_length()
|
||||||
|
|
|
@ -462,7 +462,8 @@ class vmmCreate(vmmGObjectUI):
|
||||||
can_storage = (is_local or is_storage_capable)
|
can_storage = (is_local or is_storage_capable)
|
||||||
is_pv = (self.capsguest.os_type == "xen")
|
is_pv = (self.capsguest.os_type == "xen")
|
||||||
is_container = self.conn.is_container()
|
is_container = self.conn.is_container()
|
||||||
can_remote_url = virtinst.support.check_stream_support(self.conn.vmm,
|
can_remote_url = virtinst.support.check_stream_support(
|
||||||
|
self.conn.get_backend(),
|
||||||
virtinst.support.SUPPORT_STREAM_UPLOAD)
|
virtinst.support.SUPPORT_STREAM_UPLOAD)
|
||||||
|
|
||||||
# Install Options
|
# Install Options
|
||||||
|
@ -823,12 +824,12 @@ class vmmCreate(vmmGObjectUI):
|
||||||
break
|
break
|
||||||
|
|
||||||
(newg, newdom) = virtinst.CapabilitiesParser.guest_lookup(
|
(newg, newdom) = virtinst.CapabilitiesParser.guest_lookup(
|
||||||
conn=self.conn.vmm,
|
conn=self.conn.get_backend(),
|
||||||
caps=self.caps,
|
caps=self.caps,
|
||||||
os_type=gtype,
|
os_type=gtype,
|
||||||
typ=dtype,
|
typ=dtype,
|
||||||
accelerated=True,
|
accelerated=True,
|
||||||
arch=arch)
|
arch=arch)
|
||||||
|
|
||||||
if (self.capsguest and self.capsdomain and
|
if (self.capsguest and self.capsdomain and
|
||||||
(newg.arch == self.capsguest.arch and
|
(newg.arch == self.capsguest.arch and
|
||||||
|
@ -1487,7 +1488,7 @@ class vmmCreate(vmmGObjectUI):
|
||||||
name = self.get_config_name()
|
name = self.get_config_name()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
g = virtinst.Guest(self.conn.vmm)
|
g = virtinst.Guest(self.conn.get_backend())
|
||||||
g.name = name
|
g.name = name
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
return self.err.val_err(_("Invalid System Name"), e)
|
return self.err.val_err(_("Invalid System Name"), e)
|
||||||
|
@ -1647,6 +1648,7 @@ class vmmCreate(vmmGObjectUI):
|
||||||
def validate_storage_page(self, oldguest=None):
|
def validate_storage_page(self, oldguest=None):
|
||||||
use_storage = self.widget("enable-storage").get_active()
|
use_storage = self.widget("enable-storage").get_active()
|
||||||
instcd = self.get_config_install_page() == INSTALL_PAGE_ISO
|
instcd = self.get_config_install_page() == INSTALL_PAGE_ISO
|
||||||
|
conn = self.conn.get_backend()
|
||||||
|
|
||||||
# CD/ISO install and no disks implies LiveCD
|
# CD/ISO install and no disks implies LiveCD
|
||||||
if instcd:
|
if instcd:
|
||||||
|
@ -1685,11 +1687,8 @@ class vmmCreate(vmmGObjectUI):
|
||||||
ret = True
|
ret = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
do_exist = virtinst.VirtualDisk.path_exists(
|
do_exist = virtinst.VirtualDisk.path_exists(conn, ideal)
|
||||||
self.conn.vmm, ideal)
|
ret = virtinst.VirtualDisk.path_in_use_by(conn, ideal)
|
||||||
|
|
||||||
ret = virtinst.VirtualDisk.path_in_use_by(self.conn.vmm,
|
|
||||||
ideal)
|
|
||||||
except:
|
except:
|
||||||
logging.exception("Error checking default path usage")
|
logging.exception("Error checking default path usage")
|
||||||
|
|
||||||
|
@ -1705,7 +1704,7 @@ class vmmCreate(vmmGObjectUI):
|
||||||
if not diskpath:
|
if not diskpath:
|
||||||
return self.err.val_err(_("A storage path must be specified."))
|
return self.err.val_err(_("A storage path must be specified."))
|
||||||
|
|
||||||
disk = virtinst.VirtualDisk(conn=self.conn.vmm,
|
disk = virtinst.VirtualDisk(conn=conn,
|
||||||
path=diskpath,
|
path=diskpath,
|
||||||
size=disksize,
|
size=disksize,
|
||||||
sparse=sparse)
|
sparse=sparse)
|
||||||
|
@ -1782,7 +1781,7 @@ class vmmCreate(vmmGObjectUI):
|
||||||
|
|
||||||
# Interesting methods
|
# Interesting methods
|
||||||
def build_installer(self, instclass):
|
def build_installer(self, instclass):
|
||||||
installer = instclass(conn=self.conn.vmm,
|
installer = instclass(conn=self.conn.get_backend(),
|
||||||
type=self.capsdomain.hypervisor_type,
|
type=self.capsdomain.hypervisor_type,
|
||||||
os_type=self.capsguest.os_type)
|
os_type=self.capsguest.os_type)
|
||||||
installer.arch = self.capsguest.arch
|
installer.arch = self.capsguest.arch
|
||||||
|
@ -1908,11 +1907,6 @@ class vmmCreate(vmmGObjectUI):
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
||||||
logging.debug("Starting background install process")
|
logging.debug("Starting background install process")
|
||||||
|
|
||||||
guest.conn = util.dup_conn(self.conn).vmm
|
|
||||||
for dev in guest.get_all_devices():
|
|
||||||
dev.conn = guest.conn
|
|
||||||
|
|
||||||
guest.start_install(False, meter=meter)
|
guest.start_install(False, meter=meter)
|
||||||
logging.debug("Install completed")
|
logging.debug("Install completed")
|
||||||
|
|
||||||
|
|
|
@ -559,9 +559,11 @@ class vmmCreateInterface(vmmGObjectUI):
|
||||||
|
|
||||||
name = _("No interface selected")
|
name = _("No interface selected")
|
||||||
if itype == Interface.Interface.INTERFACE_TYPE_BRIDGE:
|
if itype == Interface.Interface.INTERFACE_TYPE_BRIDGE:
|
||||||
name = Interface.Interface.find_free_name(self.conn.vmm, "br")
|
name = Interface.Interface.find_free_name(self.conn.get_backend(),
|
||||||
|
"br")
|
||||||
elif itype == Interface.Interface.INTERFACE_TYPE_BOND:
|
elif itype == Interface.Interface.INTERFACE_TYPE_BOND:
|
||||||
name = Interface.Interface.find_free_name(self.conn.vmm, "bond")
|
name = Interface.Interface.find_free_name(self.conn.get_backend(),
|
||||||
|
"bond")
|
||||||
else:
|
else:
|
||||||
ifaces = self.get_config_selected_interfaces()
|
ifaces = self.get_config_selected_interfaces()
|
||||||
if len(ifaces) > 0:
|
if len(ifaces) > 0:
|
||||||
|
@ -921,7 +923,7 @@ class vmmCreateInterface(vmmGObjectUI):
|
||||||
return self.err.val_err(_("An interface must be selected"))
|
return self.err.val_err(_("An interface must be selected"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
iobj = iclass(name, self.conn.vmm)
|
iobj = iclass(name, self.conn.get_backend())
|
||||||
iobj.start_mode = start
|
iobj.start_mode = start
|
||||||
check_conflict = False
|
check_conflict = False
|
||||||
|
|
||||||
|
@ -1128,8 +1130,5 @@ class vmmCreateInterface(vmmGObjectUI):
|
||||||
|
|
||||||
def do_install(self, asyncjob, activate):
|
def do_install(self, asyncjob, activate):
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
||||||
self.interface.conn = util.dup_conn(self.conn).vmm
|
|
||||||
|
|
||||||
self.interface.install(meter, create=activate)
|
self.interface.install(meter, create=activate)
|
||||||
logging.debug("Install completed")
|
logging.debug("Install completed")
|
||||||
|
|
|
@ -277,9 +277,10 @@ class vmmCreatePool(vmmGObjectUI):
|
||||||
|
|
||||||
plist = []
|
plist = []
|
||||||
try:
|
try:
|
||||||
plist = Storage.StoragePool.pool_list_from_sources(self.conn.vmm,
|
plist = Storage.StoragePool.pool_list_from_sources(
|
||||||
name, pool_type,
|
self.conn.get_backend(),
|
||||||
host=host)
|
name, pool_type,
|
||||||
|
host=host)
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Pool enumeration failed")
|
logging.exception("Pool enumeration failed")
|
||||||
|
|
||||||
|
@ -454,12 +455,7 @@ class vmmCreatePool(vmmGObjectUI):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def _async_pool_create(self, asyncjob, build):
|
def _async_pool_create(self, asyncjob, build):
|
||||||
newconn = None
|
|
||||||
|
|
||||||
# Open a seperate connection to install on since this is async
|
|
||||||
newconn = util.dup_lib_conn(self._pool.conn)
|
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
self._pool.conn = newconn
|
|
||||||
|
|
||||||
logging.debug("Starting backround pool creation.")
|
logging.debug("Starting backround pool creation.")
|
||||||
poolobj = self._pool.install(create=True, meter=meter, build=build)
|
poolobj = self._pool.install(create=True, meter=meter, build=build)
|
||||||
|
@ -501,7 +497,7 @@ class vmmCreatePool(vmmGObjectUI):
|
||||||
if page == PAGE_NAME:
|
if page == PAGE_NAME:
|
||||||
typ = self.get_config_type()
|
typ = self.get_config_type()
|
||||||
name = self.get_config_name()
|
name = self.get_config_name()
|
||||||
conn = self.conn.vmm
|
conn = self.conn.get_backend()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._pool_class = Storage.StoragePool.get_pool_class(typ)
|
self._pool_class = Storage.StoragePool.get_pool_class(typ)
|
||||||
|
|
|
@ -26,7 +26,6 @@ from gi.repository import Gtk
|
||||||
from gi.repository import Gdk
|
from gi.repository import Gdk
|
||||||
# pylint: enable=E0611
|
# pylint: enable=E0611
|
||||||
|
|
||||||
from virtManager import util
|
|
||||||
from virtManager.baseclass import vmmGObjectUI
|
from virtManager.baseclass import vmmGObjectUI
|
||||||
from virtManager.asyncjob import vmmAsyncJob
|
from virtManager.asyncjob import vmmAsyncJob
|
||||||
|
|
||||||
|
@ -250,10 +249,10 @@ class vmmCreateVolume(vmmGObjectUI):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def _async_vol_create(self, asyncjob):
|
def _async_vol_create(self, asyncjob):
|
||||||
newconn = util.dup_conn(self.conn).vmm
|
conn = self.conn.get_backend()
|
||||||
|
|
||||||
# Lookup different pool obj
|
# Lookup different pool obj
|
||||||
newpool = newconn.storagePoolLookupByName(self.parent_pool.get_name())
|
newpool = conn.storagePoolLookupByName(self.parent_pool.get_name())
|
||||||
self.vol.pool = newpool
|
self.vol.pool = newpool
|
||||||
|
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
|
@ -168,7 +168,6 @@ class vmmDeleteDialog(vmmGObjectUI):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def _async_delete(self, asyncjob, paths):
|
def _async_delete(self, asyncjob, paths):
|
||||||
newconn = None
|
|
||||||
storage_errors = []
|
storage_errors = []
|
||||||
details = ""
|
details = ""
|
||||||
|
|
||||||
|
@ -177,16 +176,14 @@ class vmmDeleteDialog(vmmGObjectUI):
|
||||||
logging.debug("Forcing VM '%s' power off.", self.vm.get_name())
|
logging.debug("Forcing VM '%s' power off.", self.vm.get_name())
|
||||||
self.vm.destroy()
|
self.vm.destroy()
|
||||||
|
|
||||||
# Open a seperate connection to install on since this is async
|
conn = self.conn.get_backend()
|
||||||
logging.debug("Threading off connection to delete vol.")
|
|
||||||
newconn = util.dup_conn(self.conn).vmm
|
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
||||||
for path in paths:
|
for path in paths:
|
||||||
try:
|
try:
|
||||||
logging.debug("Deleting path: %s", path)
|
logging.debug("Deleting path: %s", path)
|
||||||
meter.start(text=_("Deleting path '%s'") % path)
|
meter.start(text=_("Deleting path '%s'") % path)
|
||||||
self._async_delete_path(newconn, path, meter)
|
self._async_delete_path(conn, path, meter)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
storage_errors.append((str(e),
|
storage_errors.append((str(e),
|
||||||
"".join(traceback.format_exc())))
|
"".join(traceback.format_exc())))
|
||||||
|
@ -382,7 +379,7 @@ def do_we_default(conn, vm_name, vol, path, ro, shared):
|
||||||
info = append_str(info, _("Storage is marked as shareable."))
|
info = append_str(info, _("Storage is marked as shareable."))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
names = virtinst.VirtualDisk.path_in_use_by(conn.vmm, path)
|
names = virtinst.VirtualDisk.path_in_use_by(conn.get_backend(), path)
|
||||||
|
|
||||||
if len(names) > 1:
|
if len(names) > 1:
|
||||||
namestr = ""
|
namestr = ""
|
||||||
|
|
|
@ -1825,7 +1825,7 @@ class vmmDetails(vmmGObjectUI):
|
||||||
|
|
||||||
def generate_cpuset(self):
|
def generate_cpuset(self):
|
||||||
mem = int(self.vm.get_memory()) / 1024 / 1024
|
mem = int(self.vm.get_memory()) / 1024 / 1024
|
||||||
return virtinst.Guest.generate_cpuset(self.conn.vmm, mem)
|
return virtinst.Guest.generate_cpuset(self.conn.get_backend(), mem)
|
||||||
|
|
||||||
# VCPUS
|
# VCPUS
|
||||||
def config_get_vcpus(self):
|
def config_get_vcpus(self):
|
||||||
|
@ -1867,7 +1867,7 @@ class vmmDetails(vmmGObjectUI):
|
||||||
def config_cpu_copy_host(self, src_ignore):
|
def config_cpu_copy_host(self, src_ignore):
|
||||||
# Update UI with output copied from host
|
# Update UI with output copied from host
|
||||||
try:
|
try:
|
||||||
CPU = virtinst.CPU(self.vm.conn.vmm)
|
CPU = virtinst.CPU(self.vm.conn.get_backend())
|
||||||
CPU.copy_host_cpu()
|
CPU.copy_host_cpu()
|
||||||
|
|
||||||
self._refresh_cpu_config(CPU)
|
self._refresh_cpu_config(CPU)
|
||||||
|
@ -2202,7 +2202,8 @@ class vmmDetails(vmmGObjectUI):
|
||||||
try:
|
try:
|
||||||
new_text = new_text.strip()
|
new_text = new_text.strip()
|
||||||
vcpu_num = int(row[0])
|
vcpu_num = int(row[0])
|
||||||
pinlist = virtinst.Guest.cpuset_str_to_tuple(conn.vmm, new_text)
|
pinlist = virtinst.Guest.cpuset_str_to_tuple(
|
||||||
|
conn.get_backend(), new_text)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.err.val_err(_("Error building pin list"), e)
|
self.err.val_err(_("Error building pin list"), e)
|
||||||
return
|
return
|
||||||
|
@ -2223,7 +2224,8 @@ class vmmDetails(vmmGObjectUI):
|
||||||
if self.vm.vcpu_pinning() == cpuset:
|
if self.vm.vcpu_pinning() == cpuset:
|
||||||
return
|
return
|
||||||
|
|
||||||
pinlist = virtinst.Guest.cpuset_str_to_tuple(conn.vmm, cpuset)
|
pinlist = virtinst.Guest.cpuset_str_to_tuple(
|
||||||
|
conn.get_backend(), cpuset)
|
||||||
for row in vcpu_model:
|
for row in vcpu_model:
|
||||||
vcpu_num = row[0]
|
vcpu_num = row[0]
|
||||||
self.vm.pin_vcpu(int(vcpu_num), pinlist)
|
self.vm.pin_vcpu(int(vcpu_num), pinlist)
|
||||||
|
|
|
@ -407,7 +407,7 @@ class vmmDomain(vmmLibvirtObject):
|
||||||
return self._guest
|
return self._guest
|
||||||
|
|
||||||
def _build_guest(self, xml):
|
def _build_guest(self, xml):
|
||||||
return virtinst.Guest(self.conn.vmm,
|
return virtinst.Guest(self.conn.get_backend(),
|
||||||
parsexml=xml,
|
parsexml=xml,
|
||||||
caps=self.conn.get_capabilities())
|
caps=self.conn.get_capabilities())
|
||||||
|
|
||||||
|
@ -1289,13 +1289,14 @@ class vmmDomain(vmmLibvirtObject):
|
||||||
flags |= libvirt.VIR_MIGRATE_PEER2PEER
|
flags |= libvirt.VIR_MIGRATE_PEER2PEER
|
||||||
flags |= libvirt.VIR_MIGRATE_TUNNELLED
|
flags |= libvirt.VIR_MIGRATE_TUNNELLED
|
||||||
|
|
||||||
|
destconn = destconn.get_backend().libvirtconn
|
||||||
logging.debug("Migrating: conn=%s flags=%s dname=%s uri=%s rate=%s",
|
logging.debug("Migrating: conn=%s flags=%s dname=%s uri=%s rate=%s",
|
||||||
destconn.vmm, flags, newname, interface, rate)
|
destconn, flags, newname, interface, rate)
|
||||||
|
|
||||||
if meter:
|
if meter:
|
||||||
start_job_progress_thread(self, meter, _("Migrating domain"))
|
start_job_progress_thread(self, meter, _("Migrating domain"))
|
||||||
|
|
||||||
self._backend.migrate(destconn.vmm, flags, newname, interface, rate)
|
self._backend.migrate(destconn, flags, newname, interface, rate)
|
||||||
|
|
||||||
def define_cb():
|
def define_cb():
|
||||||
newxml = self.get_xml(inactive=True)
|
newxml = self.get_xml(inactive=True)
|
||||||
|
|
|
@ -796,8 +796,10 @@ class vmmEngine(vmmGObject):
|
||||||
if vm.getjobinfo_supported:
|
if vm.getjobinfo_supported:
|
||||||
_cancel_cb = (self._save_cancel, vm)
|
_cancel_cb = (self._save_cancel, vm)
|
||||||
|
|
||||||
progWin = vmmAsyncJob(self._save_callback,
|
def cb(asyncjob):
|
||||||
[vm, path],
|
vm.save(path, meter=asyncjob.get_meter())
|
||||||
|
|
||||||
|
progWin = vmmAsyncJob(cb, [],
|
||||||
_("Saving Virtual Machine"),
|
_("Saving Virtual Machine"),
|
||||||
_("Saving virtual machine memory to disk "),
|
_("Saving virtual machine memory to disk "),
|
||||||
src.topwin, cancel_cb=_cancel_cb)
|
src.topwin, cancel_cb=_cancel_cb)
|
||||||
|
@ -822,13 +824,6 @@ class vmmEngine(vmmGObject):
|
||||||
asyncjob.job_canceled = True
|
asyncjob.job_canceled = True
|
||||||
return
|
return
|
||||||
|
|
||||||
def _save_callback(self, asyncjob, vm, file_to_save):
|
|
||||||
conn = util.dup_conn(vm.conn)
|
|
||||||
newvm = conn.get_vm(vm.get_uuid())
|
|
||||||
meter = asyncjob.get_meter()
|
|
||||||
|
|
||||||
newvm.save(file_to_save, meter=meter)
|
|
||||||
|
|
||||||
def _do_restore_domain(self, src, uri):
|
def _do_restore_domain(self, src, uri):
|
||||||
conn = self._lookup_conn(uri)
|
conn = self._lookup_conn(uri)
|
||||||
if conn.is_remote():
|
if conn.is_remote():
|
||||||
|
@ -844,11 +839,7 @@ class vmmEngine(vmmGObject):
|
||||||
if not path:
|
if not path:
|
||||||
return
|
return
|
||||||
|
|
||||||
def cb():
|
vmmAsyncJob.simple_async_noshow(conn.restore, [path], src,
|
||||||
newconn = util.dup_conn(conn)
|
|
||||||
newconn.restore(path)
|
|
||||||
|
|
||||||
vmmAsyncJob.simple_async_noshow(cb, [], src,
|
|
||||||
_("Error restoring domain"))
|
_("Error restoring domain"))
|
||||||
|
|
||||||
def _do_destroy_domain(self, src, uri, uuid):
|
def _do_destroy_domain(self, src, uri, uuid):
|
||||||
|
|
|
@ -984,7 +984,8 @@ class vmmHost(vmmGObjectUI):
|
||||||
namestr = None
|
namestr = None
|
||||||
try:
|
try:
|
||||||
if path:
|
if path:
|
||||||
names = VirtualDisk.path_in_use_by(self.conn.vmm, path)
|
names = VirtualDisk.path_in_use_by(self.conn.get_backend(),
|
||||||
|
path)
|
||||||
namestr = ", ".join(names)
|
namestr = ", ".join(names)
|
||||||
if not namestr:
|
if not namestr:
|
||||||
namestr = None
|
namestr = None
|
||||||
|
|
|
@ -531,10 +531,10 @@ class vmmMigrateDialog(vmmGObjectUI):
|
||||||
secure, max_downtime):
|
secure, max_downtime):
|
||||||
meter = asyncjob.get_meter()
|
meter = asyncjob.get_meter()
|
||||||
|
|
||||||
srcconn = util.dup_conn(origvm.conn)
|
srcconn = origvm.conn
|
||||||
dstconn = util.dup_conn(origdconn)
|
dstconn = origdconn
|
||||||
|
|
||||||
vminst = srcconn.vmm.lookupByName(origvm.get_name())
|
vminst = srcconn.get_backend().lookupByName(origvm.get_name())
|
||||||
vm = vmmDomain(srcconn, vminst, vminst.UUID())
|
vm = vmmDomain(srcconn, vminst, vminst.UUID())
|
||||||
|
|
||||||
logging.debug("Migrating vm=%s from %s to %s", vm.get_name(),
|
logging.debug("Migrating vm=%s from %s to %s", vm.get_name(),
|
||||||
|
|
|
@ -59,7 +59,7 @@ class vmmNetwork(vmmLibvirtObject):
|
||||||
def _XMLDesc(self, flags):
|
def _XMLDesc(self, flags):
|
||||||
return self.net.XMLDesc(flags)
|
return self.net.XMLDesc(flags)
|
||||||
def _define(self, xml):
|
def _define(self, xml):
|
||||||
return self.conn.vmm.networkDefineXML(xml)
|
return self.conn.get_backend().networkDefineXML(xml)
|
||||||
|
|
||||||
def set_active(self, state):
|
def set_active(self, state):
|
||||||
self.active = state
|
self.active = state
|
||||||
|
|
|
@ -202,7 +202,8 @@ class LibvirtConsoleConnection(ConsoleConnection):
|
||||||
if not name:
|
if not name:
|
||||||
raise RuntimeError(_("Cannot open a device with no alias name"))
|
raise RuntimeError(_("Cannot open a device with no alias name"))
|
||||||
|
|
||||||
self.stream = self.conn.vmm.newStream(libvirt.VIR_STREAM_NONBLOCK)
|
self.stream = self.conn.get_backend().newStream(
|
||||||
|
libvirt.VIR_STREAM_NONBLOCK)
|
||||||
|
|
||||||
self.vm.open_console(name, self.stream)
|
self.vm.open_console(name, self.stream)
|
||||||
|
|
||||||
|
|
|
@ -340,7 +340,7 @@ class vmmStorageBrowser(vmmGObjectUI):
|
||||||
try:
|
try:
|
||||||
if path:
|
if path:
|
||||||
names = virtinst.VirtualDisk.path_in_use_by(
|
names = virtinst.VirtualDisk.path_in_use_by(
|
||||||
self.conn.vmm, path)
|
self.conn.get_backend(), path)
|
||||||
namestr = ", ".join(names)
|
namestr = ", ".join(names)
|
||||||
if not namestr:
|
if not namestr:
|
||||||
namestr = None
|
namestr = None
|
||||||
|
|
|
@ -52,7 +52,7 @@ class vmmStoragePool(vmmLibvirtObject):
|
||||||
def _XMLDesc(self, flags):
|
def _XMLDesc(self, flags):
|
||||||
return self.pool.XMLDesc(flags)
|
return self.pool.XMLDesc(flags)
|
||||||
def _define(self, xml):
|
def _define(self, xml):
|
||||||
return self.conn.vmm.storagePoolDefineXML(xml, 0)
|
return self.conn.get_backend().storagePoolDefineXML(xml, 0)
|
||||||
|
|
||||||
|
|
||||||
def set_active(self, state):
|
def set_active(self, state):
|
||||||
|
@ -91,7 +91,7 @@ class vmmStoragePool(vmmLibvirtObject):
|
||||||
return self.pool.autostart()
|
return self.pool.autostart()
|
||||||
|
|
||||||
def get_target_path(self):
|
def get_target_path(self):
|
||||||
return util.xpath(self.get_xml(), "/pool/target/path")
|
return util.xpath(self.get_xml(), "/pool/target/path") or ""
|
||||||
|
|
||||||
def get_allocation(self):
|
def get_allocation(self):
|
||||||
return long(util.xpath(self.get_xml(), "/pool/allocation"))
|
return long(util.xpath(self.get_xml(), "/pool/allocation"))
|
||||||
|
|
|
@ -164,7 +164,7 @@ def populate_video_combo(vm, video_dev, no_default=None):
|
||||||
if v.model_type == "qxl"])
|
if v.model_type == "qxl"])
|
||||||
|
|
||||||
video_dev_model.clear()
|
video_dev_model.clear()
|
||||||
tmpdev = virtinst.VirtualVideoDevice(vm.conn.vmm)
|
tmpdev = virtinst.VirtualVideoDevice(vm.conn.get_backend())
|
||||||
for m in tmpdev.model_types:
|
for m in tmpdev.model_types:
|
||||||
if not vm.rhel6_defaults():
|
if not vm.rhel6_defaults():
|
||||||
if m == "qxl" and not has_spice and not has_qxl:
|
if m == "qxl" and not has_spice and not has_qxl:
|
||||||
|
@ -641,7 +641,8 @@ def populate_network_list(net_list, conn, show_direct_interfaces=True):
|
||||||
bridge_name = name
|
bridge_name = name
|
||||||
brlabel = _("(Empty bridge)")
|
brlabel = _("(Empty bridge)")
|
||||||
else:
|
else:
|
||||||
if (show_direct_interfaces and virtinst.support.check_conn_support(conn.vmm,
|
if (show_direct_interfaces and
|
||||||
|
virtinst.support.check_conn_support(conn.get_backend(),
|
||||||
virtinst.support.SUPPORT_CONN_HV_DIRECT_INTERFACE)):
|
virtinst.support.SUPPORT_CONN_HV_DIRECT_INTERFACE)):
|
||||||
sensitive = True
|
sensitive = True
|
||||||
nettype = VirtualNetworkInterface.TYPE_DIRECT
|
nettype = VirtualNetworkInterface.TYPE_DIRECT
|
||||||
|
@ -713,7 +714,7 @@ def validate_network(parent, conn, nettype, devname, macaddr, model=None):
|
||||||
|
|
||||||
# Make sure VirtualNetwork is running
|
# Make sure VirtualNetwork is running
|
||||||
if (nettype == VirtualNetworkInterface.TYPE_VIRTUAL and
|
if (nettype == VirtualNetworkInterface.TYPE_VIRTUAL and
|
||||||
devname not in conn.vmm.listNetworks()):
|
devname not in conn.get_backend().listNetworks()):
|
||||||
|
|
||||||
res = err_dial.yes_no(_("Virtual Network is not active."),
|
res = err_dial.yes_no(_("Virtual Network is not active."),
|
||||||
_("Virtual Network '%s' is not active. "
|
_("Virtual Network '%s' is not active. "
|
||||||
|
@ -724,7 +725,7 @@ def validate_network(parent, conn, nettype, devname, macaddr, model=None):
|
||||||
|
|
||||||
# Try to start the network
|
# Try to start the network
|
||||||
try:
|
try:
|
||||||
virnet = conn.vmm.networkLookupByName(devname)
|
virnet = conn.get_backend().networkLookupByName(devname)
|
||||||
virnet.create()
|
virnet.create()
|
||||||
logging.info("Started network '%s'", devname)
|
logging.info("Started network '%s'", devname)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
@ -744,7 +745,7 @@ def validate_network(parent, conn, nettype, devname, macaddr, model=None):
|
||||||
elif nettype == VirtualNetworkInterface.TYPE_USER:
|
elif nettype == VirtualNetworkInterface.TYPE_USER:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
net = VirtualNetworkInterface(conn=conn.vmm,
|
net = VirtualNetworkInterface(conn=conn.get_backend(),
|
||||||
type=nettype,
|
type=nettype,
|
||||||
bridge=bridge,
|
bridge=bridge,
|
||||||
network=netname,
|
network=netname,
|
||||||
|
@ -759,7 +760,7 @@ def validate_network(parent, conn, nettype, devname, macaddr, model=None):
|
||||||
return err_dial.val_err(_("Error with network parameters."), e)
|
return err_dial.val_err(_("Error with network parameters."), e)
|
||||||
|
|
||||||
# Make sure there is no mac address collision
|
# Make sure there is no mac address collision
|
||||||
isfatal, errmsg = net.is_conflict_net(conn.vmm)
|
isfatal, errmsg = net.is_conflict_net(conn.get_backend())
|
||||||
if isfatal:
|
if isfatal:
|
||||||
return err_dial.val_err(_("Mac address collision."), errmsg)
|
return err_dial.val_err(_("Mac address collision."), errmsg)
|
||||||
elif errmsg is not None:
|
elif errmsg is not None:
|
||||||
|
@ -775,8 +776,8 @@ def validate_network(parent, conn, nettype, devname, macaddr, model=None):
|
||||||
def generate_macaddr(conn):
|
def generate_macaddr(conn):
|
||||||
newmac = ""
|
newmac = ""
|
||||||
try:
|
try:
|
||||||
net = VirtualNetworkInterface(conn=conn.vmm)
|
net = VirtualNetworkInterface(conn=conn.get_backend())
|
||||||
net.setup(conn.vmm)
|
net.setup(conn.get_backend())
|
||||||
newmac = net.macaddr
|
newmac = net.macaddr
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -983,7 +984,8 @@ def check_path_search_for_qemu(parent, conn, path):
|
||||||
user = util.running_config.default_qemu_user
|
user = util.running_config.default_qemu_user
|
||||||
|
|
||||||
skip_paths = util.running_config.get_perms_fix_ignore()
|
skip_paths = util.running_config.get_perms_fix_ignore()
|
||||||
broken_paths = VirtualDisk.check_path_search_for_user(conn.vmm, path, user)
|
broken_paths = VirtualDisk.check_path_search_for_user(conn.get_backend(),
|
||||||
|
path, user)
|
||||||
for p in broken_paths:
|
for p in broken_paths:
|
||||||
if p in skip_paths:
|
if p in skip_paths:
|
||||||
broken_paths.remove(p)
|
broken_paths.remove(p)
|
||||||
|
@ -1005,7 +1007,8 @@ def check_path_search_for_qemu(parent, conn, path):
|
||||||
return
|
return
|
||||||
|
|
||||||
logging.debug("Attempting to correct permission issues.")
|
logging.debug("Attempting to correct permission issues.")
|
||||||
errors = VirtualDisk.fix_path_search_for_user(conn.vmm, path, user)
|
errors = VirtualDisk.fix_path_search_for_user(conn.get_backend(),
|
||||||
|
path, user)
|
||||||
if not errors:
|
if not errors:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import libvirt
|
||||||
import logging
|
import logging
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
import virtManager
|
|
||||||
import virtinst
|
import virtinst
|
||||||
|
|
||||||
running_config = None
|
running_config = None
|
||||||
|
@ -46,7 +45,7 @@ def build_default_pool(vmmconn):
|
||||||
"""
|
"""
|
||||||
Helper to build the 'default' storage pool
|
Helper to build the 'default' storage pool
|
||||||
"""
|
"""
|
||||||
conn = vmmconn.vmm
|
conn = vmmconn.get_backend()
|
||||||
|
|
||||||
path = get_default_pool_path(vmmconn)
|
path = get_default_pool_path(vmmconn)
|
||||||
name = get_default_pool_name(vmmconn)
|
name = get_default_pool_name(vmmconn)
|
||||||
|
@ -255,44 +254,6 @@ def browse_local(parent, dialog_name, conn, start_folder=None,
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def dup_lib_conn(libconn):
|
|
||||||
conn = _dup_all_conn(None, libconn)
|
|
||||||
if isinstance(conn, virtManager.connection.vmmConnection):
|
|
||||||
return conn.vmm
|
|
||||||
return conn
|
|
||||||
|
|
||||||
|
|
||||||
def dup_conn(conn):
|
|
||||||
return _dup_all_conn(conn, None)
|
|
||||||
|
|
||||||
|
|
||||||
def _dup_all_conn(conn, libconn):
|
|
||||||
if libconn:
|
|
||||||
uri = libconn.getURI()
|
|
||||||
is_test = uri.startswith("test")
|
|
||||||
vmm = libconn
|
|
||||||
else:
|
|
||||||
is_test = conn.is_test_conn()
|
|
||||||
uri = conn.get_uri()
|
|
||||||
vmm = conn.vmm
|
|
||||||
|
|
||||||
if is_test:
|
|
||||||
# Skip duplicating a test conn, since it doesn't maintain state
|
|
||||||
# between instances
|
|
||||||
return conn or vmm
|
|
||||||
|
|
||||||
if running_config.support_threading:
|
|
||||||
# Libvirt 0.6.0 implemented client side request threading: this
|
|
||||||
# removes the need to actually duplicate the connection.
|
|
||||||
return conn or vmm
|
|
||||||
|
|
||||||
logging.debug("Duplicating connection for async operation.")
|
|
||||||
newconn = virtManager.connection.vmmConnection(uri)
|
|
||||||
newconn.open(sync=True)
|
|
||||||
|
|
||||||
return newconn
|
|
||||||
|
|
||||||
|
|
||||||
def pretty_hv(gtype, domtype):
|
def pretty_hv(gtype, domtype):
|
||||||
"""
|
"""
|
||||||
Convert XML <domain type='foo'> and <os><type>bar</type>
|
Convert XML <domain type='foo'> and <os><type>bar</type>
|
||||||
|
|
|
@ -712,8 +712,7 @@ def guest_lookup(conn, caps=None, os_type=None, arch=None, typ=None,
|
||||||
This function throws C{ValueError}s if any of the requested values are
|
This function throws C{ValueError}s if any of the requested values are
|
||||||
not found.
|
not found.
|
||||||
|
|
||||||
@param conn: virConnect instance
|
@param conn: libvirt connection
|
||||||
@type conn: libvirt.virConnect
|
|
||||||
@param caps: Optional L{Capabilities} instance (saves a lookup)
|
@param caps: Optional L{Capabilities} instance (saves a lookup)
|
||||||
@type caps: L{Capabilities}
|
@type caps: L{Capabilities}
|
||||||
@param typ: Virtualization type ('hvm', 'xen', ...)
|
@param typ: Virtualization type ('hvm', 'xen', ...)
|
||||||
|
|
|
@ -110,8 +110,6 @@ class Interface(object):
|
||||||
def _get_conn(self):
|
def _get_conn(self):
|
||||||
return self._conn
|
return self._conn
|
||||||
def _set_conn(self, val):
|
def _set_conn(self, val):
|
||||||
if not isinstance(val, libvirt.virConnect):
|
|
||||||
raise ValueError(_("'conn' must be a libvirt connection object."))
|
|
||||||
if not support.check_conn_support(val, support.SUPPORT_CONN_INTERFACE):
|
if not support.check_conn_support(val, support.SUPPORT_CONN_INTERFACE):
|
||||||
raise ValueError(_("Passed connection is not libvirt interface "
|
raise ValueError(_("Passed connection is not libvirt interface "
|
||||||
"capable"))
|
"capable"))
|
||||||
|
|
|
@ -401,7 +401,6 @@ def is_nodedev_capable(conn):
|
||||||
Check if the passed libvirt connection supports host device routines
|
Check if the passed libvirt connection supports host device routines
|
||||||
|
|
||||||
@param conn: Connection to check
|
@param conn: Connection to check
|
||||||
@type conn: libvirt.virConnect
|
|
||||||
|
|
||||||
@rtype: C{bool}
|
@rtype: C{bool}
|
||||||
"""
|
"""
|
||||||
|
@ -413,7 +412,6 @@ def is_pci_detach_capable(conn):
|
||||||
Check if the passed libvirt connection support pci device Detach/Reset
|
Check if the passed libvirt connection support pci device Detach/Reset
|
||||||
|
|
||||||
@param conn: Connection to check
|
@param conn: Connection to check
|
||||||
@type conn: libvirt.virConnect
|
|
||||||
|
|
||||||
@rtype: C{bool}
|
@rtype: C{bool}
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -148,8 +148,6 @@ class StorageObject(object):
|
||||||
def get_conn(self):
|
def get_conn(self):
|
||||||
return self._conn
|
return self._conn
|
||||||
def set_conn(self, val):
|
def set_conn(self, val):
|
||||||
if not isinstance(val, libvirt.virConnect):
|
|
||||||
raise ValueError(_("'conn' must be a libvirt connection object."))
|
|
||||||
if not util.is_storage_capable(val):
|
if not util.is_storage_capable(val):
|
||||||
raise ValueError(_("Passed connection is not libvirt storage "
|
raise ValueError(_("Passed connection is not libvirt storage "
|
||||||
"capable"))
|
"capable"))
|
||||||
|
@ -987,7 +985,7 @@ class StorageVolume(StorageObject):
|
||||||
"""
|
"""
|
||||||
@param name: Name for the new storage volume
|
@param name: Name for the new storage volume
|
||||||
@param capacity: Total size of the new volume (in bytes)
|
@param capacity: Total size of the new volume (in bytes)
|
||||||
@param conn: optional virConnect instance to lookup pool_name on
|
@param conn: optional connection instance to lookup pool_name on
|
||||||
@param pool_name: optional pool_name to install on
|
@param pool_name: optional pool_name to install on
|
||||||
@param pool: virStoragePool object to install on
|
@param pool: virStoragePool object to install on
|
||||||
@param allocation: amount of storage to actually allocate (default 0)
|
@param allocation: amount of storage to actually allocate (default 0)
|
||||||
|
|
|
@ -76,7 +76,6 @@ class VirtualDevice(XMLBuilderDomain):
|
||||||
Initialize device state
|
Initialize device state
|
||||||
|
|
||||||
@param conn: libvirt connection to validate device against
|
@param conn: libvirt connection to validate device against
|
||||||
@type conn: virConnect
|
|
||||||
"""
|
"""
|
||||||
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode,
|
XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode,
|
||||||
caps=caps)
|
caps=caps)
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
import copy
|
import copy
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import libvirt
|
|
||||||
import libxml2
|
import libxml2
|
||||||
|
|
||||||
from virtinst import CapabilitiesParser
|
from virtinst import CapabilitiesParser
|
||||||
|
@ -397,7 +396,7 @@ class XMLBuilderDomain(object):
|
||||||
Initialize state
|
Initialize state
|
||||||
|
|
||||||
@param conn: libvirt connection to validate device against
|
@param conn: libvirt connection to validate device against
|
||||||
@type conn: virConnect
|
@type conn: VirtualConnection
|
||||||
@param parsexml: Optional XML string to parse
|
@param parsexml: Optional XML string to parse
|
||||||
@type parsexml: C{str}
|
@type parsexml: C{str}
|
||||||
@param parsexmlnode: Option xpathNode to use
|
@param parsexmlnode: Option xpathNode to use
|
||||||
|
@ -453,8 +452,6 @@ class XMLBuilderDomain(object):
|
||||||
def get_conn(self):
|
def get_conn(self):
|
||||||
return self._conn
|
return self._conn
|
||||||
def set_conn(self, val):
|
def set_conn(self, val):
|
||||||
if not isinstance(val, libvirt.virConnect):
|
|
||||||
raise ValueError(_("'conn' must be a virConnect instance."))
|
|
||||||
self._conn = val
|
self._conn = val
|
||||||
self._conn_uri = self._conn.getURI()
|
self._conn_uri = self._conn.getURI()
|
||||||
self.__remote = uriutil.is_uri_remote(self._conn_uri, conn=self._conn)
|
self.__remote = uriutil.is_uri_remote(self._conn_uri, conn=self._conn)
|
||||||
|
|
|
@ -49,3 +49,4 @@ from virtinst.CloneManager import Cloner
|
||||||
from virtinst.Clock import Clock
|
from virtinst.Clock import Clock
|
||||||
from virtinst.CPU import CPU, CPUFeature
|
from virtinst.CPU import CPU, CPUFeature
|
||||||
from virtinst.Seclabel import Seclabel
|
from virtinst.Seclabel import Seclabel
|
||||||
|
from virtinst.connection import VirtualConnection
|
||||||
|
|
138
virtinst/cli.py
138
virtinst/cli.py
|
@ -25,10 +25,8 @@ import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import libvirt
|
import libvirt
|
||||||
|
@ -236,142 +234,15 @@ def setupLogging(appname, debug_stdout, do_quiet, cli_app=True):
|
||||||
# Libvirt connection helpers #
|
# Libvirt connection helpers #
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
_virtinst_uri_magic = "__virtinst_test__"
|
|
||||||
|
|
||||||
|
|
||||||
def is_virtinst_test_uri(uri):
|
|
||||||
return uri and uri.startswith(_virtinst_uri_magic)
|
|
||||||
|
|
||||||
|
|
||||||
def open_test_uri(uri):
|
|
||||||
"""
|
|
||||||
This hack allows us to fake various drivers via passing a magic
|
|
||||||
URI string to virt-*. Helps with testing
|
|
||||||
"""
|
|
||||||
uri = uri.replace(_virtinst_uri_magic, "")
|
|
||||||
ret = uri.split(",", 1)
|
|
||||||
uri = ret[0]
|
|
||||||
opts = parse_optstr(len(ret) > 1 and ret[1] or "")
|
|
||||||
|
|
||||||
conn = open_connection(uri)
|
|
||||||
|
|
||||||
def sanitize_xml(xml):
|
|
||||||
import difflib
|
|
||||||
|
|
||||||
orig = xml
|
|
||||||
xml = re.sub("arch='.*'", "arch='i686'", xml)
|
|
||||||
xml = re.sub("domain type='.*'", "domain type='test'", xml)
|
|
||||||
xml = re.sub("machine type='.*'", "", xml)
|
|
||||||
xml = re.sub(">exe<", ">hvm<", xml)
|
|
||||||
|
|
||||||
logging.debug("virtinst test sanitizing diff\n:%s",
|
|
||||||
"\n".join(difflib.unified_diff(orig.split("\n"),
|
|
||||||
xml.split("\n"))))
|
|
||||||
return xml
|
|
||||||
|
|
||||||
# Need tmpfile names to be deterministic
|
|
||||||
if "predictable" in opts:
|
|
||||||
setattr(conn, "_virtinst__fake_conn_predictable", True)
|
|
||||||
|
|
||||||
def fakemkstemp(prefix, *args, **kwargs):
|
|
||||||
ignore = args
|
|
||||||
ignore = kwargs
|
|
||||||
filename = os.path.join(".", prefix)
|
|
||||||
return os.open(filename, os.O_RDWR | os.O_CREAT), filename
|
|
||||||
tempfile.mkstemp = fakemkstemp
|
|
||||||
|
|
||||||
# Fake remote status
|
|
||||||
if "remote" in opts:
|
|
||||||
setattr(conn, "_virtinst__fake_conn_remote", True)
|
|
||||||
|
|
||||||
# Fake capabilities
|
|
||||||
if "caps" in opts:
|
|
||||||
capsxml = file(opts["caps"]).read()
|
|
||||||
conn.getCapabilities = lambda: capsxml
|
|
||||||
|
|
||||||
if ("qemu" in opts) or ("xen" in opts) or ("lxc" in opts):
|
|
||||||
conn.getVersion = lambda: 10000000000
|
|
||||||
|
|
||||||
origcreate = conn.createLinux
|
|
||||||
origdefine = conn.defineXML
|
|
||||||
def newcreate(xml, flags):
|
|
||||||
xml = sanitize_xml(xml)
|
|
||||||
return origcreate(xml, flags)
|
|
||||||
def newdefine(xml):
|
|
||||||
xml = sanitize_xml(xml)
|
|
||||||
return origdefine(xml)
|
|
||||||
conn.createLinux = newcreate
|
|
||||||
conn.defineXML = newdefine
|
|
||||||
|
|
||||||
if "qemu" in opts:
|
|
||||||
conn.getURI = lambda: "qemu+abc:///system"
|
|
||||||
if "xen" in opts:
|
|
||||||
conn.getURI = lambda: "xen+abc:///"
|
|
||||||
if "lxc" in opts:
|
|
||||||
conn.getURI = lambda: "lxc+abc:///"
|
|
||||||
|
|
||||||
# These need to come after the HV setter, since that sets a default
|
|
||||||
# conn version
|
|
||||||
if "connver" in opts:
|
|
||||||
ver = int(opts["connver"])
|
|
||||||
def newconnversion():
|
|
||||||
return ver
|
|
||||||
conn.getVersion = newconnversion
|
|
||||||
|
|
||||||
if "libver" in opts:
|
|
||||||
ver = int(opts["libver"])
|
|
||||||
def newlibversion(drv=None):
|
|
||||||
if drv:
|
|
||||||
return (ver, ver)
|
|
||||||
return ver
|
|
||||||
libvirt.getVersion = newlibversion
|
|
||||||
|
|
||||||
setattr(conn, "_virtinst__fake_conn", True)
|
|
||||||
|
|
||||||
return conn
|
|
||||||
|
|
||||||
|
|
||||||
def getConnection(uri):
|
def getConnection(uri):
|
||||||
# Hack to facilitate virtinst unit testing
|
|
||||||
if is_virtinst_test_uri(uri):
|
|
||||||
return open_test_uri(uri)
|
|
||||||
|
|
||||||
logging.debug("Requesting libvirt URI %s", (uri or "default"))
|
logging.debug("Requesting libvirt URI %s", (uri or "default"))
|
||||||
conn = open_connection(uri)
|
conn = virtinst.VirtualConnection(uri)
|
||||||
|
conn.open(_do_creds_authname)
|
||||||
logging.debug("Received libvirt URI %s", conn.getURI())
|
logging.debug("Received libvirt URI %s", conn.getURI())
|
||||||
|
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
|
||||||
def open_connection(uri):
|
|
||||||
open_flags = 0
|
|
||||||
valid_auth_options = [libvirt.VIR_CRED_AUTHNAME,
|
|
||||||
libvirt.VIR_CRED_PASSPHRASE,
|
|
||||||
libvirt.VIR_CRED_EXTERNAL]
|
|
||||||
authcb = do_creds
|
|
||||||
authcb_data = None
|
|
||||||
|
|
||||||
return libvirt.openAuth(uri, [valid_auth_options, authcb, authcb_data],
|
|
||||||
open_flags)
|
|
||||||
|
|
||||||
|
|
||||||
def do_creds(creds, cbdata):
|
|
||||||
try:
|
|
||||||
return _do_creds(creds, cbdata)
|
|
||||||
except:
|
|
||||||
logging.debug("Error in creds callback.", exc_info=True)
|
|
||||||
raise
|
|
||||||
|
|
||||||
|
|
||||||
def _do_creds(creds, cbdata_ignore):
|
|
||||||
for cred in creds:
|
|
||||||
if cred[0] == libvirt.VIR_CRED_EXTERNAL:
|
|
||||||
print_stderr("Don't know to do handle external cred %s" % cred[2])
|
|
||||||
return -1
|
|
||||||
|
|
||||||
return _do_creds_authname(creds)
|
|
||||||
|
|
||||||
|
|
||||||
# SASL username/pass auth
|
# SASL username/pass auth
|
||||||
def _do_creds_authname(creds):
|
def _do_creds_authname(creds):
|
||||||
retindex = 4
|
retindex = 4
|
||||||
|
@ -387,11 +258,10 @@ def _do_creds_authname(creds):
|
||||||
import getpass
|
import getpass
|
||||||
res = getpass.getpass(prompt)
|
res = getpass.getpass(prompt)
|
||||||
else:
|
else:
|
||||||
print_stderr("Unknown auth type in creds callback: %d" % credtype)
|
raise RuntimeError("Unknown auth type in creds callback: %d" %
|
||||||
return -1
|
credtype)
|
||||||
|
|
||||||
cred[retindex] = res
|
cred[retindex] = res
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
#
|
||||||
|
# Copyright 2013 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program 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 General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301 USA.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
import libvirt
|
||||||
|
|
||||||
|
from virtinst.cli import parse_optstr
|
||||||
|
|
||||||
|
_virtinst_uri_magic = "__virtinst_test__"
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualConnection(object):
|
||||||
|
"""
|
||||||
|
Wrapper for libvirt connection that provides various bits like
|
||||||
|
- caching static data
|
||||||
|
- lookup for API feature support
|
||||||
|
- simplified API wrappers that handle new and old ways of doing things
|
||||||
|
"""
|
||||||
|
def __init__(self, uri):
|
||||||
|
self._uri = uri
|
||||||
|
self._libvirtconn = None
|
||||||
|
|
||||||
|
self.is_virtinst_test_uri = uri and uri.startswith(_virtinst_uri_magic)
|
||||||
|
|
||||||
|
|
||||||
|
# Just proxy virConnect access for now
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
if attr in self.__dict__:
|
||||||
|
return self.__dict__[attr]
|
||||||
|
libvirtconn = self.__dict__.get("_libvirtconn")
|
||||||
|
return getattr(libvirtconn, attr)
|
||||||
|
|
||||||
|
|
||||||
|
##############
|
||||||
|
# Properties #
|
||||||
|
##############
|
||||||
|
|
||||||
|
uri = property(lambda self: getattr(self, "_uri"))
|
||||||
|
libvirtconn = property(lambda self: getattr(self, "_libvirtconn"))
|
||||||
|
|
||||||
|
|
||||||
|
##############
|
||||||
|
# Public API #
|
||||||
|
##############
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self._libvirtconn = None
|
||||||
|
|
||||||
|
def is_open(self):
|
||||||
|
return bool(self._libvirtconn)
|
||||||
|
|
||||||
|
def open(self, passwordcb):
|
||||||
|
open_flags = 0
|
||||||
|
valid_auth_options = [libvirt.VIR_CRED_AUTHNAME,
|
||||||
|
libvirt.VIR_CRED_PASSPHRASE]
|
||||||
|
authcb = self._auth_cb
|
||||||
|
authcb_data = passwordcb
|
||||||
|
|
||||||
|
testopts = []
|
||||||
|
uri = self.uri
|
||||||
|
if self.is_virtinst_test_uri:
|
||||||
|
uri = uri.replace(_virtinst_uri_magic, "")
|
||||||
|
ret = uri.split(",", 1)
|
||||||
|
uri = ret[0]
|
||||||
|
testopts = parse_optstr(len(ret) > 1 and ret[1] or "")
|
||||||
|
|
||||||
|
conn = libvirt.openAuth(uri,
|
||||||
|
[valid_auth_options, authcb,
|
||||||
|
(authcb_data, valid_auth_options)],
|
||||||
|
open_flags)
|
||||||
|
|
||||||
|
if testopts:
|
||||||
|
self._fixup_virtinst_test_uri(conn, testopts)
|
||||||
|
self._libvirtconn = conn
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###################
|
||||||
|
# Private helpers #
|
||||||
|
###################
|
||||||
|
|
||||||
|
def _auth_cb(self, creds, (passwordcb, passwordcreds)):
|
||||||
|
for cred in creds:
|
||||||
|
if cred[0] not in passwordcreds:
|
||||||
|
raise RuntimeError("Unknown cred type '%s', expected only "
|
||||||
|
"%s" % (cred[0], passwordcreds))
|
||||||
|
return passwordcb(creds)
|
||||||
|
|
||||||
|
def _fixup_virtinst_test_uri(self, conn, opts):
|
||||||
|
"""
|
||||||
|
This hack allows us to fake various drivers via passing a magic
|
||||||
|
URI string to virt-*. Helps with testing
|
||||||
|
"""
|
||||||
|
def sanitize_xml(xml):
|
||||||
|
import difflib
|
||||||
|
|
||||||
|
orig = xml
|
||||||
|
xml = re.sub("arch='.*'", "arch='i686'", xml)
|
||||||
|
xml = re.sub("domain type='.*'", "domain type='test'", xml)
|
||||||
|
xml = re.sub("machine type='.*'", "", xml)
|
||||||
|
xml = re.sub(">exe<", ">hvm<", xml)
|
||||||
|
|
||||||
|
logging.debug("virtinst test sanitizing diff\n:%s",
|
||||||
|
"\n".join(difflib.unified_diff(orig.split("\n"),
|
||||||
|
xml.split("\n"))))
|
||||||
|
return xml
|
||||||
|
|
||||||
|
# Need tmpfile names to be deterministic
|
||||||
|
if "predictable" in opts:
|
||||||
|
opts.pop("predictable")
|
||||||
|
import tempfile
|
||||||
|
setattr(self, "_virtinst__fake_conn_predictable", True)
|
||||||
|
|
||||||
|
def fakemkstemp(prefix, *args, **kwargs):
|
||||||
|
ignore = args
|
||||||
|
ignore = kwargs
|
||||||
|
filename = os.path.join(".", prefix)
|
||||||
|
return os.open(filename, os.O_RDWR | os.O_CREAT), filename
|
||||||
|
tempfile.mkstemp = fakemkstemp
|
||||||
|
|
||||||
|
# Fake remote status
|
||||||
|
if "remote" in opts:
|
||||||
|
opts.pop("remote")
|
||||||
|
setattr(self, "_virtinst__fake_conn_remote", True)
|
||||||
|
|
||||||
|
# Fake capabilities
|
||||||
|
if "caps" in opts:
|
||||||
|
capsxml = file(opts.pop("caps")).read()
|
||||||
|
conn.getCapabilities = lambda: capsxml
|
||||||
|
|
||||||
|
if ("qemu" in opts) or ("xen" in opts) or ("lxc" in opts):
|
||||||
|
conn.getVersion = lambda: 10000000000
|
||||||
|
|
||||||
|
origcreate = conn.createLinux
|
||||||
|
origdefine = conn.defineXML
|
||||||
|
def newcreate(xml, flags):
|
||||||
|
xml = sanitize_xml(xml)
|
||||||
|
return origcreate(xml, flags)
|
||||||
|
def newdefine(xml):
|
||||||
|
xml = sanitize_xml(xml)
|
||||||
|
return origdefine(xml)
|
||||||
|
conn.createLinux = newcreate
|
||||||
|
conn.defineXML = newdefine
|
||||||
|
|
||||||
|
if "qemu" in opts:
|
||||||
|
opts.pop("qemu")
|
||||||
|
conn.getURI = lambda: "qemu+abc:///system"
|
||||||
|
if "xen" in opts:
|
||||||
|
opts.pop("xen")
|
||||||
|
conn.getURI = lambda: "xen+abc:///"
|
||||||
|
if "lxc" in opts:
|
||||||
|
opts.pop("lxc")
|
||||||
|
conn.getURI = lambda: "lxc+abc:///"
|
||||||
|
|
||||||
|
# These need to come after the HV setter, since that sets a default
|
||||||
|
# conn version
|
||||||
|
if "connver" in opts:
|
||||||
|
ver = int(opts.pop("connver"))
|
||||||
|
def newconnversion():
|
||||||
|
return ver
|
||||||
|
conn.getVersion = newconnversion
|
||||||
|
|
||||||
|
if "libver" in opts:
|
||||||
|
ver = int(opts.pop("libver"))
|
||||||
|
def newlibversion(drv=None):
|
||||||
|
if drv:
|
||||||
|
return (ver, ver)
|
||||||
|
return ver
|
||||||
|
libvirt.getVersion = newlibversion
|
||||||
|
|
||||||
|
if opts:
|
||||||
|
raise RuntimeError("Unhandled virtinst test uri options %s" % opts)
|
||||||
|
|
||||||
|
setattr(self, "_virtinst__fake_conn", True)
|
|
@ -428,7 +428,6 @@ def _check_support(conn, feature, data=None):
|
||||||
the passed connection.
|
the passed connection.
|
||||||
|
|
||||||
@param conn: Libvirt connection to check feature on
|
@param conn: Libvirt connection to check feature on
|
||||||
@type conn: virConnect
|
|
||||||
@param feature: Feature type to check support for
|
@param feature: Feature type to check support for
|
||||||
@type feature: One of the SUPPORT_* flags
|
@type feature: One of the SUPPORT_* flags
|
||||||
@param data: Option libvirt object to use in feature checking
|
@param data: Option libvirt object to use in feature checking
|
||||||
|
@ -437,12 +436,15 @@ def _check_support(conn, feature, data=None):
|
||||||
|
|
||||||
@returns: True if feature is supported, False otherwise
|
@returns: True if feature is supported, False otherwise
|
||||||
"""
|
"""
|
||||||
|
# Temporary hack to make this work
|
||||||
|
if "VirtualConnection" in repr(conn):
|
||||||
|
conn = getattr(conn, "_libvirtconn")
|
||||||
|
if "VirtualConnection" in repr(data):
|
||||||
|
data = getattr(data, "_libvirtconn")
|
||||||
|
|
||||||
support_info = _support_dict[feature]
|
support_info = _support_dict[feature]
|
||||||
key_list = support_info.keys()
|
key_list = support_info.keys()
|
||||||
|
|
||||||
if not isinstance(conn, libvirt.virConnect):
|
|
||||||
raise ValueError(_("'conn' must be a virConnect instance."))
|
|
||||||
|
|
||||||
def get_value(key):
|
def get_value(key):
|
||||||
if key in key_list:
|
if key in key_list:
|
||||||
key_list.remove(key)
|
key_list.remove(key)
|
||||||
|
@ -502,8 +504,9 @@ def _check_support(conn, feature, data=None):
|
||||||
if object_name:
|
if object_name:
|
||||||
classobj = _get_command(object_name)
|
classobj = _get_command(object_name)
|
||||||
if not isinstance(data, classobj):
|
if not isinstance(data, classobj):
|
||||||
raise ValueError("Passed obj with args must be of type " +
|
raise ValueError(
|
||||||
str(classobj))
|
"Passed obj %s with args must be of type %s, was %s" %
|
||||||
|
(data, str(classobj), type(data)))
|
||||||
|
|
||||||
cmd = _get_command(function_name, obj=data)
|
cmd = _get_command(function_name, obj=data)
|
||||||
|
|
||||||
|
@ -604,10 +607,6 @@ def support_threading():
|
||||||
return bool(_local_lib_ver() >= 6000)
|
return bool(_local_lib_ver() >= 6000)
|
||||||
|
|
||||||
|
|
||||||
def support_openauth():
|
|
||||||
return bool(_local_lib_ver() >= 4000)
|
|
||||||
|
|
||||||
|
|
||||||
def check_conn_support(conn, feature):
|
def check_conn_support(conn, feature):
|
||||||
return _check_support(conn, feature, conn)
|
return _check_support(conn, feature, conn)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue