summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTushar Patil <tushar.vitthal.patil@gmail.com>2011-07-14 16:37:40 -0700
committerTushar Patil <tushar.vitthal.patil@gmail.com>2011-07-14 16:37:40 -0700
commit793a02f30be7bcfd19d5651919c28fcbab8b1a24 (patch)
tree52f1f7ed813f771212a381b2587d5bd3888a99d2
parent0655f97b2cce1e28485ddb4c37a854a65cbbc276 (diff)
parent5c4ff1e78588ffde1485f6376db3693ff9990701 (diff)
downloadnova-793a02f30be7bcfd19d5651919c28fcbab8b1a24.tar.gz
nova-793a02f30be7bcfd19d5651919c28fcbab8b1a24.tar.xz
nova-793a02f30be7bcfd19d5651919c28fcbab8b1a24.zip
Merged with trunk and fixed pep errors
-rw-r--r--Authors1
-rwxr-xr-xbin/nova-manage62
-rw-r--r--nova/api/openstack/common.py17
-rw-r--r--nova/api/openstack/images.py111
-rw-r--r--nova/api/openstack/views/images.py28
-rw-r--r--nova/api/openstack/wsgi.py23
-rw-r--r--nova/network/manager.py4
-rw-r--r--nova/tests/api/openstack/test_common.py33
-rw-r--r--nova/tests/api/openstack/test_images.py532
-rw-r--r--nova/tests/integrated/test_servers.py2
10 files changed, 595 insertions, 218 deletions
diff --git a/Authors b/Authors
index 2e50cfbe0..a366cec87 100644
--- a/Authors
+++ b/Authors
@@ -85,6 +85,7 @@ Ryan Lucio <rlucio@internap.com>
Salvatore Orlando <salvatore.orlando@eu.citrix.com>
Sandy Walsh <sandy.walsh@rackspace.com>
Sateesh Chodapuneedi <sateesh.chodapuneedi@citrix.com>
+Scott Moser <smoser@ubuntu.com>
Soren Hansen <soren.hansen@rackspace.com>
Thierry Carrez <thierry@openstack.org>
Todd Willey <todd@ansolabs.com>
diff --git a/bin/nova-manage b/bin/nova-manage
index 53e3d5c93..47bf81008 100755
--- a/bin/nova-manage
+++ b/bin/nova-manage
@@ -414,8 +414,11 @@ class ProjectCommands(object):
except (exception.UserNotFound, exception.ProjectNotFound) as ex:
print ex
raise
- with open(filename, 'w') as f:
- f.write(rc)
+ if filename == "-":
+ sys.stdout.write(rc)
+ else:
+ with open(filename, 'w') as f:
+ f.write(rc)
def list(self, username=None):
"""Lists all projects
@@ -465,8 +468,11 @@ class ProjectCommands(object):
arguments: project_id user_id [filename='nova.zip]"""
try:
zip_file = self.manager.get_credentials(user_id, project_id)
- with open(filename, 'w') as f:
- f.write(zip_file)
+ if filename == "-":
+ sys.stdout.write(zip_file)
+ else:
+ with open(filename, 'w') as f:
+ f.write(zip_file)
except (exception.UserNotFound, exception.ProjectNotFound) as ex:
print ex
raise
@@ -615,17 +621,22 @@ class NetworkCommands(object):
def list(self):
"""List all created networks"""
- print "%-5s\t%-18s\t%-15s\t%-15s\t%-15s" % (_('id'),
- _('network'),
- _('netmask'),
- _('start address'),
- 'DNS')
+ print "%-5s\%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s" % (_('id'),
+ _('network'),
+ _('netmask'),
+ _('start address'),
+ _('DNS'),
+ _('VlanID'),
+ 'project')
for network in db.network_get_all(context.get_admin_context()):
- print "%-5s\t%-18s\t%-15s\t%-15s\t%-15s" % (network.id,
- network.cidr,
- network.netmask,
- network.dhcp_start,
- network.dns)
+ print "%-5s\t%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s" % (
+ network.id,
+ network.cidr,
+ network.netmask,
+ network.dhcp_start,
+ network.dns,
+ network.vlan,
+ network.project_id)
def delete(self, fixed_range):
"""Deletes a network"""
@@ -814,6 +825,28 @@ class ServiceCommands(object):
{"method": "update_available_resource"})
+class HostCommands(object):
+ """List hosts"""
+
+ def list(self, zone=None):
+ """Show a list of all physical hosts. Filter by zone.
+ args: [zone]"""
+ print "%-25s\t%-15s" % (_('host'),
+ _('zone'))
+ ctxt = context.get_admin_context()
+ now = utils.utcnow()
+ services = db.service_get_all(ctxt)
+ if zone:
+ services = [s for s in services if s['availability_zone'] == zone]
+ hosts = []
+ for srv in services:
+ if not [h for h in hosts if h['host'] == srv['host']]:
+ hosts.append(srv)
+
+ for h in hosts:
+ print "%-25s\t%-15s" % (h['host'], h['availability_zone'])
+
+
class DbCommands(object):
"""Class for managing the database."""
@@ -1187,6 +1220,7 @@ CATEGORIES = [
('fixed', FixedIpCommands),
('flavor', InstanceTypeCommands),
('floating', FloatingIpCommands),
+ ('host', HostCommands),
('instance_type', InstanceTypeCommands),
('image', ImageCommands),
('network', NetworkCommands),
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index 9aa384f33..79969d393 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -133,14 +133,25 @@ def get_id_from_href(href):
return int(urlparse(href).path.split('/')[-1])
except:
LOG.debug(_("Error extracting id from href: %s") % href)
- raise webob.exc.HTTPBadRequest(_('could not parse id from href'))
+ raise ValueError(_('could not parse id from href'))
-def remove_version_from_href(base_url):
+def remove_version_from_href(href):
"""Removes the api version from the href.
Given: 'http://www.nova.com/v1.1/123'
Returns: 'http://www.nova.com/123'
"""
- return base_url.rsplit('/', 1).pop(0)
+ try:
+ #matches /v#.#
+ new_href = re.sub(r'[/][v][0-9]*.[0-9]*', '', href)
+ except:
+ LOG.debug(_("Error removing version from href: %s") % href)
+ msg = _('could not parse version from href')
+ raise ValueError(msg)
+
+ if new_href == href:
+ msg = _('href does not contain version')
+ raise ValueError(msg)
+ return new_href
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index 8ff92b8fe..d0317583e 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -27,6 +27,7 @@ from nova import log
from nova.api.openstack import common
from nova.api.openstack import faults
from nova.api.openstack import image_metadata
+from nova.api.openstack import servers
from nova.api.openstack.views import images as images_view
from nova.api.openstack import wsgi
@@ -274,59 +275,99 @@ class ControllerV11(Controller):
class ImageXMLSerializer(wsgi.XMLDictSerializer):
- metadata = {
- "attributes": {
- "image": ["id", "name", "updated", "created", "status",
- "serverId", "progress", "serverRef"],
- "link": ["rel", "type", "href"],
- },
- }
-
xmlns = wsgi.XMLNS_V11
def __init__(self):
self.metadata_serializer = image_metadata.ImageMetadataXMLSerializer()
def _image_to_xml(self, xml_doc, image):
- try:
- metadata = image.pop('metadata').items()
- except Exception:
- LOG.debug(_("Image object missing metadata attribute"))
- metadata = {}
-
- node = self._to_xml_node(xml_doc, self.metadata, 'image', image)
- metadata_node = self.metadata_serializer.meta_list_to_xml(xml_doc,
- metadata)
- node.appendChild(metadata_node)
- return node
-
- def _image_list_to_xml(self, xml_doc, images):
+ image_node = xml_doc.createElement('image')
+ image_node.setAttribute('id', str(image['id']))
+ image_node.setAttribute('name', image['name'])
+ link_nodes = self._create_link_nodes(xml_doc,
+ image['links'])
+ for link_node in link_nodes:
+ image_node.appendChild(link_node)
+ return image_node
+
+ def _image_to_xml_detailed(self, xml_doc, image):
+ image_node = xml_doc.createElement('image')
+ self._add_image_attributes(image_node, image)
+
+ if 'server' in image:
+ server_node = self._create_server_node(xml_doc, image['server'])
+ image_node.appendChild(server_node)
+
+ metadata = image.get('metadata', {}).items()
+ if len(metadata) > 0:
+ metadata_node = self._create_metadata_node(xml_doc, metadata)
+ image_node.appendChild(metadata_node)
+
+ link_nodes = self._create_link_nodes(xml_doc,
+ image['links'])
+ for link_node in link_nodes:
+ image_node.appendChild(link_node)
+
+ return image_node
+
+ def _add_image_attributes(self, node, image):
+ node.setAttribute('id', str(image['id']))
+ node.setAttribute('name', image['name'])
+ node.setAttribute('created', image['created'])
+ node.setAttribute('updated', image['updated'])
+ node.setAttribute('status', image['status'])
+ if 'progress' in image:
+ node.setAttribute('progress', str(image['progress']))
+
+ def _create_metadata_node(self, xml_doc, metadata):
+ return self.metadata_serializer.meta_list_to_xml(xml_doc, metadata)
+
+ def _create_server_node(self, xml_doc, server):
+ server_node = xml_doc.createElement('server')
+ server_node.setAttribute('id', str(server['id']))
+ link_nodes = self._create_link_nodes(xml_doc,
+ server['links'])
+ for link_node in link_nodes:
+ server_node.appendChild(link_node)
+ return server_node
+
+ def _image_list_to_xml(self, xml_doc, images, detailed):
container_node = xml_doc.createElement('images')
+ if detailed:
+ image_to_xml = self._image_to_xml_detailed
+ else:
+ image_to_xml = self._image_to_xml
+
for image in images:
- item_node = self._image_to_xml(xml_doc, image)
+ item_node = image_to_xml(xml_doc, image)
container_node.appendChild(item_node)
return container_node
- def _image_to_xml_string(self, image):
- xml_doc = minidom.Document()
- item_node = self._image_to_xml(xml_doc, image)
- self._add_xmlns(item_node)
- return item_node.toprettyxml(indent=' ')
-
- def _image_list_to_xml_string(self, images):
+ def index(self, images_dict):
xml_doc = minidom.Document()
- container_node = self._image_list_to_xml(xml_doc, images)
- self._add_xmlns(container_node)
- return container_node.toprettyxml(indent=' ')
+ node = self._image_list_to_xml(xml_doc,
+ images_dict['images'],
+ detailed=False)
+ return self.to_xml_string(node, True)
def detail(self, images_dict):
- return self._image_list_to_xml_string(images_dict['images'])
+ xml_doc = minidom.Document()
+ node = self._image_list_to_xml(xml_doc,
+ images_dict['images'],
+ detailed=True)
+ return self.to_xml_string(node, True)
def show(self, image_dict):
- return self._image_to_xml_string(image_dict['image'])
+ xml_doc = minidom.Document()
+ node = self._image_to_xml_detailed(xml_doc,
+ image_dict['image'])
+ return self.to_xml_string(node, True)
def create(self, image_dict):
- return self._image_to_xml_string(image_dict['image'])
+ xml_doc = minidom.Document()
+ node = self._image_to_xml_detailed(xml_doc,
+ image_dict['image'])
+ return self.to_xml_string(node, True)
def create_resource(version='1.0'):
diff --git a/nova/api/openstack/views/images.py b/nova/api/openstack/views/images.py
index 005341c62..5c0510377 100644
--- a/nova/api/openstack/views/images.py
+++ b/nova/api/openstack/views/images.py
@@ -98,7 +98,20 @@ class ViewBuilderV11(ViewBuilder):
def _build_server(self, image, image_obj):
try:
- image['serverRef'] = image_obj['properties']['instance_ref']
+ serverRef = image_obj['properties']['instance_ref']
+ image['server'] = {
+ "id": common.get_id_from_href(serverRef),
+ "links": [
+ {
+ "rel": "self",
+ "href": serverRef,
+ },
+ {
+ "rel": "bookmark",
+ "href": common.remove_version_from_href(serverRef),
+ },
+ ]
+ }
except KeyError:
return
@@ -108,18 +121,17 @@ class ViewBuilderV11(ViewBuilder):
href = self.generate_href(image_obj["id"])
bookmark = self.generate_bookmark(image_obj["id"])
- if detail:
- image["metadata"] = image_obj.get("properties", {})
-
image["links"] = [{
"rel": "self",
"href": href,
- },
- {
- "rel": "bookmark",
- "href": bookmark,
}]
+ if detail:
+ image["metadata"] = image_obj.get("properties", {})
+ image["links"].append({"rel": "bookmark",
+ "href": bookmark,
+ })
+
return image
def generate_bookmark(self, image_id):
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index 8eff9e441..c3f841aa5 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -270,13 +270,21 @@ class XMLDictSerializer(DictSerializer):
doc = minidom.Document()
node = self._to_xml_node(doc, self.metadata, root_key, data[root_key])
- self._add_xmlns(node)
+ return self.to_xml_string(node)
- return node.toprettyxml(indent=' ', encoding='utf-8')
+ def to_xml_string(self, node, has_atom=False):
+ self._add_xmlns(node, has_atom)
+ return node.toprettyxml(indent=' ', encoding='UTF-8')
- def _add_xmlns(self, node):
+ #NOTE (ameade): the has_atom should be removed after all of the
+ # xml serializers and view builders have been updated to the current
+ # spec that required all responses include the xmlns:atom, the has_atom
+ # flag is to prevent current tests from breaking
+ def _add_xmlns(self, node, has_atom=False):
if self.xmlns is not None:
node.setAttribute('xmlns', self.xmlns)
+ if has_atom:
+ node.setAttribute('xmlns:atom', "http://www.w3.org/2005/Atom")
def _to_xml_node(self, doc, metadata, nodename, data):
"""Recursive method to convert data members to XML nodes."""
@@ -332,6 +340,15 @@ class XMLDictSerializer(DictSerializer):
result.appendChild(node)
return result
+ def _create_link_nodes(self, xml_doc, links):
+ link_nodes = []
+ for link in links:
+ link_node = xml_doc.createElement('atom:link')
+ link_node.setAttribute('rel', link['rel'])
+ link_node.setAttribute('href', link['href'])
+ link_nodes.append(link_node)
+ return link_nodes
+
class ResponseHeadersSerializer(ActionDispatcher):
"""Default response headers serialization"""
diff --git a/nova/network/manager.py b/nova/network/manager.py
index b2b9335a9..349faa84d 100644
--- a/nova/network/manager.py
+++ b/nova/network/manager.py
@@ -354,7 +354,7 @@ class NetworkManager(manager.SchedulerDependentManager):
"""Set the network hosts for any networks which are unset."""
try:
networks = self.db.network_get_all(context)
- except Exception.NoNetworksFound:
+ except exception.NoNetworksFound:
# we don't care if no networks are found
pass
@@ -376,7 +376,7 @@ class NetworkManager(manager.SchedulerDependentManager):
else:
try:
networks = self.db.network_get_all(context)
- except Exception.NoNetworksFound:
+ except exception.NoNetworksFound:
# we don't care if no networks are found
pass
diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py
index 29cb8b944..7440bccfb 100644
--- a/nova/tests/api/openstack/test_common.py
+++ b/nova/tests/api/openstack/test_common.py
@@ -190,3 +190,36 @@ class PaginationParamsTest(test.TestCase):
req = Request.blank('/?limit=20&marker=40')
self.assertEqual(common.get_pagination_params(req),
{'marker': 40, 'limit': 20})
+
+
+class MiscFunctionsTest(test.TestCase):
+
+ def test_remove_version_from_href(self):
+ fixture = 'http://www.testsite.com/v1.1/images'
+ expected = 'http://www.testsite.com/images'
+ actual = common.remove_version_from_href(fixture)
+ self.assertEqual(actual, expected)
+
+ def test_remove_version_from_href_2(self):
+ fixture = 'http://www.testsite.com/v1.1/'
+ expected = 'http://www.testsite.com/'
+ actual = common.remove_version_from_href(fixture)
+ self.assertEqual(actual, expected)
+
+ def test_remove_version_from_href_bad_request(self):
+ fixture = 'http://www.testsite.com/1.1/images'
+ self.assertRaises(ValueError,
+ common.remove_version_from_href,
+ fixture)
+
+ def test_get_id_from_href(self):
+ fixture = 'http://www.testsite.com/dir/45'
+ actual = common.get_id_from_href(fixture)
+ expected = 45
+ self.assertEqual(actual, expected)
+
+ def test_get_id_from_href_bad_request(self):
+ fixture = 'http://45'
+ self.assertRaises(ValueError,
+ common.get_id_from_href,
+ fixture)
diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py
index f451ee145..c1bdd6906 100644
--- a/nova/tests/api/openstack/test_images.py
+++ b/nova/tests/api/openstack/test_images.py
@@ -401,15 +401,27 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
href = "http://localhost/v1.1/images/124"
bookmark = "http://localhost/images/124"
+ server_href = "http://localhost/v1.1/servers/42"
+ server_bookmark = "http://localhost/servers/42"
expected_image = {
"image": {
"id": 124,
"name": "queued snapshot",
- "serverRef": "http://localhost/v1.1/servers/42",
"updated": self.NOW_API_FORMAT,
"created": self.NOW_API_FORMAT,
"status": "QUEUED",
+ 'server': {
+ 'id': 42,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
"metadata": {
"instance_ref": "http://localhost/v1.1/servers/42",
"user_id": "1",
@@ -559,10 +571,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
"links": [{
"rel": "self",
"href": href,
- },
- {
- "rel": "bookmark",
- "href": bookmark,
}],
}
self.assertTrue(test_image in response_list)
@@ -628,6 +636,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
response_dict = json.loads(response.body)
response_list = response_dict["images"]
+ server_href = "http://localhost/v1.1/servers/42"
+ server_bookmark = "http://localhost/servers/42"
expected = [{
'id': 123,
@@ -652,10 +662,20 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
u'instance_ref': u'http://localhost/v1.1/servers/42',
u'user_id': u'1',
},
- 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'QUEUED',
+ 'server': {
+ 'id': 42,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
"links": [{
"rel": "self",
"href": "http://localhost/v1.1/images/124",
@@ -672,11 +692,21 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
u'instance_ref': u'http://localhost/v1.1/servers/42',
u'user_id': u'1',
},
- 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'SAVING',
'progress': 0,
+ 'server': {
+ 'id': 42,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
"links": [{
"rel": "self",
"href": "http://localhost/v1.1/images/125",
@@ -693,10 +723,20 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
u'instance_ref': u'http://localhost/v1.1/servers/42',
u'user_id': u'1',
},
- 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'ACTIVE',
+ 'server': {
+ 'id': 42,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
"links": [{
"rel": "self",
"href": "http://localhost/v1.1/images/126",
@@ -713,10 +753,20 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
u'instance_ref': u'http://localhost/v1.1/servers/42',
u'user_id': u'1',
},
- 'serverRef': "http://localhost/v1.1/servers/42",
'updated': self.NOW_API_FORMAT,
'created': self.NOW_API_FORMAT,
'status': 'FAILED',
+ 'server': {
+ 'id': 42,
+ "links": [{
+ "rel": "self",
+ "href": server_href,
+ },
+ {
+ "rel": "bookmark",
+ "href": server_bookmark,
+ }],
+ },
"links": [{
"rel": "self",
"href": "http://localhost/v1.1/images/127",
@@ -1036,6 +1086,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
def test_create_image_v1_1_actual_server_ref(self):
serverRef = 'http://localhost/v1.1/servers/1'
+ serverBookmark = 'http://localhost/servers/1'
body = dict(image=dict(serverRef=serverRef, name='Backup 1'))
req = webob.Request.blank('/v1.1/images')
req.method = 'POST'
@@ -1044,11 +1095,25 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
response = req.get_response(fakes.wsgi_app())
self.assertEqual(200, response.status_int)
result = json.loads(response.body)
- self.assertEqual(result['image']['serverRef'], serverRef)
+ expected = {
+ 'id': 1,
+ 'links': [
+ {
+ 'rel': 'self',
+ 'href': serverRef,
+ },
+ {
+ 'rel': 'bookmark',
+ 'href': serverBookmark,
+ },
+ ]
+ }
+ self.assertEqual(result['image']['server'], expected)
def test_create_image_v1_1_actual_server_ref_port(self):
serverRef = 'http://localhost:8774/v1.1/servers/1'
+ serverBookmark = 'http://localhost:8774/servers/1'
body = dict(image=dict(serverRef=serverRef, name='Backup 1'))
req = webob.Request.blank('/v1.1/images')
req.method = 'POST'
@@ -1057,7 +1122,20 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
response = req.get_response(fakes.wsgi_app())
self.assertEqual(200, response.status_int)
result = json.loads(response.body)
- self.assertEqual(result['image']['serverRef'], serverRef)
+ expected = {
+ 'id': 1,
+ 'links': [
+ {
+ 'rel': 'self',
+ 'href': serverRef,
+ },
+ {
+ 'rel': 'bookmark',
+ 'href': serverBookmark,
+ },
+ ]
+ }
+ self.assertEqual(result['image']['server'], expected)
def test_create_image_v1_1_server_ref_bad_hostname(self):
@@ -1080,6 +1158,28 @@ class ImageControllerWithGlanceServiceTest(test.TestCase):
response = req.get_response(fakes.wsgi_app())
self.assertEqual(400, response.status_int)
+ def test_create_image_v1_1_server_ref_missing_version(self):
+
+ serverRef = 'http://localhost/servers/1'
+ body = dict(image=dict(serverRef=serverRef, name='Backup 1'))
+ req = webob.Request.blank('/v1.1/images')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ response = req.get_response(fakes.wsgi_app())
+ self.assertEqual(400, response.status_int)
+
+ def test_create_image_v1_1_server_ref_missing_id(self):
+
+ serverRef = 'http://localhost/v1.1/servers'
+ body = dict(image=dict(serverRef=serverRef, name='Backup 1'))
+ req = webob.Request.blank('/v1.1/images')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ response = req.get_response(fakes.wsgi_app())
+ self.assertEqual(400, response.status_int)
+
@classmethod
def _make_image_fixtures(cls):
image_id = 123
@@ -1128,7 +1228,9 @@ class ImageXMLSerializationTest(test.TestCase):
TIMESTAMP = "2010-10-11T10:30:22Z"
SERVER_HREF = 'http://localhost/v1.1/servers/123'
+ SERVER_BOOKMARK = 'http://localhost/servers/123'
IMAGE_HREF = 'http://localhost/v1.1/images/%s'
+ IMAGE_BOOKMARK = 'http://localhost/images/%s'
def test_show(self):
serializer = images.ImageXMLSerializer()
@@ -1139,16 +1241,32 @@ class ImageXMLSerializationTest(test.TestCase):
'name': 'Image1',
'created': self.TIMESTAMP,
'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
'status': 'ACTIVE',
+ 'progress': 80,
+ 'server': {
+ 'id': 1,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
'metadata': {
'key1': 'value1',
},
'links': [
{
- 'href': self.IMAGE_HREF % (1,),
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
'rel': 'bookmark',
- 'type': 'application/json',
},
],
},
@@ -1158,25 +1276,30 @@ class ImageXMLSerializationTest(test.TestCase):
actual = minidom.parseString(output.replace(" ", ""))
expected_server_href = self.SERVER_HREF
- expected_href = self.IMAGE_HREF % (1, )
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_href = self.IMAGE_HREF % 1
+ expected_bookmark = self.IMAGE_BOOKMARK % 1
expected_now = self.TIMESTAMP
expected = minidom.parseString("""
<image id="1"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
name="Image1"
- serverRef="%(expected_server_href)s"
updated="%(expected_now)s"
created="%(expected_now)s"
status="ACTIVE"
- xmlns="http://docs.openstack.org/compute/api/v1.1">
- <links>
- <link href="%(expected_href)s" rel="bookmark"
- type="application/json" />
- </links>
+ progress="80">
+ <server id="1">
+ <atom:link rel="self" href="%(expected_server_href)s"/>
+ <atom:link rel="bookmark" href="%(expected_server_bookmark)s"/>
+ </server>
<metadata>
<meta key="key1">
value1
</meta>
</metadata>
+ <atom:link href="%(expected_href)s" rel="self"/>
+ <atom:link href="%(expected_bookmark)s" rel="bookmark"/>
</image>
""".replace(" ", "") % (locals()))
@@ -1191,14 +1314,29 @@ class ImageXMLSerializationTest(test.TestCase):
'name': 'Image1',
'created': self.TIMESTAMP,
'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
'status': 'ACTIVE',
+ 'server': {
+ 'id': 1,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
'metadata': {},
'links': [
{
- 'href': self.IMAGE_HREF % (1,),
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
'rel': 'bookmark',
- 'type': 'application/json',
},
],
},
@@ -1208,21 +1346,24 @@ class ImageXMLSerializationTest(test.TestCase):
actual = minidom.parseString(output.replace(" ", ""))
expected_server_href = self.SERVER_HREF
- expected_href = self.IMAGE_HREF % (1, )
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_href = self.IMAGE_HREF % 1
+ expected_bookmark = self.IMAGE_BOOKMARK % 1
expected_now = self.TIMESTAMP
expected = minidom.parseString("""
<image id="1"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
name="Image1"
- serverRef="%(expected_server_href)s"
updated="%(expected_now)s"
created="%(expected_now)s"
- status="ACTIVE"
- xmlns="http://docs.openstack.org/compute/api/v1.1">
- <links>
- <link href="%(expected_href)s" rel="bookmark"
- type="application/json" />
- </links>
- <metadata />
+ status="ACTIVE">
+ <server id="1">
+ <atom:link rel="self" href="%(expected_server_href)s"/>
+ <atom:link rel="bookmark" href="%(expected_server_bookmark)s"/>
+ </server>
+ <atom:link href="%(expected_href)s" rel="self"/>
+ <atom:link href="%(expected_bookmark)s" rel="bookmark"/>
</image>
""".replace(" ", "") % (locals()))
@@ -1237,16 +1378,30 @@ class ImageXMLSerializationTest(test.TestCase):
'name': 'Image1',
'created': self.TIMESTAMP,
'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
'status': 'ACTIVE',
+ 'server': {
+ 'id': 1,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
'links': [
{
- 'href': self.IMAGE_HREF % (1,),
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
'rel': 'bookmark',
- 'type': 'application/json',
},
],
-
},
}
@@ -1254,21 +1409,76 @@ class ImageXMLSerializationTest(test.TestCase):
actual = minidom.parseString(output.replace(" ", ""))
expected_server_href = self.SERVER_HREF
- expected_href = self.IMAGE_HREF % (1, )
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_href = self.IMAGE_HREF % 1
+ expected_bookmark = self.IMAGE_BOOKMARK % 1
expected_now = self.TIMESTAMP
expected = minidom.parseString("""
<image id="1"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
name="Image1"
- serverRef="%(expected_server_href)s"
updated="%(expected_now)s"
created="%(expected_now)s"
- status="ACTIVE"
- xmlns="http://docs.openstack.org/compute/api/v1.1">
- <links>
- <link href="%(expected_href)s" rel="bookmark"
- type="application/json" />
- </links>
- <metadata />
+ status="ACTIVE">
+ <server id="1">
+ <atom:link rel="self" href="%(expected_server_href)s"/>
+ <atom:link rel="bookmark" href="%(expected_server_bookmark)s"/>
+ </server>
+ <atom:link href="%(expected_href)s" rel="self"/>
+ <atom:link href="%(expected_bookmark)s" rel="bookmark"/>
+ </image>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_show_no_server(self):
+ serializer = images.ImageXMLSerializer()
+
+ fixture = {
+ 'image': {
+ 'id': 1,
+ 'name': 'Image1',
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ 'status': 'ACTIVE',
+ 'metadata': {
+ 'key1': 'value1',
+ },
+ 'links': [
+ {
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ }
+
+ output = serializer.serialize(fixture, 'show')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected_href = self.IMAGE_HREF % 1
+ expected_bookmark = self.IMAGE_BOOKMARK % 1
+ expected_now = self.TIMESTAMP
+ expected = minidom.parseString("""
+ <image id="1"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ name="Image1"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ status="ACTIVE">
+ <metadata>
+ <meta key="key1">
+ value1
+ </meta>
+ </metadata>
+ <atom:link href="%(expected_href)s" rel="self"/>
+ <atom:link href="%(expected_bookmark)s" rel="bookmark"/>
</image>
""".replace(" ", "") % (locals()))
@@ -1277,70 +1487,51 @@ class ImageXMLSerializationTest(test.TestCase):
def test_index(self):
serializer = images.ImageXMLSerializer()
- fixtures = {
+ fixture = {
'images': [
{
'id': 1,
'name': 'Image1',
- 'created': self.TIMESTAMP,
- 'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
- 'status': 'ACTIVE',
'links': [
{
- 'href': 'http://localhost/v1.1/images/1',
- 'rel': 'bookmark',
- 'type': 'application/json',
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
},
],
},
{
'id': 2,
- 'name': 'queued image',
- 'created': self.TIMESTAMP,
- 'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
- 'status': 'QUEUED',
+ 'name': 'Image2',
'links': [
{
- 'href': 'http://localhost/v1.1/images/2',
- 'rel': 'bookmark',
- 'type': 'application/json',
+ 'href': self.IMAGE_HREF % 2,
+ 'rel': 'self',
},
],
},
- ],
+ ]
}
- output = serializer.serialize(fixtures, 'index')
+ output = serializer.serialize(fixture, 'index')
actual = minidom.parseString(output.replace(" ", ""))
- expected_serverRef = self.SERVER_HREF
+ expected_server_href = self.SERVER_HREF
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_href = self.IMAGE_HREF % 1
+ expected_bookmark = self.IMAGE_BOOKMARK % 1
+ expected_href_two = self.IMAGE_HREF % 2
+ expected_bookmark_two = self.IMAGE_BOOKMARK % 2
expected_now = self.TIMESTAMP
expected = minidom.parseString("""
- <images xmlns="http://docs.openstack.org/compute/api/v1.1">
- <image id="1"
- name="Image1"
- serverRef="%(expected_serverRef)s"
- updated="%(expected_now)s"
- created="%(expected_now)s"
- status="ACTIVE">
- <links>
- <link href="http://localhost/v1.1/images/1" rel="bookmark"
- type="application/json" />
- </links>
- </image>
- <image id="2"
- name="queued image"
- serverRef="%(expected_serverRef)s"
- updated="%(expected_now)s"
- created="%(expected_now)s"
- status="QUEUED">
- <links>
- <link href="http://localhost/v1.1/images/2" rel="bookmark"
- type="application/json" />
- </links>
- </image>
+ <images
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom">
+ <image id="1" name="Image1">
+ <atom:link href="%(expected_href)s" rel="self"/>
+ </image>
+ <image id="2" name="Image2">
+ <atom:link href="%(expected_href_two)s" rel="self"/>
+ </image>
</images>
""".replace(" ", "") % (locals()))
@@ -1356,10 +1547,10 @@ class ImageXMLSerializationTest(test.TestCase):
output = serializer.serialize(fixtures, 'index')
actual = minidom.parseString(output.replace(" ", ""))
- expected_serverRef = self.SERVER_HREF
- expected_now = self.TIMESTAMP
expected = minidom.parseString("""
- <images xmlns="http://docs.openstack.org/compute/api/v1.1" />
+ <images
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom" />
""".replace(" ", "") % (locals()))
self.assertEqual(expected.toxml(), actual.toxml())
@@ -1367,84 +1558,102 @@ class ImageXMLSerializationTest(test.TestCase):
def test_detail(self):
serializer = images.ImageXMLSerializer()
- fixtures = {
+ fixture = {
'images': [
{
'id': 1,
'name': 'Image1',
'created': self.TIMESTAMP,
'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
'status': 'ACTIVE',
- 'metadata': {
- 'key1': 'value1',
- 'key2': 'value2',
+ 'server': {
+ 'id': 1,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
},
'links': [
{
- 'href': 'http://localhost/v1.1/images/1',
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
'rel': 'bookmark',
- 'type': 'application/json',
},
],
},
{
'id': 2,
- 'name': 'queued image',
+ 'name': 'Image2',
'created': self.TIMESTAMP,
'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
- 'metadata': {},
- 'status': 'QUEUED',
+ 'status': 'SAVING',
+ 'progress': 80,
+ 'metadata': {
+ 'key1': 'value1',
+ },
'links': [
{
- 'href': 'http://localhost/v1.1/images/2',
+ 'href': self.IMAGE_HREF % 2,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 2,
'rel': 'bookmark',
- 'type': 'application/json',
},
],
},
- ],
+ ]
}
- output = serializer.serialize(fixtures, 'detail')
+ output = serializer.serialize(fixture, 'detail')
actual = minidom.parseString(output.replace(" ", ""))
- expected_serverRef = self.SERVER_HREF
+ expected_server_href = self.SERVER_HREF
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_href = self.IMAGE_HREF % 1
+ expected_bookmark = self.IMAGE_BOOKMARK % 1
+ expected_href_two = self.IMAGE_HREF % 2
+ expected_bookmark_two = self.IMAGE_BOOKMARK % 2
expected_now = self.TIMESTAMP
expected = minidom.parseString("""
- <images xmlns="http://docs.openstack.org/compute/api/v1.1">
- <image id="1"
- name="Image1"
- serverRef="%(expected_serverRef)s"
- updated="%(expected_now)s"
- created="%(expected_now)s"
- status="ACTIVE">
- <links>
- <link href="http://localhost/v1.1/images/1" rel="bookmark"
- type="application/json" />
- </links>
- <metadata>
- <meta key="key2">
- value2
- </meta>
- <meta key="key1">
- value1
- </meta>
- </metadata>
- </image>
- <image id="2"
- name="queued image"
- serverRef="%(expected_serverRef)s"
- updated="%(expected_now)s"
- created="%(expected_now)s"
- status="QUEUED">
- <links>
- <link href="http://localhost/v1.1/images/2" rel="bookmark"
- type="application/json" />
- </links>
- <metadata />
- </image>
+ <images
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom">
+ <image id="1"
+ name="Image1"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ status="ACTIVE">
+ <server id="1">
+ <atom:link rel="self" href="%(expected_server_href)s"/>
+ <atom:link rel="bookmark" href="%(expected_server_bookmark)s"/>
+ </server>
+ <atom:link href="%(expected_href)s" rel="self"/>
+ <atom:link href="%(expected_bookmark)s" rel="bookmark"/>
+ </image>
+ <image id="2"
+ name="Image2"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ status="SAVING"
+ progress="80">
+ <metadata>
+ <meta key="key1">
+ value1
+ </meta>
+ </metadata>
+ <atom:link href="%(expected_href_two)s" rel="self"/>
+ <atom:link href="%(expected_bookmark_two)s" rel="bookmark"/>
+ </image>
</images>
""".replace(" ", "") % (locals()))
@@ -1459,16 +1668,32 @@ class ImageXMLSerializationTest(test.TestCase):
'name': 'Image1',
'created': self.TIMESTAMP,
'updated': self.TIMESTAMP,
- 'serverRef': self.SERVER_HREF,
- 'status': 'ACTIVE',
+ 'status': 'SAVING',
+ 'progress': 80,
+ 'server': {
+ 'id': 1,
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
'metadata': {
'key1': 'value1',
},
'links': [
{
- 'href': self.IMAGE_HREF % (1,),
+ 'href': self.IMAGE_HREF % 1,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.IMAGE_BOOKMARK % 1,
'rel': 'bookmark',
- 'type': 'application/json',
},
],
},
@@ -1478,25 +1703,30 @@ class ImageXMLSerializationTest(test.TestCase):
actual = minidom.parseString(output.replace(" ", ""))
expected_server_href = self.SERVER_HREF
- expected_href = self.IMAGE_HREF % (1, )
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_href = self.IMAGE_HREF % 1
+ expected_bookmark = self.IMAGE_BOOKMARK % 1
expected_now = self.TIMESTAMP
expected = minidom.parseString("""
<image id="1"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
name="Image1"
- serverRef="%(expected_server_href)s"
updated="%(expected_now)s"
created="%(expected_now)s"
- status="ACTIVE"
- xmlns="http://docs.openstack.org/compute/api/v1.1">
- <links>
- <link href="%(expected_href)s" rel="bookmark"
- type="application/json" />
- </links>
+ status="SAVING"
+ progress="80">
+ <server id="1">
+ <atom:link rel="self" href="%(expected_server_href)s"/>
+ <atom:link rel="bookmark" href="%(expected_server_bookmark)s"/>
+ </server>
<metadata>
<meta key="key1">
value1
</meta>
</metadata>
+ <atom:link href="%(expected_href)s" rel="self"/>
+ <atom:link href="%(expected_bookmark)s" rel="bookmark"/>
</image>
""".replace(" ", "") % (locals()))
diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py
index 08522f720..0c8d6c313 100644
--- a/nova/tests/integrated/test_servers.py
+++ b/nova/tests/integrated/test_servers.py
@@ -209,7 +209,6 @@ class ServersTest(integrated_helpers._IntegratedTestBase):
network_list = [{'id': 1, 'fixed_ip': '10.0.0.3'},
{'id': 2, 'fixed_ip': '10.0.0.12'}]
-
server['networks'] = network_list
post = {'server': server}
@@ -326,7 +325,6 @@ class ServersTest(integrated_helpers._IntegratedTestBase):
self.assertRaises(client.OpenStackApiException,
self.api.post_server, post)
-
def test_create_server_with_networks_empty_fixed_ip(self):
"""Creates a server with networks."""