# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import quota QUOTAS = quota.QUOTAS XMLNS = "http://docs.openstack.org/compute/ext/used_limits/api/v1.1" ALIAS = "os-used-limits" authorize = extensions.soft_extension_authorizer('compute', 'used_limits') authorize_for_admin = extensions.extension_authorizer('compute', 'used_limits_for_admin') class UsedLimitsController(wsgi.Controller): def __init__(self, ext_mgr): self.ext_mgr = ext_mgr @staticmethod def _reserved(req): try: return int(req.GET['reserved']) except (ValueError, KeyError): return False
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Flavor extra data extension OpenStack API version 1.1 lists "name", "ram", "disk", "vcpus" as flavor attributes. This extension adds to that list: - OS-FLV-EXT-DATA:ephemeral """ from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'flavorextradata') class FlavorextradataController(wsgi.Controller): def _extend_flavors(self, req, flavors): for flavor in flavors: db_flavor = req.get_db_flavor(flavor['id']) key = "%s:ephemeral" % Flavorextradata.alias flavor[key] = db_flavor['ephemeral_gb'] def _show(self, req, resp_obj): if not authorize(req.environ['patron.context']): return if 'flavor' in resp_obj.obj: self._extend_flavors(req, [resp_obj.obj['flavor']])
# License for the specific language governing permissions and limitations # under the License. """Extension for hiding server addresses in certain states.""" from oslo_config import cfg from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron.compute import vm_states CONF = cfg.CONF CONF.import_opt("osapi_hide_server_address_states", "patron.api.openstack.compute.plugins.v3.hide_server_addresses") authorize = extensions.soft_extension_authorizer("compute", "hide_server_addresses") class Controller(wsgi.Controller): def __init__(self, *args, **kwargs): super(Controller, self).__init__(*args, **kwargs) hidden_states = CONF.osapi_hide_server_address_states # NOTE(jkoelker) _ is not considered uppercase ;) valid_vm_states = [getattr(vm_states, state) for state in dir(vm_states) if state.isupper()] self.hide_address_states = [state.lower() for state in hidden_states if state in valid_vm_states] def _perhaps_hide_addresses(self, instance, resp_server): if instance.get("vm_state") in self.hide_address_states: resp_server["addresses"] = {}
# Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Extended Ips API extension.""" import itertools from patron.api.openstack import common from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import compute authorize = extensions.soft_extension_authorizer('compute', 'extended_ips') class ExtendedIpsController(wsgi.Controller): def __init__(self, *args, **kwargs): super(ExtendedIpsController, self).__init__(*args, **kwargs) self.compute_api = compute.API() def _extend_server(self, context, server, instance): key = "%s:type" % Extended_ips.alias networks = common.get_networks_for_instance(context, instance) for label, network in networks.items(): # NOTE(vish): ips are hidden in some states via the # hide_server_addresses extension. if label in server['addresses']: all_ips = itertools.chain(network["ips"],
# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Flavor Swap API extension.""" from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'flavor_swap') class FlavorSwapController(wsgi.Controller): def _extend_flavors(self, req, flavors): for flavor in flavors: db_flavor = req.get_db_flavor(flavor['id']) key = 'swap' flavor[key] = db_flavor['swap'] or "" def _show(self, req, resp_obj): if not authorize(req.environ['patron.context']): return if 'flavor' in resp_obj.obj: self._extend_flavors(req, [resp_obj.obj['flavor']])
# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Extended Ips API extension.""" import itertools from patron.api.openstack import common from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'extended_ips_mac') class ExtendedIpsMacController(wsgi.Controller): def __init__(self, *args, **kwargs): super(ExtendedIpsMacController, self).__init__(*args, **kwargs) def _extend_server(self, context, server, instance): key = "%s:mac_addr" % Extended_ips_mac.alias networks = common.get_networks_for_instance(context, instance) for label, network in networks.items(): # NOTE(vish): ips are hidden in some states via the # hide_server_addresses extension. if label in server['addresses']: all_ips = itertools.chain(network["ips"], network["floating_ips"])
import webob from webob import exc from patron.api.openstack import common from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import compute from patron import exception from patron.i18n import _ from patron.network.security_group import openstack_driver from patron.virt import netutils LOG = logging.getLogger(__name__) authorize = extensions.extension_authorizer('compute', 'security_groups') softauth = extensions.soft_extension_authorizer('compute', 'security_groups') def _authorize_context(req): context = req.environ['patron.context'] authorize(context) return context @contextlib.contextmanager def translate_exceptions(): """Translate patron exceptions to http exceptions.""" try: yield except exception.Invalid as exp: msg = exp.format_message()
"""Keypair management extension.""" import webob import webob.exc from patron.api.openstack.compute import servers from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron.compute import api as compute_api from patron import exception from patron.i18n import _ authorize = extensions.extension_authorizer('compute', 'keypairs') soft_authorize = extensions.soft_extension_authorizer('compute', 'keypairs') class KeypairController(object): """Keypair API controller for the OpenStack API.""" def __init__(self): self.api = compute_api.KeypairAPI() def _filter_keypair(self, keypair, **attrs): clean = { 'name': keypair.name, 'public_key': keypair.public_key, 'fingerprint': keypair.fingerprint, } for attr in attrs:
# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from oslo_log import log as logging from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import compute LOG = logging.getLogger(__name__) authorize = extensions.soft_extension_authorizer('compute', 'server_usage') class ServerUsageController(wsgi.Controller): def __init__(self, *args, **kwargs): super(ServerUsageController, self).__init__(*args, **kwargs) self.compute_api = compute.API() def _extend_server(self, server, instance): for k in ['launched_at', 'terminated_at']: key = "%s:%s" % (Server_usage.alias, k) # NOTE(danms): Historically, this timestamp has been generated # merely by grabbing str(datetime) of a TZ-naive object. The # only way we can keep that with instance objects is to strip # the tzinfo from the stamp and str() it. server[key] = (instance[k].replace(
# not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Flavor Disabled API extension.""" from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'flavor_disabled') class FlavorDisabledController(wsgi.Controller): def _extend_flavors(self, req, flavors): for flavor in flavors: db_flavor = req.get_db_flavor(flavor['id']) key = "%s:disabled" % Flavor_disabled.alias flavor[key] = db_flavor['disabled'] def _show(self, req, resp_obj): if not authorize(req.environ['patron.context']): return if 'flavor' in resp_obj.obj: self._extend_flavors(req, [resp_obj.obj['flavor']])
# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'image_size') class ImageSizeController(wsgi.Controller): def _extend_image(self, image, image_cache): key = "%s:size" % Image_size.alias image[key] = image_cache['size'] @wsgi.extends def show(self, req, resp_obj, id): context = req.environ["patron.context"] if authorize(context): image_resp = resp_obj.obj['image'] # image guaranteed to be in the cache due to the core API adding # it in its 'show' method image_cached = req.get_db_item('images', image_resp['id'])
# a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import network authorize = extensions.soft_extension_authorizer('compute', 'extended_vif_net') class ExtendedServerVIFNetController(wsgi.Controller): def __init__(self): super(ExtendedServerVIFNetController, self).__init__() self.network_api = network.API() @wsgi.extends def index(self, req, resp_obj, server_id): key = "%s:net_id" % Extended_virtual_interfaces_net.alias context = req.environ['patron.context'] if authorize(context): for vif in resp_obj.obj['virtual_interfaces']: vif1 = self.network_api.get_vif_by_mac_address(context, vif['mac_address'])
import six import webob from webob import exc from patron.api.openstack import common from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import compute from patron import exception from patron.i18n import _ from patron.network.security_group import openstack_driver from patron.virt import netutils LOG = logging.getLogger(__name__) authorize = extensions.extension_authorizer('compute', 'security_groups') softauth = extensions.soft_extension_authorizer('compute', 'security_groups') def _authorize_context(req): context = req.environ['patron.context'] authorize(context) return context @contextlib.contextmanager def translate_exceptions(): """Translate patron exceptions to http exceptions.""" try: yield except exception.Invalid as exp: msg = exp.format_message()
# not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Extended Status Admin API extension.""" from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'extended_status') class ExtendedStatusController(wsgi.Controller): def __init__(self, *args, **kwargs): super(ExtendedStatusController, self).__init__(*args, **kwargs) def _extend_server(self, server, instance): for state in ['task_state', 'vm_state', 'power_state']: key = "%s:%s" % (Extended_status.alias, state) server[key] = instance[state] @wsgi.extends def show(self, req, resp_obj, id): context = req.environ['patron.context'] if authorize(context):
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The flavor access extension.""" import webob from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import context as patron_context from patron import exception from patron.i18n import _ from patron import objects soft_authorize = extensions.soft_extension_authorizer('compute', 'flavor_access') authorize = extensions.extension_authorizer('compute', 'flavor_access') def _marshall_flavor_access(flavor): rval = [] for project_id in flavor.projects: rval.append({'flavor_id': flavor.flavorid, 'tenant_id': project_id}) return {'flavor_access': rval} class FlavorAccessController(object): """The flavor access API controller for the OpenStack API.""" def __init__(self): super(FlavorAccessController, self).__init__()
# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Extended Availability Zone Status API extension.""" from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import availability_zones as avail_zone authorize = extensions.soft_extension_authorizer('compute', 'extended_availability_zone') class ExtendedAZController(wsgi.Controller): def _extend_server(self, context, server, instance): key = "%s:availability_zone" % Extended_availability_zone.alias az = avail_zone.get_instance_availability_zone(context, instance) if not az and instance.get('availability_zone'): # Likely hasn't reached a viable compute node yet so give back the # desired availability_zone that *may* exist in the instance # record itself. az = instance.availability_zone server[key] = az @wsgi.extends def show(self, req, resp_obj, id):
# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Config Drive extension.""" from patron.api.openstack.compute import servers from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'config_drive') class Controller(servers.Controller): def _add_config_drive(self, req, servers): for server in servers: db_server = req.get_db_instance(server['id']) # server['id'] is guaranteed to be in the cache due to # the core API adding it in its 'show'/'detail' methods. server['config_drive'] = db_server['config_drive'] def _show(self, req, resp_obj): if 'server' in resp_obj.obj: server = resp_obj.obj['server'] self._add_config_drive(req, [server])
# License for the specific language governing permissions and limitations # under the License. """The flavor access extension.""" import webob from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import context as patron_context from patron import exception from patron.i18n import _ from patron import objects soft_authorize = extensions.soft_extension_authorizer('compute', 'flavor_access') authorize = extensions.extension_authorizer('compute', 'flavor_access') def _marshall_flavor_access(flavor): rval = [] for project_id in flavor.projects: rval.append({'flavor_id': flavor.flavorid, 'tenant_id': project_id}) return {'flavor_access': rval} class FlavorAccessController(object): """The flavor access API controller for the OpenStack API."""
# Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from webob import exc from patron.api.openstack import common from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import compute authorize_actions = extensions.extension_authorizer('compute', 'instance_actions') authorize_events = extensions.soft_extension_authorizer('compute', 'instance_actions:events') ACTION_KEYS = ['action', 'instance_uuid', 'request_id', 'user_id', 'project_id', 'start_time', 'message'] EVENT_KEYS = ['event', 'start_time', 'finish_time', 'result', 'traceback'] class InstanceActionsController(wsgi.Controller): def __init__(self): super(InstanceActionsController, self).__init__() self.compute_api = compute.API() self.action_api = compute.InstanceActionAPI() def _format_action(self, action_raw): action = {}
# License for the specific language governing permissions and limitations # under the License. """The Flavor extra data extension OpenStack API version 1.1 lists "name", "ram", "disk", "vcpus" as flavor attributes. This extension adds to that list: - OS-FLV-EXT-DATA:ephemeral """ from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'flavorextradata') class FlavorextradataController(wsgi.Controller): def _extend_flavors(self, req, flavors): for flavor in flavors: db_flavor = req.get_db_flavor(flavor['id']) key = "%s:ephemeral" % Flavorextradata.alias flavor[key] = db_flavor['ephemeral_gb'] def _show(self, req, resp_obj): if not authorize(req.environ['patron.context']): return if 'flavor' in resp_obj.obj: self._extend_flavors(req, [resp_obj.obj['flavor']])
# License for the specific language governing permissions and limitations # under the License. """Keypair management extension.""" import webob import webob.exc from patron.api.openstack.compute import servers from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron.compute import api as compute_api from patron import exception from patron.i18n import _ authorize = extensions.extension_authorizer('compute', 'keypairs') soft_authorize = extensions.soft_extension_authorizer('compute', 'keypairs') class KeypairController(object): """Keypair API controller for the OpenStack API.""" def __init__(self): self.api = compute_api.KeypairAPI() def _filter_keypair(self, keypair, **attrs): clean = { 'name': keypair.name, 'public_key': keypair.public_key, 'fingerprint': keypair.fingerprint, } for attr in attrs: clean[attr] = keypair[attr]
# a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Extended Server Attributes API extension.""" from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'extended_server_attributes') class ExtendedServerAttributesController(wsgi.Controller): def _extend_server(self, context, server, instance): key = "%s:hypervisor_hostname" % Extended_server_attributes.alias server[key] = instance.node for attr in ['host', 'name']: if attr == 'name': key = "%s:instance_%s" % (Extended_server_attributes.alias, attr) else: key = "%s:%s" % (Extended_server_attributes.alias, attr) server[key] = instance[attr]
# License for the specific language governing permissions and limitations # under the License. """Extension for hiding server addresses in certain states.""" from oslo_config import cfg from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron.compute import vm_states CONF = cfg.CONF CONF.import_opt( 'osapi_hide_server_address_states', 'patron.api.openstack.compute.plugins.v3.hide_server_addresses') authorize = extensions.soft_extension_authorizer('compute', 'hide_server_addresses') class Controller(wsgi.Controller): def __init__(self, *args, **kwargs): super(Controller, self).__init__(*args, **kwargs) hidden_states = CONF.osapi_hide_server_address_states # NOTE(jkoelker) _ is not considered uppercase ;) valid_vm_states = [ getattr(vm_states, state) for state in dir(vm_states) if state.isupper() ] self.hide_address_states = [ state.lower() for state in hidden_states if state in valid_vm_states
# not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Flavor Swap API extension.""" from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'flavor_swap') class FlavorSwapController(wsgi.Controller): def _extend_flavors(self, req, flavors): for flavor in flavors: db_flavor = req.get_db_flavor(flavor['id']) key = 'swap' flavor[key] = db_flavor['swap'] or "" def _show(self, req, resp_obj): if not authorize(req.environ['patron.context']): return if 'flavor' in resp_obj.obj: self._extend_flavors(req, [resp_obj.obj['flavor']])
# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'image_size') class ImageSizeController(wsgi.Controller): def _extend_image(self, image, image_cache): key = "%s:size" % Image_size.alias image[key] = image_cache['size'] @wsgi.extends def show(self, req, resp_obj, id): context = req.environ["patron.context"] if authorize(context): image_resp = resp_obj.obj['image'] # image guaranteed to be in the cache due to the core API adding # it in its 'show' method
# a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """Config Drive extension.""" from patron.api.openstack.compute import servers from patron.api.openstack import extensions from patron.api.openstack import wsgi authorize = extensions.soft_extension_authorizer('compute', 'config_drive') class Controller(servers.Controller): def _add_config_drive(self, req, servers): for server in servers: db_server = req.get_db_instance(server['id']) # server['id'] is guaranteed to be in the cache due to # the core API adding it in its 'show'/'detail' methods. server['config_drive'] = db_server['config_drive'] def _show(self, req, resp_obj): if 'server' in resp_obj.obj: server = resp_obj.obj['server'] self._add_config_drive(req, [server])
# under the License. """Disk Config extension.""" from oslo_utils import strutils from webob import exc from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron.i18n import _ ALIAS = 'OS-DCF' XMLNS_DCF = "http://docs.openstack.org/compute/ext/disk_config/api/v1.1" API_DISK_CONFIG = "%s:diskConfig" % ALIAS INTERNAL_DISK_CONFIG = "auto_disk_config" authorize = extensions.soft_extension_authorizer('compute', 'disk_config') def disk_config_to_api(value): return 'AUTO' if value else 'MANUAL' def disk_config_from_api(value): if value == 'AUTO': return True elif value == 'MANUAL': return False else: msg = _("%s must be either 'MANUAL' or 'AUTO'.") % API_DISK_CONFIG raise exc.HTTPBadRequest(explanation=msg)
# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from oslo_log import log as logging from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import compute LOG = logging.getLogger(__name__) authorize = extensions.soft_extension_authorizer('compute', 'server_usage') class ServerUsageController(wsgi.Controller): def __init__(self, *args, **kwargs): super(ServerUsageController, self).__init__(*args, **kwargs) self.compute_api = compute.API() def _extend_server(self, server, instance): for k in ['launched_at', 'terminated_at']: key = "%s:%s" % (Server_usage.alias, k) # NOTE(danms): Historically, this timestamp has been generated # merely by grabbing str(datetime) of a TZ-naive object. The # only way we can keep that with instance objects is to strip # the tzinfo from the stamp and str() it. server[key] = (instance[k].replace(tzinfo=None)
# a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """The Extended Volumes API extension.""" from patron.api.openstack import extensions from patron.api.openstack import wsgi from patron import objects authorize = extensions.soft_extension_authorizer('compute', 'extended_volumes') class ExtendedVolumesController(wsgi.Controller): def __init__(self, *args, **kwargs): super(ExtendedVolumesController, self).__init__(*args, **kwargs) def _extend_server(self, context, server, instance): bdms = objects.BlockDeviceMappingList.get_by_instance_uuid( context, instance.uuid) volume_ids = [bdm.volume_id for bdm in bdms if bdm.volume_id] key = "%s:volumes_attached" % Extended_volumes.alias server[key] = [{'id': volume_id} for volume_id in volume_ids] @wsgi.extends def show(self, req, resp_obj, id):