core3: fixes from Marek

This is adapted from commit 90a50dca406e3d40c88ea338566e0460589df7a3.
This commit is contained in:
Wojtek Porczyk 2015-09-17 12:08:03 +02:00
parent e9b998400d
commit 80d664441d
8 changed files with 134 additions and 49 deletions

View File

@ -640,7 +640,7 @@ class property(object): # pylint: disable=redefined-builtin,invalid-name
if self._setter is not None:
value = self._setter(instance, self, value)
if self._type is not None:
if self._type is not None: # XXX what about QubesVM and other types?
value = self._type(value)
if has_oldvalue:
@ -705,7 +705,7 @@ class property(object): # pylint: disable=redefined-builtin,invalid-name
#
class DontSave(Exception):
'''This exception may be raised from saver to sing that property should
'''This exception may be raised from saver to sign that property should
not be saved.
'''
pass
@ -1023,23 +1023,28 @@ class VMProperty(property):
raise TypeError(
"'vmclass' should specify a subclass of qubes.vm.BaseVM")
super(VMProperty, self).__init__(name, **kwargs)
super(VMProperty, self).__init__(name,
saver=(lambda self, prop, value: value.name if value else 'None'),
**kwargs)
self.vmclass = vmclass
self.allow_none = allow_none
def __set__(self, instance, value):
if value is None:
if self.allow_none:
super(VMProperty, self).__set__(self, instance, value)
super(VMProperty, self).__set__(instance, value)
return
else:
raise ValueError(
'Property {!r} does not allow setting to {!r}'.format(
self.__name__, value))
app = instance if isinstance(instance, Qubes) else instance.app
# XXX this may throw LookupError; that's good until introduction
# of QubesNoSuchVMException or whatever
vm = instance.app.domains[value]
vm = app.domains[value]
if not isinstance(vm, self.vmclass):
raise TypeError('wrong VM class: domains[{!r}] if of type {!s} '
@ -1047,7 +1052,7 @@ class VMProperty(property):
vm.__class__.__name__,
self.vmclass.__name__))
super(VMProperty, self).__set__(self, instance, vm)
super(VMProperty, self).__set__(instance, vm)
import qubes.vm.qubesvm
@ -1100,11 +1105,11 @@ class Qubes(PropertyHolder):
'''
default_netvm = VMProperty('default_netvm', load_stage=3,
default=None,
default=None, allow_none=True,
doc='''Default NetVM for AppVMs. Initial state is `None`, which means
that AppVMs are not connected to the Internet.''')
default_fw_netvm = VMProperty('default_fw_netvm', load_stage=3,
default=None,
default=None, allow_none=True,
doc='''Default NetVM for ProxyVMs. Initial state is `None`, which means
that ProxyVMs (including FirewallVM) are not connected to the
Internet.''')
@ -1112,9 +1117,11 @@ class Qubes(PropertyHolder):
vmclass=qubes.vm.templatevm.TemplateVM,
doc='Default template for new AppVMs')
updatevm = VMProperty('updatevm', load_stage=3,
allow_none=True,
doc='''Which VM to use as `yum` proxy for updating AdminVM and
TemplateVMs''')
clockvm = VMProperty('clockvm', load_stage=3,
allow_none=True,
doc='Which VM to use as NTP proxy for updating AdminVM')
default_kernel = property('default_kernel', load_stage=3,
doc='Which kernel to use when not overriden in VM')
@ -1209,7 +1216,7 @@ class Qubes(PropertyHolder):
# Disable ntpd in ClockVM - to not conflict with ntpdate (both are
# using 123/udp port)
if hasattr(self, 'clockvm'):
if hasattr(self, 'clockvm') and self.clockvm is not None:
if 'ntpd' in self.clockvm.services:
if self.clockvm.services['ntpd']:
self.log.warning("VM set as clockvm ({!r}) has enabled "
@ -1367,6 +1374,8 @@ class Qubes(PropertyHolder):
@qubes.events.handler('property-pre-set:clockvm')
def on_property_pre_set_clockvm(self, event, name, newvalue, oldvalue=None):
# pylint: disable=unused-argument,no-self-use
if newvalue is None:
return
if 'ntpd' in newvalue.services:
if newvalue.services['ntpd']:
raise QubesException('Cannot set {!r} as {!r} property since '

View File

@ -102,7 +102,8 @@ class Emitter(object):
def __init__(self, *args, **kwargs):
super(Emitter, self).__init__(*args, **kwargs)
self.events_enabled = False
if not hasattr(self, 'events_enabled'):
self.events_enabled = False
@classmethod

5
qubes/qdb.py Normal file
View File

@ -0,0 +1,5 @@
# This is mock file, not installed. It is needed. because pylint needs to
# import all the modules, and qubes.qbd is one of them.
def QubesDB(dummy):
return None

View File

@ -353,7 +353,7 @@ class BaseVM(qubes.PropertyHolder):
args['name'] = self.name
if hasattr(self, 'kernels_dir'):
args['kerneldir'] = self.kernels_dir
args['uuidnode'] = '<uuid>{!r}</uuid>'.format(self.uuid) \
args['uuidnode'] = '<uuid>{!s}</uuid>'.format(self.uuid) \
if hasattr(self, 'uuid') else ''
args['vmdir'] = self.dir_path
args['pcidevs'] = ''.join(lxml.etree.tostring(self.lvxml_pci_dev(dev))
@ -398,6 +398,8 @@ class BaseVM(qubes.PropertyHolder):
"Debug mode: adding 'earlyprintk=xen' to kernel opts")
args['kernelopts'] += ' earlyprintk=xen'
return args
def create_config_file(self, file_path=None, prepare_dvm=False):
'''Create libvirt's XML domain config file

View File

@ -1,6 +1,7 @@
#!/usr/bin/python2 -O
# vim: fileencoding=utf-8
import qubes.events
import qubes.vm.qubesvm
class AppVM(qubes.vm.qubesvm.QubesVM):
@ -11,9 +12,11 @@ class AppVM(qubes.vm.qubesvm.QubesVM):
ls_width=31,
doc='Template, on which this AppVM is based.')
def __init__(self, D):
super(AppVM, self).__init__(D)
def __init__(self, *args, **kwargs):
super(AppVM, self).__init__(*args, **kwargs)
@qubes.events.handler('domain-loaded')
def on_domain_loaded(self, event):
# Some additional checks for template based VM
assert self.template
self.template.appvms.add(self)
#self.template.appvms.add(self) # XXX

View File

@ -3,7 +3,32 @@
import qubes.vm.qubesvm
class NetVM(qubes.vm.qubesvm.QubesVM):
class NetVM(qubes.vm.appvm.AppVM):
'''Network interface VM'''
def __init__(self, D):
super(NetVM, self).__init__(D)
netvm = qubes.property('netvm', setter=qubes.property.forbidden)
def __init__(self, *args, **kwargs):
super(NetVM, self).__init__(*args, **kwargs)
def get_ip_for_vm(self, vm):
return '10.137.{}.{}'.format(self.qid, vm.qid + 2)
@property
def gateway(self):
return '10.137.{}.1'.format(self.qid)
@property
def secondary_dns(self):
return '10.137.{}.254'.format(self.qid)
# @property
# def netmask(self):
# return '255.255.255.0'
#
# @property
# def provides_network(self):
# return True
netmask = '255.255.255.0'
provides_network = True

View File

@ -24,6 +24,8 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
from __future__ import absolute_import
import datetime
import lxml.etree
import os
@ -34,11 +36,13 @@ import subprocess
import sys
import time
import uuid
import warnings
import libvirt
import qubes
import qubes.config
#import qubes.qdb
import qubes.qdb
#import qubes.qmemman
#import qubes.qmemman_algo
import qubes.storage
@ -90,19 +94,29 @@ def _setter_name(self, prop, value):
def _setter_kernel(self, prop, value):
# pylint: disable=unused-argument
if not os.path.exists(os.path.join(
qubes.config.system_path['qubes_kernels_base_dir'], value)):
dirname = os.path.join(
qubes.config.system_path['qubes_base_dir'],
qubes.config.system_path['qubes_kernels_base_dir'],
value)
if not os.path.exists(dirname):
raise qubes.QubesException('Kernel {!r} not installed'.format(value))
for filename in ('vmlinuz', 'modules.img'):
if not os.path.exists(os.path.join(
qubes.config.system_path['qubes_kernels_base_dir'],
value, filename)):
if not os.path.exists(os.path.join(dirname, filename)):
raise qubes.QubesException(
'Kernel {!r} not properly installed: missing {!r} file'.format(
value, filename))
return value
def _setter_label(self, prop, value):
if isinstance(value, qubes.Label):
return value
if value.startswith('label-'):
return self.app.labels[int(value.split('-', 1)[1])]
return self.app.get_label(value)
def _default_conf_file(self, name=None):
return (name or self.name) + '.conf'
@ -115,7 +129,8 @@ class QubesVM(qubes.vm.BaseVM):
#
label = qubes.property('label',
setter=(lambda self, prop, value: self.app.get_label(value)),
setter=_setter_label,
saver=(lambda self, prop, value: 'label-{}'.format(value.index)),
ls_width=14,
doc='''Colourful label assigned to VM. This is where the colour of the
padlock is set.''')
@ -129,9 +144,9 @@ class QubesVM(qubes.vm.BaseVM):
`None`, machine is disconnected. When absent, domain uses default
NetVM.''')
provides_network = qubes.property('provides_network',
type=bool, setter=qubes.property.bool,
doc='`True` if it is NetVM or ProxyVM, false otherwise.')
# provides_network = qubes.property('provides_network',
# type=bool, setter=qubes.property.bool,
# doc='`True` if it is NetVM or ProxyVM, false otherwise.')
qid = qubes.property('qid', type=int,
setter=_setter_qid,
@ -180,8 +195,9 @@ class QubesVM(qubes.vm.BaseVM):
doc='''Internal VM (not shown in qubes-manager, don't create appmenus
entries.''')
# XXX what is that
vcpus = qubes.property('vcpus', default=None,
# FIXME self.app.host could not exist - only self.app.vm required by API
vcpus = qubes.property('vcpus',
default=(lambda self: self.app.host.no_cpus),
ls_width=2,
doc='FIXME')
@ -215,7 +231,8 @@ class QubesVM(qubes.vm.BaseVM):
# XXX shouldn't this go to standalone VM and TemplateVM, and leave here
# only plain property?
default_user = qubes.property('default_user', type=str,
default=(lambda self: self.template.default_user),
default=(lambda self: self.template.default_user
if hasattr(self, 'template') else 'user'),
ls_width=12,
doc='FIXME')
@ -353,7 +370,7 @@ class QubesVM(qubes.vm.BaseVM):
If :py:attr:`self.kernel` is :py:obj:`None`, the this points inside
:py:attr:`self.dir_path`
'''
return os.path.join(
return os.path.join(qubes.config.system_path['qubes_base_dir'],
qubes.config.system_path['qubes_kernels_base_dir'], self.kernel) \
if self.kernel is not None \
else os.path.join(self.dir_path,
@ -379,17 +396,25 @@ class QubesVM(qubes.vm.BaseVM):
# XXX I don't know what to do with these; probably should be isinstance(...)
# def is_template(self):
# return False
#
# def is_appvm(self):
# return False
#
# def is_proxyvm(self):
# return False
#
# def is_disposablevm(self):
# return False
def is_template(self):
warnings.warn('vm.is_template() is deprecated, use isinstance()',
DeprecationWarning)
return isinstance(self, qubes.vm.templatevm.TemplateVM)
def is_appvm(self):
warnings.warn('vm.is_appvm() is deprecated, use isinstance()',
DeprecationWarning)
return isinstance(self, qubes.vm.appvm.AppVM)
def is_proxyvm(self):
warnings.warn('vm.is_proxyvm() is deprecated, use isinstance()',
DeprecationWarning)
return isinstance(self, qubes.vm.proxyvm.ProxyVM)
def is_disposablevm(self):
warnings.warn('vm.is_disposable() is deprecated, use isinstance()',
DeprecationWarning)
return isinstance(self, qubes.vm.dispvm.DispVM)
# network-related
@ -399,7 +424,7 @@ class QubesVM(qubes.vm.BaseVM):
def ip(self):
'''IP address of this domain.'''
if self.netvm is not None:
return self.netvm.get_ip_for_vm(self.qid)
return self.netvm.get_ip_for_vm(self)
else:
return None
@ -441,6 +466,13 @@ class QubesVM(qubes.vm.BaseVM):
return None
return "vif{0}.+".format(self.xid)
@property
def provides_network(self):
''':py:obj:`True` if it is :py:class:`qubes.vm.netvm.NetVM` or
:py:class:`qubes.vm.proxyvm.ProxyVM`, :py:obj:`False` otherwise'''
return isinstance(self,
(qubes.vm.netvm.NetVM, qubes.vm.proxyvm.ProxyVM))
#
# constructor
#
@ -472,8 +504,8 @@ class QubesVM(qubes.vm.BaseVM):
self.maxmem = self.memory * 10
# By default allow use all VCPUs
if not hasattr(self, 'vcpus') and not self.app.vmm.offline_mode:
self.vcpus = self.app.host.no_cpus
# if not hasattr(self, 'vcpus') and not self.app.vmm.offline_mode:
# self.vcpus = self.app.host.no_cpus
if len(self.devices['pci']) > 0:
# Force meminfo-writer disabled when VM have PCI devices
@ -486,10 +518,11 @@ class QubesVM(qubes.vm.BaseVM):
# Initialize VM image storage class
self.storage = qubes.storage.get_storage(self)
if self.kernels_dir is not None: # it is None for AdminVM
self.storage.modules_img = os.path.join(self.kernels_dir,
'modules.img')
self.storage.modules_img_rw = self.kernel is None
# XXX should be moved to defaults in storage class
# if self.kernels_dir is not None: # it is None for AdminVM
# self.storage.modules_img = os.path.join(self.kernels_dir,
# 'modules.img')
# self.storage.modules_img_rw = self.kernel is None
# fire hooks
self.fire_event('domain-init')

View File

@ -1,6 +1,8 @@
#!/usr/bin/python2 -O
# vim: fileencoding=utf-8
import os.path
import qubes
import qubes.vm.qubesvm
@ -38,3 +40,8 @@ class TemplateVM(qubes.vm.qubesvm.QubesVM):
self.log.info(
'Commiting template update; COW: {}'.format(self.rootcow_img))
self.storage.commit_template_changes()
@property
def rootcow_img(self):
return os.path.join(self.dir_path, qubes.config.vm_files['rootcow_img'])