Use QubesDB instead of Xenstore.
Mostly done. Things still using xenstore/not working at all: - DispVM - qubesutils.py (especially qvm-block and qvm-usb code) - external IP change notification for ProxyVM (should be done via RPC service)
This commit is contained in:
parent
31424603fa
commit
f159f3e168
@ -39,6 +39,7 @@ from qubes import qmemman_algo
|
||||
import libvirt
|
||||
import warnings
|
||||
|
||||
from qubes.qdb import QubesDB
|
||||
from qubes.qubes import dry_run,vmm
|
||||
from qubes.qubes import register_qubes_vm_class
|
||||
from qubes.qubes import QubesVmCollection,QubesException,QubesHost,QubesVmLabels
|
||||
@ -292,6 +293,7 @@ class QubesVm(object):
|
||||
self.__qid = self._qid
|
||||
|
||||
self._libvirt_domain = None
|
||||
self._qdb_connection = None
|
||||
|
||||
assert self.__qid < qubes_max_qid, "VM id out of bounds!"
|
||||
assert self.name is not None
|
||||
@ -549,6 +551,8 @@ class QubesVm(object):
|
||||
self.pre_rename(name)
|
||||
self.libvirt_domain.undefine()
|
||||
self._libvirt_domain = None
|
||||
self._qdb_connection.close()
|
||||
self._qdb_connection = None
|
||||
|
||||
new_conf = os.path.join(self.dir_path, name + '.conf')
|
||||
if os.path.exists(self.conf_file):
|
||||
@ -641,6 +645,13 @@ class QubesVm(object):
|
||||
def is_disposablevm(self):
|
||||
return False
|
||||
|
||||
@property
|
||||
def qdb(self):
|
||||
if self._qdb_connection is None:
|
||||
if self.is_running():
|
||||
self._qdb_connection = QubesDB(self.name)
|
||||
return self._qdb_connection
|
||||
|
||||
@property
|
||||
def xid(self):
|
||||
if self.libvirt_domain is None:
|
||||
@ -926,74 +937,41 @@ class QubesVm(object):
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
if xid is None:
|
||||
xid = self.xid
|
||||
|
||||
assert xid >= 0, "Invalid XID value"
|
||||
|
||||
domain_path = vmm.xs.get_domain_path(xid)
|
||||
|
||||
# Set Xen Store entires with VM networking info:
|
||||
|
||||
vmm.xs.write('', "{0}/qubes-vm-type".format(domain_path),
|
||||
self.type)
|
||||
vmm.xs.write('', "{0}/qubes-vm-updateable".format(domain_path),
|
||||
str(self.updateable))
|
||||
self.qdb.write("/name", self.name)
|
||||
self.qdb.write("/qubes-vm-type", self.type)
|
||||
self.qdb.write("/qubes-vm-updateable", str(self.updateable))
|
||||
|
||||
if self.is_netvm():
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-gateway".format(domain_path),
|
||||
self.gateway)
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-secondary-dns".format(domain_path),
|
||||
self.secondary_dns)
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-netmask".format(domain_path),
|
||||
self.netmask)
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-netvm-network".format(domain_path),
|
||||
self.network)
|
||||
self.qdb.write("/qubes-netvm-gateway", self.gateway)
|
||||
self.qdb.write("/qubes-netvm-secondary-dns", self.secondary_dns)
|
||||
self.qdb.write("/qubes-netvm-netmask", self.netmask)
|
||||
self.qdb.write("/qubes-netvm-network", self.network)
|
||||
|
||||
if self.netvm is not None:
|
||||
vmm.xs.write('', "{0}/qubes-ip".format(domain_path), self.ip)
|
||||
vmm.xs.write('', "{0}/qubes-netmask".format(domain_path),
|
||||
self.netvm.netmask)
|
||||
vmm.xs.write('', "{0}/qubes-gateway".format(domain_path),
|
||||
self.netvm.gateway)
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-secondary-dns".format(domain_path),
|
||||
self.netvm.secondary_dns)
|
||||
self.qdb.write("/qubes-ip", self.ip)
|
||||
self.qdb.write("/qubes-netmask", self.netvm.netmask)
|
||||
self.qdb.write("/qubes-gateway", self.netvm.gateway)
|
||||
self.qdb.write("/qubes-secondary-dns", self.netvm.secondary_dns)
|
||||
|
||||
tzname = self.get_timezone()
|
||||
if tzname:
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-timezone".format(domain_path),
|
||||
tzname)
|
||||
self.qdb.write("/qubes-timezone", tzname)
|
||||
|
||||
for srv in self.services.keys():
|
||||
# convert True/False to "1"/"0"
|
||||
vmm.xs.write('', "{0}/qubes-service/{1}".format(domain_path, srv),
|
||||
self.qdb.write("/qubes-service/{0}".format(srv),
|
||||
str(int(self.services[srv])))
|
||||
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-block-devices".format(domain_path),
|
||||
'')
|
||||
self.qdb.write("/qubes-block-devices", '')
|
||||
|
||||
vmm.xs.write('',
|
||||
"{0}/qubes-usb-devices".format(domain_path),
|
||||
'')
|
||||
self.qdb.write("/qubes-usb-devices", '')
|
||||
|
||||
vmm.xs.write('', "{0}/qubes-debug-mode".format(domain_path),
|
||||
str(int(self.debug)))
|
||||
self.qdb.write("/qubes-debug-mode", str(int(self.debug)))
|
||||
|
||||
# Fix permissions
|
||||
vmm.xs.set_permissions('', '{0}/device'.format(domain_path),
|
||||
[{ 'dom': xid }])
|
||||
vmm.xs.set_permissions('', '{0}/memory'.format(domain_path),
|
||||
[{ 'dom': xid }])
|
||||
vmm.xs.set_permissions('', '{0}/qubes-block-devices'.format(domain_path),
|
||||
[{ 'dom': xid }])
|
||||
vmm.xs.set_permissions('', '{0}/qubes-usb-devices'.format(domain_path),
|
||||
# TODO: Currently whole qmemman is quite Xen-specific, so stay with
|
||||
# xenstore for it until decided otherwise
|
||||
vmm.xs.set_permissions('', '/local/domain/{0}/memory'.format(self.xid),
|
||||
[{ 'dom': xid }])
|
||||
|
||||
# fire hooks
|
||||
@ -1712,6 +1690,15 @@ class QubesVm(object):
|
||||
if (retcode != 0) :
|
||||
raise OSError ("Cannot execute qrexec-daemon!")
|
||||
|
||||
def start_qubesdb(self):
|
||||
retcode = subprocess.call ([
|
||||
system_path["qubesdb_daemon_path"],
|
||||
str(self.xid),
|
||||
self.name])
|
||||
if retcode != 0:
|
||||
self.force_shutdown()
|
||||
raise OSError("ERROR: Cannot execute qubesdb-daemon!")
|
||||
|
||||
def start(self, verbose = False, preparing_dvm = False, start_guid = True,
|
||||
notify_function = None, mem_required = None):
|
||||
if dry_run:
|
||||
@ -1754,12 +1741,16 @@ class QubesVm(object):
|
||||
|
||||
self.libvirt_domain.createWithFlags(libvirt.VIR_DOMAIN_START_PAUSED)
|
||||
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Starting Qubes DB..."
|
||||
self.start_qubesdb()
|
||||
|
||||
xid = self.xid
|
||||
|
||||
if preparing_dvm:
|
||||
self.services['qubes-dvm'] = True
|
||||
if verbose:
|
||||
print >> sys.stderr, "--> Setting Xen Store info for the VM..."
|
||||
print >> sys.stderr, "--> Setting Qubes DB info for the VM..."
|
||||
self.create_xenstore_entries(xid)
|
||||
|
||||
qvm_collection = QubesVmCollection()
|
||||
|
@ -106,35 +106,10 @@ class QubesNetVm(QubesVm):
|
||||
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)
|
||||
vmm.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
|
||||
|
||||
perms = [ { 'dom': xid } ]
|
||||
|
||||
for xid in self.__external_ip_allowed_xids:
|
||||
perms.append({ 'dom': xid, 'read': True })
|
||||
|
||||
try:
|
||||
vmm.xs.set_permissions('', '/local/domain/{0}/qubes-netvm-external-ip'.format(xid),
|
||||
perms)
|
||||
except xen.lowlevel.xs.Error as e:
|
||||
print >>sys.stderr, "WARNING: failed to update external IP " \
|
||||
"permissions: %s" % (str(e))
|
||||
# TODO: VMs in __external_ip_allowed_xids should be notified via RPC
|
||||
# service on exteran IP change
|
||||
pass
|
||||
|
||||
def start(self, **kwargs):
|
||||
if dry_run:
|
||||
|
@ -99,9 +99,7 @@ class QubesProxyVm(QubesNetVm):
|
||||
|
||||
|
||||
super(QubesProxyVm, self).create_xenstore_entries(xid)
|
||||
vmm.xs.write('', "/local/domain/{0}/qubes-iptables-error".format(xid), '')
|
||||
vmm.xs.set_permissions('', "/local/domain/{0}/qubes-iptables-error".format(xid),
|
||||
[{ 'dom': xid, 'write': True }])
|
||||
self.qdb.write("/qubes-iptables-error", '')
|
||||
self.write_iptables_xenstore_entry()
|
||||
|
||||
def write_netvm_domid_entry(self, xid = -1):
|
||||
@ -112,14 +110,14 @@ class QubesProxyVm(QubesNetVm):
|
||||
xid = self.get_xid()
|
||||
|
||||
if self.netvm is None:
|
||||
vmm.xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid), '')
|
||||
self.qdb.write("/qubes-netvm-domid", '')
|
||||
else:
|
||||
vmm.xs.write('', "/local/domain/{0}/qubes-netvm-domid".format(xid),
|
||||
self.qdb.write("/qubes-netvm-domid",
|
||||
"{0}".format(self.netvm.get_xid()))
|
||||
|
||||
def write_iptables_xenstore_entry(self):
|
||||
vmm.xs.rm('', "/local/domain/{0}/qubes-iptables-domainrules".format(self.get_xid()))
|
||||
iptables = "# Generated by Qubes Core on {0}\n".format(datetime.now().ctime())
|
||||
self.qdb.rm("/qubes-iptables-domainrules/")
|
||||
iptables = "# Generated by Qubes Core on \n".format(datetime.now().ctime())
|
||||
iptables += "*filter\n"
|
||||
iptables += ":INPUT DROP [0:0]\n"
|
||||
iptables += ":FORWARD DROP [0:0]\n"
|
||||
@ -140,7 +138,7 @@ class QubesProxyVm(QubesNetVm):
|
||||
# Deny inter-VMs networking
|
||||
iptables += "-A FORWARD -i vif+ -o vif+ -j DROP\n"
|
||||
iptables += "COMMIT\n"
|
||||
vmm.xs.write('', "/local/domain/{0}/qubes-iptables-header".format(self.get_xid()), iptables)
|
||||
self.qdb.write("/qubes-iptables-header", iptables)
|
||||
|
||||
vms = [vm for vm in self.connected_vms.values()]
|
||||
for vm in vms:
|
||||
@ -168,18 +166,18 @@ class QubesProxyVm(QubesNetVm):
|
||||
rules_action = accept_action
|
||||
|
||||
for rule in conf["rules"]:
|
||||
iptables += "-A FORWARD -s {0} -d {1}".format(ip, rule["address"])
|
||||
iptables += "-A FORWARD -s -d {1}".format(ip, rule["address"])
|
||||
if rule["netmask"] != 32:
|
||||
iptables += "/{0}".format(rule["netmask"])
|
||||
iptables += "/".format(rule["netmask"])
|
||||
|
||||
if rule["proto"] is not None and rule["proto"] != "any":
|
||||
iptables += " -p {0}".format(rule["proto"])
|
||||
iptables += " -p ".format(rule["proto"])
|
||||
if rule["portBegin"] is not None and rule["portBegin"] > 0:
|
||||
iptables += " --dport {0}".format(rule["portBegin"])
|
||||
iptables += " --dport ".format(rule["portBegin"])
|
||||
if rule["portEnd"] is not None and rule["portEnd"] > rule["portBegin"]:
|
||||
iptables += ":{0}".format(rule["portEnd"])
|
||||
iptables += ":".format(rule["portEnd"])
|
||||
|
||||
iptables += " -j {0}\n".format(rules_action)
|
||||
iptables += " -j \n".format(rules_action)
|
||||
|
||||
if conf["allowDns"] and self.netvm is not None:
|
||||
# PREROUTING does DNAT to NetVM DNSes, so we need self.netvm.
|
||||
@ -193,20 +191,20 @@ class QubesProxyVm(QubesNetVm):
|
||||
iptables += "-A FORWARD -s {0} -p tcp -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)
|
||||
iptables += "-A FORWARD -s -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)
|
||||
iptables += "-A FORWARD -s -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 -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 += "-A FORWARD -s -j {1}\n".format(ip, default_action)
|
||||
iptables += "COMMIT\n"
|
||||
vmm.xs.write('', "/local/domain/"+str(self.get_xid())+"/qubes-iptables-domainrules/"+str(xid), iptables)
|
||||
self.qdb.write("/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
|
||||
vmm.xs.write('', "/local/domain/{0}/qubes-iptables".format(self.get_xid()), 'reload')
|
||||
self.qdb.write("/qubes-iptables", 'reload')
|
||||
|
||||
register_qubes_vm_class(QubesProxyVm)
|
||||
|
@ -110,6 +110,7 @@ class QubesDisposableVm(QubesVm):
|
||||
def create_xenstore_entries(self, xid):
|
||||
super(QubesDisposableVm, self).create_xenstore_entries(xid)
|
||||
|
||||
# TODO!
|
||||
domain_path = vmm.xs.get_domain_path(xid)
|
||||
|
||||
vmm.xs.write('', "{0}/qubes-restore-complete".format(domain_path),
|
||||
|
@ -49,6 +49,7 @@ system_path = {
|
||||
'qubes_guid_path': '/usr/bin/qubes-guid',
|
||||
'qrexec_daemon_path': '/usr/lib/qubes/qrexec-daemon',
|
||||
'qrexec_client_path': '/usr/lib/qubes/qrexec-client',
|
||||
'qubesdb_daemon_path': '/usr/sbin/qubesdb-daemon',
|
||||
|
||||
'qubes_base_dir': qubes_base_dir,
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=Qubes Dom0 startup setup
|
||||
After=qubes-db-dom0.service
|
||||
# Cover legacy init.d script
|
||||
|
||||
[Service]
|
||||
|
@ -48,6 +48,7 @@ Requires(preun): systemd-units
|
||||
Requires(postun): systemd-units
|
||||
Requires: python, pciutils, python-inotify, python-daemon
|
||||
Requires: qubes-core-dom0-linux >= 2.0.24
|
||||
Requires: qubes-db-dom0
|
||||
Requires: python-lxml
|
||||
Requires: python-psutil
|
||||
# TODO: R: qubes-gui-dom0 >= 2.1.11
|
||||
|
Loading…
Reference in New Issue
Block a user