mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Fix xm scsi-attach/detach/list for inactive managed domains
Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
This commit is contained in:
1 parent
44ffb080b3
commit
416b905545
9 files changed
+125
-69
No files matched your search
@@ -23,7 +23,7 @@ from xen.xend import sxp
|
||||
from xen.xend.XendClient import server
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend.xenstore.xstransact import xstransact
|
||||
from xen.xend.server import DevController
|
||||
from xen.xend.server import DevConstants
|
||||
|
||||
import xen.xend.XendProtocol
|
||||
|
||||
@@ -169,7 +169,7 @@ def diagnose_hotplugging():
|
||||
|
||||
|
||||
def stateString(state):
|
||||
return state and DevController.xenbusState[int(state)] or '<None>'
|
||||
return state and DevConstants.xenbusState[int(state)] or '<None>'
|
||||
|
||||
|
||||
def main(argv = None):
|
||||
|
||||
@@ -1602,21 +1602,21 @@ class XendConfig(dict):
|
||||
# [vscsi,
|
||||
# [dev,
|
||||
# [devid, 0], [p-devname, sdb], [p-dev, 1:0:0:1],
|
||||
# [v-dev, 0:0:0:0], [state, Initialising]
|
||||
# [v-dev, 0:0:0:0], [state, 1]
|
||||
# ],
|
||||
# [dev,
|
||||
# [devid, 0], [p-devname, sdc], [p-dev, 1:0:0:2],
|
||||
# [v-dev, 0:0:0:1], [satet, Initialising]
|
||||
# [v-dev, 0:0:0:1], [satet, 1]
|
||||
# ]
|
||||
# ],
|
||||
# [vscsi,
|
||||
# [dev,
|
||||
# [devid, 1], [p-devname, sdg], [p-dev, 2:0:0:0],
|
||||
# [v-dev, 1:0:0:0], [state, Initialising]
|
||||
# [v-dev, 1:0:0:0], [state, 1]
|
||||
# ],
|
||||
# [dev,
|
||||
# [devid, 1], [p-devname, sdh], [p-dev, 2:0:0:1],
|
||||
# [v-dev, 1:0:0:1], [satet, Initialising]
|
||||
# [v-dev, 1:0:0:1], [satet, 1]
|
||||
# ]
|
||||
# ]
|
||||
# ]
|
||||
@@ -1632,18 +1632,19 @@ class XendConfig(dict):
|
||||
# [vscsi,
|
||||
# [dev,
|
||||
# [devid, 0], [p-devname, sdd], [p-dev, 1:0:0:3],
|
||||
# [v-dev, 0:0:0:2], [state, Initialising]
|
||||
# [v-dev, 0:0:0:2], [state, 1]
|
||||
# ]
|
||||
# ]
|
||||
# ]
|
||||
#
|
||||
# state 'Initialising' indicates that the device is being attached,
|
||||
# while state 'Closing' indicates that the device is being detached.
|
||||
# state xenbusState['Initialising'] indicates that the device is
|
||||
# being attached, while state xenbusState['Closing'] indicates
|
||||
# that the device is being detached.
|
||||
#
|
||||
# The Dict looks like this:
|
||||
#
|
||||
# { devs: [ {devid: 0, p-devname: sdd, p-dev: 1:0:0:3,
|
||||
# v-dev: 0:0:0:2, state: Initialising} ] }
|
||||
# v-dev: 0:0:0:2, state: 1} ] }
|
||||
|
||||
dev_config = {}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain, SetTarget,
|
||||
from xen.xend.xenstore.xswatch import xswatch
|
||||
from xen.xend.XendConstants import *
|
||||
from xen.xend.XendAPIConstants import *
|
||||
from xen.xend.server.DevConstants import xenbusState
|
||||
|
||||
from xen.xend.XendVMMetrics import XendVMMetrics
|
||||
|
||||
@@ -797,7 +798,7 @@ class XendDomainInfo:
|
||||
existing_dev_info = self._getDeviceInfo_vscsi(req_devid, dev['v-dev'])
|
||||
state = dev['state']
|
||||
|
||||
if state == 'Initialising':
|
||||
if state == xenbusState['Initialising']:
|
||||
# new create
|
||||
# If request devid does not exist, create and exit.
|
||||
if existing_dev_info is None:
|
||||
@@ -806,25 +807,48 @@ class XendDomainInfo:
|
||||
elif existing_dev_info == "exists":
|
||||
raise XendError("The virtual device %s is already defined" % dev['v-dev'])
|
||||
|
||||
elif state == 'Closing':
|
||||
elif state == xenbusState['Closing']:
|
||||
if existing_dev_info is None:
|
||||
raise XendError("Cannot detach vscsi device does not exist")
|
||||
|
||||
# use DevController.reconfigureDevice to change device config
|
||||
dev_control = self.getDeviceController(dev_class)
|
||||
dev_uuid = dev_control.reconfigureDevice(req_devid, dev_config)
|
||||
dev_control.waitForDevice_reconfigure(req_devid)
|
||||
num_devs = dev_control.cleanupDevice(req_devid)
|
||||
if self.domid is not None:
|
||||
# use DevController.reconfigureDevice to change device config
|
||||
dev_control = self.getDeviceController(dev_class)
|
||||
dev_uuid = dev_control.reconfigureDevice(req_devid, dev_config)
|
||||
dev_control.waitForDevice_reconfigure(req_devid)
|
||||
num_devs = dev_control.cleanupDevice(req_devid)
|
||||
|
||||
# update XendConfig with new device info
|
||||
if dev_uuid:
|
||||
new_dev_sxp = dev_control.configuration(req_devid)
|
||||
# update XendConfig with new device info
|
||||
if dev_uuid:
|
||||
new_dev_sxp = dev_control.configuration(req_devid)
|
||||
self.info.device_update(dev_uuid, new_dev_sxp)
|
||||
|
||||
# If there is no device left, destroy vscsi and remove config.
|
||||
if num_devs == 0:
|
||||
self.destroyDevice('vscsi', req_devid)
|
||||
del self.info['devices'][dev_uuid]
|
||||
|
||||
else:
|
||||
cur_dev_sxp = self._getDeviceInfo_vscsi(req_devid, None)
|
||||
new_dev_sxp = ['vscsi']
|
||||
for cur_dev in sxp.children(cur_dev_sxp, 'dev'):
|
||||
if state == xenbusState['Closing']:
|
||||
cur_dev_vdev = sxp.child_value(cur_dev, 'v-dev')
|
||||
if cur_dev_vdev == dev['v-dev']:
|
||||
continue
|
||||
new_dev_sxp.append(cur_dev)
|
||||
|
||||
if state == xenbusState['Initialising']:
|
||||
new_dev_sxp.append(sxp.child0(dev_sxp, 'dev'))
|
||||
|
||||
dev_uuid = sxp.child_value(cur_dev_sxp, 'uuid')
|
||||
self.info.device_update(dev_uuid, new_dev_sxp)
|
||||
|
||||
# If there is no device left, destroy vscsi and remove config.
|
||||
if num_devs == 0:
|
||||
self.destroyDevice('vscsi', req_devid)
|
||||
del self.info['devices'][dev_uuid]
|
||||
# If there is only 'vscsi' in new_dev_sxp, remove the config.
|
||||
if len(sxp.children(new_dev_sxp, 'dev')) == 0:
|
||||
del self.info['devices'][dev_uuid]
|
||||
|
||||
xen.xend.XendDomain.instance().managed_config_save(self)
|
||||
|
||||
return True
|
||||
|
||||
@@ -986,7 +1010,17 @@ class XendDomainInfo:
|
||||
sxprs = []
|
||||
dev_num = 0
|
||||
for dev_type, dev_info in self.info.all_devices_sxpr():
|
||||
if dev_type == deviceClass:
|
||||
if dev_type != deviceClass:
|
||||
continue
|
||||
|
||||
if deviceClass == 'vscsi':
|
||||
vscsi_devs = ['devs', []]
|
||||
for vscsi_dev in sxp.children(dev_info, 'dev'):
|
||||
vscsi_dev.append(['frontstate', None])
|
||||
vscsi_devs[1].append(vscsi_dev)
|
||||
dev_num = int(sxp.child_value(vscsi_dev, 'devid'))
|
||||
sxprs.append([dev_num, [vscsi_devs]])
|
||||
else:
|
||||
sxprs.append([dev_num, dev_info])
|
||||
dev_num += 1
|
||||
return sxprs
|
||||
@@ -2380,11 +2414,10 @@ class XendDomainInfo:
|
||||
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']))
|
||||
xstransact.Write(paths, 'state', str(xenbusState['Closing']))
|
||||
# force
|
||||
xstransact.Remove(paths)
|
||||
|
||||
@@ -3439,7 +3472,7 @@ class XendDomainInfo:
|
||||
['p-devname', pscsi.get_dev_name()],
|
||||
['p-dev', pscsi.get_physical_HCTL()],
|
||||
['v-dev', xenapi_dscsi.get('virtual_HCTL')],
|
||||
['state', 'Initialising'],
|
||||
['state', xenbusState['Initialising']],
|
||||
['uuid', dscsi_uuid]
|
||||
]
|
||||
]
|
||||
@@ -3558,7 +3591,7 @@ class XendDomainInfo:
|
||||
if target_dev is None:
|
||||
raise XendError('Failed to destroy device')
|
||||
|
||||
target_dev.append(['state', 'Closing'])
|
||||
target_dev.append(['state', xenbusState['Closing']])
|
||||
target_vscsi_sxp = ['vscsi', target_dev]
|
||||
|
||||
if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING:
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#============================================================================
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#============================================================================
|
||||
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (C) 2005 XenSource Ltd
|
||||
#============================================================================
|
||||
|
||||
DEVICE_CREATE_TIMEOUT = 100
|
||||
DEVICE_DESTROY_TIMEOUT = 100
|
||||
HOTPLUG_STATUS_NODE = "hotplug-status"
|
||||
HOTPLUG_ERROR_NODE = "hotplug-error"
|
||||
HOTPLUG_STATUS_ERROR = "error"
|
||||
HOTPLUG_STATUS_BUSY = "busy"
|
||||
|
||||
Connected = 1
|
||||
Error = 2
|
||||
Missing = 3
|
||||
Timeout = 4
|
||||
Busy = 5
|
||||
Disconnected = 6
|
||||
|
||||
xenbusState = {
|
||||
'Unknown' : 0,
|
||||
'Initialising' : 1,
|
||||
'InitWait' : 2,
|
||||
'Initialised' : 3,
|
||||
'Connected' : 4,
|
||||
'Closing' : 5,
|
||||
'Closed' : 6,
|
||||
'Reconfiguring' : 7,
|
||||
'Reconfigured' : 8,
|
||||
}
|
||||
xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys())))
|
||||
|
||||
@@ -23,42 +23,15 @@ from xen.xend import sxp, XendOptions
|
||||
from xen.xend.XendError import VmError
|
||||
from xen.xend.XendLogging import log
|
||||
import xen.xend.XendConfig
|
||||
from xen.xend.server.DevConstants import *
|
||||
|
||||
from xen.xend.xenstore.xstransact import xstransact, complete
|
||||
from xen.xend.xenstore.xswatch import xswatch
|
||||
|
||||
import os
|
||||
|
||||
DEVICE_CREATE_TIMEOUT = 100
|
||||
DEVICE_DESTROY_TIMEOUT = 100
|
||||
HOTPLUG_STATUS_NODE = "hotplug-status"
|
||||
HOTPLUG_ERROR_NODE = "hotplug-error"
|
||||
HOTPLUG_STATUS_ERROR = "error"
|
||||
HOTPLUG_STATUS_BUSY = "busy"
|
||||
|
||||
Connected = 1
|
||||
Error = 2
|
||||
Missing = 3
|
||||
Timeout = 4
|
||||
Busy = 5
|
||||
Disconnected = 6
|
||||
|
||||
xenbusState = {
|
||||
'Unknown' : 0,
|
||||
'Initialising' : 1,
|
||||
'InitWait' : 2,
|
||||
'Initialised' : 3,
|
||||
'Connected' : 4,
|
||||
'Closing' : 5,
|
||||
'Closed' : 6,
|
||||
'Reconfiguring': 7,
|
||||
'Reconfigured' : 8,
|
||||
}
|
||||
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys())))
|
||||
|
||||
|
||||
class DevController:
|
||||
"""Abstract base class for a device controller. Device controllers create
|
||||
|
||||
@@ -25,7 +25,8 @@ from xen.xend import arch
|
||||
from xen.xend.XendError import VmError
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
from xen.xend.server.DevController import DevController, xenbusState
|
||||
from xen.xend.server.DevController import DevController
|
||||
from xen.xend.server.DevConstants import xenbusState
|
||||
|
||||
import xen.lowlevel.xc
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ from xen.xend import sxp
|
||||
from xen.xend.XendError import VmError
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
from xen.xend.server.DevController import DevController, xenbusState
|
||||
from xen.xend.server.DevController import DevController
|
||||
from xen.xend.server.DevConstants import xenbusState
|
||||
from xen.xend.xenstore.xstransact import xstransact
|
||||
|
||||
class VSCSIController(DevController):
|
||||
@@ -92,8 +93,8 @@ class VSCSIController(DevController):
|
||||
back[devpath + '/p-devname'] = pdevname
|
||||
vdev = vscsi_config.get('v-dev', '')
|
||||
back[devpath + '/v-dev'] = vdev
|
||||
state = vscsi_config.get('state', '')
|
||||
back[devpath + '/state'] = str(xenbusState[state])
|
||||
state = vscsi_config.get('state', xenbusState['Unknown'])
|
||||
back[devpath + '/state'] = str(state)
|
||||
devid = vscsi_config.get('devid', '')
|
||||
back[devpath + '/devid'] = str(devid)
|
||||
|
||||
@@ -168,17 +169,17 @@ class VSCSIController(DevController):
|
||||
(devid, back, front) = self.getDeviceDetails(config)
|
||||
devid = int(devid)
|
||||
vscsi_config = config['devs'][0]
|
||||
state = vscsi_config.get('state', '')
|
||||
state = vscsi_config.get('state', xenbusState['Unknown'])
|
||||
driver_state = self.readBackend(devid, 'state')
|
||||
if str(xenbusState['Connected']) != driver_state:
|
||||
raise VmError("Driver status is not connected")
|
||||
|
||||
uuid = self.readBackend(devid, 'uuid')
|
||||
if state == 'Initialising':
|
||||
if state == xenbusState['Initialising']:
|
||||
back['uuid'] = uuid
|
||||
self.writeBackend(devid, back)
|
||||
|
||||
elif state == 'Closing':
|
||||
elif state == xenbusState['Closing']:
|
||||
found = False
|
||||
devs = self.readBackendList(devid, "vscsi-devs")
|
||||
vscsipath = "vscsi-devs/"
|
||||
@@ -198,7 +199,7 @@ class VSCSIController(DevController):
|
||||
|
||||
else:
|
||||
raise XendError("Error configuring device invalid "
|
||||
"state '%s'" % state)
|
||||
"state '%s'" % xenbusState[state])
|
||||
|
||||
self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring']))
|
||||
return self.readBackend(devid, 'uuid')
|
||||
|
||||
@@ -32,6 +32,7 @@ from xen.xend import PrettyPrint as SXPPrettyPrint
|
||||
from xen.xend import osdep
|
||||
import xen.xend.XendClient
|
||||
from xen.xend.XendBootloader import bootloader
|
||||
from xen.xend.server.DevConstants import xenbusState
|
||||
from xen.util import blkif
|
||||
from xen.util import vscsi_util
|
||||
import xen.util.xsm.xsm as security
|
||||
@@ -707,7 +708,7 @@ def configure_vscsis(config_devs, vals):
|
||||
vscsi_util.vscsi_get_hctl_and_devname_by(p_dev, scsi_devices)
|
||||
|
||||
if p_hctl == None:
|
||||
raise ValueError("Cannot find device \"%s\"" % p_dev)
|
||||
raise ValueError('Cannot find device "%s"' % p_dev)
|
||||
|
||||
for config in config_scsi:
|
||||
dev = vscsi_convert_sxp_to_dict(config)
|
||||
@@ -717,7 +718,7 @@ def configure_vscsis(config_devs, vals):
|
||||
v_hctl = v_dev.split(':')
|
||||
devid = int(v_hctl[0])
|
||||
config_scsi.append(['dev', \
|
||||
['state', 'Initialising'], \
|
||||
['state', xenbusState['Initialising']], \
|
||||
['devid', devid], \
|
||||
['p-dev', p_hctl], \
|
||||
['p-devname', devname], \
|
||||
|
||||
@@ -47,6 +47,7 @@ from xen.xend import PrettyPrint
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendClient
|
||||
from xen.xend.XendConstants import *
|
||||
from xen.xend.server.DevConstants import xenbusState
|
||||
|
||||
from xen.xm.opts import OptionError, Opts, wrap, set_true
|
||||
from xen.xm import console
|
||||
@@ -2515,7 +2516,7 @@ def xm_scsi_attach(args):
|
||||
dom = args[0]
|
||||
p_scsi = args[1]
|
||||
v_hctl = args[2]
|
||||
scsi = parse_scsi_configuration(p_scsi, v_hctl, 'Initialising')
|
||||
scsi = parse_scsi_configuration(p_scsi, v_hctl, xenbusState['Initialising'])
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
|
||||
@@ -2635,7 +2636,7 @@ def xm_scsi_detach(args):
|
||||
arg_check(args, 'scsi-detach', 2)
|
||||
dom = args[0]
|
||||
v_hctl = args[1]
|
||||
scsi = parse_scsi_configuration(None, v_hctl, 'Closing')
|
||||
scsi = parse_scsi_configuration(None, v_hctl, xenbusState['Closing'])
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
|
||||
|
||||