183 return val[0].value if val else None |
183 return val[0].value if val else None |
184 |
184 |
185 |
185 |
186 def lookup_resource_property_value(zone, resource, prop, value): |
186 def lookup_resource_property_value(zone, resource, prop, value): |
187 """Lookup specified property with value from specified Solaris Zone |
187 """Lookup specified property with value from specified Solaris Zone |
188 resource. Returns property if matching value is found, else None |
188 resource. Returns resource object if matching value is found, else None |
189 """ |
189 """ |
190 try: |
190 try: |
191 resources = zone.getResources(zonemgr.Resource(resource)) |
191 resources = zone.getResources(zonemgr.Resource(resource)) |
192 for resource in resources: |
192 for resource in resources: |
193 for propertee in resource.properties: |
193 for propertee in resource.properties: |
194 if propertee.name == prop and propertee.value == value: |
194 if propertee.name == prop and propertee.value == value: |
195 return propertee |
195 return resource |
196 else: |
196 else: |
197 return None |
197 return None |
198 except rad.client.ObjectError: |
198 except rad.client.ObjectError: |
199 return None |
199 return None |
200 except Exception: |
200 except Exception: |
2396 % brand) |
2396 % brand) |
2397 raise NotImplementedError(reason) |
2397 raise NotImplementedError(reason) |
2398 |
2398 |
2399 suri = self._suri_from_volume_info(connection_info) |
2399 suri = self._suri_from_volume_info(connection_info) |
2400 |
2400 |
|
2401 resource_scope = [zonemgr.Property("storage", suri)] |
|
2402 if connection_info.get('serial') is not None: |
|
2403 volume = self._volume_api.get(context, connection_info['serial']) |
|
2404 if volume['bootable']: |
|
2405 resource_scope.append(zonemgr.Property("bootpri", "1")) |
|
2406 |
2401 with ZoneConfig(zone) as zc: |
2407 with ZoneConfig(zone) as zc: |
2402 zc.addresource("device", [zonemgr.Property("storage", suri)]) |
2408 zc.addresource("device", resource_scope) |
2403 |
2409 |
2404 # apply the configuration to the running zone |
2410 # apply the configuration to the running zone |
2405 if zone.state == ZONE_STATE_RUNNING: |
2411 if zone.state == ZONE_STATE_RUNNING: |
2406 try: |
2412 try: |
2407 zone.apply() |
2413 zone.apply() |
2408 except Exception as ex: |
2414 except Exception as ex: |
2409 reason = zonemgr_strerror(ex) |
2415 reason = zonemgr_strerror(ex) |
2410 LOG.error(_("Unable to attach '%s' to instance '%s' via " |
2416 LOG.error(_("Unable to attach '%s' to instance '%s' via " |
2411 "zonemgr(3RAD): %s") % (suri, name, reason)) |
2417 "zonemgr(3RAD): %s") % (suri, name, reason)) |
2412 with ZoneConfig(zone) as zc: |
2418 with ZoneConfig(zone) as zc: |
2413 zc.removeresources("device", [zonemgr.Property("storage", |
2419 zc.removeresources("device", resource_scope) |
2414 suri)]) |
|
2415 raise |
2420 raise |
2416 |
2421 |
2417 def detach_volume(self, connection_info, instance, mountpoint, |
2422 def detach_volume(self, connection_info, instance, mountpoint, |
2418 encryption=None): |
2423 encryption=None): |
2419 """Detach the disk attached to the instance.""" |
2424 """Detach the disk attached to the instance.""" |
2431 raise NotImplementedError(reason) |
2436 raise NotImplementedError(reason) |
2432 |
2437 |
2433 suri = self._suri_from_volume_info(connection_info) |
2438 suri = self._suri_from_volume_info(connection_info) |
2434 |
2439 |
2435 # Check if the specific property value exists before attempting removal |
2440 # Check if the specific property value exists before attempting removal |
2436 prop = lookup_resource_property_value(zone, "device", "storage", suri) |
2441 resource = lookup_resource_property_value(zone, "device", "storage", |
2437 if not prop: |
2442 suri) |
|
2443 if not resource: |
2438 LOG.warning(_("Storage resource '%s' is not attached to instance " |
2444 LOG.warning(_("Storage resource '%s' is not attached to instance " |
2439 "'%s'") % (suri, name)) |
2445 "'%s'") % (suri, name)) |
2440 return |
2446 return |
2441 |
2447 |
2442 with ZoneConfig(zone) as zc: |
2448 with ZoneConfig(zone) as zc: |
2443 zc.removeresources("device", [zonemgr.Property("storage", suri)]) |
2449 zc.removeresources("device", [zonemgr.Property("storage", suri)]) |
2444 |
2450 |
2445 # apply the configuration to the running zone |
2451 # apply the configuration to the running zone |
2446 if zone.state == ZONE_STATE_RUNNING: |
2452 if zone.state == ZONE_STATE_RUNNING: |
2447 zone.apply() |
2453 try: |
|
2454 zone.apply() |
|
2455 except: |
|
2456 LOG.error(_("Unable to apply the detach of resource '%s' to " |
|
2457 "running instance '%s' because the resource is " |
|
2458 "most likely in use.") % (suri, name)) |
|
2459 |
|
2460 # re-add the entry to the zone configuration so that the |
|
2461 # configuration will reflect what is in cinder before we raise |
|
2462 # the exception, therefor failing the detach and leaving the |
|
2463 # volume in-use. |
|
2464 needed_props = ["storage", "bootpri"] |
|
2465 props = filter(lambda prop: prop.name in needed_props, |
|
2466 resource.properties) |
|
2467 with ZoneConfig(zone) as zc: |
|
2468 zc.addresource("device", props) |
|
2469 |
|
2470 raise |
2448 |
2471 |
2449 def swap_volume(self, old_connection_info, new_connection_info, |
2472 def swap_volume(self, old_connection_info, new_connection_info, |
2450 instance, mountpoint, resize_to): |
2473 instance, mountpoint, resize_to): |
2451 """Replace the disk attached to the instance. |
2474 """Replace the disk attached to the instance. |
2452 |
2475 |