[blktap] Allow HVM booting from blktap device(s)

Signed-off-by: wim colgate <wim@xensource.com>
This commit is contained in:
wim@xen-wim.site committed 2007-02-07 16:53:01 -08:00
1 parent 2b30444fe2
commit 51efffe712
5 files changed
+230 -2

No files matched your search

+41
View File
@@ -1148,6 +1148,47 @@ class XendConfig(dict):
# no valid device to add
return ''
def phantom_device_add(self, dev_type, cfg_xenapi = None,
target = None):
"""Add a phantom tap device configuration in XenAPI struct format.
"""
if target == None:
target = self
if dev_type not in XendDevices.valid_devices() and \
dev_type not in XendDevices.pseudo_devices():
raise XendConfigError("XendConfig: %s not a valid device type" %
dev_type)
if cfg_xenapi == None:
raise XendConfigError("XendConfig: device_add requires some "
"config.")
if cfg_xenapi:
log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi))
if cfg_xenapi:
dev_info = {}
if dev_type in ('vbd', 'tap'):
if dev_type == 'vbd':
dev_info['uname'] = cfg_xenapi.get('image', '')
dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device')
elif dev_type == 'tap':
if cfg_xenapi.get('image').find('tap:') == -1:
dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image')
dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device')
dev_info['uname'] = cfg_xenapi.get('image')
dev_info['mode'] = cfg_xenapi.get('mode')
dev_info['backend'] = '0'
dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
dev_info['uuid'] = dev_uuid
self['devices'][dev_uuid] = (dev_type, dev_info)
self['vbd_refs'].append(dev_uuid)
return dev_uuid
return ''
def console_add(self, protocol, location, other_config = {}):
dev_uuid = uuid.createString()
if protocol == 'vt100':
+55 -1
View File
@@ -1565,19 +1565,54 @@ class XendDomainInfo:
# VM Destroy
#
def _prepare_phantom_paths(self):
# get associated devices to destroy
# build list of phantom devices to be removed after normal devices
plist = []
from xen.xend.xenstore.xstransact import xstransact
t = xstransact("%s/device/vbd" % GetDomainPath(self.domid))
for dev in t.list():
backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \
% (self.dompath, dev))
if backend_phantom_vbd is not None:
frontend_phantom_vbd = xstransact.Read("%s/frontend" \
% backend_phantom_vbd)
plist.append(backend_phantom_vbd)
plist.append(frontend_phantom_vbd)
return plist
def _cleanup_phantom_devs(self, plist):
# remove phantom devices
if not plist == []:
time.sleep(2)
for paths in plist:
if paths.find('backend') != -1:
from xen.xend.server import DevController
# Modify online status /before/ updating state (latter is watched by
# drivers, so this ordering avoids a race).
xstransact.Write(paths, 'online', "0")
xstransact.Write(paths, 'state', str(DevController.xenbusState['Closing']))
# force
xstransact.Remove(paths)
def destroy(self):
"""Cleanup VM and destroy domain. Nothrow guarantee."""
log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid))
paths = self._prepare_phantom_paths()
self._cleanupVm()
if self.dompath is not None:
self.destroyDomain()
self._cleanup_phantom_devs(paths)
def destroyDomain(self):
log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid))
paths = self._prepare_phantom_paths()
try:
if self.domid is not None:
xc.domain_destroy(self.domid)
@@ -1591,7 +1626,7 @@ class XendDomainInfo:
XendDomain.instance().remove_domain(self)
self.cleanupDomain()
self._cleanup_phantom_devs(paths)
def resumeDomain(self):
log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid))
@@ -2211,6 +2246,25 @@ class XendDomainInfo:
return dev_uuid
def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path):
"""Create a VBD using a VDI from XendStorageRepository.
@param xenapi_vbd: vbd struct from the Xen API
@param vdi_image_path: VDI UUID
@rtype: string
@return: uuid of the device
"""
xenapi_vbd['image'] = vdi_image_path
dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd)
if not dev_uuid:
raise XendError('Failed to create device')
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
_, config = self.info['devices'][dev_uuid]
config['devid'] = self.getDeviceController('tap').createDevice(config)
return config['devid']
def create_vif(self, xenapi_vif):
"""Create VIF device from the passed struct in Xen API format.
@@ -2,7 +2,10 @@
from xen.xend.server.blkif import BlkifController
from xen.xend.XendLogging import log
phantomDev = 0;
phantomId = 0;
class BlktapController(BlkifController):
def __init__(self, vm):
@@ -12,3 +15,62 @@ class BlktapController(BlkifController):
"""@see DevController#frontendRoot"""
return "%s/device/vbd" % self.vm.getDomainPath()
def getDeviceDetails(self, config):
(devid, back, front) = BlkifController.getDeviceDetails(self, config)
phantomDevid = 0
wrapped = False
try:
imagetype = self.vm.info['image']['type']
except:
imagetype = ""
if imagetype == 'hvm':
tdevname = back['dev']
index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \
'j', 'l', 'm', 'n', 'o', 'p']
while True:
global phantomDev
global phantomId
import os, stat
phantomId = phantomId + 1
if phantomId == 16:
if index[phantomDev] == index[-1]:
if wrapped:
raise VmError(" No loopback block \
devices are available. ")
wrapped = True
phantomDev = 0
else:
phantomDev = phantomDev + 1
phantomId = 1
devname = 'xvd%s%d' % (index[phantomDev], phantomId)
try:
info = os.stat('/dev/%s' % devname)
except:
break
vbd = { 'mode': 'w', 'device': devname }
fn = 'tap:%s' % back['params']
# recurse ... by creating the vbd, then fallthrough
# and finish creating the original device
from xen.xend import XendDomain
dom0 = XendDomain.instance().privilegedDomain()
phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn)
# we need to wait for this device at a higher level
# the vbd that gets created will have a link to us
# and will let them do it there
# add a hook to point to the phantom device,
# root path is always the same (dom0 tap)
if phantomDevid != 0:
front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \
% str(phantomDevid)
return (devid, back, front)
@@ -473,6 +473,19 @@ class DevController:
def waitForBackend(self, devid):
frontpath = self.frontendPath(devid)
# lookup a phantom
phantomPath = xstransact.Read(frontpath, 'phantom_vbd')
if phantomPath is not None:
log.debug("Waiting for %s's phantom %s.", devid, phantomPath)
statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE
ev = Event()
result = { 'status': Timeout }
xswatch(statusPath, hotplugStatusCallback, ev, result)
ev.wait(DEVICE_CREATE_TIMEOUT)
err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE)
if result['status'] != 'Connected':
return (result['status'], err)
backpath = xstransact.Read(frontpath, "backend")
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.