summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2011-12-09 17:31:34 +0000
committerGerrit Code Review <review@openstack.org>2011-12-09 17:31:34 +0000
commit2aadaba580f0253d64a69a5cf4127e50346a34fb (patch)
tree10b7434fdf5a221720e79f70ff3811a723634cf9 /nova/api
parent8920181a0d8cfb4f78af0fa0b868e864d8971744 (diff)
parentf7df18f22715e958510805db42df818ac0f0d243 (diff)
downloadnova-2aadaba580f0253d64a69a5cf4127e50346a34fb.tar.gz
nova-2aadaba580f0253d64a69a5cf4127e50346a34fb.tar.xz
nova-2aadaba580f0253d64a69a5cf4127e50346a34fb.zip
Merge "Add templates for selected resource extensions."
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/v2/contrib/security_groups.py100
-rw-r--r--nova/api/openstack/v2/contrib/simple_tenant_usage.py51
-rw-r--r--nova/api/openstack/v2/contrib/virtual_interfaces.py31
-rw-r--r--nova/api/openstack/v2/contrib/volumes.py130
-rw-r--r--nova/api/openstack/v2/contrib/volumetypes.py81
5 files changed, 343 insertions, 50 deletions
diff --git a/nova/api/openstack/v2/contrib/security_groups.py b/nova/api/openstack/v2/contrib/security_groups.py
index 50f129bd6..3c4f0e473 100644
--- a/nova/api/openstack/v2/contrib/security_groups.py
+++ b/nova/api/openstack/v2/contrib/security_groups.py
@@ -24,6 +24,7 @@ import webob
from nova.api.openstack import common
from nova.api.openstack.v2 import extensions
from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
from nova import compute
from nova import db
from nova import exception
@@ -355,6 +356,85 @@ class SecurityGroupRulesController(SecurityGroupController):
return webob.Response(status_int=202)
+def make_rule(elem):
+ elem.set('id')
+ elem.set('parent_group_id')
+
+ proto = xmlutil.SubTemplateElement(elem, 'ip_protocol')
+ proto.text = 'ip_protocol'
+
+ from_port = xmlutil.SubTemplateElement(elem, 'from_port')
+ from_port.text = 'from_port'
+
+ to_port = xmlutil.SubTemplateElement(elem, 'to_port')
+ to_port.text = 'to_port'
+
+ group = xmlutil.SubTemplateElement(elem, 'group', selector='group')
+ name = xmlutil.SubTemplateElement(group, 'name')
+ name.text = 'name'
+ tenant_id = xmlutil.SubTemplateElement(group, 'tenant_id')
+ tenant_id.text = 'tenant_id'
+
+ ip_range = xmlutil.SubTemplateElement(elem, 'ip_range',
+ selector='ip_range')
+ cidr = xmlutil.SubTemplateElement(ip_range, 'cidr')
+ cidr.text = 'cidr'
+
+
+def make_sg(elem):
+ elem.set('id')
+ elem.set('tenant_id')
+ elem.set('name')
+
+ desc = xmlutil.SubTemplateElement(elem, 'description')
+ desc.text = 'description'
+
+ rules = xmlutil.SubTemplateElement(elem, 'rules')
+ rule = xmlutil.SubTemplateElement(rules, 'rule', selector='rules')
+ make_rule(rule)
+
+
+sg_nsmap = {None: wsgi.XMLNS_V11}
+
+
+class SecurityGroupRuleTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('security_group_rule',
+ selector='security_group_rule')
+ make_rule(root)
+ return xmlutil.MasterTemplate(root, 1, nsmap=sg_nsmap)
+
+
+class SecurityGroupTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('security_group',
+ selector='security_group')
+ make_sg(root)
+ return xmlutil.MasterTemplate(root, 1, nsmap=sg_nsmap)
+
+
+class SecurityGroupsTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('security_groups')
+ elem = xmlutil.SubTemplateElement(root, 'security_group',
+ selector='security_groups')
+ make_sg(elem)
+ return xmlutil.MasterTemplate(root, 1, nsmap=sg_nsmap)
+
+
+class SecurityGroupXMLSerializer(xmlutil.XMLTemplateSerializer):
+ def index(self):
+ return SecurityGroupsTemplate()
+
+ def default(self):
+ return SecurityGroupTemplate()
+
+
+class SecurityGroupRulesXMLSerializer(xmlutil.XMLTemplateSerializer):
+ def default(self):
+ return SecurityGroupRuleTemplate()
+
+
class Security_groups(extensions.ExtensionDescriptor):
"""Security group support"""
@@ -439,10 +519,8 @@ class Security_groups(extensions.ExtensionDescriptor):
def get_resources(self):
resources = []
- metadata = _get_metadata()
body_serializers = {
- 'application/xml': wsgi.XMLDictSerializer(metadata=metadata,
- xmlns=wsgi.XMLNS_V11),
+ 'application/xml': SecurityGroupXMLSerializer(),
}
serializer = wsgi.ResponseSerializer(body_serializers, None)
@@ -458,6 +536,11 @@ class Security_groups(extensions.ExtensionDescriptor):
resources.append(res)
+ body_serializers = {
+ 'application/xml': SecurityGroupRulesXMLSerializer(),
+ }
+ serializer = wsgi.ResponseSerializer(body_serializers, None)
+
body_deserializers = {
'application/xml': SecurityGroupRulesXMLDeserializer(),
}
@@ -538,14 +621,3 @@ class SecurityGroupRulesXMLDeserializer(wsgi.MetadataXMLDeserializer):
sg_rule['cidr'] = self.extract_text(cidr_node)
return sg_rule
-
-
-def _get_metadata():
- metadata = {
- "attributes": {
- "security_group": ["id", "tenant_id", "name"],
- "rule": ["id", "parent_group_id"],
- "security_group_rule": ["id", "parent_group_id"],
- }
- }
- return metadata
diff --git a/nova/api/openstack/v2/contrib/simple_tenant_usage.py b/nova/api/openstack/v2/contrib/simple_tenant_usage.py
index e896371ed..4204c53bf 100644
--- a/nova/api/openstack/v2/contrib/simple_tenant_usage.py
+++ b/nova/api/openstack/v2/contrib/simple_tenant_usage.py
@@ -23,6 +23,8 @@ from webob import exc
from nova.api.openstack.v2 import extensions
from nova.api.openstack.v2 import views
+from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
from nova.compute import api
from nova.db.sqlalchemy.session import get_session
from nova import exception
@@ -211,6 +213,47 @@ class SimpleTenantUsageController(object):
return {'tenant_usage': usage}
+def make_usage(elem):
+ for subelem_tag in ('tenant_id', 'total_local_gb_usage',
+ 'total_vcpus_usage', 'total_memory_mb_usage',
+ 'total_hours', 'start', 'stop'):
+ subelem = xmlutil.SubTemplateElement(elem, subelem_tag)
+ subelem.text = subelem_tag
+
+ server_usages = xmlutil.SubTemplateElement(elem, 'server_usages')
+ server_usage = xmlutil.SubTemplateElement(server_usages, 'server_usage',
+ selector='server_usages')
+ for subelem_tag in ('name', 'hours', 'memory_mb', 'local_gb', 'vcpus',
+ 'tenant_id', 'flavor', 'started_at', 'ended_at',
+ 'state', 'uptime'):
+ subelem = xmlutil.SubTemplateElement(server_usage, subelem_tag)
+ subelem.text = subelem_tag
+
+
+class SimpleTenantUsageTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('tenant_usage', selector='tenant_usage')
+ make_usage(root)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class SimpleTenantUsagesTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('tenant_usages')
+ elem = xmlutil.SubTemplateElement(root, 'tenant_usage',
+ selector='tenant_usages')
+ make_usage(elem)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class SimpleTenantUsageSerializer(xmlutil.XMLTemplateSerializer):
+ def index(self):
+ return SimpleTenantUsagesTemplate()
+
+ def show(self):
+ return SimpleTenantUsageTemplate()
+
+
class Simple_tenant_usage(extensions.ExtensionDescriptor):
"""Simple tenant usage extension"""
@@ -222,8 +265,14 @@ class Simple_tenant_usage(extensions.ExtensionDescriptor):
def get_resources(self):
resources = []
+ body_serializers = {
+ 'application/xml': SimpleTenantUsageSerializer(),
+ }
+ serializer = wsgi.ResponseSerializer(body_serializers)
+
res = extensions.ResourceExtension('os-simple-tenant-usage',
- SimpleTenantUsageController())
+ SimpleTenantUsageController(),
+ serializer=serializer)
resources.append(res)
return resources
diff --git a/nova/api/openstack/v2/contrib/virtual_interfaces.py b/nova/api/openstack/v2/contrib/virtual_interfaces.py
index 1975a8dc0..211b8c9be 100644
--- a/nova/api/openstack/v2/contrib/virtual_interfaces.py
+++ b/nova/api/openstack/v2/contrib/virtual_interfaces.py
@@ -18,6 +18,7 @@
from nova.api.openstack import common
from nova.api.openstack.v2 import extensions
from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
from nova import log as logging
from nova import network
@@ -33,13 +34,6 @@ def _translate_vif_summary_view(_context, vif):
return d
-def _get_metadata():
- metadata = {
- "attributes": {
- 'virtual_interface': ["id", "mac_address"]}}
- return metadata
-
-
class ServerVirtualInterfaceController(object):
"""The instance VIF API controller for the Openstack API.
"""
@@ -63,6 +57,24 @@ class ServerVirtualInterfaceController(object):
entity_maker=_translate_vif_summary_view)
+vif_nsmap = {None: wsgi.XMLNS_V11}
+
+
+class VirtualInterfaceTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('virtual_interfaces')
+ elem = xmlutil.SubTemplateElement(root, 'virtual_interface',
+ selector='virtual_interfaces')
+ elem.set('id')
+ elem.set('mac_address')
+ return xmlutil.MasterTemplate(root, 1, nsmap=vif_nsmap)
+
+
+class VirtualInterfaceSerializer(xmlutil.XMLTemplateSerializer):
+ def default(self):
+ return VirtualInterfaceTemplate()
+
+
class Virtual_interfaces(extensions.ExtensionDescriptor):
"""Virtual interface support"""
@@ -74,10 +86,9 @@ class Virtual_interfaces(extensions.ExtensionDescriptor):
def get_resources(self):
resources = []
- metadata = _get_metadata()
body_serializers = {
- 'application/xml': wsgi.XMLDictSerializer(metadata=metadata,
- xmlns=wsgi.XMLNS_V11)}
+ 'application/xml': VirtualInterfaceSerializer()
+ }
serializer = wsgi.ResponseSerializer(body_serializers, None)
res = extensions.ResourceExtension(
'os-virtual-interfaces',
diff --git a/nova/api/openstack/v2/contrib/volumes.py b/nova/api/openstack/v2/contrib/volumes.py
index 5d86282f2..75d8af803 100644
--- a/nova/api/openstack/v2/contrib/volumes.py
+++ b/nova/api/openstack/v2/contrib/volumes.py
@@ -21,6 +21,8 @@ import webob
from nova.api.openstack import common
from nova.api.openstack.v2 import extensions
from nova.api.openstack.v2 import servers
+from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
from nova import compute
from nova import db
from nova import exception
@@ -86,21 +88,6 @@ def _translate_volume_summary_view(context, vol):
class VolumeController(object):
"""The Volumes API controller for the OpenStack API."""
- _serialization_metadata = {
- 'application/xml': {
- "attributes": {
- "volume": [
- "id",
- "status",
- "size",
- "availabilityZone",
- "createdAt",
- "displayName",
- "displayDescription",
- "volumeType",
- "metadata",
- ]}}}
-
def __init__(self):
self.volume_api = volume.API()
super(VolumeController, self).__init__()
@@ -180,6 +167,51 @@ class VolumeController(object):
return {'volume': retval}
+def make_volume(elem):
+ elem.set('id')
+ elem.set('status')
+ elem.set('size')
+ elem.set('availabilityZone')
+ elem.set('createdAt')
+ elem.set('displayName')
+ elem.set('displayDescription')
+ elem.set('volumeType')
+
+ attachments = xmlutil.SubTemplateElement(elem, 'attachments')
+ attachment = xmlutil.SubTemplateElement(attachments, 'attachment',
+ selector='attachments')
+ make_attachment(attachment)
+
+ metadata = xmlutil.make_flat_dict('metadata')
+ elem.append(metadata)
+
+
+class VolumeTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('volume', selector='volume')
+ make_volume(root)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumesTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('volumes')
+ elem = xmlutil.SubTemplateElement(root, 'volume', selector='volumes')
+ make_volume(elem)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeSerializer(xmlutil.XMLTemplateSerializer):
+ def default(self):
+ return VolumeTemplate()
+
+ def index(self):
+ return VolumesTemplate()
+
+ def detail(self):
+ return VolumesTemplate()
+
+
def _translate_attachment_detail_view(_context, vol):
"""Maps keys for attachment details view."""
@@ -216,14 +248,6 @@ class VolumeAttachmentController(object):
"""
- _serialization_metadata = {
- 'application/xml': {
- 'attributes': {
- 'volumeAttachment': ['id',
- 'serverId',
- 'volumeId',
- 'device']}}}
-
def __init__(self):
self.compute_api = compute.API()
self.volume_api = volume.API()
@@ -331,6 +355,38 @@ class VolumeAttachmentController(object):
return {'volumeAttachments': res}
+def make_attachment(elem):
+ elem.set('id')
+ elem.set('serverId')
+ elem.set('volumeId')
+ elem.set('device')
+
+
+class VolumeAttachmentTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('volumeAttachment',
+ selector='volumeAttachment')
+ make_attachment(root)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeAttachmentsTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('volumeAttachments')
+ elem = xmlutil.SubTemplateElement(root, 'volumeAttachment',
+ selector='volumeAttachments')
+ make_attachment(elem)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeAttachmentSerializer(xmlutil.XMLTemplateSerializer):
+ def default(self):
+ return VolumeAttachmentTemplate()
+
+ def index(self):
+ return VolumeAttachmentsTemplate()
+
+
class BootFromVolumeController(servers.Controller):
"""The boot from volume API controller for the Openstack API."""
@@ -349,22 +405,48 @@ class Volumes(extensions.ExtensionDescriptor):
def get_resources(self):
resources = []
+ body_serializers = {
+ 'application/xml': VolumeSerializer(),
+ }
+ serializer = wsgi.ResponseSerializer(body_serializers)
+
# NOTE(justinsb): No way to provide singular name ('volume')
# Does this matter?
res = extensions.ResourceExtension('os-volumes',
VolumeController(),
+ serializer=serializer,
collection_actions={'detail': 'GET'})
resources.append(res)
+ body_serializers = {
+ 'application/xml': VolumeAttachmentSerializer(),
+ }
+ serializer = wsgi.ResponseSerializer(body_serializers)
+
res = extensions.ResourceExtension('os-volume_attachments',
VolumeAttachmentController(),
+ serializer=serializer,
parent=dict(
member_name='server',
collection_name='servers'))
resources.append(res)
+ headers_serializer = servers.HeadersSerializer()
+ body_serializers = {
+ 'application/xml': servers.ServerXMLSerializer(),
+ }
+ serializer = wsgi.ResponseSerializer(body_serializers,
+ headers_serializer)
+
+ body_deserializers = {
+ 'application/xml': servers.ServerXMLDeserializer(),
+ }
+ deserializer = wsgi.RequestDeserializer(body_deserializers)
+
res = extensions.ResourceExtension('os-volumes_boot',
- BootFromVolumeController())
+ BootFromVolumeController(),
+ serializer=serializer,
+ deserializer=deserializer)
resources.append(res)
return resources
diff --git a/nova/api/openstack/v2/contrib/volumetypes.py b/nova/api/openstack/v2/contrib/volumetypes.py
index ca3866c99..24ac87d01 100644
--- a/nova/api/openstack/v2/contrib/volumetypes.py
+++ b/nova/api/openstack/v2/contrib/volumetypes.py
@@ -21,6 +21,7 @@ from webob import exc
from nova.api.openstack.v2 import extensions
from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
from nova import db
from nova import exception
from nova.volume import volume_types
@@ -89,6 +90,37 @@ class VolumeTypesController(object):
raise error
+def make_voltype(elem):
+ elem.set('id')
+ elem.set('name')
+ extra_specs = xmlutil.make_flat_dict('extra_specs', selector='extra_specs')
+ elem.append(extra_specs)
+
+
+class VolumeTypeTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('volume_type', selector='volume_type')
+ make_voltype(root)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeTypesTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('volume_types')
+ sel = lambda obj, do_raise=False: obj.values()
+ elem = xmlutil.SubTemplateElement(root, 'volume_type', selector=sel)
+ make_voltype(elem)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeTypesSerializer(xmlutil.XMLTemplateSerializer):
+ def index(self):
+ return VolumeTypesTemplate()
+
+ def default(self):
+ return VolumeTypeTemplate()
+
+
class VolumeTypeExtraSpecsController(object):
""" The volume type extra specs API controller for the Openstack API """
@@ -160,6 +192,40 @@ class VolumeTypeExtraSpecsController(object):
raise error
+class VolumeTypeExtraSpecsTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.make_flat_dict('extra_specs', selector='extra_specs')
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeTypeExtraSpecTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ tagname = xmlutil.Selector('key')
+
+ def extraspec_sel(obj, do_raise=False):
+ # Have to extract the key and value for later use...
+ key, value = obj.items()[0]
+ return dict(key=key, value=value)
+
+ root = xmlutil.TemplateElement(tagname, selector=extraspec_sel)
+ root.text = 'value'
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeTypeExtraSpecsSerializer(xmlutil.XMLTemplateSerializer):
+ def index(self):
+ return VolumeTypeExtraSpecsTemplate()
+
+ def create(self):
+ return VolumeTypeExtraSpecsTemplate()
+
+ def update(self):
+ return VolumeTypeExtraSpecTemplate()
+
+ def show(self):
+ return VolumeTypeExtraSpecTemplate()
+
+
class Volumetypes(extensions.ExtensionDescriptor):
"""Volume types support"""
@@ -170,13 +236,26 @@ class Volumetypes(extensions.ExtensionDescriptor):
def get_resources(self):
resources = []
+
+ body_serializers = {
+ 'application/xml': VolumeTypesSerializer(),
+ }
+ serializer = wsgi.ResponseSerializer(body_serializers)
+
res = extensions.ResourceExtension(
'os-volume-types',
- VolumeTypesController())
+ VolumeTypesController(),
+ serializer=serializer)
resources.append(res)
+ body_serializers = {
+ 'application/xml': VolumeTypeExtraSpecsSerializer(),
+ }
+ serializer = wsgi.ResponseSerializer(body_serializers)
+
res = extensions.ResourceExtension('extra_specs',
VolumeTypeExtraSpecsController(),
+ serializer=serializer,
parent=dict(
member_name='vol_type',
collection_name='os-volume-types'))