[XEND] Preliminary console support in Xen API

Made serial/vnc consoles a 'fake' device so that we can take advantage
of storing state information in xenstore.

Signed-off-by: Alastair Tse <atse@xensource.com>
This commit is contained in:
Alastair Tse committed 2007-01-25 18:54:25 +00:00
1 parent 4b3c5bc127
commit 690dd07a38
7 files changed
+164 -24

No files matched your search

+28 -1
View File
@@ -40,6 +40,7 @@ VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\
VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
CONSOLE_LIST_FORMAT = '%(uuid)-36s %(protocol)-8s %(uri)-32s'
COMMANDS = {
'host-info': ('', 'Get Xen Host Info'),
@@ -485,7 +486,8 @@ def xapi_vbd_list(args, async = False):
for vbd in vbds:
vbd_struct = execute(server, 'VBD.get_record', (session, vbd))
print VBD_LIST_FORMAT % vbd_struct
def xapi_vbd_stats(args, async = False):
server, session = connect()
domname = args[0]
@@ -519,6 +521,31 @@ def xapi_vif_list(args, async = False):
vif_struct = execute(server, 'VIF.get_record', (session, vif))
pprint(vif_struct)
def xapi_console_list(args, async = False):
server, session = connect()
opts, args = parse_args('vdi-list', args, set_defaults = True)
is_long = opts and opts.long
domname = args[0]
dom_uuid = resolve_vm(server, session, domname)
consoles = execute(server, 'VM.get_consoles', (session, dom_uuid))
if not is_long:
print CONSOLE_LIST_FORMAT % {'protocol': 'Protocol',
'uri': 'URI',
'uuid': 'UUID'}
for console in consoles:
console_struct = execute(server, 'console.get_record',
(session, console))
print CONSOLE_LIST_FORMAT % console_struct
else:
for console in consoles:
console_struct = execute(server, 'console.get_record',
(session, console))
pprint(console_struct)
def xapi_vdi_list(args, async = False):
opts, args = parse_args('vdi-list', args, set_defaults = True)
+67 -2
View File
@@ -228,6 +228,18 @@ def valid_vtpm(func):
_check_ref(lambda r: XendDomain.instance().is_valid_dev('vtpm', r),
'VTPM_HANDLE_INVALID', func, *args, **kwargs)
def valid_console(func):
"""Decorator to verify if console_ref is valid before calling method.
@param func: function with params: (self, session, console_ref, ...)
@rtype: callable object
"""
return lambda *args, **kwargs: \
_check_ref(lambda r: XendDomain.instance().is_valid_dev('console',
r),
'CONSOLE_HANDLE_INVALID', func, *args, **kwargs)
def valid_sr(func):
"""Decorator to verify if sr_ref is valid before calling method.
@@ -346,6 +358,7 @@ class XendAPI(object):
'VIF' : valid_vif,
'VDI' : valid_vdi,
'VTPM' : valid_vtpm,
'console' : valid_console,
'SR' : valid_sr,
'PIF' : valid_pif,
'task' : valid_task,
@@ -983,14 +996,18 @@ class XendAPI(object):
def VM_get_VTPMs(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_success(dom.get_vtpms())
def VM_get_consoles(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_success(dom.get_consoles())
def VM_get_PCI_bus(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_todo() # unsupported by xc
return dom.get_pci_bus()
def VM_get_tools_version(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_todo()
return dom.get_tools_version()
# attributes (rw)
def VM_get_name_label(self, session, vm_ref):
@@ -1784,6 +1801,54 @@ class XendAPI(object):
vtpms = reduce(lambda x, y: x + y, vtpms)
return xen_api_success(vtpms)
# Xen API: Class console
# ----------------------------------------------------------------
console_attr_ro = ['uri', 'protocol', 'VM']
console_attr_rw = []
def console_get_all(self, session):
xendom = XendDomain.instance()
cons = [d.get_consoles() for d in XendDomain.instance().list('all')]
cons = reduce(lambda x, y: x + y, cons)
return xen_api_success(cons)
def console_get_uri(self, session, console_ref):
return xen_api_success(xendom.get_dev_property_by_uuid('console',
console_ref,
'uri'))
def console_get_protocol(self, session, console_ref):
return xen_api_success(xendom.get_dev_property_by_uuid('console',
console_ref,
'protocol'))
def console_get_VM(self, session, console_ref):
xendom = XendDomain.instance()
vm = xendom.get_vm_with_dev_uuid('console', console_ref)
return xen_api_success(vm.get_uuid())
# object methods
def console_get_record(self, session, console_ref):
xendom = XendDomain.instance()
vm = xendom.get_vm_with_dev_uuid('console', console_ref)
if not vm:
return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref])
cfg = vm.get_dev_xenapi_config('console', console_ref)
if not cfg:
return xen_api_error(['CONSOLE_HANDLE_INVALID', console_ref])
valid_console_keys = self.console_attr_ro + self.console_attr_rw + \
self.Base_attr_ro + self.Base_attr_rw
return_cfg = {}
for k in cfg.keys():
if k in valid_console_keys:
return_cfg[k] = cfg[k]
return xen_api_success(return_cfg)
# Xen API: Class SR
# ----------------------------------------------------------------
@@ -75,3 +75,4 @@ XEN_API_VDI_TYPE = ['system', 'user', 'ephemeral']
XEN_API_DRIVER_TYPE = ['ioemu', 'paravirtualised']
XEN_API_VBD_TYPE = ['CD', 'Disk']
XEN_API_TASK_STATUS_TYPE = ['pending', 'success', 'failure']
XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp']
+31 -9
View File
@@ -918,8 +918,7 @@ class XendConfig(dict):
if target == None:
target = self
if dev_type not in XendDevices.valid_devices() and \
dev_type not in XendDevices.pseudo_devices():
if dev_type not in XendDevices.valid_devices():
raise XendConfigError("XendConfig: %s not a valid device type" %
dev_type)
@@ -927,10 +926,10 @@ class XendConfig(dict):
raise XendConfigError("XendConfig: device_add requires some "
"config.")
if cfg_sxp:
log.debug("XendConfig.device_add: %s" % str(cfg_sxp))
if cfg_xenapi:
log.debug("XendConfig.device_add: %s" % str(cfg_xenapi))
#if cfg_sxp:
# log.debug("XendConfig.device_add: %s" % str(cfg_sxp))
#if cfg_xenapi:
# log.debug("XendConfig.device_add: %s" % str(cfg_xenapi))
if cfg_sxp:
if sxp.child0(cfg_sxp) == 'device':
@@ -971,7 +970,12 @@ class XendConfig(dict):
target['vbd_refs'] = []
if dev_uuid not in target['vbd_refs']:
target['vbd_refs'].append(dev_uuid)
elif dev_type in ('console',):
if 'console_refs' not in target:
target['console_refs'] = []
if dev_uuid not in target['console_refs']:
target['console_refs'].append(dev_uuid)
return dev_uuid
if cfg_xenapi:
@@ -1031,7 +1035,25 @@ class XendConfig(dict):
# no valid device to add
return ''
def console_add(self, protocol, uri):
dev_uuid = uuid.createString()
dev_info = {
'uuid': dev_uuid,
'protocol': protocol,
'uri': uri
}
if 'devices' not in self:
self['devices'] = {}
self['devices'][dev_uuid] = ('console', dev_info)
self['console_refs'].append(dev_uuid)
return dev_info
def console_get_all(self, protocol):
consoles = [dinfo for dtype, dinfo in self['devices'].values()
if dtype == 'console']
return [c for c in consoles if c.get('protocol') == protocol]
def device_update(self, dev_uuid, cfg_sxp):
"""Update an existing device with the new configuration.
@@ -1211,7 +1233,7 @@ class XendConfig(dict):
self[apikey] = val
#
# debugging
#
+3 -5
View File
@@ -21,6 +21,8 @@
from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, usbif, vfbif
from xen.xend.server.BlktapController import BlktapController
from xen.xend.server.ConsoleController import ConsoleController
class XendDevices:
""" An ugly halfway point between the module local device name
@@ -43,6 +45,7 @@ class XendDevices:
'tap': BlktapController,
'vfb': vfbif.VfbifController,
'vkbd': vfbif.VkbdifController,
'console': ConsoleController,
}
#@classmethod
@@ -50,11 +53,6 @@ class XendDevices:
return cls.controllers.keys()
valid_devices = classmethod(valid_devices)
#@classmethod
def pseudo_devices(cls):
return ['console']
pseudo_devices = classmethod(pseudo_devices)
#@classmethod
def make_controller(cls, name, domain):
"""Factory function to make device controllers per domain.
+30 -6
View File
@@ -682,6 +682,29 @@ class XendDomainInfo:
for device in devices:
self.info.device_add(device[0], cfg_sxp = device)
self._update_consoles()
def _update_consoles(self):
if self.domid == None or self.domid == 0:
return
# Update VT100 port if it exists
self.console_port = self.readDom('console/port')
if self.console_port is not None:
serial_consoles = self.info.console_get_all('vt100')
if not serial_consoles:
cfg = self.info.console_add('vt100', self.console_port)
self._createDevice('console', cfg)
# Update VNC port if it exists
vnc_port = self.readDom('console/vnc-port')
if vnc_port is not None:
vnc_consoles = self.info.console_get_all('rfb')
if not vnc_consoles:
cfg = self.info.console_add('rfb', 'localhost:%s' %
str(vnc_port))
self._createDevice('console', cfg)
#
# Function to update xenstore /vm/*
#
@@ -1892,7 +1915,8 @@ class XendDomainInfo:
# TODO: we should eventually get rid of old_dom_states
self.info.update_config(info)
self._update_consoles()
if refresh:
self.refreshShutdown(info)
@@ -1904,11 +1928,11 @@ class XendDomainInfo:
ignore_devices = ignore_store,
legacy_only = legacy_only)
if not ignore_store and self.dompath:
vnc_port = self.readDom('console/vnc-port')
if vnc_port is not None:
result.append(['device',
['console', ['vnc-port', str(vnc_port)]]])
#if not ignore_store and self.dompath:
# vnc_port = self.readDom('console/vnc-port')
# if vnc_port is not None:
# result.append(['device',
# ['console', ['vnc-port', str(vnc_port)]]])
return result
@@ -75,7 +75,7 @@ class DevController:
def __init__(self, vm):
self.vm = vm
self.hotplug = True
def createDevice(self, config):
"""Trigger the creation of a device with the given configuration.
@@ -151,6 +151,9 @@ class DevController:
def waitForDevice(self, devid):
log.debug("Waiting for %s.", devid)
if not self.hotplug:
return
status = self.waitForBackend(devid)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.