QubesVM add docstrings & fix pylint errors

This commit is contained in:
Bahtiar `kalkin-` Gadimov 2016-06-16 21:07:36 +02:00
parent a2668d81e3
commit ba3b191702
No known key found for this signature in database
GPG Key ID: 96ED3C3BA19C3DEE

View File

@ -1,6 +1,5 @@
#!/usr/bin/python2 -O
# vim: fileencoding=utf-8
#
# The Qubes OS Project, https://www.qubes-os.org/
#
@ -40,7 +39,7 @@ import uuid
import warnings
import lxml
import libvirt
import libvirt # pylint: disable=import-error
import qubes
import qubes.config
@ -65,6 +64,7 @@ MEM_OVERHEAD_PER_VCPU = 3 * 1024 * 1024 / 2
def _setter_qid(self, prop, value):
''' Helper for setting the domain qid '''
# pylint: disable=unused-argument
value = int(value)
if not 0 <= value <= qubes.config.max_qid:
@ -75,6 +75,7 @@ def _setter_qid(self, prop, value):
def _setter_name(self, prop, value):
''' Helper for setting the domain name '''
if not isinstance(value, basestring):
raise TypeError('{} value must be string, {!r} found'.format(
prop.__name__, type(value).__name__))
@ -106,7 +107,8 @@ def _setter_name(self, prop, value):
def _setter_kernel(self, prop, value):
# pylint: disable=unused-argument
''' Helper for setting the domain kernel and running sanity checks on it.
''' # pylint: disable=unused-argument
if value is None:
return value
value = str(value)
@ -126,6 +128,7 @@ def _setter_kernel(self, prop, value):
def _setter_label(self, prop, value):
''' Helper for setting the domain label '''
# pylint: disable=unused-argument
if isinstance(value, qubes.Label):
return value
@ -135,6 +138,7 @@ def _setter_label(self, prop, value):
return self.app.get_label(value)
def _setter_positive_int(self, prop, value):
''' Helper for setting a positive int. Checks that the int is >= 0 '''
# pylint: disable=unused-argument
value = int(value)
if value <= 0:
@ -190,7 +194,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
doc='''Use full virtualisation (HVM) for this qube,
instead of paravirtualisation (PV)''')
# XXX this should be part of qubes.xml
# SEE: 1815 this should be part of qubes.xml
firewall_conf = qubes.property('firewall_conf', type=str,
default='firewall.xml')
@ -217,7 +221,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
doc='''Internal VM (not shown in qubes-manager, don't create appmenus
entries.''')
# FIXME self.app.host could not exist - only self.app.vm required by API
vcpus = qubes.property('vcpus',
type=int,
setter=_setter_positive_int,
@ -229,20 +232,18 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
default='default',
doc='storage pool for this qube devices')
# XXX swallowed uses_default_kernel
# XXX not applicable to HVM?
# CORE2: swallowed uses_default_kernel
kernel = qubes.property('kernel', type=str,
setter=_setter_kernel,
default=(lambda self: self.app.default_kernel),
ls_width=12,
doc='Kernel used by this domain.')
# XXX swallowed uses_default_kernelopts
# XXX not applicable to HVM?
# CORE2: swallowed uses_default_kernelopts
kernelopts = qubes.property('kernelopts', type=str, load_stage=4,
default=(lambda self: qubes.config.defaults['kernelopts_pcidevs'] \
if len(self.devices['pci']) > 0 \
else self.template.kernelopts if hasattr(self, 'template') \
default=(lambda self: qubes.config.defaults['kernelopts_pcidevs']
if len(self.devices['pci']) > 0
else self.template.kernelopts if hasattr(self, 'template')
else qubes.config.defaults['kernelopts']),
ls_width=30,
doc='Kernel command line passed to domain.')
@ -292,7 +293,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
saver=(lambda self, prop, value: value.strftime('%s')),
doc='FIXME')
#
# static, class-wide properties
#
@ -326,7 +326,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
e.get_error_code()))
raise
@property
def libvirt_domain(self):
'''Libvirt domain object from libvirt.
@ -382,12 +381,10 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
def icon_path(self):
return os.path.join(self.dir_path, 'icon.png')
@property
def conf_file(self):
return os.path.join(self.dir_path, 'libvirt.xml')
# XXX I don't know what to do with these; probably should be isinstance(...)
def is_template(self):
warnings.warn('vm.is_template() is deprecated, use isinstance()',
@ -418,10 +415,8 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return isinstance(self, qubes.vm.mix.net.NetVMMixin) \
and self.provides_network
# network-related
#
# constructor
#
@ -481,7 +476,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
if xml is None:
# new qube, disable updates check if requested for new qubes
# TODO: when features (#1637) are done, migrate to plugin
# SEE: 1637 when features are done, migrate to plugin
if not self.app.check_updates_vm:
self.features['check-updates'] = None
@ -514,12 +509,10 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
self.uuid = uuid.uuid4()
# Initialize VM image storage class
# XXX why not in constructor?
self.storage = qubes.storage.Storage(self)
vm_pool = qubes.storage.domain.DomainPool(self)
self.app.pools[vm_pool.name] = vm_pool
@qubes.events.handler('property-set:label')
def on_property_set_label(self, event, name, new_label, old_label=None):
# pylint: disable=unused-argument
@ -530,7 +523,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
pass
if hasattr(os, "symlink"):
os.symlink(new_label.icon_path, self.icon_path)
# FIXME: some os-independent wrapper?
subprocess.call(['sudo', 'xdg-icon-resource', 'forceupdate'])
else:
shutil.copy(new_label.icon_path, self.icon_path)
@ -597,7 +589,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
raise qubes.exc.QubesException(
'Failed to set autostart for VM in systemd')
@qubes.events.handler('device-pre-attach:pci')
def on_device_pre_attached_pci(self, event, device):
# pylint: disable=unused-argument
@ -617,7 +608,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
self.log.exception('Failed to attach PCI device {!r} on the fly,'
' changes will be seen after VM restart.'.format(device), e)
@qubes.events.handler('device-pre-detach:pci')
def on_device_pre_detached_pci(self, event, device):
# pylint: disable=unused-argument
@ -648,7 +638,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
' changes will be seen after VM restart.'.format(device), e)
raise
def bind_pci_to_pciback(self, device):
'''Bind PCI device to pciback driver.
@ -676,7 +665,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
else:
raise
#
# methods for changing domain state
#
@ -704,6 +692,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
self.storage.verify_files()
if self.netvm is not None:
# pylint: disable = no-member
if self.netvm.qid != 0:
if not self.netvm.is_running():
self.netvm.start(start_guid=start_guid,
@ -761,7 +750,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def shutdown(self, force=False):
'''Shutdown domain.
@ -792,7 +780,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def kill(self):
'''Forcefuly shutdown (destroy) domain.
@ -808,7 +795,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def force_shutdown(self, *args, **kwargs):
'''Deprecated alias for :py:meth:`kill`'''
warnings.warn(
@ -818,7 +804,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def suspend(self):
'''Suspend (pause) domain.
@ -833,8 +818,8 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
if len(self.devices['pci']) > 0:
raise qubes.exc.QubesNotImplementedError(
'Cannot suspend domain {!r} which has PCI devices attached' \
.format(self.name))
'Cannot suspend domain {!r} which has PCI devices attached'
.format(self.name))
else:
if self.hvm:
self.libvirt_domain.pause()
@ -843,7 +828,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def pause(self):
'''Pause (suspend) domain. This currently delegates to \
:py:meth:`suspend`.'''
@ -855,7 +839,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def resume(self):
'''Resume suspended domain.
@ -871,7 +854,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def unpause(self):
'''Resume (unpause) a domain'''
if not self.is_paused():
@ -881,7 +863,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self
def run(self, command, user=None, autostart=False, notify_function=None,
passio=False, passio_popen=False, passio_stderr=False,
ignore_stderr=False, localcmd=None, wait=False, gui=True,
@ -969,7 +950,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
null.close()
return retcode
def run_service(self, service, source=None, user=None,
passio_popen=False, input=None, localcmd=None, gui=False,
wait=True, passio_stderr=False):
@ -982,7 +962,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
:param str user: username to run service as
:param bool passio_popen: passed verbatim to :py:meth:`run`
:param str input: string passed as input to service
''' # pylint: disable=redefined-builtin
''' # pylint: disable=redefined-builtin
if len([i for i in (input, passio_popen, localcmd) if i]) > 1:
raise TypeError(
@ -1039,7 +1019,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return qmemman_client
def start_qrexec_daemon(self):
'''Start qrexec daemon.
@ -1066,7 +1045,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
except subprocess.CalledProcessError:
raise qubes.exc.QubesVMError(self, 'Cannot execute qrexec-daemon!')
def start_qubesdb(self):
'''Start QubesDB daemon.
@ -1083,7 +1061,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
if retcode != 0:
raise qubes.exc.QubesException('Cannot execute qubesdb-daemon')
def wait_for_session(self):
'''Wait until machine finished boot sequence.
@ -1098,8 +1075,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
user="root", passio_popen=True, gui=False, wait=True)
p.communicate(input=self.default_user)
# TODO rename to create
def create_on_disk(self, source_template=None):
'''Create files needed for VM.
@ -1166,7 +1141,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
# fire hooks
self.fire_event('domain-clone-files', src)
#
# methods for querying domain state
#
@ -1275,7 +1249,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainState
Libvirt's enum describing precise state of a domain.
''' # pylint: disable=too-many-return-statements
''' # pylint: disable=too-many-return-statements
libvirt_domain = self.libvirt_domain
if libvirt_domain is None:
@ -1292,7 +1266,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return "Halting"
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTOFF:
return "Dying"
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PMSUSPENDED:
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PMSUSPENDED: # nopep8
return "Suspended"
else:
if not self.is_fully_usable():
@ -1331,7 +1305,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
# TODO context manager #1693
return self.libvirt_domain and self.libvirt_domain.isActive()
def is_paused(self):
'''Check whether this domain is paused.
@ -1343,7 +1316,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return self.libvirt_domain \
and self.libvirt_domain.state() == libvirt.VIR_DOMAIN_PAUSED
def is_qrexec_running(self):
'''Check whether qrexec for this domain is available.
@ -1355,23 +1327,20 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return False
return os.path.exists('/var/run/qubes/qrexec.%s' % self.name)
def is_fully_usable(self):
return all(self.fire_event('domain-is-fully-usable'))
@qubes.events.handler('domain-is-fully-usable')
def on_domain_is_fully_usable(self, event):
'''Check whether domain is running and sane.
Currently this checks for running qrexec.
''' # pylint: disable=unused-argument
''' # pylint: disable=unused-argument
# Running gui-daemon implies also VM running
if not self.is_qrexec_running():
yield False
# memory and disk
def get_mem(self):
@ -1395,8 +1364,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
libvirt.VIR_ERR_NO_DOMAIN,
# libxl_domain_info failed (race condition from isActive)
libvirt.VIR_ERR_INTERNAL_ERROR,
):
libvirt.VIR_ERR_INTERNAL_ERROR):
return 0
else:
@ -1404,7 +1372,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
'libvirt error code: {!r}'.format(e.get_error_code()))
raise
def get_mem_static_max(self):
'''Get maximum memory available to VM.
@ -1424,8 +1391,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
libvirt.VIR_ERR_NO_DOMAIN,
# libxl_domain_info failed (race condition from isActive)
libvirt.VIR_ERR_INTERNAL_ERROR,
):
libvirt.VIR_ERR_INTERNAL_ERROR):
return 0
else:
@ -1433,7 +1399,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
'libvirt error code: {!r}'.format(e.get_error_code()))
raise
def get_cputime(self):
'''Get total CPU time burned by this domain since start.
@ -1465,8 +1430,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
libvirt.VIR_ERR_NO_DOMAIN,
# libxl_domain_info failed (race condition from isActive)
libvirt.VIR_ERR_INTERNAL_ERROR,
):
libvirt.VIR_ERR_INTERNAL_ERROR):
return 0
else:
@ -1492,8 +1456,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
else:
return None
# XXX this probably should go to AppVM
def is_outdated(self):
'''Check whether domain needs restart to update root image from \
template.
@ -1547,7 +1509,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
return os.path.relpath(path, self.dir_path)
def create_qdb_entries(self):
'''Create entries in Qubes DB.
'''
@ -1601,7 +1562,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
self.fire_event('domain-qdb-create')
def _update_libvirt_domain(self):
'''Re-initialise :py:attr:`libvirt_domain`.'''
domain_config = self.create_config_file()
@ -1617,7 +1577,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
else:
raise
#
# workshop -- those are to be reworked later
#
@ -1636,38 +1595,3 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
domain.memory_maximum = self.get_mem_static_max() * 1024
return qubes.qmemman.algo.prefmem(domain) / 1024
#
# landfill -- those are unneeded
#
# attrs = {
# XXX probably will be obsoleted by .events_enabled
# "_do_not_reset_firewall": { "func": lambda x: False },
# "_start_guid_first": { "func": lambda x: False },
# }
# this function appears unused
# def _cleanup_zombie_domains(self):
# """
# This function is workaround broken libxl (which leaves not fully
# created domain on failure) and vchan on domain crash behaviour
# @return: None
# """
# xc = self.get_xc_dominfo()
# if xc and xc['dying'] == 1:
# # GUID still running?
# guid_pidfile = '/var/run/qubes/guid-running.%d' % xc['domid']
# if os.path.exists(guid_pidfile):
# guid_pid = open(guid_pidfile).read().strip()
# os.kill(int(guid_pid), 15)
# # qrexec still running?
# if self.is_qrexec_running():
# #TODO: kill qrexec daemon
# pass