Merge branch 'hvm' of 10.141.1.101:/var/lib/qubes/git/marmarek/core into hvm

Conflicts:
	version_dom0
This commit is contained in:
Joanna Rutkowska 2012-03-09 00:01:06 +01:00
commit 608c142756
13 changed files with 293 additions and 240 deletions

BIN
dom0/icons/dispvm-black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
dom0/icons/dispvm-blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
dom0/icons/dispvm-gray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
dom0/icons/dispvm-green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
dom0/icons/dispvm-red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -186,6 +186,17 @@ QubesVmLabels = {
"black" : QubesVmLabel ("black", 8), "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_appvm_label = QubesVmLabels["red"]
default_template_label = QubesVmLabels["gray"] default_template_label = QubesVmLabels["gray"]
default_servicevm_label = QubesVmLabels["red"] default_servicevm_label = QubesVmLabels["red"]
@ -198,140 +209,141 @@ class QubesVm(object):
Note that qid is not the same as Xen's domid! Note that qid is not the same as Xen's domid!
""" """
def __init__(self, qid, name, def _get_attrs_config(self):
dir_path, conf_file = None, """ Object attributes for serialization/deserialization
uses_default_netvm = True, inner dict keys:
netvm = None, - order: initialization order (to keep dependency intact)
installed_by_rpm = False, attrs without order will be evaluated at the end
updateable = False, - default: default value used when attr not given to object constructor
label = None, - attr: set value to this attribute instead of parameter name
root_img = None, - eval: assign result of this expression instead of value directly;
private_img = None, local variable 'value' contains attribute value (or default if it was not given)
memory = default_memory, - save: use evaluation result as value for XML serialization; only attrs with 'save' key will be saved in XML
maxmem = None, - save_skip: if present and evaluates to true, attr will be omitted in XML
template_vm = None, - save_attr: save to this XML attribute instead of parameter name
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):
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!" ### Mark attrs for XML inclusion
self.__qid = qid # Simple string attrs
self.name = name 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 return attrs
self.netvm = netvm
if netvm is not None:
netvm.connected_vms[qid] = self
self._mac = mac def __init__(self, **kwargs):
# We use it in remove from disk to avoid removing rpm files (for templates) attrs = self._get_attrs_config()
self.installed_by_rpm = installed_by_rpm 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 #Init private attrs
self.root_img = self.absolute_path(root_img, default_root_img) 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) # Not in generic way to not create QubesHost() to frequently
if self.maxmem is None:
self.config_file_template = config_template_pv qubes_host = QubesHost()
total_mem_mb = qubes_host.memory_total/1024
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
self.maxmem = total_mem_mb/2 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 # By default allow use all VCPUs
if vcpus is None: if self.vcpus is None:
qubes_host = QubesHost() qubes_host = QubesHost()
self.vcpus = qubes_host.no_cpus 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: else:
self.vcpus = vcpus assert self.root_img is not None, "Missing root_img for standalone VM!"
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
self.xid = -1 self.xid = -1
self.xid = self.get_xid() 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) self.appmenus_templates_dir = self.appmenus_templates_dir.replace(old_dirpath, new_dirpath)
if self.icon_path is not None: if self.icon_path is not None:
self.icon_path = self.icon_path.replace(old_dirpath, new_dirpath) 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.kernels_dir = self.kernels_dir.replace(old_dirpath, new_dirpath)
self.post_rename(old_name) self.post_rename(old_name)
@ -1408,6 +1420,18 @@ class QubesVm(object):
subprocess.call (['/usr/sbin/xl', 'destroy', self.name]) subprocess.call (['/usr/sbin/xl', 'destroy', self.name])
#xc.domain_destroy(self.get_xid()) #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): def remove_from_disk(self):
if dry_run: if dry_run:
return return
@ -1417,25 +1441,16 @@ class QubesVm(object):
def get_xml_attrs(self): def get_xml_attrs(self):
attrs = {} attrs = {}
attrs["qid"] = str(self.qid) attrs_config = self._get_attrs_config()
attrs["name"] = self.name for attr in attrs_config:
attrs["dir_path"] = self.dir_path attr_config = attrs_config[attr]
# Simple paths if 'save' in attr_config:
for prop in ['conf_file', 'root_img', 'volatile_img', 'private_img']: if 'save_skip' in attr_config and eval(attr_config['save_skip']):
if hasattr(self, prop) and self.__getattribute__(prop) is not None: continue
attrs[prop] = self.relative_path(self.__getattribute__(prop)) if 'save_attr' in attr_config:
# Simple string attrs attrs[attr_config['save_attr']] = eval(attr_config['save'])
for prop in ['memory', 'maxmem', 'pcidevs', 'vcpus', 'internal',\ else:
'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\ attrs[attr] = eval(attr_config['save'])
'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
return attrs return attrs
def create_xml_element(self): def create_xml_element(self):
@ -1453,28 +1468,27 @@ class QubesTemplateVm(QubesVm):
""" """
A class that represents an TemplateVM. A child of 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): 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) 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() self.appvms = QubesVmCollection()
@property @property
@ -1649,44 +1663,40 @@ class QubesTemplateVm(QubesVm):
f_cow.close () f_cow.close ()
f_root.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): class QubesNetVm(QubesVm):
""" """
A class that represents a NetVM. A child of QubesCowVM. 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): def __init__(self, **kwargs):
netid = kwargs.pop("netid") super(QubesNetVm, self).__init__(**kwargs)
self.netid = netid self.connected_vms = QubesVmCollection()
self.__network = "10.137.{0}.0".format(netid)
self.netprefix = "10.137.{0}.".format(netid) self.__network = "10.137.{0}.0".format(self.netid)
self.dispnetprefix = "10.138.{0}.".format(netid)
self.__netmask = vm_default_netmask self.__netmask = vm_default_netmask
self.__gateway = self.netprefix + "1" self.__gateway = self.netprefix + "1"
self.__secondary_dns = self.netprefix + "254" 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() 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 @property
def type(self): def type(self):
return "NetVM" return "NetVM"
@ -1794,19 +1804,20 @@ class QubesNetVm(QubesVm):
self.__external_ip_allowed_xids.discard(int(xid)) self.__external_ip_allowed_xids.discard(int(xid))
self.update_external_ip_permissions() 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): class QubesProxyVm(QubesNetVm):
""" """
A class that represents a ProxyVM, ex FirewallVM. A child of 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): def __init__(self, **kwargs):
kwargs["uses_default_netvm"] = False
super(QubesProxyVm, self).__init__(**kwargs) super(QubesProxyVm, self).__init__(**kwargs)
self.rules_applied = None self.rules_applied = None
@ -1884,12 +1895,12 @@ class QubesProxyVm(QubesNetVm):
if xid < 0: # VM not active ATM if xid < 0: # VM not active ATM
continue continue
vif = vm.vif ip = vm.ip
if vif is None: if ip is None:
continue continue
iptables += "# '{0}' VM:\n".format(vm.name) 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" accept_action = "ACCEPT"
reject_action = "REJECT --reject-with icmp-host-prohibited" reject_action = "REJECT --reject-with icmp-host-prohibited"
@ -1902,7 +1913,7 @@ class QubesProxyVm(QubesNetVm):
rules_action = accept_action rules_action = accept_action
for rule in conf["rules"]: 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: if rule["netmask"] != 32:
iptables += "/{0}".format(rule["netmask"]) iptables += "/{0}".format(rule["netmask"])
@ -1917,12 +1928,12 @@ class QubesProxyVm(QubesNetVm):
if conf["allowDns"]: if conf["allowDns"]:
# PREROUTING does DNAT to NetVM DNSes, so we need self.netvm. properties # 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 -s {0} -p udp -d {1} --dport 53 -j ACCEPT\n".format(ip,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.secondary_dns)
if conf["allowIcmp"]: 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" iptables += "COMMIT\n"
xs.write('', "/local/domain/"+str(self.get_xid())+"/qubes_iptables_domainrules/"+str(xid), iptables) 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 # no need for ending -A FORWARD -j DROP, cause default action is DROP
@ -1932,11 +1943,6 @@ class QubesProxyVm(QubesNetVm):
self.rules_applied = None self.rules_applied = None
xs.write('', "/local/domain/{0}/qubes_iptables".format(self.get_xid()), 'reload') 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): class QubesDom0NetVm(QubesNetVm):
def __init__(self): def __init__(self):
super(QubesDom0NetVm, self).__init__(qid=0, name="dom0", netid=0, 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. 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): 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) 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 @property
def type(self): def type(self):
return "DisposableVM" return "DisposableVM"
@ -2023,6 +2040,7 @@ class QubesDisposableVm(QubesVm):
def get_xml_attrs(self): def get_xml_attrs(self):
# Minimal set - do not inherit rest of attributes
attrs = {} attrs = {}
attrs["qid"] = str(self.qid) attrs["qid"] = str(self.qid)
attrs["name"] = self.name attrs["name"] = self.name
@ -2040,12 +2058,11 @@ class QubesAppVm(QubesVm):
""" """
A class that represents an AppVM. A child of 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: return attrs_config
kwargs["dir_path"] = qubes_appvms_dir + "/" + kwargs["name"]
super(QubesAppVm, self).__init__(**kwargs)
@property @property
def type(self): def type(self):
@ -2090,6 +2107,22 @@ class QubesHVm(QubesVm):
# FIXME: logically should inherit after QubesAppVm, but none of its methods # FIXME: logically should inherit after QubesAppVm, but none of its methods
# are useful for HVM # 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): def __init__(self, **kwargs):
if "dir_path" not in kwargs or kwargs["dir_path"] is None: if "dir_path" not in kwargs or kwargs["dir_path"] is None:
@ -2102,22 +2135,10 @@ class QubesHVm(QubesVm):
kwargs["memory"] = default_hvm_memory kwargs["memory"] = default_hvm_memory
super(QubesHVm, self).__init__(**kwargs) super(QubesHVm, self).__init__(**kwargs)
self.updateable = True
self.config_file_template = config_template_hvm 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 # HVM doesn't support dynamic memory management
self.maxmem = self.memory self.maxmem = self.memory
self.drive = None
if 'drive' in kwargs.keys():
self.drive = kwargs['drive']
@property @property
def type(self): def type(self):
return "HVM" return "HVM"
@ -2125,15 +2146,6 @@ class QubesHVm(QubesVm):
def is_appvm(self): def is_appvm(self):
return True 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): def create_on_disk(self, verbose, source_template = None):
if dry_run: if dry_run:
return return
@ -2235,6 +2247,20 @@ class QubesHVm(QubesVm):
def start_qrexec_daemon(self, **kwargs): def start_qrexec_daemon(self, **kwargs):
pass 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): def get_xml_attrs(self):
attrs = super(QubesHVm, self).get_xml_attrs() attrs = super(QubesHVm, self).get_xml_attrs()
attrs["drive"] = str(self.drive) attrs["drive"] = str(self.drive)
@ -2608,7 +2634,7 @@ class QubesVmCollection(dict):
"installed_by_rpm", "updateable", "internal", "installed_by_rpm", "updateable", "internal",
"uses_default_netvm", "label", "memory", "vcpus", "pcidevs", "uses_default_netvm", "label", "memory", "vcpus", "pcidevs",
"maxmem", "kernel", "uses_default_kernel", "kernelopts", "uses_default_kernelopts", "maxmem", "kernel", "uses_default_kernel", "kernelopts", "uses_default_kernelopts",
"mac", "services" ) "mac", "services", "include_in_backups" )
for attribute in common_attr_list: for attribute in common_attr_list:
kwargs[attribute] = element.get(attribute) kwargs[attribute] = element.get(attribute)
@ -2619,6 +2645,9 @@ class QubesVmCollection(dict):
if "updateable" in kwargs: if "updateable" in kwargs:
kwargs["updateable"] = True if kwargs["updateable"] == "True" else False 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: if "installed_by_rpm" in kwargs:
kwargs["installed_by_rpm"] = True if kwargs["installed_by_rpm"] == "True" else False kwargs["installed_by_rpm"] = True if kwargs["installed_by_rpm"] == "True" else False

View File

@ -43,6 +43,7 @@ def do_list(vm):
print fmt.format ("netvm", vm.netvm.name) print fmt.format ("netvm", vm.netvm.name)
print fmt.format ("updateable?", vm.is_updateable()) print fmt.format ("updateable?", vm.is_updateable())
print fmt.format ("installed by RPM?", vm.installed_by_rpm) 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 ("dir", vm.dir_path)
print fmt.format ("config", vm.conf_file) print fmt.format ("config", vm.conf_file)
print fmt.format ("pcidevs", vm.pcidevs) print fmt.format ("pcidevs", vm.pcidevs)
@ -326,7 +327,24 @@ def set_drive(vms, vm, args):
vm.drive = args[0] vm.drive = args[0]
return True 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 = { properties = {
"include_in_backups": set_include_in_backups,
"updateable": set_updateable, "updateable": set_updateable,
"nonupdateable": set_nonupdateable, "nonupdateable": set_nonupdateable,
"pcidevs": set_pcidevs, "pcidevs": set_pcidevs,

View File

@ -63,13 +63,13 @@ def vm_run_cmd(vm, cmd, options):
if options.pause: if options.pause:
if options.verbose: if options.verbose:
print >> sys.stderr, "Pausing VM: '{0}'...".format(vm.name) print >> sys.stderr, "Pausing VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xl", "pause", vm.name]) vm.pause()
return return
if options.unpause: if options.unpause:
if options.verbose: if options.verbose:
print >> sys.stderr, "UnPausing VM: '{0}'...".format(vm.name) print >> sys.stderr, "UnPausing VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xl", "unpause", vm.name]) vm.unpause()
return return
if options.verbose: if options.verbose:

View File

@ -29,7 +29,7 @@ case "$command" in
online) online)
ifconfig ${vif} up ifconfig ${vif} up
echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp
ipcmd='replace' ipcmd='add'
iptables_cmd='-I PREROUTING 1' iptables_cmd='-I PREROUTING 1'
cmdprefix='' cmdprefix=''
;; ;;
@ -41,14 +41,20 @@ case "$command" in
;; ;;
esac 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 [ "${ip}" ] ; then
# If we've been given a list of IP addresses, then add routes from dom0 to # If we've been given a list of IP addresses, then add routes from dom0 to
# the guest using those addresses. # the guest using those addresses.
for addr in ${ip} ; do for addr in ${ip} ; do
${cmdprefix} ip route ${ipcmd} ${addr} dev ${vif} || true ${cmdprefix} ip route ${ipcmd} ${addr} dev ${vif} metric $metric
done done
echo ${cmdprefix} iptables -t raw $iptables_cmd -i ${vif} \! -s ${ip} -j DROP 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 fi
log debug "Successful vif-route-qubes $command for $vif." log debug "Successful vif-route-qubes $command for $vif."