Split core qubes.py into modules
This commit is contained in:
parent
41675aa30a
commit
ecd8837113
1516
dom0/core-modules/000QubesVm.py
Normal file
1516
dom0/core-modules/000QubesVm.py
Normal file
File diff suppressed because it is too large
Load Diff
212
dom0/core-modules/003QubesTemplateVm.py
Normal file
212
dom0/core-modules/003QubesTemplateVm.py
Normal file
@ -0,0 +1,212 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
# Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from qubes.qubes import QubesVm,register_qubes_vm_class,dry_run
|
||||
from qubes.qubes import QubesVmCollection,QubesException,QubesVmLabels
|
||||
from qubes.qubes import defaults,system_path,vm_files
|
||||
|
||||
class QubesTemplateVm(QubesVm):
|
||||
"""
|
||||
A class that represents an TemplateVM. A child of QubesVm.
|
||||
"""
|
||||
|
||||
# In which order load this VM type from qubes.xml
|
||||
load_order = 50
|
||||
|
||||
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 os.path.join(system_path["qubes_templates_dir"], self.name)'
|
||||
attrs_config['label']['default'] = defaults["template_label"]
|
||||
|
||||
# New attributes
|
||||
|
||||
# Image for template changes
|
||||
attrs_config['rootcow_img'] = { 'eval': 'os.path.join(self.dir_path, vm_files["rootcow_img"])' }
|
||||
# Clean image for root-cow and swap (AppVM side)
|
||||
attrs_config['clean_volatile_img'] = { 'eval': 'os.path.join(self.dir_path, vm_files["clean_volatile_img"])' }
|
||||
|
||||
attrs_config['appmenus_templates_dir'] = { 'eval': 'os.path.join(self.dir_path, vm_files["appmenus_templates_subdir"])' }
|
||||
return attrs_config
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
super(QubesTemplateVm, self).__init__(**kwargs)
|
||||
|
||||
self.appvms = QubesVmCollection()
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "TemplateVM"
|
||||
|
||||
@property
|
||||
def updateable(self):
|
||||
return True
|
||||
|
||||
def is_template(self):
|
||||
return True
|
||||
|
||||
def get_firewall_defaults(self):
|
||||
return { "rules": list(), "allow": False, "allowDns": False, "allowIcmp": False, "allowYumProxy": True }
|
||||
|
||||
def get_rootdev(self, source_template=None):
|
||||
return "'script:origin:{dir}/root.img:{dir}/root-cow.img,xvda,w',".format(dir=self.dir_path)
|
||||
|
||||
def clone_disk_files(self, src_vm, verbose):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
super(QubesTemplateVm, self).clone_disk_files(src_vm=src_vm, verbose=verbose)
|
||||
|
||||
for whitelist in ['vm-' + vm_files["whitelisted_appmenus"], 'netvm-' + vm_files["whitelisted_appmenus"]]:
|
||||
if os.path.exists(os.path.join(src_vm.dir_path, whitelist)):
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Copying default whitelisted apps list: {0}".\
|
||||
format(os.path.join(self.dir_path, whitelist))
|
||||
shutil.copy(os.path.join(src_vm.dir_path, whitelist),
|
||||
os.path.join(self.dir_path, whitelist))
|
||||
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Copying the template's clean volatile image:\n{0} ==>\n{1}".\
|
||||
format(src_vm.clean_volatile_img, self.clean_volatile_img)
|
||||
# We prefer to use Linux's cp, because it nicely handles sparse files
|
||||
retcode = subprocess.call (["cp", src_vm.clean_volatile_img, self.clean_volatile_img])
|
||||
if retcode != 0:
|
||||
raise IOError ("Error while copying {0} to {1}".\
|
||||
format(src_vm.clean_volatile_img, self.clean_volatile_img))
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Copying the template's volatile image:\n{0} ==>\n{1}".\
|
||||
format(self.clean_volatile_img, self.volatile_img)
|
||||
# We prefer to use Linux's cp, because it nicely handles sparse files
|
||||
retcode = subprocess.call (["cp", self.clean_volatile_img, self.volatile_img])
|
||||
if retcode != 0:
|
||||
raise IOError ("Error while copying {0} to {1}".\
|
||||
format(self.clean_img, self.volatile_img))
|
||||
|
||||
# Create root-cow.img
|
||||
self.commit_changes(verbose=verbose)
|
||||
|
||||
def create_appmenus(self, verbose=False, source_template = None):
|
||||
if source_template is None:
|
||||
source_template = self.template
|
||||
|
||||
try:
|
||||
subprocess.check_call ([system_path["qubes_appmenu_create_cmd"], self.appmenus_templates_dir, self.name, "vm-templates"])
|
||||
except subprocess.CalledProcessError:
|
||||
print >> sys.stderr, "Ooops, there was a problem creating appmenus for {0} VM!".format (self.name)
|
||||
|
||||
def remove_appmenus(self):
|
||||
subprocess.check_call ([system_path["qubes_appmenu_remove_cmd"], self.name, "vm-templates"])
|
||||
|
||||
def pre_rename(self, new_name):
|
||||
self.remove_appmenus()
|
||||
|
||||
def post_rename(self, old_name):
|
||||
self.create_appmenus(verbose=False)
|
||||
|
||||
old_dirpath = os.path.join(os.path.dirname(self.dir_path), old_name)
|
||||
self.clean_volatile_img = self.clean_volatile_img.replace(old_dirpath, self.dir_path)
|
||||
self.rootcow_img = self.rootcow_img.replace(old_dirpath, self.dir_path)
|
||||
|
||||
def remove_from_disk(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
self.remove_appmenus()
|
||||
super(QubesTemplateVm, self).remove_from_disk()
|
||||
|
||||
def verify_files(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
|
||||
if not os.path.exists (self.dir_path):
|
||||
raise QubesException (
|
||||
"VM directory doesn't exist: {0}".\
|
||||
format(self.dir_path))
|
||||
|
||||
if not os.path.exists (self.root_img):
|
||||
raise QubesException (
|
||||
"VM root image file doesn't exist: {0}".\
|
||||
format(self.root_img))
|
||||
|
||||
if not os.path.exists (self.private_img):
|
||||
raise QubesException (
|
||||
"VM private image file doesn't exist: {0}".\
|
||||
format(self.private_img))
|
||||
|
||||
if not os.path.exists (self.volatile_img):
|
||||
raise QubesException (
|
||||
"VM volatile image file doesn't exist: {0}".\
|
||||
format(self.volatile_img))
|
||||
|
||||
if not os.path.exists (self.clean_volatile_img):
|
||||
raise QubesException (
|
||||
"Clean VM volatile image file doesn't exist: {0}".\
|
||||
format(self.clean_volatile_img))
|
||||
|
||||
if not os.path.exists (self.kernels_dir):
|
||||
raise QubesException (
|
||||
"VM's kernels directory does not exist: {0}".\
|
||||
format(self.kernels_dir))
|
||||
|
||||
return True
|
||||
|
||||
def reset_volatile_storage(self, verbose = False):
|
||||
assert not self.is_running(), "Attempt to clean volatile image of running Template VM!"
|
||||
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Cleaning volatile image: {0}...".format (self.volatile_img)
|
||||
if dry_run:
|
||||
return
|
||||
if os.path.exists (self.volatile_img):
|
||||
os.remove (self.volatile_img)
|
||||
|
||||
retcode = subprocess.call (["tar", "xf", self.clean_volatile_img, "-C", self.dir_path])
|
||||
if retcode != 0:
|
||||
raise IOError ("Error while unpacking {0} to {1}".\
|
||||
format(self.template.clean_volatile_img, self.volatile_img))
|
||||
|
||||
def commit_changes (self, verbose = False):
|
||||
|
||||
assert not self.is_running(), "Attempt to commit changes on running Template VM!"
|
||||
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Commiting template updates... COW: {0}...".format (self.rootcow_img)
|
||||
|
||||
if dry_run:
|
||||
return
|
||||
if os.path.exists (self.rootcow_img):
|
||||
os.rename (self.rootcow_img, self.rootcow_img + '.old')
|
||||
|
||||
f_cow = open (self.rootcow_img, "w")
|
||||
f_root = open (self.root_img, "r")
|
||||
f_root.seek(0, os.SEEK_END)
|
||||
f_cow.truncate (f_root.tell()) # make empty sparse file of the same size as root.img
|
||||
f_cow.close ()
|
||||
f_root.close()
|
||||
|
||||
register_qubes_vm_class(QubesTemplateVm)
|
201
dom0/core-modules/005QubesNetVm.py
Normal file
201
dom0/core-modules/005QubesNetVm.py
Normal file
@ -0,0 +1,201 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
# Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVm,register_qubes_vm_class,xs,dry_run
|
||||
from qubes.qubes import defaults,system_path,vm_files
|
||||
from qubes.qubes import QubesVmCollection,QubesException
|
||||
|
||||
class QubesNetVm(QubesVm):
|
||||
"""
|
||||
A class that represents a NetVM. A child of QubesCowVM.
|
||||
"""
|
||||
|
||||
# In which order load this VM type from qubes.xml
|
||||
load_order = 70
|
||||
|
||||
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 os.path.join(system_path["qubes_servicevms_dir"], self.name)'
|
||||
attrs_config['label']['default'] = defaults["servicevm_label"]
|
||||
attrs_config['memory']['default'] = 200
|
||||
|
||||
# New attributes
|
||||
attrs_config['netid'] = { 'save': 'str(self.netid)', 'order': 30,
|
||||
'eval': 'value if value is not None else collection.get_new_unused_netid()' }
|
||||
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):
|
||||
super(QubesNetVm, self).__init__(**kwargs)
|
||||
self.connected_vms = QubesVmCollection()
|
||||
|
||||
self.__network = "10.137.{0}.0".format(self.netid)
|
||||
self.__netmask = defaults["vm_default_netmask"]
|
||||
self.__gateway = self.netprefix + "1"
|
||||
self.__secondary_dns = self.netprefix + "254"
|
||||
|
||||
self.__external_ip_allowed_xids = set()
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "NetVM"
|
||||
|
||||
def is_netvm(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
def gateway(self):
|
||||
return self.__gateway
|
||||
|
||||
@property
|
||||
def secondary_dns(self):
|
||||
return self.__secondary_dns
|
||||
|
||||
@property
|
||||
def netmask(self):
|
||||
return self.__netmask
|
||||
|
||||
@property
|
||||
def network(self):
|
||||
return self.__network
|
||||
|
||||
def get_ip_for_vm(self, qid):
|
||||
lo = qid % 253 + 2
|
||||
assert lo >= 2 and lo <= 254, "Wrong IP address for VM"
|
||||
return self.netprefix + "{0}".format(lo)
|
||||
|
||||
def get_ip_for_dispvm(self, dispid):
|
||||
lo = dispid % 254 + 1
|
||||
assert lo >= 1 and lo <= 254, "Wrong IP address for VM"
|
||||
return self.dispnetprefix + "{0}".format(lo)
|
||||
|
||||
def create_xenstore_entries(self, xid = None):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
if xid is None:
|
||||
xid = self.xid
|
||||
|
||||
|
||||
super(QubesNetVm, self).create_xenstore_entries(xid)
|
||||
xs.write('', "/local/domain/{0}/qubes-netvm-external-ip".format(xid), '')
|
||||
self.update_external_ip_permissions(xid)
|
||||
|
||||
def update_external_ip_permissions(self, xid = -1):
|
||||
if xid < 0:
|
||||
xid = self.get_xid()
|
||||
if xid < 0:
|
||||
return
|
||||
|
||||
command = [
|
||||
"/usr/bin/xenstore-chmod",
|
||||
"/local/domain/{0}/qubes-netvm-external-ip".format(xid)
|
||||
]
|
||||
|
||||
command.append("n{0}".format(xid))
|
||||
|
||||
for id in self.__external_ip_allowed_xids:
|
||||
command.append("r{0}".format(id))
|
||||
|
||||
return subprocess.check_call(command)
|
||||
|
||||
def start(self, **kwargs):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
xid=super(QubesNetVm, self).start(**kwargs)
|
||||
|
||||
# Connect vif's of already running VMs
|
||||
for vm in self.connected_vms.values():
|
||||
if not vm.is_running():
|
||||
continue
|
||||
|
||||
if 'verbose' in kwargs and kwargs['verbose']:
|
||||
print >> sys.stderr, "--> Attaching network to '{0}'...".format(vm.name)
|
||||
|
||||
# Cleanup stale VIFs
|
||||
vm.cleanup_vifs()
|
||||
|
||||
# force frontend to forget about this device
|
||||
# module actually will be loaded back by udev, as soon as network is attached
|
||||
vm.run("modprobe -r xen-netfront xennet", user="root")
|
||||
|
||||
try:
|
||||
vm.attach_network(wait=False)
|
||||
except QubesException as ex:
|
||||
print >> sys.stderr, ("WARNING: Cannot attach to network to '{0}': {1}".format(vm.name, ex))
|
||||
|
||||
return xid
|
||||
|
||||
def shutdown(self, force=False):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
connected_vms = [vm for vm in self.connected_vms.values() if vm.is_running()]
|
||||
if connected_vms and not force:
|
||||
raise QubesException("There are other VMs connected to this VM: " + str([vm.name for vm in connected_vms]))
|
||||
|
||||
super(QubesNetVm, self).shutdown(force=force)
|
||||
|
||||
def add_external_ip_permission(self, xid):
|
||||
if int(xid) < 0:
|
||||
return
|
||||
self.__external_ip_allowed_xids.add(int(xid))
|
||||
self.update_external_ip_permissions()
|
||||
|
||||
def remove_external_ip_permission(self, xid):
|
||||
self.__external_ip_allowed_xids.discard(int(xid))
|
||||
self.update_external_ip_permissions()
|
||||
|
||||
def create_on_disk(self, verbose, source_template = None):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
super(QubesNetVm, self).create_on_disk(verbose, source_template=source_template)
|
||||
|
||||
if os.path.exists(os.path.join(source_template.dir_path, 'netvm-' + vm_files["whitelisted_appmenus"])):
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Creating default whitelisted apps list: {0}".\
|
||||
format(self.dir_path + '/' + vm_files["whitelisted_appmenus"])
|
||||
shutil.copy(os.path.join(source_template.dir_path, 'netvm-' + vm_files["whitelisted_appmenus"]),
|
||||
os.path.join(self.dir_path, vm_files["whitelisted_appmenus"]))
|
||||
|
||||
if not self.internal:
|
||||
self.create_appmenus (verbose=verbose, source_template=source_template)
|
||||
|
||||
def remove_from_disk(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
if not self.internal:
|
||||
self.remove_appmenus()
|
||||
super(QubesNetVm, self).remove_from_disk()
|
||||
|
||||
|
||||
register_qubes_vm_class(QubesNetVm)
|
89
dom0/core-modules/006QubesDom0NetVm.py
Normal file
89
dom0/core-modules/006QubesDom0NetVm.py
Normal file
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
# Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesNetVm,register_qubes_vm_class,xl_ctx,xc
|
||||
from qubes.qubes import defaults
|
||||
from qubes.qubes import QubesException,dry_run
|
||||
|
||||
class QubesDom0NetVm(QubesNetVm):
|
||||
def __init__(self, **kwargs):
|
||||
super(QubesDom0NetVm, self).__init__(qid=0, name="dom0", netid=0,
|
||||
dir_path=None,
|
||||
private_img = None,
|
||||
template = None,
|
||||
label = defaults["template_label"],
|
||||
**kwargs)
|
||||
self.xid = 0
|
||||
|
||||
def is_running(self):
|
||||
return True
|
||||
|
||||
def get_xid(self):
|
||||
return 0
|
||||
|
||||
def get_power_state(self):
|
||||
return "Running"
|
||||
|
||||
def get_disk_usage(self, file_or_dir):
|
||||
return 0
|
||||
|
||||
def get_disk_utilization(self):
|
||||
return 0
|
||||
|
||||
def get_disk_utilization_private_img(self):
|
||||
return 0
|
||||
|
||||
def get_private_img_sz(self):
|
||||
return 0
|
||||
|
||||
@property
|
||||
def ip(self):
|
||||
return "10.137.0.2"
|
||||
|
||||
def start(self, **kwargs):
|
||||
raise QubesException ("Cannot start Dom0 fake domain!")
|
||||
|
||||
def get_xl_dominfo(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
domains = xl_ctx.list_domains()
|
||||
for dominfo in domains:
|
||||
if dominfo.domid == 0:
|
||||
return dominfo
|
||||
return None
|
||||
|
||||
def get_xc_dominfo(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
domains = xc.domain_getinfo(0, 1)
|
||||
return domains[0]
|
||||
|
||||
def create_xml_element(self):
|
||||
return None
|
||||
|
||||
def verify_files(self):
|
||||
return True
|
||||
|
||||
register_qubes_vm_class(QubesDom0NetVm)
|
201
dom0/core-modules/006QubesProxyVm.py
Normal file
201
dom0/core-modules/006QubesProxyVm.py
Normal file
@ -0,0 +1,201 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
# Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from qubes.qubes import QubesNetVm,register_qubes_vm_class,xs
|
||||
from qubes.qubes import QubesVmCollection,QubesException
|
||||
|
||||
yum_proxy_ip = '10.137.255.254'
|
||||
yum_proxy_port = '8082'
|
||||
|
||||
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):
|
||||
super(QubesProxyVm, self).__init__(**kwargs)
|
||||
self.rules_applied = None
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "ProxyVM"
|
||||
|
||||
def is_proxyvm(self):
|
||||
return True
|
||||
|
||||
def _set_netvm(self, new_netvm):
|
||||
old_netvm = self.netvm
|
||||
super(QubesProxyVm, self)._set_netvm(new_netvm)
|
||||
if self.netvm is not None:
|
||||
self.netvm.add_external_ip_permission(self.get_xid())
|
||||
self.write_netvm_domid_entry()
|
||||
if old_netvm is not None:
|
||||
old_netvm.remove_external_ip_permission(self.get_xid())
|
||||
|
||||
def post_vm_net_attach(self, vm):
|
||||
""" Called after some VM net-attached to this ProxyVm """
|
||||
|
||||
self.write_iptables_xenstore_entry()
|
||||
|
||||
def post_vm_net_detach(self, vm):
|
||||
""" Called after some VM net-detached from this ProxyVm """
|
||||
|
||||
self.write_iptables_xenstore_entry()
|
||||
|
||||
def start(self, **kwargs):
|
||||
if dry_run:
|
||||
return
|
||||
retcode = super(QubesProxyVm, self).start(**kwargs)
|
||||
if self.netvm is not None:
|
||||
self.netvm.add_external_ip_permission(self.get_xid())
|
||||
self.write_netvm_domid_entry()
|
||||
return retcode
|
||||
|
||||
def force_shutdown(self, **kwargs):
|
||||
if dry_run:
|
||||
return
|
||||
if self.netvm is not None:
|
||||
self.netvm.remove_external_ip_permission(kwargs['xid'] if 'xid' in kwargs else self.get_xid())
|
||||
super(QubesProxyVm, self).force_shutdown(**kwargs)
|
||||
|
||||
def create_xenstore_entries(self, xid = None):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
if xid is None:
|
||||
xid = self.xid
|
||||
|
||||
|
||||
super(QubesProxyVm, self).create_xenstore_entries(xid)
|
||||
xs.write('', "/local/domain/{0}/qubes-iptables-error".format(xid), '')
|
||||
xs.set_permissions('', "/local/domain/{0}/qubes-iptables-error".format(xid),
|
||||
[{ 'dom': xid, 'write': True }])
|
||||
self.write_iptables_xenstore_entry()
|
||||
|
||||
def write_netvm_domid_entry(self, xid = -1):
|
||||
if not self.is_running():
|
||||
return
|
||||
|
||||
if xid < 0:
|
||||
xid = self.get_xid()
|
||||
|
||||
if self.netvm is None:
|
||||
xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid), '')
|
||||
else:
|
||||
xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid),
|
||||
"{0}".format(self.netvm.get_xid()))
|
||||
|
||||
def write_iptables_xenstore_entry(self):
|
||||
xs.rm('', "/local/domain/{0}/qubes-iptables-domainrules".format(self.get_xid()))
|
||||
iptables = "# Generated by Qubes Core on {0}\n".format(datetime.now().ctime())
|
||||
iptables += "*filter\n"
|
||||
iptables += ":INPUT DROP [0:0]\n"
|
||||
iptables += ":FORWARD DROP [0:0]\n"
|
||||
iptables += ":OUTPUT ACCEPT [0:0]\n"
|
||||
|
||||
# Strict INPUT rules
|
||||
iptables += "-A INPUT -i vif+ -p udp -m udp --dport 68 -j DROP\n"
|
||||
iptables += "-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
|
||||
iptables += "-A INPUT -p icmp -j ACCEPT\n"
|
||||
iptables += "-A INPUT -i lo -j ACCEPT\n"
|
||||
iptables += "-A INPUT -j REJECT --reject-with icmp-host-prohibited\n"
|
||||
|
||||
iptables += "-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT\n"
|
||||
# Allow dom0 networking
|
||||
iptables += "-A FORWARD -i vif0.0 -j ACCEPT\n"
|
||||
# Deny inter-VMs networking
|
||||
iptables += "-A FORWARD -i vif+ -o vif+ -j DROP\n"
|
||||
iptables += "COMMIT\n"
|
||||
xs.write('', "/local/domain/{0}/qubes-iptables-header".format(self.get_xid()), iptables)
|
||||
|
||||
vms = [vm for vm in self.connected_vms.values()]
|
||||
for vm in vms:
|
||||
iptables="*filter\n"
|
||||
conf = vm.get_firewall_conf()
|
||||
|
||||
xid = vm.get_xid()
|
||||
if xid < 0: # VM not active ATM
|
||||
continue
|
||||
|
||||
ip = vm.ip
|
||||
if ip is None:
|
||||
continue
|
||||
|
||||
# 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"
|
||||
|
||||
if conf["allow"]:
|
||||
default_action = accept_action
|
||||
rules_action = reject_action
|
||||
else:
|
||||
default_action = reject_action
|
||||
rules_action = accept_action
|
||||
|
||||
for rule in conf["rules"]:
|
||||
iptables += "-A FORWARD -s {0} -d {1}".format(ip, rule["address"])
|
||||
if rule["netmask"] != 32:
|
||||
iptables += "/{0}".format(rule["netmask"])
|
||||
|
||||
if rule["proto"] is not None and rule["proto"] != "any":
|
||||
iptables += " -p {0}".format(rule["proto"])
|
||||
if rule["portBegin"] is not None and rule["portBegin"] > 0:
|
||||
iptables += " --dport {0}".format(rule["portBegin"])
|
||||
if rule["portEnd"] is not None and rule["portEnd"] > rule["portBegin"]:
|
||||
iptables += ":{0}".format(rule["portEnd"])
|
||||
|
||||
iptables += " -j {0}\n".format(rules_action)
|
||||
|
||||
if conf["allowDns"] and self.netvm is not None:
|
||||
# PREROUTING does DNAT to NetVM DNSes, so we need self.netvm. properties
|
||||
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 -s {0} -p icmp -j ACCEPT\n".format(ip)
|
||||
if conf["allowYumProxy"]:
|
||||
iptables += "-A FORWARD -s {0} -p tcp -d {1} --dport {2} -j ACCEPT\n".format(ip, yum_proxy_ip, yum_proxy_port)
|
||||
else:
|
||||
iptables += "-A FORWARD -s {0} -p tcp -d {1} --dport {2} -j DROP\n".format(ip, yum_proxy_ip, yum_proxy_port)
|
||||
|
||||
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
|
||||
|
||||
self.write_netvm_domid_entry()
|
||||
|
||||
self.rules_applied = None
|
||||
xs.write('', "/local/domain/{0}/qubes-iptables".format(self.get_xid()), 'reload')
|
||||
|
||||
register_qubes_vm_class(QubesProxyVm)
|
59
dom0/core-modules/01QubesAppVm.py
Normal file
59
dom0/core-modules/01QubesAppVm.py
Normal file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
# Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from qubes.qubes import QubesVm,QubesVmLabel,register_qubes_vm_class
|
||||
|
||||
class QubesAppVm(QubesVm):
|
||||
"""
|
||||
A class that represents an AppVM. A child of QubesVm.
|
||||
"""
|
||||
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 os.path.join(system_path["qubes_appvms_dir"], self.name)'
|
||||
|
||||
return attrs_config
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "AppVM"
|
||||
|
||||
def is_appvm(self):
|
||||
return True
|
||||
|
||||
def create_on_disk(self, verbose, source_template = None):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
super(QubesAppVm, self).create_on_disk(verbose, source_template=source_template)
|
||||
|
||||
if not self.internal:
|
||||
self.create_appmenus (verbose=verbose, source_template=source_template)
|
||||
|
||||
def remove_from_disk(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
self.remove_appmenus()
|
||||
super(QubesAppVm, self).remove_from_disk()
|
||||
|
||||
register_qubes_vm_class(QubesAppVm)
|
97
dom0/core-modules/01QubesDisposableVm.py
Normal file
97
dom0/core-modules/01QubesDisposableVm.py
Normal file
@ -0,0 +1,97 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
# Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import sys
|
||||
from qubes.qubes import QubesVm,QubesVmLabel,register_qubes_vm_class
|
||||
|
||||
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"),
|
||||
}
|
||||
|
||||
class QubesDisposableVm(QubesVm):
|
||||
"""
|
||||
A class that represents an DisposableVM. A child of QubesVm.
|
||||
"""
|
||||
|
||||
# In which order load this VM type from qubes.xml
|
||||
load_order = 120
|
||||
|
||||
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):
|
||||
|
||||
super(QubesDisposableVm, self).__init__(dir_path="/nonexistent", **kwargs)
|
||||
|
||||
assert self.template is not None, "Missing template 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"
|
||||
|
||||
def is_disposablevm(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
def ip(self):
|
||||
if self.netvm is not None:
|
||||
return self.netvm.get_ip_for_dispvm(self.dispid)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def get_xml_attrs(self):
|
||||
# Minimal set - do not inherit rest of attributes
|
||||
attrs = {}
|
||||
attrs["qid"] = str(self.qid)
|
||||
attrs["name"] = self.name
|
||||
attrs["dispid"] = str(self.dispid)
|
||||
attrs["template_qid"] = str(self.template.qid)
|
||||
attrs["label"] = self.label.name
|
||||
attrs["firewall_conf"] = self.relative_path(self.firewall_conf)
|
||||
attrs["netvm_qid"] = str(self.netvm.qid) if self.netvm is not None else "none"
|
||||
return attrs
|
||||
|
||||
def verify_files(self):
|
||||
return True
|
||||
|
||||
# register classes
|
||||
sys.modules['qubes.qubes'].QubesDispVmLabels = QubesDispVmLabels
|
||||
register_qubes_vm_class(QubesDisposableVm)
|
302
dom0/core-modules/01QubesHVm.py
Normal file
302
dom0/core-modules/01QubesHVm.py
Normal file
@ -0,0 +1,302 @@
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
|
||||
# Copyright (C) 2013 Marek Marczykowski <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
from qubes.qubes import QubesVm,register_qubes_vm_class,xs,dry_run
|
||||
from qubes.qubes import system_path,defaults
|
||||
|
||||
system_path["config_template_hvm"] = '/usr/share/qubes/vm-template-hvm.conf'
|
||||
|
||||
defaults["hvm_disk_size"] = 20*1024*1024*1024
|
||||
defaults["hvm_private_img_size"] = 2*1024*1024*1024
|
||||
defaults["hvm_memory"] = 512
|
||||
|
||||
|
||||
class QubesHVm(QubesVm):
|
||||
"""
|
||||
A class that represents an HVM. A child of 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['dir_path']['eval'] = 'value if value is not None else os.path.join(system_path["qubes_appvms_dir"], self.name)'
|
||||
attrs['volatile_img']['eval'] = 'None'
|
||||
attrs['config_file_template']['eval'] = 'system_path["config_template_hvm"]'
|
||||
attrs['drive'] = { 'save': 'str(self.drive)' }
|
||||
attrs['maxmem'].pop('save')
|
||||
attrs['timezone'] = { 'default': 'localtime', 'save': 'str(self.timezone)' }
|
||||
attrs['qrexec_installed'] = { 'default': False, 'save': 'str(self.qrexec_installed)' }
|
||||
attrs['guiagent_installed'] = { 'default' : False, 'save': 'str(self.guiagent_installed)' }
|
||||
attrs['_start_guid_first']['eval'] = 'True'
|
||||
attrs['services']['default'] = "{'meminfo-writer': False}"
|
||||
|
||||
# only standalone HVM supported for now
|
||||
attrs['template']['eval'] = 'None'
|
||||
attrs['memory']['default'] = defaults["hvm_memory"]
|
||||
|
||||
return attrs
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
super(QubesHVm, self).__init__(**kwargs)
|
||||
|
||||
# Default for meminfo-writer have changed to (correct) False in the
|
||||
# same version as introduction of guiagent_installed, so for older VMs
|
||||
# with wrong setting, change is based on 'guiagent_installed' presence
|
||||
if "guiagent_installed" not in kwargs and \
|
||||
(not 'xml_element' in kwargs or kwargs['xml_element'].get('guiagent_installed') is None):
|
||||
self.services['meminfo-writer'] = False
|
||||
|
||||
# HVM normally doesn't support dynamic memory management
|
||||
if not ('meminfo-writer' in self.services and self.services['meminfo-writer']):
|
||||
self.maxmem = self.memory
|
||||
|
||||
# Disable qemu GUID if the user installed qubes gui agent
|
||||
if self.guiagent_installed:
|
||||
self._start_guid_first = False
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return "HVM"
|
||||
|
||||
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 += [ 'timezone' ]
|
||||
attrs += [ 'qrexec_installed' ]
|
||||
attrs += [ 'guiagent_installed' ]
|
||||
return attrs
|
||||
|
||||
def create_on_disk(self, verbose, source_template = None):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Creating directory: {0}".format(self.dir_path)
|
||||
os.mkdir (self.dir_path)
|
||||
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Creating icon symlink: {0} -> {1}".format(self.icon_path, self.label.icon_path)
|
||||
os.symlink (self.label.icon_path, self.icon_path)
|
||||
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Creating appmenus directory: {0}".format(self.appmenus_templates_dir)
|
||||
os.mkdir (self.appmenus_templates_dir)
|
||||
shutil.copy (system_path["start_appmenu_template"], self.appmenus_templates_dir)
|
||||
|
||||
if not self.internal:
|
||||
self.create_appmenus (verbose, source_template=source_template)
|
||||
|
||||
self.create_config_file()
|
||||
|
||||
# create empty disk
|
||||
f_root = open(self.root_img, "w")
|
||||
f_root.truncate(defaults["hvm_disk_size"])
|
||||
f_root.close()
|
||||
|
||||
# create empty private.img
|
||||
f_private = open(self.private_img, "w")
|
||||
f_private.truncate(defaults["hvm_private_img_size"])
|
||||
f_root.close()
|
||||
|
||||
def remove_from_disk(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
self.remove_appmenus()
|
||||
super(QubesHVm, self).remove_from_disk()
|
||||
|
||||
def get_disk_utilization_private_img(self):
|
||||
return 0
|
||||
|
||||
def get_private_img_sz(self):
|
||||
return 0
|
||||
|
||||
def resize_private_img(self, size):
|
||||
raise NotImplementedError("HVM has no private.img")
|
||||
|
||||
def get_config_params(self, source_template=None):
|
||||
|
||||
params = super(QubesHVm, self).get_config_params(source_template=source_template)
|
||||
|
||||
params['volatiledev'] = ''
|
||||
if self.drive:
|
||||
type_mode = ":cdrom,r"
|
||||
drive_path = self.drive
|
||||
# leave empty to use standard syntax in case of dom0
|
||||
backend_domain = ""
|
||||
if drive_path.startswith("hd:"):
|
||||
type_mode = ",w"
|
||||
drive_path = drive_path[3:]
|
||||
elif drive_path.startswith("cdrom:"):
|
||||
type_mode = ":cdrom,r"
|
||||
drive_path = drive_path[6:]
|
||||
backend_split = re.match(r"^([a-zA-Z0-9-]*):(.*)", drive_path)
|
||||
if backend_split:
|
||||
backend_domain = "," + backend_split.group(1)
|
||||
drive_path = backend_split.group(2)
|
||||
|
||||
# FIXME: os.stat will work only when backend in dom0...
|
||||
stat_res = None
|
||||
if backend_domain == "":
|
||||
stat_res = os.stat(drive_path)
|
||||
if stat_res and stat.S_ISBLK(stat_res.st_mode):
|
||||
params['otherdevs'] = "'phy:%s,xvdc%s%s'," % (drive_path, type_mode, backend_domain)
|
||||
else:
|
||||
params['otherdevs'] = "'script:file:%s,xvdc%s%s'," % (drive_path, type_mode, backend_domain)
|
||||
else:
|
||||
params['otherdevs'] = ''
|
||||
|
||||
# Disable currently unused private.img - to be enabled when TemplateHVm done
|
||||
params['privatedev'] = ''
|
||||
|
||||
if self.timezone.lower() == 'localtime':
|
||||
params['localtime'] = '1'
|
||||
params['timeoffset'] = '0'
|
||||
elif self.timezone.isdigit():
|
||||
params['localtime'] = '0'
|
||||
params['timeoffset'] = self.timezone
|
||||
else:
|
||||
print >>sys.stderr, "WARNING: invalid 'timezone' value: %s" % self.timezone
|
||||
params['localtime'] = '0'
|
||||
params['timeoffset'] = '0'
|
||||
return params
|
||||
|
||||
def verify_files(self):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
if not os.path.exists (self.dir_path):
|
||||
raise QubesException (
|
||||
"VM directory doesn't exist: {0}".\
|
||||
format(self.dir_path))
|
||||
|
||||
if self.is_updateable() and not os.path.exists (self.root_img):
|
||||
raise QubesException (
|
||||
"VM root image file doesn't exist: {0}".\
|
||||
format(self.root_img))
|
||||
|
||||
if not os.path.exists (self.private_img):
|
||||
print >>sys.stderr, "WARNING: Creating empty VM private image file: {0}".\
|
||||
format(self.private_img)
|
||||
f_private = open(self.private_img, "w")
|
||||
f_private.truncate(defaults["hvm_private_img_size"])
|
||||
f_private.close()
|
||||
|
||||
return True
|
||||
|
||||
def reset_volatile_storage(self, **kwargs):
|
||||
pass
|
||||
|
||||
@property
|
||||
def vif(self):
|
||||
if self.xid < 0:
|
||||
return None
|
||||
if self.netvm is None:
|
||||
return None
|
||||
return "vif{0}.+".format(self.stubdom_xid)
|
||||
|
||||
def run(self, command, **kwargs):
|
||||
if self.qrexec_installed:
|
||||
if 'gui' in kwargs and kwargs['gui']==False:
|
||||
command = "nogui:" + command
|
||||
return super(QubesHVm, self).run(command, **kwargs)
|
||||
else:
|
||||
raise QubesException("Needs qrexec agent installed in VM to use this function. See also qvm-prefs.")
|
||||
|
||||
@property
|
||||
def stubdom_xid(self):
|
||||
if self.xid < 0:
|
||||
return -1
|
||||
|
||||
stubdom_xid_str = xs.read('', '/local/domain/%d/image/device-model-domid' % self.xid)
|
||||
if stubdom_xid_str is not None:
|
||||
return int(stubdom_xid_str)
|
||||
else:
|
||||
return -1
|
||||
|
||||
def start_guid(self, verbose = True, notify_function = None):
|
||||
# If user force the guiagent, start_guid will mimic a standard QubesVM
|
||||
if self.guiagent_installed:
|
||||
super(QubesHVm, self).start_guid(verbose, notify_function)
|
||||
else:
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Starting Qubes GUId..."
|
||||
|
||||
retcode = subprocess.call ([system_path["qubes_guid_path"], "-d", str(self.stubdom_xid), "-c", self.label.color, "-i", self.label.icon_path, "-l", str(self.label.index)])
|
||||
if (retcode != 0) :
|
||||
raise QubesException("Cannot start qubes-guid!")
|
||||
|
||||
def start_qrexec_daemon(self, **kwargs):
|
||||
if self.qrexec_installed:
|
||||
super(QubesHVm, self).start_qrexec_daemon(**kwargs)
|
||||
|
||||
if self._start_guid_first:
|
||||
if kwargs.get('verbose'):
|
||||
print >> sys.stderr, "--> Waiting for user '%s' login..." % self.default_user
|
||||
|
||||
self.wait_for_session(notify_function=kwargs.get('notify_function', None))
|
||||
|
||||
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 is_guid_running(self):
|
||||
# If user force the guiagent, is_guid_running will mimic a standard QubesVM
|
||||
if self.guiagent_installed:
|
||||
return super(QubesHVm, self).is_guid_running()
|
||||
else:
|
||||
xid = self.stubdom_xid
|
||||
if xid < 0:
|
||||
return False
|
||||
if not os.path.exists('/var/run/qubes/guid-running.%d' % xid):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
register_qubes_vm_class(QubesHVm)
|
5
dom0/core-modules/README.txt
Normal file
5
dom0/core-modules/README.txt
Normal file
@ -0,0 +1,5 @@
|
||||
This directory contains Qubes core modules. It will be loaded in
|
||||
lexicographical order, use numeric prefix to force load ordering.
|
||||
|
||||
0* - Qubes base modules
|
||||
00* - Qubes core VM classes
|
0
dom0/core-modules/__init__.py
Normal file
0
dom0/core-modules/__init__.py
Normal file
2439
dom0/core/qubes.py
2439
dom0/core/qubes.py
File diff suppressed because it is too large
Load Diff
@ -50,6 +50,7 @@ Requires(postun): systemd-units
|
||||
Requires: python, xen-runtime, pciutils, python-inotify, python-daemon, kernel-qubes-dom0
|
||||
Requires: qubes-qrexec-dom0
|
||||
Requires: python-lxml
|
||||
# TODO: R: qubes-gui-dom0 >= 2.1.11
|
||||
Conflicts: qubes-gui-dom0 < 1.1.13
|
||||
Requires: xen >= 4.1.0-2
|
||||
Requires: xen-hvm
|
||||
@ -75,8 +76,8 @@ ln -sf . %{name}-%{version}
|
||||
%setup -T -D
|
||||
|
||||
%build
|
||||
python -m compileall dom0/core dom0/qmemman
|
||||
python -O -m compileall dom0/core dom0/qmemman
|
||||
python -m compileall dom0/core dom0/core-modules dom0/qmemman
|
||||
python -O -m compileall dom0/core dom/core-modules dom0/qmemman
|
||||
for dir in dom0/dispvm dom0/qubes-rpc dom0/qmemman; do
|
||||
(cd $dir; make)
|
||||
done
|
||||
@ -118,6 +119,11 @@ cp core/__init__.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
cp core/__init__.py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
cp qmemman/qmemman*py $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
cp qmemman/qmemman*py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes
|
||||
mkdir -p $RPM_BUILD_ROOT%{python_sitearch}/qubes/modules
|
||||
cp core-modules/0*.py $RPM_BUILD_ROOT%{python_sitearch}/qubes/modules
|
||||
cp core-modules/0*.py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes/modules
|
||||
cp core-modules/__init__.py $RPM_BUILD_ROOT%{python_sitearch}/qubes/modules
|
||||
cp core-modules/__init__.py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes/modules
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/qubes
|
||||
cp qmemman/qmemman.conf $RPM_BUILD_ROOT%{_sysconfdir}/qubes/
|
||||
@ -359,6 +365,8 @@ fi
|
||||
%{python_sitearch}/qubes/__init__.pyc
|
||||
%{python_sitearch}/qubes/__init__.pyo
|
||||
%{python_sitearch}/qubes/qmemman*.py*
|
||||
%{python_sitearch}/qubes/modules/0*.py*
|
||||
%{python_sitearch}/qubes/modules/__init__.py*
|
||||
/usr/lib/qubes/unbind-pci-device.sh
|
||||
/usr/lib/qubes/cleanup-dispvms
|
||||
/usr/lib/qubes/convert-apptemplate2vm.sh
|
||||
|
Loading…
Reference in New Issue
Block a user