ia64/xen-unstable

view tools/python/xen/xend/server/blkif.py @ 17578:94c6501c4ffe

xend: Refactor security.on() call

I am refactoring the security.on() call to return the actual type of
the security module that is found to be enabled rather than just
returning True or False.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 06 10:05:52 2008 +0100 (2008-05-06)
parents 09d8b6eb3131
children 0a8fc1a62796
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (C) 2005, 2006 XenSource Inc.
17 #============================================================================
19 import re
20 import string
22 from xen.util import blkif
23 import xen.util.xsm.xsm as security
24 from xen.xend.XendError import VmError
25 from xen.xend.server.DevController import DevController
26 from xen.util import xsconstants
28 class BlkifController(DevController):
29 """Block device interface controller. Handles all block devices
30 for a domain.
31 """
33 def __init__(self, vm):
34 """Create a block device controller.
35 """
36 DevController.__init__(self, vm)
38 def getDeviceDetails(self, config):
39 """@see DevController.getDeviceDetails"""
40 uname = config.get('uname', '')
41 dev = config.get('dev', '')
43 if 'ioemu:' in dev:
44 (_, dev) = string.split(dev, ':', 1)
45 try:
46 (dev, dev_type) = string.split(dev, ':', 1)
47 except ValueError:
48 dev_type = "disk"
50 if uname is None:
51 if dev_type == 'cdrom':
52 (typ, params) = ("", "")
53 else:
54 raise VmError(
55 'Block device must have physical details specified')
56 else:
57 try:
58 (typ, params) = string.split(uname, ':', 1)
59 except ValueError:
60 (typ, params) = ("", "")
62 mode = config.get('mode', 'r')
63 if mode not in ('r', 'w', 'w!'):
64 raise VmError('Invalid mode')
66 back = {'dev' : dev,
67 'type' : typ,
68 'params' : params,
69 'mode' : mode,
70 }
72 uuid = config.get('uuid')
73 if uuid:
74 back['uuid'] = uuid
76 if security.on() == xsconstants.XS_POLICY_ACM:
77 self.do_access_control(config, uname)
79 devid = blkif.blkdev_name_to_number(dev)
80 if devid is None:
81 raise VmError('Unable to find number for device (%s)' % (dev))
83 front = { 'virtual-device' : "%i" % devid,
84 'device-type' : dev_type
85 }
87 return (devid, back, front)
89 def do_access_control(self, config, uname):
90 (label, ssidref, policy) = \
91 security.get_res_security_details(uname)
92 domain_label = self.vm.get_security_label()
93 if domain_label:
94 rc = security.res_security_check_xapi(label, ssidref, policy,
95 domain_label)
96 if rc == 0:
97 raise VmError("VM's access to block device '%s' denied" %
98 uname)
99 else:
100 from xen.util.acmpolicy import ACM_LABEL_UNLABELED
101 if label != ACM_LABEL_UNLABELED:
102 raise VmError("VM must have a security label to access "
103 "block device '%s'" % uname)
105 def reconfigureDevice(self, _, config):
106 """@see DevController.reconfigureDevice"""
107 (devid, new_back, new_front) = self.getDeviceDetails(config)
109 (dev, mode) = self.readBackend(devid, 'dev', 'mode')
110 dev_type = self.readFrontend(devid, 'device-type')
112 if (dev_type == 'cdrom' and new_front['device-type'] == 'cdrom' and
113 dev == new_back['dev'] and mode == 'r'):
114 # dummy device
115 self.writeBackend(devid,
116 'type', new_back['type'],
117 'params', '')
118 # new backend-device
119 self.writeBackend(devid,
120 'type', new_back['type'],
121 'params', new_back['params'])
122 return new_back.get('uuid')
123 else:
124 raise VmError('Refusing to reconfigure device %s:%d to %s' %
125 (self.deviceClass, devid, config))
128 def getDeviceConfiguration(self, devid, transaction = None):
129 """Returns the configuration of a device.
131 @note: Similar to L{configuration} except it returns a dict.
132 @return: dict
133 """
134 config = DevController.getDeviceConfiguration(self, devid, transaction)
135 if transaction is None:
136 devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
137 'uuid')
138 else:
139 devinfo = self.readBackendTxn(transaction, devid,
140 'dev', 'type', 'params', 'mode', 'uuid')
141 dev, typ, params, mode, uuid = devinfo
143 if dev:
144 if transaction is None:
145 dev_type = self.readFrontend(devid, 'device-type')
146 else:
147 dev_type = self.readFrontendTxn(transaction, devid, 'device-type')
148 if dev_type:
149 dev += ':' + dev_type
150 config['dev'] = dev
151 if typ and params:
152 config['uname'] = typ +':' + params
153 else:
154 config['uname'] = None
155 if mode:
156 config['mode'] = mode
157 if uuid:
158 config['uuid'] = uuid
160 return config
162 def destroyDevice(self, devid, force):
163 """@see DevController.destroyDevice"""
165 # vbd device IDs can be either string or integer. Further, the
166 # following string values are possible:
167 # - devicetype/deviceid (vbd/51728)
168 # - devicetype/devicename (/dev/xvdb)
169 # - devicename (xvdb)
170 # Let our superclass handle integer or devicetype/deviceid forms.
171 # If we are given a device name form, then look up the device ID
172 # from it, and destroy that ID instead.
173 try:
174 DevController.destroyDevice(self, devid, force)
175 except ValueError:
176 dev = self.convertToDeviceNumber(devid)
178 for i in self.deviceIDs():
179 if i == dev:
180 DevController.destroyDevice(self, i, force)
181 return
182 raise VmError("Device %s not connected" % devid)
184 def convertToDeviceNumber(self, devid):
185 try:
186 dev = int(devid)
187 except ValueError:
188 if type(devid) is not str:
189 raise VmError("devid %s is wrong type" % str(devid))
190 try:
191 dev = devid.split('/')[-1]
192 dev = int(dev)
193 except ValueError:
194 dev = blkif.blkdev_name_to_number(dev)
195 return dev