Merge branch 'hvm' of 10.141.1.101:/var/lib/qubes/git/marmarek/core into hvm
Conflicts: version_dom0
BIN
dom0/icons/dispvm-black.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
dom0/icons/dispvm-blue.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
dom0/icons/dispvm-gray.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
dom0/icons/dispvm-green.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
dom0/icons/dispvm-orange.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
dom0/icons/dispvm-padlock-layers.xcf
Normal file
BIN
dom0/icons/dispvm-purple.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
dom0/icons/dispvm-red.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
dom0/icons/dispvm-yellow.png
Normal file
After Width: | Height: | Size: 12 KiB |
@ -186,6 +186,17 @@ QubesVmLabels = {
|
||||
"black" : QubesVmLabel ("black", 8),
|
||||
}
|
||||
|
||||
QubesDispVmLabels = {
|
||||
"red" : QubesVmLabel ("red", 1, icon="dispvm-red"),
|
||||
"orange" : QubesVmLabel ("orange", 2, icon="dispvm-orange"),
|
||||
"yellow" : QubesVmLabel ("yellow", 3, icon="dispvm-yellow"),
|
||||
"green" : QubesVmLabel ("green", 4, color="0x5fa05e", icon="dispvm-green"),
|
||||
"gray" : QubesVmLabel ("gray", 5, icon="dispvm-gray"),
|
||||
"blue" : QubesVmLabel ("blue", 6, icon="dispvm-blue"),
|
||||
"purple" : QubesVmLabel ("purple", 7, color="0xb83374", icon="dispvm-purple"),
|
||||
"black" : QubesVmLabel ("black", 8, icon="dispvm-black"),
|
||||
}
|
||||
|
||||
default_appvm_label = QubesVmLabels["red"]
|
||||
default_template_label = QubesVmLabels["gray"]
|
||||
default_servicevm_label = QubesVmLabels["red"]
|
||||
@ -198,140 +209,141 @@ class QubesVm(object):
|
||||
Note that qid is not the same as Xen's domid!
|
||||
"""
|
||||
|
||||
def __init__(self, qid, name,
|
||||
dir_path, conf_file = None,
|
||||
uses_default_netvm = True,
|
||||
netvm = None,
|
||||
installed_by_rpm = False,
|
||||
updateable = False,
|
||||
label = None,
|
||||
root_img = None,
|
||||
private_img = None,
|
||||
memory = default_memory,
|
||||
maxmem = None,
|
||||
template_vm = None,
|
||||
firewall_conf = None,
|
||||
volatile_img = None,
|
||||
pcidevs = None,
|
||||
internal = False,
|
||||
vcpus = None,
|
||||
kernel = None,
|
||||
uses_default_kernel = True,
|
||||
kernelopts = "",
|
||||
uses_default_kernelopts = True,
|
||||
mac = None,
|
||||
services = None):
|
||||
def _get_attrs_config(self):
|
||||
""" Object attributes for serialization/deserialization
|
||||
inner dict keys:
|
||||
- order: initialization order (to keep dependency intact)
|
||||
attrs without order will be evaluated at the end
|
||||
- default: default value used when attr not given to object constructor
|
||||
- attr: set value to this attribute instead of parameter name
|
||||
- eval: assign result of this expression instead of value directly;
|
||||
local variable 'value' contains attribute value (or default if it was not given)
|
||||
- save: use evaluation result as value for XML serialization; only attrs with 'save' key will be saved in XML
|
||||
- save_skip: if present and evaluates to true, attr will be omitted in XML
|
||||
- save_attr: save to this XML attribute instead of parameter name
|
||||
"""
|
||||
|
||||
attrs = {
|
||||
# __qid cannot be accessed by setattr, so must be set manually in __init__
|
||||
"qid": { "attr": "_qid", "order": 0 },
|
||||
"name": { "order": 1 },
|
||||
"dir_path": { "default": None, "order": 2 },
|
||||
"conf_file": { "eval": 'self.absolute_path(value, self.name + ".conf")', 'order': 3 },
|
||||
# order >= 10: have base attrs set
|
||||
"root_img": { "eval": 'self.absolute_path(value, default_root_img)', 'order': 10 },
|
||||
"private_img": { "eval": 'self.absolute_path(value, default_private_img)', 'order': 10 },
|
||||
"volatile_img": { "eval": 'self.absolute_path(value, default_volatile_img)', 'order': 10 },
|
||||
"firewall_conf": { "eval": 'self.absolute_path(value, default_firewall_conf_file)', 'order': 10 },
|
||||
"installed_by_rpm": { "default": False, 'order': 10 },
|
||||
"updateable": { "default": False, 'order': 10 },
|
||||
"template_vm": { "default": None, 'order': 10 },
|
||||
# order >= 20: have template set
|
||||
"uses_default_netvm": { "default": True, 'order': 20 },
|
||||
"netvm": { "default": None, 'order': 20 },
|
||||
"label": { "attr": "_label", "default": QubesVmLabels["red"], 'order': 20 },
|
||||
"memory": { "default": default_memory, 'order': 20 },
|
||||
"maxmem": { "default": None, 'order': 25 },
|
||||
"pcidevs": { "default": '[]', 'order': 25, "eval": \
|
||||
'[] if value in ["none", None] else eval(value) if value.find("[") >= 0 else eval("[" + value + "]")' },
|
||||
# Internal VM (not shown in qubes-manager, doesn't create appmenus entries
|
||||
"internal": { "default": False },
|
||||
"vcpus": { "default": None },
|
||||
"kernel": { "default": None, 'eval': \
|
||||
'self.template_vm.kernel if self.template_vm is not None else value' },
|
||||
"uses_default_kernel": { "default": True },
|
||||
"uses_default_kernelopts": { "default": True },
|
||||
"kernelopts": { "default": "", "eval": \
|
||||
'value if not self.uses_default_kernelopts else default_kernelopts_pcidevs if len(self.pcidevs) > 0 else default_kernelopts' },
|
||||
"mac": { "attr": "_mac", "default": None },
|
||||
"include_in_backups": { "default": True },
|
||||
"services": { "default": {}, "eval": "eval(str(value))" },
|
||||
##### Internal attributes - will be overriden in __init__ regardless of args
|
||||
"appmenus_templates_dir": { "eval": \
|
||||
'self.dir_path + "/" + default_appmenus_templates_subdir if self.updateable else ' + \
|
||||
'self.template_vm.appmenus_templates_dir if self.template_vm is not None else None' },
|
||||
"config_file_template": { "eval": "config_template_pv" },
|
||||
"icon_path": { "eval": 'self.dir_path + "/icon.png" if self.dir_path is not None else None' },
|
||||
"kernels_dir": { 'eval': 'self.template_vm.kernels_dir if self.template_vm is not None else ' + \
|
||||
'qubes_kernels_base_dir + "/" + self.kernel if self.kernel is not None else ' + \
|
||||
# for backward compatibility (or another rare case): kernel=None -> kernel in VM dir
|
||||
'self.dir_path + "/" + default_kernels_subdir' },
|
||||
}
|
||||
|
||||
assert qid < qubes_max_qid, "VM id out of bounds!"
|
||||
self.__qid = qid
|
||||
self.name = name
|
||||
### Mark attrs for XML inclusion
|
||||
# Simple string attrs
|
||||
for prop in ['qid', 'name', 'dir_path', 'memory', 'maxmem', 'pcidevs', 'vcpus', 'internal',\
|
||||
'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\
|
||||
'kernelopts', 'services', 'updateable', 'installed_by_rpm',\
|
||||
'uses_default_netvm', 'include_in_backups' ]:
|
||||
attrs[prop]['save'] = 'str(self.%s)' % prop
|
||||
# Simple paths
|
||||
for prop in ['conf_file', 'root_img', 'volatile_img', 'private_img']:
|
||||
attrs[prop]['save'] = 'self.relative_path(self.%s)' % prop
|
||||
attrs[prop]['save_skip'] = 'self.%s is None' % prop
|
||||
|
||||
self.dir_path = dir_path
|
||||
attrs['mac']['save'] = 'str(self._mac)'
|
||||
attrs['mac']['save_skip'] = 'self._mac is None'
|
||||
|
||||
self.conf_file = self.absolute_path(conf_file, name + ".conf")
|
||||
attrs['netvm']['save'] = 'str(self.netvm.qid) if self.netvm is not None else "none"'
|
||||
attrs['netvm']['save_attr'] = "netvm_qid"
|
||||
attrs['template_vm']['save'] = 'str(self.template_vm.qid) if self.template_vm and not self.is_updateable() else "none"'
|
||||
attrs['template_vm']['save_attr'] = "template_qid"
|
||||
attrs['label']['save'] = 'self.label.name'
|
||||
|
||||
self.uses_default_netvm = uses_default_netvm
|
||||
self.netvm = netvm
|
||||
if netvm is not None:
|
||||
netvm.connected_vms[qid] = self
|
||||
return attrs
|
||||
|
||||
self._mac = mac
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
# We use it in remove from disk to avoid removing rpm files (for templates)
|
||||
self.installed_by_rpm = installed_by_rpm
|
||||
attrs = self._get_attrs_config()
|
||||
for attr_name in sorted(attrs, key=lambda _x: attrs[_x]['order'] if 'order' in attrs[_x] else 1000):
|
||||
attr_config = attrs[attr_name]
|
||||
attr = attr_name
|
||||
if 'attr' in attr_config:
|
||||
attr = attr_config['attr']
|
||||
value = None
|
||||
if attr_name not in kwargs:
|
||||
if 'default' in attr_config:
|
||||
value = attr_config['default']
|
||||
else:
|
||||
value = kwargs[attr_name]
|
||||
if 'eval' in attr_config:
|
||||
setattr(self, attr, eval(attr_config['eval']))
|
||||
else:
|
||||
#print "setting %s to %s" % (attr, value)
|
||||
setattr(self, attr, value)
|
||||
|
||||
# Setup standard VM storage; some VM types may not use them all
|
||||
self.root_img = self.absolute_path(root_img, default_root_img)
|
||||
#Init private attrs
|
||||
self.__qid = self._qid
|
||||
|
||||
self.volatile_img = self.absolute_path(volatile_img, default_volatile_img)
|
||||
assert self.__qid < qubes_max_qid, "VM id out of bounds!"
|
||||
assert self.name is not None
|
||||
|
||||
self.private_img = self.absolute_path(private_img, default_private_img)
|
||||
if self.netvm is not None:
|
||||
self.netvm.connected_vms[self.qid] = self
|
||||
|
||||
self.firewall_conf = self.absolute_path(firewall_conf, default_firewall_conf_file)
|
||||
|
||||
self.config_file_template = config_template_pv
|
||||
|
||||
self.updateable = updateable
|
||||
self._label = label if label is not None else QubesVmLabels["red"]
|
||||
if self.dir_path is not None:
|
||||
self.icon_path = self.dir_path + "/icon.png"
|
||||
else:
|
||||
self.icon_path = None
|
||||
|
||||
# PCI devices - used only by NetVM
|
||||
if pcidevs is None or pcidevs == "none":
|
||||
self.pcidevs = []
|
||||
elif pcidevs.find('[') < 0:
|
||||
# Backward compatibility
|
||||
self.pcidevs = eval('[' + pcidevs + ']')
|
||||
else:
|
||||
self.pcidevs = eval(pcidevs)
|
||||
|
||||
self.memory = memory
|
||||
|
||||
if maxmem is None:
|
||||
host = QubesHost()
|
||||
total_mem_mb = host.memory_total/1024
|
||||
# Not in generic way to not create QubesHost() to frequently
|
||||
if self.maxmem is None:
|
||||
qubes_host = QubesHost()
|
||||
total_mem_mb = qubes_host.memory_total/1024
|
||||
self.maxmem = total_mem_mb/2
|
||||
else:
|
||||
self.maxmem = maxmem
|
||||
|
||||
self.template_vm = template_vm
|
||||
if template_vm is not None:
|
||||
if updateable:
|
||||
print >> sys.stderr, "ERROR: Template based VM cannot be updateable!"
|
||||
return False
|
||||
if not template_vm.is_template():
|
||||
print >> sys.stderr, "ERROR: template_qid={0} doesn't point to a valid TemplateVM".\
|
||||
format(template_vm.qid)
|
||||
return False
|
||||
|
||||
template_vm.appvms[qid] = self
|
||||
else:
|
||||
assert self.root_img is not None, "Missing root_img for standalone VM!"
|
||||
|
||||
self.kernel = kernel
|
||||
|
||||
if template_vm is not None:
|
||||
self.kernels_dir = template_vm.kernels_dir
|
||||
self.kernel = template_vm.kernel
|
||||
elif self.kernel is not None:
|
||||
self.kernels_dir = qubes_kernels_base_dir + "/" + self.kernel
|
||||
else:
|
||||
# for backward compatibility (or another rare case): kernel=None -> kernel in VM dir
|
||||
self.kernels_dir = self.dir_path + "/" + default_kernels_subdir
|
||||
|
||||
self.uses_default_kernel = uses_default_kernel
|
||||
|
||||
self.appmenus_templates_dir = None
|
||||
if updateable:
|
||||
self.appmenus_templates_dir = self.dir_path + "/" + default_appmenus_templates_subdir
|
||||
elif template_vm is not None:
|
||||
self.appmenus_templates_dir = template_vm.appmenus_templates_dir
|
||||
|
||||
# By default allow use all VCPUs
|
||||
if vcpus is None:
|
||||
if self.vcpus is None:
|
||||
qubes_host = QubesHost()
|
||||
self.vcpus = qubes_host.no_cpus
|
||||
|
||||
# Some additional checks for template based VM
|
||||
if self.template_vm is not None:
|
||||
if self.updateable:
|
||||
print >> sys.stderr, "ERROR: Template based VM cannot be updateable!"
|
||||
return False
|
||||
if not self.template_vm.is_template():
|
||||
print >> sys.stderr, "ERROR: template_qid={0} doesn't point to a valid TemplateVM".\
|
||||
format(self.template_vm.qid)
|
||||
return False
|
||||
self.template_vm.appvms[self.qid] = self
|
||||
else:
|
||||
self.vcpus = vcpus
|
||||
|
||||
self.uses_default_kernelopts = uses_default_kernelopts
|
||||
if self.uses_default_kernelopts:
|
||||
if len(self.pcidevs) > 0:
|
||||
self.kernelopts = default_kernelopts_pcidevs
|
||||
else:
|
||||
self.kernelopts = default_kernelopts
|
||||
else:
|
||||
self.kernelopts = kernelopts
|
||||
|
||||
self.services = {}
|
||||
if services is not None:
|
||||
self.services = eval(str(services))
|
||||
|
||||
# Internal VM (not shown in qubes-manager, doesn't create appmenus entries
|
||||
self.internal = internal
|
||||
assert self.root_img is not None, "Missing root_img for standalone VM!"
|
||||
|
||||
self.xid = -1
|
||||
self.xid = self.get_xid()
|
||||
@ -482,7 +494,7 @@ class QubesVm(object):
|
||||
self.appmenus_templates_dir = self.appmenus_templates_dir.replace(old_dirpath, new_dirpath)
|
||||
if self.icon_path is not None:
|
||||
self.icon_path = self.icon_path.replace(old_dirpath, new_dirpath)
|
||||
if 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.post_rename(old_name)
|
||||
@ -1408,6 +1420,18 @@ class QubesVm(object):
|
||||
subprocess.call (['/usr/sbin/xl', 'destroy', self.name])
|
||||
#xc.domain_destroy(self.get_xid())
|
||||
|
||||
def pause(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
xc.domain_pause(self.get_xid())
|
||||
|
||||
def unpause(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
xc.domain_unpause(self.get_xid())
|
||||
|
||||
def remove_from_disk(self):
|
||||
if dry_run:
|
||||
return
|
||||
@ -1417,25 +1441,16 @@ class QubesVm(object):
|
||||
|
||||
def get_xml_attrs(self):
|
||||
attrs = {}
|
||||
attrs["qid"] = str(self.qid)
|
||||
attrs["name"] = self.name
|
||||
attrs["dir_path"] = self.dir_path
|
||||
# Simple paths
|
||||
for prop in ['conf_file', 'root_img', 'volatile_img', 'private_img']:
|
||||
if hasattr(self, prop) and self.__getattribute__(prop) is not None:
|
||||
attrs[prop] = self.relative_path(self.__getattribute__(prop))
|
||||
# Simple string attrs
|
||||
for prop in ['memory', 'maxmem', 'pcidevs', 'vcpus', 'internal',\
|
||||
'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\
|
||||
'kernelopts', 'services', 'updateable', 'installed_by_rpm',\
|
||||
'uses_default_netvm' ]:
|
||||
if hasattr(self, prop):
|
||||
attrs[prop] = str(self.__getattribute__(prop))
|
||||
if self._mac is not None:
|
||||
attrs["mac"] = str(self._mac)
|
||||
attrs["netvm_qid"] = str(self.netvm.qid) if self.netvm is not None else "none"
|
||||
attrs["template_qid"] = str(self.template_vm.qid) if self.template_vm and not self.is_updateable() else "none"
|
||||
attrs["label"] = self.label.name
|
||||
attrs_config = self._get_attrs_config()
|
||||
for attr in attrs_config:
|
||||
attr_config = attrs_config[attr]
|
||||
if 'save' in attr_config:
|
||||
if 'save_skip' in attr_config and eval(attr_config['save_skip']):
|
||||
continue
|
||||
if 'save_attr' in attr_config:
|
||||
attrs[attr_config['save_attr']] = eval(attr_config['save'])
|
||||
else:
|
||||
attrs[attr] = eval(attr_config['save'])
|
||||
return attrs
|
||||
|
||||
def create_xml_element(self):
|
||||
@ -1453,28 +1468,27 @@ class QubesTemplateVm(QubesVm):
|
||||
"""
|
||||
A class that represents an TemplateVM. A child of QubesVm.
|
||||
"""
|
||||
|
||||
def _get_attrs_config(self):
|
||||
attrs_config = super(QubesTemplateVm, self)._get_attrs_config()
|
||||
attrs_config['dir_path']['eval'] = 'value if value is not None else qubes_templates_dir + "/" + self.name'
|
||||
attrs_config['updateable']['default'] = True
|
||||
attrs_config['label']['default'] = default_template_label
|
||||
|
||||
# New attributes
|
||||
|
||||
# Image for template changes
|
||||
attrs_config['rootcow_img'] = { 'eval': 'self.dir_path + "/" + default_rootcow_img' }
|
||||
# Clean image for root-cow and swap (AppVM side)
|
||||
attrs_config['clean_volatile_img'] = { 'eval': 'self.dir_path + "/" + default_clean_volatile_img' }
|
||||
|
||||
attrs_config['appmenus_templates_dir'] = { 'eval': 'self.dir_path + "/" + default_appmenus_templates_subdir' }
|
||||
return attrs_config
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
if "dir_path" not in kwargs or kwargs["dir_path"] is None:
|
||||
kwargs["dir_path"] = qubes_templates_dir + "/" + kwargs["name"]
|
||||
|
||||
if "updateable" not in kwargs or kwargs["updateable"] is None :
|
||||
kwargs["updateable"] = True
|
||||
|
||||
if "label" not in kwargs or kwargs["label"] == None:
|
||||
kwargs["label"] = default_template_label
|
||||
|
||||
super(QubesTemplateVm, self).__init__(**kwargs)
|
||||
|
||||
dir_path = kwargs["dir_path"]
|
||||
|
||||
# Clean image for root-cow and swap (AppVM side)
|
||||
self.clean_volatile_img = self.dir_path + "/" + default_clean_volatile_img
|
||||
|
||||
# Image for template changes
|
||||
self.rootcow_img = self.dir_path + "/" + default_rootcow_img
|
||||
|
||||
self.appmenus_templates_dir = self.dir_path + "/" + default_appmenus_templates_subdir
|
||||
self.appvms = QubesVmCollection()
|
||||
|
||||
@property
|
||||
@ -1649,44 +1663,40 @@ class QubesTemplateVm(QubesVm):
|
||||
f_cow.close ()
|
||||
f_root.close()
|
||||
|
||||
def get_xml_attrs(self):
|
||||
attrs = super(QubesTemplateVm, self).get_xml_attrs()
|
||||
attrs["clean_volatile_img"] = self.clean_volatile_img
|
||||
attrs["rootcow_img"] = self.rootcow_img
|
||||
return attrs
|
||||
|
||||
class QubesNetVm(QubesVm):
|
||||
"""
|
||||
A class that represents a NetVM. A child of QubesCowVM.
|
||||
"""
|
||||
def _get_attrs_config(self):
|
||||
attrs_config = super(QubesNetVm, self)._get_attrs_config()
|
||||
attrs_config['dir_path']['eval'] = 'value if value is not None else qubes_servicevms_dir + "/" + self.name'
|
||||
attrs_config['label']['default'] = default_servicevm_label
|
||||
attrs_config['vcpus']['default'] = default_servicevm_vcpus
|
||||
attrs_config['memory']['default'] = 200
|
||||
attrs_config['maxmem']['eval'] = 'self.memory'
|
||||
|
||||
# New attributes
|
||||
attrs_config['netid'] = { 'save': 'str(self.netid)', 'order': 30 }
|
||||
attrs_config['netprefix'] = { 'eval': '"10.137.{0}.".format(self.netid)' }
|
||||
attrs_config['dispnetprefix'] = { 'eval': '"10.138.{0}.".format(self.netid)' }
|
||||
|
||||
# Dont save netvm prop
|
||||
attrs_config['netvm'].pop('save')
|
||||
attrs_config['uses_default_netvm'].pop('save')
|
||||
|
||||
return attrs_config
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
netid = kwargs.pop("netid")
|
||||
self.netid = netid
|
||||
self.__network = "10.137.{0}.0".format(netid)
|
||||
self.netprefix = "10.137.{0}.".format(netid)
|
||||
self.dispnetprefix = "10.138.{0}.".format(netid)
|
||||
super(QubesNetVm, self).__init__(**kwargs)
|
||||
self.connected_vms = QubesVmCollection()
|
||||
|
||||
self.__network = "10.137.{0}.0".format(self.netid)
|
||||
self.__netmask = vm_default_netmask
|
||||
self.__gateway = self.netprefix + "1"
|
||||
self.__secondary_dns = self.netprefix + "254"
|
||||
|
||||
if "dir_path" not in kwargs or kwargs["dir_path"] is None:
|
||||
kwargs["dir_path"] = qubes_servicevms_dir + "/" + kwargs["name"]
|
||||
self.__external_ip_allowed_xids = set()
|
||||
|
||||
if "label" not in kwargs or kwargs["label"] is None:
|
||||
kwargs["label"] = default_servicevm_label
|
||||
|
||||
if "vcpus" not in kwargs or kwargs["vcpus"] is None:
|
||||
kwargs["vcpus"] = default_servicevm_vcpus
|
||||
|
||||
if "memory" not in kwargs or kwargs["memory"] is None:
|
||||
kwargs["memory"] = 200
|
||||
|
||||
kwargs["maxmem"] = kwargs["memory"]
|
||||
|
||||
super(QubesNetVm, self).__init__(**kwargs)
|
||||
self.connected_vms = QubesVmCollection()
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "NetVM"
|
||||
@ -1794,19 +1804,20 @@ class QubesNetVm(QubesVm):
|
||||
self.__external_ip_allowed_xids.discard(int(xid))
|
||||
self.update_external_ip_permissions()
|
||||
|
||||
def get_xml_attrs(self):
|
||||
attrs = super(QubesNetVm, self).get_xml_attrs()
|
||||
attrs.pop("netvm_qid")
|
||||
attrs.pop("uses_default_netvm")
|
||||
attrs["netid"] = str(self.netid)
|
||||
return attrs
|
||||
|
||||
class QubesProxyVm(QubesNetVm):
|
||||
"""
|
||||
A class that represents a ProxyVM, ex FirewallVM. A child of QubesNetVM.
|
||||
"""
|
||||
|
||||
def _get_attrs_config(self):
|
||||
attrs_config = super(QubesProxyVm, self)._get_attrs_config()
|
||||
attrs_config['uses_default_netvm']['eval'] = 'False'
|
||||
# Save netvm prop again
|
||||
attrs_config['netvm']['save'] = 'str(self.netvm.qid) if self.netvm is not None else "none"'
|
||||
|
||||
return attrs_config
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
kwargs["uses_default_netvm"] = False
|
||||
super(QubesProxyVm, self).__init__(**kwargs)
|
||||
self.rules_applied = None
|
||||
|
||||
@ -1884,12 +1895,12 @@ class QubesProxyVm(QubesNetVm):
|
||||
if xid < 0: # VM not active ATM
|
||||
continue
|
||||
|
||||
vif = vm.vif
|
||||
if vif is None:
|
||||
ip = vm.ip
|
||||
if ip is None:
|
||||
continue
|
||||
|
||||
iptables += "# '{0}' VM:\n".format(vm.name)
|
||||
iptables += "-A FORWARD ! -s {0}/32 -i {1} -j DROP\n".format(vm.ip, vif)
|
||||
# Anti-spoof rules are added by vif-script (vif-route-qubes), here we trust IP address
|
||||
|
||||
accept_action = "ACCEPT"
|
||||
reject_action = "REJECT --reject-with icmp-host-prohibited"
|
||||
@ -1902,7 +1913,7 @@ class QubesProxyVm(QubesNetVm):
|
||||
rules_action = accept_action
|
||||
|
||||
for rule in conf["rules"]:
|
||||
iptables += "-A FORWARD -i {0} -d {1}".format(vif, rule["address"])
|
||||
iptables += "-A FORWARD -s {0} -d {1}".format(ip, rule["address"])
|
||||
if rule["netmask"] != 32:
|
||||
iptables += "/{0}".format(rule["netmask"])
|
||||
|
||||
@ -1917,12 +1928,12 @@ class QubesProxyVm(QubesNetVm):
|
||||
|
||||
if conf["allowDns"]:
|
||||
# PREROUTING does DNAT to NetVM DNSes, so we need self.netvm. properties
|
||||
iptables += "-A FORWARD -i {0} -p udp -d {1} --dport 53 -j ACCEPT\n".format(vif,self.netvm.gateway)
|
||||
iptables += "-A FORWARD -i {0} -p udp -d {1} --dport 53 -j ACCEPT\n".format(vif,self.netvm.secondary_dns)
|
||||
iptables += "-A FORWARD -s {0} -p udp -d {1} --dport 53 -j ACCEPT\n".format(ip,self.netvm.gateway)
|
||||
iptables += "-A FORWARD -s {0} -p udp -d {1} --dport 53 -j ACCEPT\n".format(ip,self.netvm.secondary_dns)
|
||||
if conf["allowIcmp"]:
|
||||
iptables += "-A FORWARD -i {0} -p icmp -j ACCEPT\n".format(vif)
|
||||
iptables += "-A FORWARD -s {0} -p icmp -j ACCEPT\n".format(ip)
|
||||
|
||||
iptables += "-A FORWARD -i {0} -j {1}\n".format(vif, default_action)
|
||||
iptables += "-A FORWARD -s {0} -j {1}\n".format(ip, default_action)
|
||||
iptables += "COMMIT\n"
|
||||
xs.write('', "/local/domain/"+str(self.get_xid())+"/qubes_iptables_domainrules/"+str(xid), iptables)
|
||||
# no need for ending -A FORWARD -j DROP, cause default action is DROP
|
||||
@ -1932,11 +1943,6 @@ class QubesProxyVm(QubesNetVm):
|
||||
self.rules_applied = None
|
||||
xs.write('', "/local/domain/{0}/qubes_iptables".format(self.get_xid()), 'reload')
|
||||
|
||||
def get_xml_attrs(self):
|
||||
attrs = super(QubesProxyVm, self).get_xml_attrs()
|
||||
attrs["netvm_qid"] = str(self.netvm.qid) if self.netvm is not None else "none"
|
||||
return attrs
|
||||
|
||||
class QubesDom0NetVm(QubesNetVm):
|
||||
def __init__(self):
|
||||
super(QubesDom0NetVm, self).__init__(qid=0, name="dom0", netid=0,
|
||||
@ -2001,15 +2007,26 @@ class QubesDisposableVm(QubesVm):
|
||||
"""
|
||||
A class that represents an DisposableVM. A child of QubesVm.
|
||||
"""
|
||||
|
||||
def _get_attrs_config(self):
|
||||
attrs_config = super(QubesDisposableVm, self)._get_attrs_config()
|
||||
|
||||
# New attributes
|
||||
attrs_config['dispid'] = { 'save': 'str(self.dispid)' }
|
||||
|
||||
return attrs_config
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
template_vm = kwargs["template_vm"]
|
||||
assert template_vm is not None, "Missing template_vm for DisposableVM!"
|
||||
|
||||
self.dispid = kwargs.pop("dispid")
|
||||
|
||||
super(QubesDisposableVm, self).__init__(dir_path="/nonexistent", **kwargs)
|
||||
|
||||
assert self.template_vm is not None, "Missing template_vm for DisposableVM!"
|
||||
|
||||
# Use DispVM icon with the same color
|
||||
if self._label:
|
||||
self._label = QubesDispVmLabels[self._label.name]
|
||||
self.icon_path = self._label.icon_path
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "DisposableVM"
|
||||
@ -2023,6 +2040,7 @@ class QubesDisposableVm(QubesVm):
|
||||
|
||||
|
||||
def get_xml_attrs(self):
|
||||
# Minimal set - do not inherit rest of attributes
|
||||
attrs = {}
|
||||
attrs["qid"] = str(self.qid)
|
||||
attrs["name"] = self.name
|
||||
@ -2040,12 +2058,11 @@ class QubesAppVm(QubesVm):
|
||||
"""
|
||||
A class that represents an AppVM. A child of QubesVm.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
def _get_attrs_config(self):
|
||||
attrs_config = super(QubesAppVm, self)._get_attrs_config()
|
||||
attrs_config['dir_path']['eval'] = 'value if value is not None else qubes_appvms_dir + "/" + self.name'
|
||||
|
||||
if "dir_path" not in kwargs or kwargs["dir_path"] is None:
|
||||
kwargs["dir_path"] = qubes_appvms_dir + "/" + kwargs["name"]
|
||||
|
||||
super(QubesAppVm, self).__init__(**kwargs)
|
||||
return attrs_config
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
@ -2090,6 +2107,22 @@ class QubesHVm(QubesVm):
|
||||
|
||||
# FIXME: logically should inherit after QubesAppVm, but none of its methods
|
||||
# are useful for HVM
|
||||
|
||||
def _get_attrs_config(self):
|
||||
attrs = super(QubesHVm, self)._get_attrs_config()
|
||||
attrs.pop('kernel')
|
||||
attrs.pop('kernels_dir')
|
||||
attrs.pop('kernelopts')
|
||||
attrs.pop('uses_default_kernel')
|
||||
attrs.pop('uses_default_kernelopts')
|
||||
attrs['private_img']['eval'] = 'None'
|
||||
attrs['volatile_img']['eval'] = 'None'
|
||||
attrs['config_file_template']['eval'] = 'config_template_hvm'
|
||||
attrs['drive'] = { 'save': 'str(self.drive)' }
|
||||
attrs['maxmem'].pop('save')
|
||||
|
||||
return attrs
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
if "dir_path" not in kwargs or kwargs["dir_path"] is None:
|
||||
@ -2102,22 +2135,10 @@ class QubesHVm(QubesVm):
|
||||
kwargs["memory"] = default_hvm_memory
|
||||
|
||||
super(QubesHVm, self).__init__(**kwargs)
|
||||
self.updateable = True
|
||||
self.config_file_template = config_template_hvm
|
||||
self.private_img = None
|
||||
self.volatile_img = None
|
||||
# remove settings not used by HVM (at least for now)
|
||||
self.__delattr__('kernel')
|
||||
self.__delattr__('kernelopts')
|
||||
self.__delattr__('uses_default_kernel')
|
||||
self.__delattr__('uses_default_kernelopts')
|
||||
# HVM doesn't support dynamic memory management
|
||||
self.maxmem = self.memory
|
||||
|
||||
self.drive = None
|
||||
if 'drive' in kwargs.keys():
|
||||
self.drive = kwargs['drive']
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "HVM"
|
||||
@ -2125,15 +2146,6 @@ class QubesHVm(QubesVm):
|
||||
def is_appvm(self):
|
||||
return True
|
||||
|
||||
def get_clone_attrs(self):
|
||||
attrs = super(QubesHVm, self).get_clone_attrs()
|
||||
attrs.remove('kernel')
|
||||
attrs.remove('uses_default_kernel')
|
||||
attrs.remove('kernelopts')
|
||||
attrs.remove('uses_default_kernelopts')
|
||||
attrs.remove('maxmem')
|
||||
return attrs
|
||||
|
||||
def create_on_disk(self, verbose, source_template = None):
|
||||
if dry_run:
|
||||
return
|
||||
@ -2235,6 +2247,20 @@ class QubesHVm(QubesVm):
|
||||
def start_qrexec_daemon(self, **kwargs):
|
||||
pass
|
||||
|
||||
def pause(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
xc.domain_pause(self.stubdom_xid)
|
||||
super(QubesHVm, self).pause()
|
||||
|
||||
def unpause(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
xc.domain_unpause(self.stubdom_xid)
|
||||
super(QubesHVm, self).unpause()
|
||||
|
||||
def get_xml_attrs(self):
|
||||
attrs = super(QubesHVm, self).get_xml_attrs()
|
||||
attrs["drive"] = str(self.drive)
|
||||
@ -2608,7 +2634,7 @@ class QubesVmCollection(dict):
|
||||
"installed_by_rpm", "updateable", "internal",
|
||||
"uses_default_netvm", "label", "memory", "vcpus", "pcidevs",
|
||||
"maxmem", "kernel", "uses_default_kernel", "kernelopts", "uses_default_kernelopts",
|
||||
"mac", "services" )
|
||||
"mac", "services", "include_in_backups" )
|
||||
|
||||
for attribute in common_attr_list:
|
||||
kwargs[attribute] = element.get(attribute)
|
||||
@ -2619,6 +2645,9 @@ class QubesVmCollection(dict):
|
||||
if "updateable" in kwargs:
|
||||
kwargs["updateable"] = True if kwargs["updateable"] == "True" else False
|
||||
|
||||
if "include_in_backups" in kwargs:
|
||||
kwargs["include_in_backups"] = True if kwargs["include_in_backups"] == "True" else False
|
||||
|
||||
if "installed_by_rpm" in kwargs:
|
||||
kwargs["installed_by_rpm"] = True if kwargs["installed_by_rpm"] == "True" else False
|
||||
|
||||
|
@ -43,6 +43,7 @@ def do_list(vm):
|
||||
print fmt.format ("netvm", vm.netvm.name)
|
||||
print fmt.format ("updateable?", vm.is_updateable())
|
||||
print fmt.format ("installed by RPM?", vm.installed_by_rpm)
|
||||
print fmt.format ("include in backups", vm.include_in_backups)
|
||||
print fmt.format ("dir", vm.dir_path)
|
||||
print fmt.format ("config", vm.conf_file)
|
||||
print fmt.format ("pcidevs", vm.pcidevs)
|
||||
@ -326,7 +327,24 @@ def set_drive(vms, vm, args):
|
||||
vm.drive = args[0]
|
||||
return True
|
||||
|
||||
def set_include_in_backups(vms, vm, args):
|
||||
if len (args) != 1:
|
||||
print >> sys.stderr, "Missing value (True/False)!"
|
||||
return False
|
||||
|
||||
vm.include_in_backups = bool(eval(args[0].capitalize()))
|
||||
return True
|
||||
|
||||
def set_include_in_backups(vms, vm, args):
|
||||
if len (args) != 1:
|
||||
print >> sys.stderr, "Missing value (True/False)!"
|
||||
return False
|
||||
|
||||
vm.include_in_backups = bool(eval(args[0].capitalize()))
|
||||
return True
|
||||
|
||||
properties = {
|
||||
"include_in_backups": set_include_in_backups,
|
||||
"updateable": set_updateable,
|
||||
"nonupdateable": set_nonupdateable,
|
||||
"pcidevs": set_pcidevs,
|
||||
|
@ -63,13 +63,13 @@ def vm_run_cmd(vm, cmd, options):
|
||||
if options.pause:
|
||||
if options.verbose:
|
||||
print >> sys.stderr, "Pausing VM: '{0}'...".format(vm.name)
|
||||
subprocess.call (["/usr/sbin/xl", "pause", vm.name])
|
||||
vm.pause()
|
||||
return
|
||||
|
||||
if options.unpause:
|
||||
if options.verbose:
|
||||
print >> sys.stderr, "UnPausing VM: '{0}'...".format(vm.name)
|
||||
subprocess.call (["/usr/sbin/xl", "unpause", vm.name])
|
||||
vm.unpause()
|
||||
return
|
||||
|
||||
if options.verbose:
|
||||
|
@ -29,7 +29,7 @@ case "$command" in
|
||||
online)
|
||||
ifconfig ${vif} up
|
||||
echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp
|
||||
ipcmd='replace'
|
||||
ipcmd='add'
|
||||
iptables_cmd='-I PREROUTING 1'
|
||||
cmdprefix=''
|
||||
;;
|
||||
@ -41,14 +41,20 @@ case "$command" in
|
||||
;;
|
||||
esac
|
||||
|
||||
domid=${vif/vif/}
|
||||
domid=${domid/.*/}
|
||||
# metric must be possitive, but prefer later interface
|
||||
# 32752 is max XID aka domid
|
||||
metric=$[ 32752 - $domid ]
|
||||
|
||||
if [ "${ip}" ] ; then
|
||||
# If we've been given a list of IP addresses, then add routes from dom0 to
|
||||
# the guest using those addresses.
|
||||
for addr in ${ip} ; do
|
||||
${cmdprefix} ip route ${ipcmd} ${addr} dev ${vif} || true
|
||||
${cmdprefix} ip route ${ipcmd} ${addr} dev ${vif} metric $metric
|
||||
done
|
||||
echo ${cmdprefix} iptables -t raw $iptables_cmd -i ${vif} \! -s ${ip} -j DROP
|
||||
${cmdprefix} iptables $iptables_cmd -i ${vif} \! -s ${ip} -j DROP
|
||||
${cmdprefix} iptables -t raw $iptables_cmd -i ${vif} \! -s ${ip} -j DROP
|
||||
fi
|
||||
|
||||
log debug "Successful vif-route-qubes $command for $vif."
|
||||
|