Create permanent libvirt domain objects
Do not recreate them at each startup. This will save some time and also solve some problems from invalidated libvirt handles after domain shutdown (e.g. causes qubes-manager crashes). This requires storing uuid in qubes.xml.
This commit is contained in:
parent
1fda0502ab
commit
550d8cac68
@ -98,6 +98,7 @@ class QubesVm(object):
|
|||||||
# __qid cannot be accessed by setattr, so must be set manually in __init__
|
# __qid cannot be accessed by setattr, so must be set manually in __init__
|
||||||
"qid": { "attr": "_qid", "order": 0 },
|
"qid": { "attr": "_qid", "order": 0 },
|
||||||
"name": { "order": 1 },
|
"name": { "order": 1 },
|
||||||
|
"uuid": { "order": 0, "eval": 'uuid.UUID(value) if value else None' },
|
||||||
"dir_path": { "default": None, "order": 2 },
|
"dir_path": { "default": None, "order": 2 },
|
||||||
"conf_file": {
|
"conf_file": {
|
||||||
"func": lambda value: self.absolute_path(value, self.name +
|
"func": lambda value: self.absolute_path(value, self.name +
|
||||||
@ -186,7 +187,8 @@ class QubesVm(object):
|
|||||||
|
|
||||||
### Mark attrs for XML inclusion
|
### Mark attrs for XML inclusion
|
||||||
# Simple string attrs
|
# Simple string attrs
|
||||||
for prop in ['qid', 'name', 'dir_path', 'memory', 'maxmem', 'pcidevs', 'vcpus', 'internal',\
|
for prop in ['qid', 'uuid', 'name', 'dir_path', 'memory', 'maxmem',
|
||||||
|
'pcidevs', 'vcpus', 'internal',\
|
||||||
'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\
|
'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\
|
||||||
'kernelopts', 'services', 'installed_by_rpm',\
|
'kernelopts', 'services', 'installed_by_rpm',\
|
||||||
'uses_default_netvm', 'include_in_backups', 'debug',\
|
'uses_default_netvm', 'include_in_backups', 'debug',\
|
||||||
@ -200,6 +202,7 @@ class QubesVm(object):
|
|||||||
attrs[prop]['save_skip'] = \
|
attrs[prop]['save_skip'] = \
|
||||||
lambda prop=prop: getattr(self, prop) is None
|
lambda prop=prop: getattr(self, prop) is None
|
||||||
|
|
||||||
|
attrs['uuid']['save_skip'] = lambda: self.uuid is None
|
||||||
attrs['mac']['save'] = lambda: str(self._mac)
|
attrs['mac']['save'] = lambda: str(self._mac)
|
||||||
attrs['mac']['save_skip'] = lambda: self._mac is None
|
attrs['mac']['save_skip'] = lambda: self._mac is None
|
||||||
|
|
||||||
@ -333,8 +336,6 @@ class QubesVm(object):
|
|||||||
else:
|
else:
|
||||||
assert self.root_img is not None, "Missing root_img for standalone VM!"
|
assert self.root_img is not None, "Missing root_img for standalone VM!"
|
||||||
|
|
||||||
self.xid = self.get_xid()
|
|
||||||
|
|
||||||
# fire hooks
|
# fire hooks
|
||||||
for hook in self.hooks_init:
|
for hook in self.hooks_init:
|
||||||
hook(self)
|
hook(self)
|
||||||
@ -423,7 +424,7 @@ class QubesVm(object):
|
|||||||
|
|
||||||
if self.is_running():
|
if self.is_running():
|
||||||
# refresh IP, DNS etc
|
# refresh IP, DNS etc
|
||||||
self.create_xenstore_entries(self.get_xid())
|
self.create_xenstore_entries(self.xid)
|
||||||
self.attach_network()
|
self.attach_network()
|
||||||
if hasattr(self.netvm, 'post_vm_net_attach'):
|
if hasattr(self.netvm, 'post_vm_net_attach'):
|
||||||
self.netvm.post_vm_net_attach(self)
|
self.netvm.post_vm_net_attach(self)
|
||||||
@ -542,6 +543,7 @@ class QubesVm(object):
|
|||||||
raise QubesException("Cannot rename VM installed by RPM -- first clone VM and then use yum to remove package.")
|
raise QubesException("Cannot rename VM installed by RPM -- first clone VM and then use yum to remove package.")
|
||||||
|
|
||||||
self.pre_rename(name)
|
self.pre_rename(name)
|
||||||
|
self.libvirt_domain.undefine()
|
||||||
|
|
||||||
new_conf = os.path.join(self.dir_path, name + '.conf')
|
new_conf = os.path.join(self.dir_path, name + '.conf')
|
||||||
if os.path.exists(self.conf_file):
|
if os.path.exists(self.conf_file):
|
||||||
@ -565,6 +567,7 @@ class QubesVm(object):
|
|||||||
if hasattr(self, 'kernels_dir') and self.kernels_dir is not None:
|
if hasattr(self, 'kernels_dir') and self.kernels_dir is not None:
|
||||||
self.kernels_dir = self.kernels_dir.replace(old_dirpath, new_dirpath)
|
self.kernels_dir = self.kernels_dir.replace(old_dirpath, new_dirpath)
|
||||||
|
|
||||||
|
self._update_libvirt_domain()
|
||||||
self.post_rename(old_name)
|
self.post_rename(old_name)
|
||||||
|
|
||||||
def post_rename(self, old_name):
|
def post_rename(self, old_name):
|
||||||
@ -633,36 +636,48 @@ class QubesVm(object):
|
|||||||
def is_disposablevm(self):
|
def is_disposablevm(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_xid(self):
|
@property
|
||||||
|
def xid(self):
|
||||||
if self.libvirt_domain is None:
|
if self.libvirt_domain is None:
|
||||||
return -1
|
return -1
|
||||||
return self.libvirt_domain.ID()
|
return self.libvirt_domain.ID()
|
||||||
|
|
||||||
|
def get_xid(self):
|
||||||
|
# obsoleted
|
||||||
|
return self.xid
|
||||||
|
|
||||||
|
def _update_libvirt_domain(self):
|
||||||
|
domain_config = self.create_config_file()
|
||||||
|
self._libvirt_domain = libvirt_conn.defineXML(domain_config)
|
||||||
|
self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def libvirt_domain(self):
|
def libvirt_domain(self):
|
||||||
if self._libvirt_domain is not None:
|
if self._libvirt_domain is not None:
|
||||||
return self._libvirt_domain
|
return self._libvirt_domain
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._libvirt_domain = libvirt_conn.lookupByName(self.name)
|
if self.uuid is not None:
|
||||||
|
self._libvirt_domain = libvirt_conn.lookupByUUID(self.uuid.bytes)
|
||||||
|
else:
|
||||||
|
self._libvirt_domain = libvirt_conn.lookupByName(self.name)
|
||||||
|
self.uuid = uuid.UUID(bytes=self._libvirt_domain.UUID())
|
||||||
except libvirt.libvirtError:
|
except libvirt.libvirtError:
|
||||||
if libvirt.virGetLastError()[0] == libvirt.VIR_ERR_NO_DOMAIN:
|
if libvirt.virGetLastError()[0] == libvirt.VIR_ERR_NO_DOMAIN:
|
||||||
return None
|
self._update_libvirt_domain()
|
||||||
raise
|
else:
|
||||||
|
raise
|
||||||
return self._libvirt_domain
|
return self._libvirt_domain
|
||||||
|
|
||||||
def get_uuid(self):
|
def get_uuid(self):
|
||||||
|
# obsoleted
|
||||||
if self.libvirt_domain is None:
|
return self.uuid
|
||||||
return None
|
|
||||||
return uuid.UUID(self.libvirt_domain.UUIDString())
|
|
||||||
|
|
||||||
def get_mem(self):
|
def get_mem(self):
|
||||||
if dry_run:
|
if dry_run:
|
||||||
return 666
|
return 666
|
||||||
|
|
||||||
if self.libvirt_domain is None:
|
if not self.libvirt_domain.isActive():
|
||||||
return 0
|
return 0
|
||||||
return self.libvirt_domain.info()[1]
|
return self.libvirt_domain.info()[1]
|
||||||
|
|
||||||
@ -712,16 +727,16 @@ class QubesVm(object):
|
|||||||
return "NA"
|
return "NA"
|
||||||
|
|
||||||
libvirt_domain = self.libvirt_domain
|
libvirt_domain = self.libvirt_domain
|
||||||
if libvirt_domain:
|
if libvirt_domain.isActive():
|
||||||
if libvirt_domain.state() == libvirt.VIR_DOMAIN_PAUSED:
|
if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PAUSED:
|
||||||
return "Paused"
|
return "Paused"
|
||||||
elif libvirt_domain.state() == libvirt.VIR_DOMAIN_CRASHED:
|
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_CRASHED:
|
||||||
return "Crashed"
|
return "Crashed"
|
||||||
elif libvirt_domain.state() == libvirt.VIR_DOMAIN_SHUTDOWN:
|
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTDOWN:
|
||||||
return "Halting"
|
return "Halting"
|
||||||
elif libvirt_domain.state() == libvirt.VIR_DOMAIN_SHUTOFF:
|
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTOFF:
|
||||||
return "Dying"
|
return "Dying"
|
||||||
elif libvirt_domain.state() == libvirt.VIR_DOMAIN_PMSUSPENDED:
|
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PMSUSPENDED:
|
||||||
return "Suspended"
|
return "Suspended"
|
||||||
else:
|
else:
|
||||||
if not self.is_fully_usable():
|
if not self.is_fully_usable():
|
||||||
@ -734,7 +749,7 @@ class QubesVm(object):
|
|||||||
return "NA"
|
return "NA"
|
||||||
|
|
||||||
def is_guid_running(self):
|
def is_guid_running(self):
|
||||||
xid = self.get_xid()
|
xid = self.xid
|
||||||
if xid < 0:
|
if xid < 0:
|
||||||
return False
|
return False
|
||||||
if not os.path.exists('/var/run/qubes/guid-running.%d' % xid):
|
if not os.path.exists('/var/run/qubes/guid-running.%d' % xid):
|
||||||
@ -771,7 +786,7 @@ class QubesVm(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
uuid = self.get_uuid()
|
uuid = self.uuid
|
||||||
|
|
||||||
start_time = xs.read('', "/vm/%s/start_time" % str(uuid))
|
start_time = xs.read('', "/vm/%s/start_time" % str(uuid))
|
||||||
if start_time != '':
|
if start_time != '':
|
||||||
@ -805,7 +820,7 @@ class QubesVm(object):
|
|||||||
# FIXME
|
# FIXME
|
||||||
# 51712 (0xCA00) is xvda
|
# 51712 (0xCA00) is xvda
|
||||||
# backend node name not available through xenapi :(
|
# backend node name not available through xenapi :(
|
||||||
used_dmdev = xs.read('', "/local/domain/0/backend/vbd/{0}/51712/node".format(self.get_xid()))
|
used_dmdev = xs.read('', "/local/domain/0/backend/vbd/{0}/51712/node".format(self.xid))
|
||||||
|
|
||||||
return used_dmdev != current_dmdev
|
return used_dmdev != current_dmdev
|
||||||
|
|
||||||
@ -1036,6 +1051,7 @@ class QubesVm(object):
|
|||||||
args['name'] = self.name
|
args['name'] = self.name
|
||||||
if hasattr(self, 'kernels_dir'):
|
if hasattr(self, 'kernels_dir'):
|
||||||
args['kerneldir'] = self.kernels_dir
|
args['kerneldir'] = self.kernels_dir
|
||||||
|
args['uuidnode'] = "<uuid>%s</uuid>" % str(self.uuid) if self.uuid else ""
|
||||||
args['vmdir'] = self.dir_path
|
args['vmdir'] = self.dir_path
|
||||||
args['pcidevs'] = ''.join(map(self._format_pci_dev, self.pcidevs))
|
args['pcidevs'] = ''.join(map(self._format_pci_dev, self.pcidevs))
|
||||||
args['mem'] = str(self.memory)
|
args['mem'] = str(self.memory)
|
||||||
@ -1536,7 +1552,8 @@ class QubesVm(object):
|
|||||||
notify_function ("info", "Starting the '{0}' VM...".format(self.name))
|
notify_function ("info", "Starting the '{0}' VM...".format(self.name))
|
||||||
elif verbose:
|
elif verbose:
|
||||||
print >> sys.stderr, "Starting the VM '{0}'...".format(self.name)
|
print >> sys.stderr, "Starting the VM '{0}'...".format(self.name)
|
||||||
xid = self.start(verbose=verbose, start_guid = gui, notify_function=notify_function)
|
self.start(verbose=verbose, start_guid = gui, notify_function=notify_function)
|
||||||
|
|
||||||
except (IOError, OSError, QubesException) as err:
|
except (IOError, OSError, QubesException) as err:
|
||||||
raise QubesException("Error while starting the '{0}' VM: {1}".format(self.name, err))
|
raise QubesException("Error while starting the '{0}' VM: {1}".format(self.name, err))
|
||||||
except (MemoryError) as err:
|
except (MemoryError) as err:
|
||||||
@ -1550,11 +1567,10 @@ class QubesVm(object):
|
|||||||
raise QubesException(
|
raise QubesException(
|
||||||
"Domain '{}': qrexec not connected.".format(self.name))
|
"Domain '{}': qrexec not connected.".format(self.name))
|
||||||
|
|
||||||
xid = self.get_xid()
|
|
||||||
if gui and os.getenv("DISPLAY") is not None and not self.is_guid_running():
|
if gui and os.getenv("DISPLAY") is not None and not self.is_guid_running():
|
||||||
self.start_guid(verbose = verbose, notify_function = notify_function)
|
self.start_guid(verbose = verbose, notify_function = notify_function)
|
||||||
|
|
||||||
args = [system_path["qrexec_client_path"], "-d", str(xid), "%s:%s" % (user, command)]
|
args = [system_path["qrexec_client_path"], "-d", str(self.xid), "%s:%s" % (user, command)]
|
||||||
if localcmd is not None:
|
if localcmd is not None:
|
||||||
args += [ "-l", localcmd]
|
args += [ "-l", localcmd]
|
||||||
if filter_esc:
|
if filter_esc:
|
||||||
@ -1649,7 +1665,6 @@ class QubesVm(object):
|
|||||||
extra_guid_args=[], before_qrexec=False):
|
extra_guid_args=[], before_qrexec=False):
|
||||||
if verbose:
|
if verbose:
|
||||||
print >> sys.stderr, "--> Starting Qubes GUId..."
|
print >> sys.stderr, "--> Starting Qubes GUId..."
|
||||||
xid = self.get_xid()
|
|
||||||
|
|
||||||
guid_cmd = [system_path["qubes_guid_path"],
|
guid_cmd = [system_path["qubes_guid_path"],
|
||||||
"-d", str(xid), "-N", self.name,
|
"-d", str(xid), "-N", self.name,
|
||||||
@ -1681,8 +1696,7 @@ class QubesVm(object):
|
|||||||
def start_qrexec_daemon(self, verbose = False, notify_function = None):
|
def start_qrexec_daemon(self, verbose = False, notify_function = None):
|
||||||
if verbose:
|
if verbose:
|
||||||
print >> sys.stderr, "--> Starting the qrexec daemon..."
|
print >> sys.stderr, "--> Starting the qrexec daemon..."
|
||||||
xid = self.get_xid()
|
qrexec_args = [str(self.xid), self.name, self.default_user]
|
||||||
qrexec_args = [str(xid), self.name, self.default_user]
|
|
||||||
if not verbose:
|
if not verbose:
|
||||||
qrexec_args.insert(0, "-q")
|
qrexec_args.insert(0, "-q")
|
||||||
qrexec_env = os.environ
|
qrexec_env = os.environ
|
||||||
@ -1714,7 +1728,7 @@ class QubesVm(object):
|
|||||||
if verbose:
|
if verbose:
|
||||||
print >> sys.stderr, "--> Loading the VM (type = {0})...".format(self.type)
|
print >> sys.stderr, "--> Loading the VM (type = {0})...".format(self.type)
|
||||||
|
|
||||||
domain_config = self.create_config_file()
|
self._update_libvirt_domain()
|
||||||
|
|
||||||
if mem_required is None:
|
if mem_required is None:
|
||||||
mem_required = int(self.memory) * 1024 * 1024
|
mem_required = int(self.memory) * 1024 * 1024
|
||||||
@ -1732,10 +1746,9 @@ class QubesVm(object):
|
|||||||
nd = libvirt_conn.nodeDeviceLookupByName('pci_0000_' + pci.replace(':','_').replace('.','_'))
|
nd = libvirt_conn.nodeDeviceLookupByName('pci_0000_' + pci.replace(':','_').replace('.','_'))
|
||||||
nd.dettach()
|
nd.dettach()
|
||||||
|
|
||||||
self._libvirt_domain = libvirt_conn.createXML(domain_config, libvirt.VIR_DOMAIN_START_PAUSED)
|
self.libvirt_domain.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED)
|
||||||
|
|
||||||
xid = self.get_xid()
|
xid = self.xid
|
||||||
self.xid = xid
|
|
||||||
|
|
||||||
if preparing_dvm:
|
if preparing_dvm:
|
||||||
self.services['qubes-dvm'] = True
|
self.services['qubes-dvm'] = True
|
||||||
|
@ -38,7 +38,14 @@ class QubesAdminVm(QubesNetVm):
|
|||||||
template = None,
|
template = None,
|
||||||
label = defaults["template_label"],
|
label = defaults["template_label"],
|
||||||
**kwargs)
|
**kwargs)
|
||||||
self.xid = 0
|
|
||||||
|
@property
|
||||||
|
def xid(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def libvirt_domain(self):
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
@ -47,9 +54,6 @@ class QubesAdminVm(QubesNetVm):
|
|||||||
def is_running(self):
|
def is_running(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_xid(self):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def get_power_state(self):
|
def get_power_state(self):
|
||||||
return "Running"
|
return "Running"
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<domain type='xen'>
|
<domain type='xen'>
|
||||||
<name>{name}</name>
|
<name>{name}</name>
|
||||||
|
{uuidnode}
|
||||||
<memory unit='MiB'>{maxmem}</memory>
|
<memory unit='MiB'>{maxmem}</memory>
|
||||||
<currentMemory unit='MiB'>{mem}</currentMemory>
|
<currentMemory unit='MiB'>{mem}</currentMemory>
|
||||||
<vcpu placement='static'>{vcpus}</vcpu>
|
<vcpu placement='static'>{vcpus}</vcpu>
|
||||||
|
Loading…
Reference in New Issue
Block a user