Merge branch 'hvm' of 10.141.1.101:/var/lib/qubes/git/marmarek/core
This commit is contained in:
commit
859c99da5c
32
dom0/misc/vm-template-hvm.conf
Normal file
32
dom0/misc/vm-template-hvm.conf
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#
|
||||||
|
# This is a Xen VM config file for Qubes VM
|
||||||
|
# DO NOT EDIT - autogenerated by qubes tools
|
||||||
|
#
|
||||||
|
|
||||||
|
name = "{name}"
|
||||||
|
|
||||||
|
builder='hvm'
|
||||||
|
memory={mem}
|
||||||
|
viridian=1
|
||||||
|
kernel='hvmloader'
|
||||||
|
#acpi=1
|
||||||
|
#apic=1
|
||||||
|
boot='dca'
|
||||||
|
device_model='stubdom-dm'
|
||||||
|
#pae=1
|
||||||
|
usbdevice='tablet'
|
||||||
|
sdl=0
|
||||||
|
vnc=0
|
||||||
|
disk = [ {rootdev}
|
||||||
|
{otherdevs}
|
||||||
|
]
|
||||||
|
vif = [ {netdev} ]
|
||||||
|
pci = [ {pcidev} ]
|
||||||
|
vcpus = {vcpus}
|
||||||
|
|
||||||
|
#tsc_mode = 2
|
||||||
|
#xen_extended_power_mgmt=0
|
||||||
|
|
||||||
|
on_poweroff = 'destroy'
|
||||||
|
on_reboot = 'destroy'
|
||||||
|
on_crash = 'destroy'
|
@ -21,6 +21,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import stat
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import subprocess
|
import subprocess
|
||||||
@ -78,6 +79,11 @@ default_servicevm_vcpus = 1
|
|||||||
default_kernelopts = ""
|
default_kernelopts = ""
|
||||||
default_kernelopts_pcidevs = "iommu=soft swiotlb=2048"
|
default_kernelopts_pcidevs = "iommu=soft swiotlb=2048"
|
||||||
|
|
||||||
|
default_hvm_disk_size = 20*1024*1024*1024
|
||||||
|
|
||||||
|
config_template_pv = '/usr/share/qubes/vm-template.conf'
|
||||||
|
config_template_hvm = '/usr/share/qubes/vm-template-hvm.conf'
|
||||||
|
|
||||||
qubes_whitelisted_appmenus = 'whitelisted-appmenus.list'
|
qubes_whitelisted_appmenus = 'whitelisted-appmenus.list'
|
||||||
|
|
||||||
dom0_update_check_interval = 6*3600
|
dom0_update_check_interval = 6*3600
|
||||||
@ -238,6 +244,8 @@ class QubesVm(object):
|
|||||||
|
|
||||||
self.firewall_conf = self.absolute_path(firewall_conf, default_firewall_conf_file)
|
self.firewall_conf = self.absolute_path(firewall_conf, default_firewall_conf_file)
|
||||||
|
|
||||||
|
self.config_file_template = config_template_pv
|
||||||
|
|
||||||
self.updateable = updateable
|
self.updateable = updateable
|
||||||
self._label = label if label is not None else QubesVmLabels["red"]
|
self._label = label if label is not None else QubesVmLabels["red"]
|
||||||
if self.dir_path is not None:
|
if self.dir_path is not None:
|
||||||
@ -788,7 +796,8 @@ class QubesVm(object):
|
|||||||
def get_config_params(self, source_template=None):
|
def get_config_params(self, source_template=None):
|
||||||
args = {}
|
args = {}
|
||||||
args['name'] = self.name
|
args['name'] = self.name
|
||||||
args['kerneldir'] = self.kernels_dir
|
if hasattr(self, 'kernels_dir'):
|
||||||
|
args['kerneldir'] = self.kernels_dir
|
||||||
args['vmdir'] = self.dir_path
|
args['vmdir'] = self.dir_path
|
||||||
args['pcidev'] = str(self.pcidevs).strip('[]')
|
args['pcidev'] = str(self.pcidevs).strip('[]')
|
||||||
args['mem'] = str(self.memory)
|
args['mem'] = str(self.memory)
|
||||||
@ -804,11 +813,13 @@ class QubesVm(object):
|
|||||||
args['rootdev'] = self.get_rootdev(source_template=source_template)
|
args['rootdev'] = self.get_rootdev(source_template=source_template)
|
||||||
args['privatedev'] = "'script:file:{dir}/private.img,xvdb,w',".format(dir=self.dir_path)
|
args['privatedev'] = "'script:file:{dir}/private.img,xvdb,w',".format(dir=self.dir_path)
|
||||||
args['volatiledev'] = "'script:file:{dir}/volatile.img,xvdc,w',".format(dir=self.dir_path)
|
args['volatiledev'] = "'script:file:{dir}/volatile.img,xvdc,w',".format(dir=self.dir_path)
|
||||||
modulesmode='r'
|
if hasattr(self, 'kernel'):
|
||||||
if self.is_updateable() and self.kernel is None:
|
modulesmode='r'
|
||||||
modulesmode='w'
|
if self.is_updateable() and self.kernel is None:
|
||||||
args['otherdevs'] = "'script:file:{dir}/modules.img,xvdd,{mode}',".format(dir=self.kernels_dir, mode=modulesmode)
|
modulesmode='w'
|
||||||
args['kernelopts'] = self.kernelopts
|
args['otherdevs'] = "'script:file:{dir}/modules.img,xvdd,{mode}',".format(dir=self.kernels_dir, mode=modulesmode)
|
||||||
|
if hasattr(self, 'kernelopts'):
|
||||||
|
args['kernelopts'] = self.kernelopts
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
@ -818,7 +829,7 @@ class QubesVm(object):
|
|||||||
if source_template is None:
|
if source_template is None:
|
||||||
source_template = self.template_vm
|
source_template = self.template_vm
|
||||||
|
|
||||||
f_conf_template = open('/usr/share/qubes/vm-template.conf', 'r')
|
f_conf_template = open(self.config_file_template, 'r')
|
||||||
conf_template = f_conf_template.read()
|
conf_template = f_conf_template.read()
|
||||||
f_conf_template.close()
|
f_conf_template.close()
|
||||||
|
|
||||||
@ -1163,6 +1174,14 @@ class QubesVm(object):
|
|||||||
if notify_function is not None:
|
if notify_function is not None:
|
||||||
notify_function("error", "ERROR: Cannot start the Qubes Clipboard Notifier!")
|
notify_function("error", "ERROR: Cannot start the Qubes Clipboard Notifier!")
|
||||||
|
|
||||||
|
def start_qrexec_daemon(self, verbose = False):
|
||||||
|
if verbose:
|
||||||
|
print >> sys.stderr, "--> Starting the qrexec daemon..."
|
||||||
|
retcode = subprocess.call ([qrexec_daemon_path, str(xid)])
|
||||||
|
if (retcode != 0) :
|
||||||
|
self.force_shutdown()
|
||||||
|
raise OSError ("ERROR: Cannot execute qrexec_daemon!")
|
||||||
|
|
||||||
def start(self, debug_console = False, verbose = False, preparing_dvm = False):
|
def start(self, debug_console = False, verbose = False, preparing_dvm = False):
|
||||||
if dry_run:
|
if dry_run:
|
||||||
return
|
return
|
||||||
@ -1234,12 +1253,7 @@ class QubesVm(object):
|
|||||||
qmemman_client.close()
|
qmemman_client.close()
|
||||||
|
|
||||||
if not preparing_dvm:
|
if not preparing_dvm:
|
||||||
if verbose:
|
self.start_qrexec_daemon(verbose=verbose)
|
||||||
print >> sys.stderr, "--> Starting the qrexec daemon..."
|
|
||||||
retcode = subprocess.call ([qrexec_daemon_path, str(xid)])
|
|
||||||
if (retcode != 0) :
|
|
||||||
self.force_shutdown()
|
|
||||||
raise OSError ("ERROR: Cannot execute qrexec_daemon!")
|
|
||||||
|
|
||||||
if not preparing_dvm and os.path.exists('/var/run/shm.id'):
|
if not preparing_dvm and os.path.exists('/var/run/shm.id'):
|
||||||
self.start_guid(verbose=verbose)
|
self.start_guid(verbose=verbose)
|
||||||
@ -1285,26 +1299,20 @@ class QubesVm(object):
|
|||||||
attrs["qid"] = str(self.qid)
|
attrs["qid"] = str(self.qid)
|
||||||
attrs["name"] = self.name
|
attrs["name"] = self.name
|
||||||
attrs["dir_path"] = self.dir_path
|
attrs["dir_path"] = self.dir_path
|
||||||
attrs["conf_file"] = self.relative_path(self.conf_file)
|
# Simple paths
|
||||||
attrs["root_img"] = self.relative_path(self.root_img)
|
for prop in ['conf_file', 'root_img', 'volatile_img', 'private_img']:
|
||||||
attrs["volatile_img"] = self.relative_path(self.volatile_img)
|
if hasattr(self, prop):
|
||||||
attrs["private_img"] = self.relative_path(self.private_img)
|
attrs[prop] = self.relative_path(self.__getattribute__(prop))
|
||||||
attrs["uses_default_netvm"] = str(self.uses_default_netvm)
|
# Simple string attrs
|
||||||
|
for prop in ['memory', 'maxmem', 'pcidevs', 'vcpus', 'internal',\
|
||||||
|
'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\
|
||||||
|
'kernelopts', 'services', 'updateable', 'installed_by_rpm',\
|
||||||
|
'uses_default_netvm' ]:
|
||||||
|
if hasattr(self, prop):
|
||||||
|
attrs[prop] = str(self.__getattribute__(prop))
|
||||||
attrs["netvm_qid"] = str(self.netvm_vm.qid) if self.netvm_vm is not None else "none"
|
attrs["netvm_qid"] = str(self.netvm_vm.qid) if self.netvm_vm is not None else "none"
|
||||||
attrs["installed_by_rpm"] = str(self.installed_by_rpm)
|
|
||||||
attrs["template_qid"] = str(self.template_vm.qid) if self.template_vm and not self.is_updateable() else "none"
|
attrs["template_qid"] = str(self.template_vm.qid) if self.template_vm and not self.is_updateable() else "none"
|
||||||
attrs["updateable"] = str(self.updateable)
|
|
||||||
attrs["label"] = self.label.name
|
attrs["label"] = self.label.name
|
||||||
attrs["memory"] = str(self.memory)
|
|
||||||
attrs["maxmem"] = str(self.maxmem)
|
|
||||||
attrs["pcidevs"] = str(self.pcidevs)
|
|
||||||
attrs["vcpus"] = str(self.vcpus)
|
|
||||||
attrs["internal"] = str(self.internal)
|
|
||||||
attrs["uses_default_kernel"] = str(self.uses_default_kernel)
|
|
||||||
attrs["kernel"] = str(self.kernel)
|
|
||||||
attrs["uses_default_kernelopts"] = str(self.uses_default_kernelopts)
|
|
||||||
attrs["kernelopts"] = str(self.kernelopts)
|
|
||||||
attrs["services"] = str(self.services)
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def create_xml_element(self):
|
def create_xml_element(self):
|
||||||
@ -1988,6 +1996,127 @@ class QubesAppVm(QubesVm):
|
|||||||
def post_rename(self, old_name):
|
def post_rename(self, old_name):
|
||||||
self.create_appmenus(False)
|
self.create_appmenus(False)
|
||||||
|
|
||||||
|
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 __init__(self, **kwargs):
|
||||||
|
|
||||||
|
if "dir_path" not in kwargs or kwargs["dir_path"] is None:
|
||||||
|
kwargs["dir_path"] = qubes_appvms_dir + "/" + kwargs["name"]
|
||||||
|
|
||||||
|
super(QubesHVm, self).__init__(**kwargs)
|
||||||
|
self.updateable = True
|
||||||
|
self.config_file_template = config_template_hvm
|
||||||
|
# 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')
|
||||||
|
self.__delattr__('private_img')
|
||||||
|
self.__delattr__('volatile_img')
|
||||||
|
# HVM doesn't support dynamic memory management
|
||||||
|
self.maxmem = self.memory
|
||||||
|
|
||||||
|
self.drive = None
|
||||||
|
if 'drive' in kwargs.keys():
|
||||||
|
self.drive = kwargs['drive']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return "HVM"
|
||||||
|
|
||||||
|
def is_appvm(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
self.create_config_file()
|
||||||
|
|
||||||
|
# create empty disk
|
||||||
|
f_root = open(self.root_img, "w")
|
||||||
|
f_root.truncate(default_hvm_disk_size)
|
||||||
|
f_root.close()
|
||||||
|
|
||||||
|
|
||||||
|
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'] = ''
|
||||||
|
params['privatedev'] = ''
|
||||||
|
if self.drive:
|
||||||
|
stat_res = os.stat(self.drive)
|
||||||
|
if stat.S_ISBLK(stat_res.st_mode):
|
||||||
|
params['otherdevs'] = "'phy:%s,hdc:cdrom,r'," % self.drive
|
||||||
|
else:
|
||||||
|
params['otherdevs'] = "'script:file:%s,hdc:cdrom,r'," % self.drive
|
||||||
|
else:
|
||||||
|
params['otherdevs'] = ''
|
||||||
|
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))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def reset_volatile_storage(self, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self, command, **kwargs):
|
||||||
|
raise NotImplementedError("Needs qrexec agent - TODO")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stubdom_xid(self):
|
||||||
|
if not self.is_running():
|
||||||
|
return -1
|
||||||
|
|
||||||
|
return int(xs.read('', '/local/domain/%d/image/device-model-domid' % self.xid))
|
||||||
|
|
||||||
|
def start_guid(self, verbose = True, notify_function = None):
|
||||||
|
if verbose:
|
||||||
|
print >> sys.stderr, "--> Starting Qubes GUId..."
|
||||||
|
|
||||||
|
retcode = subprocess.call ([qubes_guid_path, "-d", str(self.stubdom_xid), "-c", self.label.color, "-i", self.label.icon, "-l", str(self.label.index)])
|
||||||
|
if (retcode != 0) :
|
||||||
|
raise QubesException("Cannot start qubes_guid!")
|
||||||
|
|
||||||
|
def start_qrexec_daemon(self, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_xml_attrs(self):
|
||||||
|
attrs = super(QubesHVm, self).get_xml_attrs()
|
||||||
|
attrs["drive"] = str(self.drive)
|
||||||
|
return attrs
|
||||||
|
|
||||||
class QubesVmCollection(dict):
|
class QubesVmCollection(dict):
|
||||||
"""
|
"""
|
||||||
@ -2046,6 +2175,20 @@ class QubesVmCollection(dict):
|
|||||||
self[vm.qid]=vm
|
self[vm.qid]=vm
|
||||||
return vm
|
return vm
|
||||||
|
|
||||||
|
def add_new_hvm(self, name, label = None):
|
||||||
|
|
||||||
|
qid = self.get_new_unused_qid()
|
||||||
|
vm = QubesHVm (qid=qid, name=name,
|
||||||
|
netvm_vm = self.get_default_netvm_vm(),
|
||||||
|
kernel = self.get_default_kernel(),
|
||||||
|
uses_default_kernel = True,
|
||||||
|
label=label)
|
||||||
|
|
||||||
|
if not self.verify_new_vm (vm):
|
||||||
|
assert False, "Wrong VM description!"
|
||||||
|
self[vm.qid]=vm
|
||||||
|
return vm
|
||||||
|
|
||||||
def add_new_disposablevm(self, name, template_vm, dispid,
|
def add_new_disposablevm(self, name, template_vm, dispid,
|
||||||
label = None):
|
label = None):
|
||||||
|
|
||||||
@ -2571,6 +2714,20 @@ class QubesVmCollection(dict):
|
|||||||
os.path.basename(sys.argv[0]), err))
|
os.path.basename(sys.argv[0]), err))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# And HVMs
|
||||||
|
for element in tree.findall("QubesHVm"):
|
||||||
|
try:
|
||||||
|
kwargs = self.parse_xml_element(element)
|
||||||
|
vm = QubesHVm(**kwargs)
|
||||||
|
|
||||||
|
self[vm.qid] = vm
|
||||||
|
|
||||||
|
self.set_netvm_dependency(element)
|
||||||
|
except (ValueError, LookupError) as err:
|
||||||
|
print("{0}: import error (QubesHVm): {1}".format(
|
||||||
|
os.path.basename(sys.argv[0]), err))
|
||||||
|
return False
|
||||||
|
|
||||||
# Really finally, read in the DisposableVMs
|
# Really finally, read in the DisposableVMs
|
||||||
for element in tree.findall("QubesDisposableVm"):
|
for element in tree.findall("QubesDisposableVm"):
|
||||||
try:
|
try:
|
||||||
|
@ -37,10 +37,14 @@ def main():
|
|||||||
help="Specify the label to use for the new VM (e.g. red, yellow, green, ...)")
|
help="Specify the label to use for the new VM (e.g. red, yellow, green, ...)")
|
||||||
parser.add_option ("-p", "--proxy", action="store_true", dest="proxyvm", default=False,
|
parser.add_option ("-p", "--proxy", action="store_true", dest="proxyvm", default=False,
|
||||||
help="Create ProxyVM")
|
help="Create ProxyVM")
|
||||||
|
parser.add_option ("-H", "--hvm", action="store_true", dest="hvm", default=False,
|
||||||
|
help="Create HVM (implies --standalone)")
|
||||||
parser.add_option ("-n", "--net", action="store_true", dest="netvm", default=False,
|
parser.add_option ("-n", "--net", action="store_true", dest="netvm", default=False,
|
||||||
help="Create NetVM")
|
help="Create NetVM")
|
||||||
parser.add_option ("-s", "--standalone", action="store_true", dest="standalone", default=False,
|
parser.add_option ("-s", "--standalone", action="store_true", dest="standalone", default=False,
|
||||||
help="Create standalone VM - independent of template ")
|
help="Create standalone VM - independent of template ")
|
||||||
|
parser.add_option ("-r", "--root", dest="root", default=None,
|
||||||
|
help="Use provided root.img instead of default/empty one (file will be MOVED)")
|
||||||
parser.add_option ("-m", "--mem", dest="mem", default=None,
|
parser.add_option ("-m", "--mem", dest="mem", default=None,
|
||||||
help="Initial memory size (in MB)")
|
help="Initial memory size (in MB)")
|
||||||
parser.add_option ("-c", "--vcpus", dest="vcpus", default=None,
|
parser.add_option ("-c", "--vcpus", dest="vcpus", default=None,
|
||||||
@ -82,6 +86,18 @@ def main():
|
|||||||
exit (1)
|
exit (1)
|
||||||
label = QubesVmLabels[options.label]
|
label = QubesVmLabels[options.label]
|
||||||
|
|
||||||
|
if options.hvm:
|
||||||
|
# Only standalone HVMs are supported for now
|
||||||
|
options.standalone = True
|
||||||
|
|
||||||
|
if not options.standalone and options.root is not None:
|
||||||
|
print >> sys.stderr, "root.img can be specified only for standalone VMs"
|
||||||
|
exit (1)
|
||||||
|
|
||||||
|
if options.root is not None and not os.path.exists(options.root):
|
||||||
|
print >> sys.stderr, "File specified as root.img does not exists"
|
||||||
|
exit (1)
|
||||||
|
|
||||||
qvm_collection = QubesVmCollection()
|
qvm_collection = QubesVmCollection()
|
||||||
qvm_collection.lock_db_for_writing()
|
qvm_collection.lock_db_for_writing()
|
||||||
qvm_collection.load()
|
qvm_collection.load()
|
||||||
@ -90,6 +106,7 @@ def main():
|
|||||||
print >> sys.stderr, "A VM with the name '{0}' already exists in the system.".format(vmname)
|
print >> sys.stderr, "A VM with the name '{0}' already exists in the system.".format(vmname)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
template_vm = None
|
||||||
if options.template is not None:
|
if options.template is not None:
|
||||||
template_vm = qvm_collection.get_vm_by_name(options.template)
|
template_vm = qvm_collection.get_vm_by_name(options.template)
|
||||||
if template_vm is None:
|
if template_vm is None:
|
||||||
@ -101,7 +118,7 @@ def main():
|
|||||||
if (options.verbose):
|
if (options.verbose):
|
||||||
print "--> Using TemplateVM: {0}".format(template_vm.name)
|
print "--> Using TemplateVM: {0}".format(template_vm.name)
|
||||||
|
|
||||||
else:
|
elif not options.hvm:
|
||||||
if qvm_collection.get_default_template_vm() is None:
|
if qvm_collection.get_default_template_vm() is None:
|
||||||
print >> sys.stderr, "No default TempleteVM defined!"
|
print >> sys.stderr, "No default TempleteVM defined!"
|
||||||
exit (1)
|
exit (1)
|
||||||
@ -120,6 +137,8 @@ def main():
|
|||||||
vm = qvm_collection.add_new_netvm(vmname, new_vm_template, label = label, updateable = options.standalone)
|
vm = qvm_collection.add_new_netvm(vmname, new_vm_template, label = label, updateable = options.standalone)
|
||||||
elif options.proxyvm:
|
elif options.proxyvm:
|
||||||
vm = qvm_collection.add_new_proxyvm(vmname, new_vm_template, label = label, updateable = options.standalone)
|
vm = qvm_collection.add_new_proxyvm(vmname, new_vm_template, label = label, updateable = options.standalone)
|
||||||
|
elif options.hvm:
|
||||||
|
vm = qvm_collection.add_new_hvm(vmname, label = label)
|
||||||
else:
|
else:
|
||||||
vm = qvm_collection.add_new_appvm(vmname, new_vm_template, label = label, updateable = options.standalone)
|
vm = qvm_collection.add_new_appvm(vmname, new_vm_template, label = label, updateable = options.standalone)
|
||||||
|
|
||||||
@ -134,6 +153,9 @@ def main():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
vm.create_on_disk(verbose=options.verbose, source_template=template_vm)
|
vm.create_on_disk(verbose=options.verbose, source_template=template_vm)
|
||||||
|
if options.root:
|
||||||
|
os.unlink(vm.root_img)
|
||||||
|
os.rename(options.root, vm.root_img)
|
||||||
|
|
||||||
except (IOError, OSError) as err:
|
except (IOError, OSError) as err:
|
||||||
print >> sys.stderr, "ERROR: {0}".format(err)
|
print >> sys.stderr, "ERROR: {0}".format(err)
|
||||||
|
@ -51,22 +51,32 @@ def do_list(vm):
|
|||||||
print fmt.format ("root COW img", vm.rootcow_img)
|
print fmt.format ("root COW img", vm.rootcow_img)
|
||||||
if vm.template_vm is not None:
|
if vm.template_vm is not None:
|
||||||
print fmt.format ("root img", vm.template_vm.root_img)
|
print fmt.format ("root img", vm.template_vm.root_img)
|
||||||
print fmt.format ("root volatile img", vm.volatile_img)
|
if hasattr(vm, 'volatile_img'):
|
||||||
|
print fmt.format ("root volatile img", vm.volatile_img)
|
||||||
|
|
||||||
print fmt.format ("private img", vm.private_img)
|
if hasattr(vm, 'private_img'):
|
||||||
|
print fmt.format ("private img", vm.private_img)
|
||||||
print fmt.format ("vcpus", str(vm.vcpus))
|
print fmt.format ("vcpus", str(vm.vcpus))
|
||||||
print fmt.format ("memory", vm.memory)
|
print fmt.format ("memory", vm.memory)
|
||||||
print fmt.format ("maxmem", vm.maxmem)
|
if hasattr(vm, 'maxmem'):
|
||||||
if vm.template_vm is not None:
|
print fmt.format ("maxmem", vm.maxmem)
|
||||||
print fmt.format ("kernel", "%s (from template)" % vm.kernel)
|
|
||||||
elif vm.uses_default_kernel:
|
if hasattr(vm, 'kernel'):
|
||||||
print fmt.format ("kernel", "%s (default)" % vm.kernel)
|
if vm.template_vm is not None:
|
||||||
else:
|
print fmt.format ("kernel", "%s (from template)" % vm.kernel)
|
||||||
print fmt.format ("kernel", vm.kernel)
|
elif vm.uses_default_kernel:
|
||||||
if vm.uses_default_kernelopts:
|
print fmt.format ("kernel", "%s (default)" % vm.kernel)
|
||||||
print fmt.format ("kernelopts", "%s (default)" % vm.kernelopts)
|
else:
|
||||||
else:
|
print fmt.format ("kernel", vm.kernel)
|
||||||
print fmt.format ("kernelopts", vm.kernelopts)
|
|
||||||
|
if hasattr(vm, 'kernelopts'):
|
||||||
|
if vm.uses_default_kernelopts:
|
||||||
|
print fmt.format ("kernelopts", "%s (default)" % vm.kernelopts)
|
||||||
|
else:
|
||||||
|
print fmt.format ("kernelopts", vm.kernelopts)
|
||||||
|
|
||||||
|
if hasattr(vm, 'drive'):
|
||||||
|
print fmt.format("drive", str(vm.drive))
|
||||||
|
|
||||||
|
|
||||||
def set_label(vms, vm, args):
|
def set_label(vms, vm, args):
|
||||||
@ -287,6 +297,13 @@ def set_name(vms, vm, args):
|
|||||||
vm.set_name(args[0])
|
vm.set_name(args[0])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def set_drive(vms, vm, args):
|
||||||
|
if len (args) != 1:
|
||||||
|
print >> sys.stderr, "Missing new drive content (file/device)!"
|
||||||
|
return False
|
||||||
|
|
||||||
|
vm.drive = args[0]
|
||||||
|
return True
|
||||||
|
|
||||||
properties = {
|
properties = {
|
||||||
"updateable": set_updateable,
|
"updateable": set_updateable,
|
||||||
@ -301,6 +318,7 @@ properties = {
|
|||||||
"vcpus" : set_vcpus,
|
"vcpus" : set_vcpus,
|
||||||
"kernelopts": set_kernelopts,
|
"kernelopts": set_kernelopts,
|
||||||
"name": set_name,
|
"name": set_name,
|
||||||
|
"drive": set_drive,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -309,6 +327,10 @@ def do_set(vms, vm, property, args):
|
|||||||
print >> sys.stderr, "ERROR: Wrong property name: '{0}'".format(property)
|
print >> sys.stderr, "ERROR: Wrong property name: '{0}'".format(property)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if not hasattr(vm, property):
|
||||||
|
print >> sys.stderr, "ERROR: Property '{0}' not available for this VM".format(property)
|
||||||
|
return False
|
||||||
|
|
||||||
return properties[property](vms, vm, args)
|
return properties[property](vms, vm, args)
|
||||||
|
|
||||||
|
|
||||||
@ -353,7 +375,8 @@ def main():
|
|||||||
print >> sys.stderr, "You must specify the property you wish to set..."
|
print >> sys.stderr, "You must specify the property you wish to set..."
|
||||||
print >> sys.stderr, "Available properties:"
|
print >> sys.stderr, "Available properties:"
|
||||||
for p in properties.keys():
|
for p in properties.keys():
|
||||||
print >> sys.stderr, "--> '{0}'".format(p)
|
if hasattr(vm, p):
|
||||||
|
print >> sys.stderr, "--> '{0}'".format(p)
|
||||||
exit (1)
|
exit (1)
|
||||||
|
|
||||||
property = args[1]
|
property = args[1]
|
||||||
|
@ -37,6 +37,8 @@ def main():
|
|||||||
help="Do not start the GUId (ignored)")
|
help="Do not start the GUId (ignored)")
|
||||||
parser.add_option ("--console", action="store_true", dest="debug_console", default=False,
|
parser.add_option ("--console", action="store_true", dest="debug_console", default=False,
|
||||||
help="Attach debugging console to the newly started VM")
|
help="Attach debugging console to the newly started VM")
|
||||||
|
parser.add_option ("--drive", dest="drive", default=None,
|
||||||
|
help="Temporarily attach specified drive as CD/DVD")
|
||||||
parser.add_option ("--dvm", action="store_true", dest="preparing_dvm", default=False,
|
parser.add_option ("--dvm", action="store_true", dest="preparing_dvm", default=False,
|
||||||
help="Do actions necessary when preparing DVM image")
|
help="Do actions necessary when preparing DVM image")
|
||||||
|
|
||||||
@ -55,6 +57,13 @@ def main():
|
|||||||
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
|
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
if options.drive:
|
||||||
|
if hasattr(vm, 'drive'):
|
||||||
|
vm.drive = options.drive
|
||||||
|
else:
|
||||||
|
print >> sys.stderr, "This VM does not support attaching drives"
|
||||||
|
exit (1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
vm.verify_files()
|
vm.verify_files()
|
||||||
xid = vm.start(debug_console=options.debug_console, verbose=options.verbose, preparing_dvm=options.preparing_dvm)
|
xid = vm.start(debug_console=options.debug_console, verbose=options.verbose, preparing_dvm=options.preparing_dvm)
|
||||||
|
@ -151,6 +151,7 @@ cp misc/qubes-vm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
|
|||||||
cp misc/qubes-templatevm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
|
cp misc/qubes-templatevm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
|
||||||
cp misc/qubes-appmenu-select.desktop $RPM_BUILD_ROOT/usr/share/qubes/
|
cp misc/qubes-appmenu-select.desktop $RPM_BUILD_ROOT/usr/share/qubes/
|
||||||
cp misc/vm-template.conf $RPM_BUILD_ROOT/usr/share/qubes/
|
cp misc/vm-template.conf $RPM_BUILD_ROOT/usr/share/qubes/
|
||||||
|
cp misc/vm-template-hvm.conf $RPM_BUILD_ROOT/usr/share/qubes/
|
||||||
|
|
||||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||||
cp ../network/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes
|
cp ../network/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes
|
||||||
@ -344,6 +345,7 @@ fi
|
|||||||
/usr/share/qubes/qubes-templatevm.directory.template
|
/usr/share/qubes/qubes-templatevm.directory.template
|
||||||
/usr/share/qubes/qubes-appmenu-select.desktop
|
/usr/share/qubes/qubes-appmenu-select.desktop
|
||||||
/usr/share/qubes/vm-template.conf
|
/usr/share/qubes/vm-template.conf
|
||||||
|
/usr/share/qubes/vm-template-hvm.conf
|
||||||
/usr/lib/qubes/qubes_setup_dnat_to_ns
|
/usr/lib/qubes/qubes_setup_dnat_to_ns
|
||||||
/usr/lib/qubes/qubes_fix_nm_conf.sh
|
/usr/lib/qubes/qubes_fix_nm_conf.sh
|
||||||
/etc/dhclient.d/qubes_setup_dnat_to_ns.sh
|
/etc/dhclient.d/qubes_setup_dnat_to_ns.sh
|
||||||
|
36
vchan/Makefile.stubdom
Normal file
36
vchan/Makefile.stubdom
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# The Qubes OS Project, http://www.qubes-os.org
|
||||||
|
#
|
||||||
|
# Copyright (C) 2012 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.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
# Assume it is placed as xen-root/tools/vchan
|
||||||
|
|
||||||
|
XEN_ROOT = ../..
|
||||||
|
include $(XEN_ROOT)/tools/Rules.mk
|
||||||
|
|
||||||
|
CFLAGS+=-Wall -I$(XEN_ROOT)/tools/libxc -DCONFIG_STUBDOM
|
||||||
|
all: libvchan.a
|
||||||
|
|
||||||
|
libvchan.a: init.o io.o
|
||||||
|
$(AR) rc $@ $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o *so *~ client server node node-select
|
||||||
|
|
||||||
|
|
87
vchan/init.c
87
vchan/init.c
@ -19,6 +19,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -29,25 +32,38 @@
|
|||||||
#include <xenctrl.h>
|
#include <xenctrl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <mm.h>
|
||||||
#include "libvchan.h"
|
#include "libvchan.h"
|
||||||
|
#ifndef CONFIG_STUBDOM
|
||||||
#include "../u2mfn/u2mfnlib.h"
|
#include "../u2mfn/u2mfnlib.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static int ring_init(struct libvchan *ctrl)
|
static int ring_init(struct libvchan *ctrl)
|
||||||
{
|
{
|
||||||
int u2mfn = open("/proc/u2mfn", O_RDONLY);
|
|
||||||
int mfn;
|
int mfn;
|
||||||
struct vchan_interface *ring;
|
struct vchan_interface *ring;
|
||||||
|
#ifdef CONFIG_STUBDOM
|
||||||
|
ring = (struct vchan_interface *) memalign(XC_PAGE_SIZE, sizeof(*ring));
|
||||||
|
|
||||||
|
if (!ring)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
mfn = virtual_to_mfn(ring);
|
||||||
|
#else
|
||||||
|
int u2mfn = open("/proc/u2mfn", O_RDONLY);
|
||||||
ring = (struct vchan_interface *) u2mfn_alloc_kpage ();
|
ring = (struct vchan_interface *) u2mfn_alloc_kpage ();
|
||||||
|
|
||||||
if (ring == MAP_FAILED)
|
if (ring == MAP_FAILED)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ctrl->ring = ring;
|
|
||||||
if (u2mfn_get_last_mfn (&mfn) < 0)
|
if (u2mfn_get_last_mfn (&mfn) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ctrl->ring_ref = mfn;
|
|
||||||
close(u2mfn);
|
close(u2mfn);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctrl->ring = ring;
|
||||||
|
ctrl->ring_ref = mfn;
|
||||||
ring->cons_in = ring->prod_in = ring->cons_out = ring->prod_out =
|
ring->cons_in = ring->prod_in = ring->cons_out = ring->prod_out =
|
||||||
0;
|
0;
|
||||||
ring->server_closed = ring->client_closed = 0;
|
ring->server_closed = ring->client_closed = 0;
|
||||||
@ -65,13 +81,18 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
|
|||||||
struct xs_handle *xs;
|
struct xs_handle *xs;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
char ref[16];
|
char ref[16];
|
||||||
|
/* XXX temp hack begin */
|
||||||
|
char *domid_s;
|
||||||
|
int domid = 0;
|
||||||
|
unsigned int len;
|
||||||
|
/* XXX temp hack end */
|
||||||
#ifdef XENCTRL_HAS_XC_INTERFACE
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
xc_evtchn *evfd;
|
xc_evtchn *evfd;
|
||||||
#else
|
#else
|
||||||
int evfd;
|
int evfd;
|
||||||
#endif
|
#endif
|
||||||
evtchn_port_or_error_t port;
|
evtchn_port_or_error_t port;
|
||||||
xs = xs_domain_open();
|
xs = xs_daemon_open();
|
||||||
if (!xs) {
|
if (!xs) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -90,20 +111,41 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
|
|||||||
if (port < 0)
|
if (port < 0)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
ctrl->evport = port;
|
ctrl->evport = port;
|
||||||
|
ctrl->devno = devno;
|
||||||
|
|
||||||
|
// stubdom debug HACK XXX
|
||||||
|
domid_s = xs_read(xs, 0, "domid", &len);
|
||||||
|
if (domid_s)
|
||||||
|
domid = atoi(domid_s);
|
||||||
|
|
||||||
snprintf(ref, sizeof ref, "%d", ctrl->ring_ref);
|
snprintf(ref, sizeof ref, "%d", ctrl->ring_ref);
|
||||||
snprintf(buf, sizeof buf, "device/vchan/%d/ring-ref", devno);
|
snprintf(buf, sizeof buf, "device/vchan/%d/ring-ref", devno);
|
||||||
if (!xs_write(xs, 0, buf, ref, strlen(ref)))
|
if (!xs_write(xs, 0, buf, ref, strlen(ref)))
|
||||||
|
#ifdef CONFIG_STUBDOM
|
||||||
|
// TEMP HACK XXX FIXME goto fail2;
|
||||||
|
fprintf(stderr, "xenstore-write /local/domain/%d/%s %s\n", domid, buf, ref);
|
||||||
|
#else
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
#endif
|
||||||
snprintf(ref, sizeof ref, "%d", ctrl->evport);
|
snprintf(ref, sizeof ref, "%d", ctrl->evport);
|
||||||
snprintf(buf, sizeof buf, "device/vchan/%d/event-channel", devno);
|
snprintf(buf, sizeof buf, "device/vchan/%d/event-channel", devno);
|
||||||
if (!xs_write(xs, 0, buf, ref, strlen(ref)))
|
if (!xs_write(xs, 0, buf, ref, strlen(ref)))
|
||||||
|
#ifdef CONFIG_STUBDOM
|
||||||
|
// TEMP HACK XXX FIXME goto fail2;
|
||||||
|
fprintf(stderr, "xenstore-write /local/domain/%d/%s %s\n", domid, buf, ref);
|
||||||
|
#else
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
#endif
|
||||||
|
// do not block in stubdom - libvchan_server_handle_connected will be
|
||||||
|
// called on first input
|
||||||
|
#ifndef CONFIG_STUBDOM
|
||||||
// wait for the peer to arrive
|
// wait for the peer to arrive
|
||||||
if (xc_evtchn_pending(evfd) == -1)
|
if (xc_evtchn_pending(evfd) == -1)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
xc_evtchn_unmask(ctrl->evfd, ctrl->evport);
|
xc_evtchn_unmask(ctrl->evfd, ctrl->evport);
|
||||||
snprintf(buf, sizeof buf, "device/vchan/%d", devno);
|
snprintf(buf, sizeof buf, "device/vchan/%d", devno);
|
||||||
xs_rm(xs, 0, buf);
|
xs_rm(xs, 0, buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
fail2:
|
fail2:
|
||||||
@ -130,7 +172,7 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Run in AppVM (any domain).
|
Run in AppVM (any domain).
|
||||||
Sleeps until the connection is established.
|
Sleeps until the connection is established. (unless in stubdom)
|
||||||
\param devno something like a well-known port.
|
\param devno something like a well-known port.
|
||||||
\returns NULL on failure, handle on success
|
\returns NULL on failure, handle on success
|
||||||
*/
|
*/
|
||||||
@ -156,6 +198,39 @@ struct libvchan *libvchan_server_init(int devno)
|
|||||||
return ctrl;
|
return ctrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int libvchan_server_handle_connected(struct libvchan *ctrl)
|
||||||
|
{
|
||||||
|
struct xs_handle *xs;
|
||||||
|
char buf[64];
|
||||||
|
int ret = -1;
|
||||||
|
int libvchan_fd;
|
||||||
|
fd_set rfds;
|
||||||
|
|
||||||
|
xs = xs_daemon_open();
|
||||||
|
if (!xs) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// clear the pending flag
|
||||||
|
xc_evtchn_pending(ctrl->evfd);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof buf, "device/vchan/%d", ctrl->devno);
|
||||||
|
xs_rm(xs, 0, buf);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fail2:
|
||||||
|
if (ret)
|
||||||
|
#ifdef XENCTRL_HAS_XC_INTERFACE
|
||||||
|
xc_evtchn_close(ctrl->evfd);
|
||||||
|
#else
|
||||||
|
close(ctrl->evfd);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
xs_daemon_close(xs);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
retrieves ring-ref and event-channel numbers from xenstore (if
|
retrieves ring-ref and event-channel numbers from xenstore (if
|
||||||
they don't exist, return error, because nobody seems to listen);
|
they don't exist, return error, because nobody seems to listen);
|
||||||
|
19
vchan/io.c
19
vchan/io.c
@ -22,6 +22,8 @@
|
|||||||
#include "libvchan.h"
|
#include "libvchan.h"
|
||||||
#include <xenctrl.h>
|
#include <xenctrl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
/**
|
/**
|
||||||
\return How much data is immediately available for reading
|
\return How much data is immediately available for reading
|
||||||
*/
|
*/
|
||||||
@ -67,7 +69,24 @@ int libvchan_is_eof(struct libvchan *ctrl)
|
|||||||
int libvchan_wait(struct libvchan *ctrl)
|
int libvchan_wait(struct libvchan *ctrl)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
#ifndef CONFIG_STUBDOM
|
||||||
ret = xc_evtchn_pending(ctrl->evfd);
|
ret = xc_evtchn_pending(ctrl->evfd);
|
||||||
|
#else
|
||||||
|
int vchan_fd = libvchan_fd_for_select(ctrl);
|
||||||
|
fd_set rfds;
|
||||||
|
|
||||||
|
libvchan_prepare_to_select(ctrl);
|
||||||
|
while ((ret = xc_evtchn_pending(ctrl->evfd)) < 0) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(0, &rfds);
|
||||||
|
FD_SET(vchan_fd, &rfds);
|
||||||
|
ret = select(vchan_fd + 1, &rfds, NULL, NULL, NULL);
|
||||||
|
if (ret < 0 && errno != EINTR) {
|
||||||
|
perror("select");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (ret!=-1 && xc_evtchn_unmask(ctrl->evfd, ctrl->evport))
|
if (ret!=-1 && xc_evtchn_unmask(ctrl->evfd, ctrl->evport))
|
||||||
return -1;
|
return -1;
|
||||||
if (ret!=-1 && libvchan_is_eof(ctrl))
|
if (ret!=-1 && libvchan_is_eof(ctrl))
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBVCHAN_H
|
||||||
|
#define _LIBVCHAN_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <xenctrl.h>
|
#include <xenctrl.h>
|
||||||
typedef uint32_t VCHAN_RING_IDX;
|
typedef uint32_t VCHAN_RING_IDX;
|
||||||
@ -44,6 +47,7 @@ struct libvchan {
|
|||||||
int evfd;
|
int evfd;
|
||||||
#endif
|
#endif
|
||||||
int evport;
|
int evport;
|
||||||
|
int devno;
|
||||||
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
|
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
|
||||||
char *rd_ring, *wr_ring;
|
char *rd_ring, *wr_ring;
|
||||||
int rd_ring_size, wr_ring_size;
|
int rd_ring_size, wr_ring_size;
|
||||||
@ -51,6 +55,7 @@ struct libvchan {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct libvchan *libvchan_server_init(int devno);
|
struct libvchan *libvchan_server_init(int devno);
|
||||||
|
int libvchan_server_handle_connected(struct libvchan *ctrl);
|
||||||
|
|
||||||
struct libvchan *libvchan_client_init(int domain, int devno);
|
struct libvchan *libvchan_client_init(int domain, int devno);
|
||||||
|
|
||||||
@ -63,3 +68,5 @@ int libvchan_fd_for_select(struct libvchan *ctrl);
|
|||||||
int libvchan_is_eof(struct libvchan *ctrl);
|
int libvchan_is_eof(struct libvchan *ctrl);
|
||||||
int libvchan_data_ready(struct libvchan *ctrl);
|
int libvchan_data_ready(struct libvchan *ctrl);
|
||||||
int libvchan_buffer_space(struct libvchan *ctrl);
|
int libvchan_buffer_space(struct libvchan *ctrl);
|
||||||
|
|
||||||
|
#endif /* _LIBVCHAN_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user