summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin L. Mitchell <kevin.mitchell@rackspace.com>2011-07-29 18:59:33 +0000
committerKevin L. Mitchell <kevin.mitchell@rackspace.com>2011-07-29 18:59:33 +0000
commit62c7ca622a42aaed9a4f23e8fc2167655b2ff58f (patch)
tree5d62b83e53098339f20f003ee99d8c0760aed7ce
parentc0355038b462cfd75b423a535601c4463c68f80f (diff)
parentab0c38efa5440347c3c75171e703e010023affe2 (diff)
pull-up from trunk; fix problem obscuring context module with context param; fix conflicts and no-longer-skipped tests
-rw-r--r--nova/api/openstack/common.py82
-rw-r--r--nova/api/openstack/create_instance_helper.py36
-rw-r--r--nova/api/openstack/image_metadata.py88
-rw-r--r--nova/api/openstack/images.py2
-rw-r--r--nova/api/openstack/servers.py142
-rw-r--r--nova/api/openstack/views/servers.py15
-rw-r--r--nova/api/openstack/wsgi.py9
-rw-r--r--nova/auth/dbdriver.py2
-rw-r--r--nova/compute/manager.py25
-rw-r--r--nova/tests/api/openstack/test_common.py201
-rw-r--r--nova/tests/api/openstack/test_extensions.py38
-rw-r--r--nova/tests/api/openstack/test_image_metadata.py201
-rw-r--r--nova/tests/api/openstack/test_limits.py14
-rw-r--r--nova/tests/api/openstack/test_servers.py831
-rw-r--r--nova/tests/integrated/test_servers.py1
-rw-r--r--nova/tests/test_compute.py6
-rw-r--r--nova/tests/test_db_api.py4
-rw-r--r--nova/tests/test_libvirt.py2
-rw-r--r--nova/tests/test_vmwareapi.py10
-rw-r--r--nova/tests/test_xenapi.py79
-rw-r--r--nova/virt/driver.py9
-rw-r--r--nova/virt/fake.py4
-rw-r--r--nova/virt/hyperv.py2
-rw-r--r--nova/virt/libvirt/connection.py4
-rw-r--r--nova/virt/vmwareapi/vmops.py4
-rw-r--r--nova/virt/vmwareapi_conn.py8
-rw-r--r--nova/virt/xenapi/vm_utils.py22
-rw-r--r--nova/virt/xenapi/vmops.py54
-rw-r--r--nova/virt/xenapi_conn.py16
29 files changed, 1449 insertions, 462 deletions
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index bd14a1389..efa4ab385 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -17,12 +17,14 @@
import re
from urlparse import urlparse
+from xml.dom import minidom
import webob
from nova import exception
from nova import flags
from nova import log as logging
+from nova.api.openstack import wsgi
LOG = logging.getLogger('nova.api.openstack.common')
@@ -192,3 +194,83 @@ def get_version_from_href(href):
except IndexError:
version = '1.0'
return version
+
+
+class MetadataXMLDeserializer(wsgi.MetadataXMLDeserializer):
+
+ def _extract_metadata_container(self, datastring):
+ dom = minidom.parseString(datastring)
+ metadata_node = self.find_first_child_named(dom, "metadata")
+ metadata = self.extract_metadata(metadata_node)
+ return {'body': {'metadata': metadata}}
+
+ def create(self, datastring):
+ return self._extract_metadata_container(datastring)
+
+ def update_all(self, datastring):
+ return self._extract_metadata_container(datastring)
+
+ def update(self, datastring):
+ dom = minidom.parseString(datastring)
+ metadata_item = self.extract_metadata(dom)
+ return {'body': {'meta': metadata_item}}
+
+
+class MetadataHeadersSerializer(wsgi.ResponseHeadersSerializer):
+
+ def delete(self, response, data):
+ response.status_int = 204
+
+
+class MetadataXMLSerializer(wsgi.XMLDictSerializer):
+ def __init__(self, xmlns=wsgi.XMLNS_V11):
+ super(MetadataXMLSerializer, self).__init__(xmlns=xmlns)
+
+ def _meta_item_to_xml(self, doc, key, value):
+ node = doc.createElement('meta')
+ doc.appendChild(node)
+ node.setAttribute('key', '%s' % key)
+ text = doc.createTextNode('%s' % value)
+ node.appendChild(text)
+ return node
+
+ def meta_list_to_xml(self, xml_doc, meta_items):
+ container_node = xml_doc.createElement('metadata')
+ for (key, value) in meta_items:
+ item_node = self._meta_item_to_xml(xml_doc, key, value)
+ container_node.appendChild(item_node)
+ return container_node
+
+ def _meta_list_to_xml_string(self, metadata_dict):
+ xml_doc = minidom.Document()
+ items = metadata_dict['metadata'].items()
+ container_node = self.meta_list_to_xml(xml_doc, items)
+ xml_doc.appendChild(container_node)
+ self._add_xmlns(container_node)
+ return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
+
+ def index(self, metadata_dict):
+ return self._meta_list_to_xml_string(metadata_dict)
+
+ def create(self, metadata_dict):
+ return self._meta_list_to_xml_string(metadata_dict)
+
+ def update_all(self, metadata_dict):
+ return self._meta_list_to_xml_string(metadata_dict)
+
+ def _meta_item_to_xml_string(self, meta_item_dict):
+ xml_doc = minidom.Document()
+ item_key, item_value = meta_item_dict.items()[0]
+ item_node = self._meta_item_to_xml(xml_doc, item_key, item_value)
+ xml_doc.appendChild(item_node)
+ self._add_xmlns(item_node)
+ return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
+
+ def show(self, meta_item_dict):
+ return self._meta_item_to_xml_string(meta_item_dict['meta'])
+
+ def update(self, meta_item_dict):
+ return self._meta_item_to_xml_string(meta_item_dict['meta'])
+
+ def default(self, *args, **kwargs):
+ return ''
diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py
index f8317565e..1342397c4 100644
--- a/nova/api/openstack/create_instance_helper.py
+++ b/nova/api/openstack/create_instance_helper.py
@@ -188,7 +188,7 @@ class CreateInstanceHelper(object):
Overrides normal behavior in the case of xml content
"""
if request.content_type == "application/xml":
- deserializer = ServerCreateRequestXMLDeserializer()
+ deserializer = ServerXMLDeserializer()
return deserializer.deserialize(request.body)
else:
return self._deserialize(request.body, request.get_content_type())
@@ -303,29 +303,29 @@ class ServerXMLDeserializer(wsgi.MetadataXMLDeserializer):
"""Marshal the server attribute of a parsed request"""
server = {}
server_node = self.find_first_child_named(node, 'server')
- for attr in ["name", "imageId", "flavorId", "imageRef", "flavorRef"]:
+
+ attributes = ["name", "imageId", "flavorId", "imageRef",
+ "flavorRef", "adminPass"]
+ for attr in attributes:
if server_node.getAttribute(attr):
server[attr] = server_node.getAttribute(attr)
+
metadata_node = self.find_first_child_named(server_node, "metadata")
- metadata = self.extract_metadata(metadata_node)
- if metadata is not None:
- server["metadata"] = metadata
- personality = self._extract_personality(server_node)
- if personality is not None:
- server["personality"] = personality
+ server["metadata"] = self.extract_metadata(metadata_node)
+
+ server["personality"] = self._extract_personality(server_node)
+
return server
def _extract_personality(self, server_node):
"""Marshal the personality attribute of a parsed request"""
- personality_node = \
- self.find_first_child_named(server_node, "personality")
- if personality_node is None:
- return None
+ node = self.find_first_child_named(server_node, "personality")
personality = []
- for file_node in self.find_children_named(personality_node, "file"):
- item = {}
- if file_node.hasAttribute("path"):
- item["path"] = file_node.getAttribute("path")
- item["contents"] = self.extract_text(file_node)
- personality.append(item)
+ if node is not None:
+ for file_node in self.find_children_named(node, "file"):
+ item = {}
+ if file_node.hasAttribute("path"):
+ item["path"] = file_node.getAttribute("path")
+ item["contents"] = self.extract_text(file_node)
+ personality.append(item)
return personality
diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py
index ee181c924..aaf64a123 100644
--- a/nova/api/openstack/image_metadata.py
+++ b/nova/api/openstack/image_metadata.py
@@ -16,12 +16,12 @@
# under the License.
from webob import exc
-from xml.dom import minidom
from nova import flags
from nova import image
from nova import quota
from nova import utils
+from nova.api.openstack import common
from nova.api.openstack import wsgi
@@ -118,95 +118,15 @@ class Controller(object):
self.image_service.update(context, image_id, img, None)
-class ImageMetadataXMLDeserializer(wsgi.MetadataXMLDeserializer):
-
- def _extract_metadata_container(self, datastring):
- dom = minidom.parseString(datastring)
- metadata_node = self.find_first_child_named(dom, "metadata")
- metadata = self.extract_metadata(metadata_node)
- return {'body': {'metadata': metadata}}
-
- def create(self, datastring):
- return self._extract_metadata_container(datastring)
-
- def update_all(self, datastring):
- return self._extract_metadata_container(datastring)
-
- def update(self, datastring):
- dom = minidom.parseString(datastring)
- metadata_item = self.extract_metadata(dom)
- return {'body': {'meta': metadata_item}}
-
-
-class HeadersSerializer(wsgi.ResponseHeadersSerializer):
-
- def delete(self, response, data):
- response.status_int = 204
-
-
-class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer):
- def __init__(self, xmlns=wsgi.XMLNS_V11):
- super(ImageMetadataXMLSerializer, self).__init__(xmlns=xmlns)
-
- def _meta_item_to_xml(self, doc, key, value):
- node = doc.createElement('meta')
- doc.appendChild(node)
- node.setAttribute('key', '%s' % key)
- text = doc.createTextNode('%s' % value)
- node.appendChild(text)
- return node
-
- def meta_list_to_xml(self, xml_doc, meta_items):
- container_node = xml_doc.createElement('metadata')
- for (key, value) in meta_items:
- item_node = self._meta_item_to_xml(xml_doc, key, value)
- container_node.appendChild(item_node)
- return container_node
-
- def _meta_list_to_xml_string(self, metadata_dict):
- xml_doc = minidom.Document()
- items = metadata_dict['metadata'].items()
- container_node = self.meta_list_to_xml(xml_doc, items)
- xml_doc.appendChild(container_node)
- self._add_xmlns(container_node)
- return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
-
- def index(self, metadata_dict):
- return self._meta_list_to_xml_string(metadata_dict)
-
- def create(self, metadata_dict):
- return self._meta_list_to_xml_string(metadata_dict)
-
- def update_all(self, metadata_dict):
- return self._meta_list_to_xml_string(metadata_dict)
-
- def _meta_item_to_xml_string(self, meta_item_dict):
- xml_doc = minidom.Document()
- item_key, item_value = meta_item_dict.items()[0]
- item_node = self._meta_item_to_xml(xml_doc, item_key, item_value)
- xml_doc.appendChild(item_node)
- self._add_xmlns(item_node)
- return xml_doc.toprettyxml(indent=' ', encoding='UTF-8')
-
- def show(self, meta_item_dict):
- return self._meta_item_to_xml_string(meta_item_dict['meta'])
-
- def update(self, meta_item_dict):
- return self._meta_item_to_xml_string(meta_item_dict['meta'])
-
- def default(self, *args, **kwargs):
- return ''
-
-
def create_resource():
- headers_serializer = HeadersSerializer()
+ headers_serializer = common.MetadataHeadersSerializer()
body_deserializers = {
- 'application/xml': ImageMetadataXMLDeserializer(),
+ 'application/xml': common.MetadataXMLDeserializer(),
}
body_serializers = {
- 'application/xml': ImageMetadataXMLSerializer(),
+ 'application/xml': common.MetadataXMLSerializer(),
}
serializer = wsgi.ResponseSerializer(body_serializers, headers_serializer)
deserializer = wsgi.RequestDeserializer(body_deserializers)
diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py
index 30e4fd389..9ba8b639e 100644
--- a/nova/api/openstack/images.py
+++ b/nova/api/openstack/images.py
@@ -284,7 +284,7 @@ class ImageXMLSerializer(wsgi.XMLDictSerializer):
xmlns = wsgi.XMLNS_V11
def __init__(self):
- self.metadata_serializer = image_metadata.ImageMetadataXMLSerializer()
+ self.metadata_serializer = common.MetadataXMLSerializer()
def _image_to_xml(self, xml_doc, image):
image_node = xml_doc.createElement('image')
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index d7cabb067..f6841318d 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -18,6 +18,7 @@ import traceback
from webob import exc
import webob
+from xml.dom import minidom
from nova import compute
from nova import db
@@ -27,6 +28,7 @@ from nova import log as logging
from nova import utils
from nova.api.openstack import common
from nova.api.openstack import create_instance_helper as helper
+from nova.api.openstack import ips
import nova.api.openstack.views.addresses
import nova.api.openstack.views.flavors
import nova.api.openstack.views.images
@@ -480,11 +482,20 @@ class ControllerV11(Controller):
raise exc.HTTPNotFound()
def _image_ref_from_req_data(self, data):
- return data['server']['imageRef']
+ try:
+ return data['server']['imageRef']
+ except (TypeError, KeyError):
+ msg = _("Missing imageRef attribute")
+ raise exc.HTTPBadRequest(explanation=msg)
def _flavor_id_from_req_data(self, data):
- href = data['server']['flavorRef']
- return common.get_id_from_href(href)
+ try:
+ flavor_ref = data['server']['flavorRef']
+ except (TypeError, KeyError):
+ msg = _("Missing flavorRef attribute")
+ raise exc.HTTPBadRequest(explanation=msg)
+
+ return common.get_id_from_href(flavor_ref)
def _build_view(self, req, instance, is_detail=False):
base_url = req.application_url
@@ -599,6 +610,123 @@ class HeadersSerializer(wsgi.ResponseHeadersSerializer):
response.status_int = 204
+class ServerXMLSerializer(wsgi.XMLDictSerializer):
+
+ xmlns = wsgi.XMLNS_V11
+
+ def __init__(self):
+ self.metadata_serializer = common.MetadataXMLSerializer()
+ self.addresses_serializer = ips.IPXMLSerializer()
+
+ def _create_basic_entity_node(self, xml_doc, id, links, name):
+ basic_node = xml_doc.createElement(name)
+ basic_node.setAttribute('id', str(id))
+ link_nodes = self._create_link_nodes(xml_doc, links)
+ for link_node in link_nodes:
+ basic_node.appendChild(link_node)
+ return basic_node
+
+ def _create_metadata_node(self, xml_doc, metadata):
+ return self.metadata_serializer.meta_list_to_xml(xml_doc, metadata)
+
+ def _create_addresses_node(self, xml_doc, addresses):
+ return self.addresses_serializer.networks_to_xml(xml_doc, addresses)
+
+ def _add_server_attributes(self, node, server):
+ node.setAttribute('id', str(server['id']))
+ node.setAttribute('uuid', str(server['uuid']))
+ node.setAttribute('hostId', str(server['hostId']))
+ node.setAttribute('name', server['name'])
+ node.setAttribute('created', str(server['created']))
+ node.setAttribute('updated', str(server['updated']))
+ node.setAttribute('status', server['status'])
+ if 'progress' in server:
+ node.setAttribute('progress', str(server['progress']))
+
+ def _server_to_xml(self, xml_doc, server):
+ server_node = xml_doc.createElement('server')
+ server_node.setAttribute('id', str(server['id']))
+ server_node.setAttribute('name', server['name'])
+ 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 _server_to_xml_detailed(self, xml_doc, server):
+ server_node = xml_doc.createElement('server')
+ self._add_server_attributes(server_node, server)
+
+ link_nodes = self._create_link_nodes(xml_doc,
+ server['links'])
+ for link_node in link_nodes:
+ server_node.appendChild(link_node)
+
+ if 'image' in server:
+ image_node = self._create_basic_entity_node(xml_doc,
+ server['image']['id'],
+ server['image']['links'],
+ 'image')
+ server_node.appendChild(image_node)
+
+ if 'flavor' in server:
+ flavor_node = self._create_basic_entity_node(xml_doc,
+ server['flavor']['id'],
+ server['flavor']['links'],
+ 'flavor')
+ server_node.appendChild(flavor_node)
+
+ metadata = server.get('metadata', {}).items()
+ if len(metadata) > 0:
+ metadata_node = self._create_metadata_node(xml_doc, metadata)
+ server_node.appendChild(metadata_node)
+
+ addresses_node = self._create_addresses_node(xml_doc,
+ server['addresses'])
+ server_node.appendChild(addresses_node)
+
+ return server_node
+
+ def _server_list_to_xml(self, xml_doc, servers, detailed):
+ container_node = xml_doc.createElement('servers')
+ if detailed:
+ server_to_xml = self._server_to_xml_detailed
+ else:
+ server_to_xml = self._server_to_xml
+
+ for server in servers:
+ item_node = server_to_xml(xml_doc, server)
+ container_node.appendChild(item_node)
+ return container_node
+
+ def index(self, servers_dict):
+ xml_doc = minidom.Document()
+ node = self._server_list_to_xml(xml_doc,
+ servers_dict['servers'],
+ detailed=False)
+ return self.to_xml_string(node, True)
+
+ def detail(self, servers_dict):
+ xml_doc = minidom.Document()
+ node = self._server_list_to_xml(xml_doc,
+ servers_dict['servers'],
+ detailed=True)
+ return self.to_xml_string(node, True)
+
+ def show(self, server_dict):
+ xml_doc = minidom.Document()
+ node = self._server_to_xml_detailed(xml_doc,
+ server_dict['server'])
+ return self.to_xml_string(node, True)
+
+ def create(self, server_dict):
+ xml_doc = minidom.Document()
+ node = self._server_to_xml_detailed(xml_doc,
+ server_dict['server'])
+ node.setAttribute('adminPass', server_dict['server']['adminPass'])
+ return self.to_xml_string(node, True)
+
+
def create_resource(version='1.0'):
controller = {
'1.0': ControllerV10,
@@ -628,9 +756,13 @@ def create_resource(version='1.0'):
headers_serializer = HeadersSerializer()
+ xml_serializer = {
+ '1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10),
+ '1.1': ServerXMLSerializer(),
+ }[version]
+
body_serializers = {
- 'application/xml': wsgi.XMLDictSerializer(metadata=metadata,
- xmlns=xmlns),
+ 'application/xml': xml_serializer,
}
body_deserializers = {
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index be25e1e40..659a43522 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import datetime
import hashlib
import os
@@ -149,8 +150,10 @@ class ViewBuilderV11(ViewBuilder):
def _build_detail(self, inst):
response = super(ViewBuilderV11, self)._build_detail(inst)
- response['server']['created'] = inst['created_at']
- response['server']['updated'] = inst['updated_at']
+ response['server']['created'] = \
+ self._convert_timeformat(inst['created_at'])
+ response['server']['updated'] = \
+ self._convert_timeformat(inst['updated_at'])
if 'status' in response['server']:
if response['server']['status'] == "ACTIVE":
response['server']['progress'] = 100
@@ -221,3 +224,11 @@ class ViewBuilderV11(ViewBuilder):
"""Create an url that refers to a specific flavor id."""
return os.path.join(common.remove_version_from_href(self.base_url),
"servers", str(server_id))
+
+ def _convert_timeformat(self, date_time):
+ """Converts the given time into the common time format
+
+ :param date_time: the datetime object to convert
+
+ """
+ return date_time.strftime(utils.TIME_FORMAT)
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index a28443d12..53dab22e8 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -165,12 +165,11 @@ class MetadataXMLDeserializer(XMLDeserializer):
def extract_metadata(self, metadata_node):
"""Marshal the metadata attribute of a parsed request"""
- if metadata_node is None:
- return None
metadata = {}
- for meta_node in self.find_children_named(metadata_node, "meta"):
- key = meta_node.getAttribute("key")
- metadata[key] = self.extract_text(meta_node)
+ if metadata_node is not None:
+ for meta_node in self.find_children_named(metadata_node, "meta"):
+ key = meta_node.getAttribute("key")
+ metadata[key] = self.extract_text(meta_node)
return metadata
diff --git a/nova/auth/dbdriver.py b/nova/auth/dbdriver.py
index 0158c4e23..c6d81ee04 100644
--- a/nova/auth/dbdriver.py
+++ b/nova/auth/dbdriver.py
@@ -127,7 +127,7 @@ class DbDriver(object):
try:
project = db.project_create(context.get_admin_context(), values)
- except (exception.Duplicate, exception.DBError):
+ except exception.DBError:
raise exception.ProjectExists(project=name)
for member in members:
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 83a218580..56331f86b 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -747,7 +747,7 @@ class ComputeManager(manager.SchedulerDependentManager):
local_gb=instance_type['local_gb'],
instance_type_id=instance_type['id']))
- self.driver.revert_resize(instance_ref)
+ self.driver.revert_migration(instance_ref)
self.db.migration_update(context, migration_id,
{'status': 'reverted'})
usage_info = utils.usage_from_instance(instance_ref)
@@ -845,21 +845,26 @@ class ComputeManager(manager.SchedulerDependentManager):
"""
migration_ref = self.db.migration_get(context, migration_id)
+
+ resize_instance = False
instance_ref = self.db.instance_get_by_uuid(context,
migration_ref.instance_uuid)
- instance_type = self.db.instance_type_get_by_flavor_id(context,
- migration_ref['new_flavor_id'])
- self.db.instance_update(context, instance_ref.uuid,
- dict(instance_type_id=instance_type['id'],
- memory_mb=instance_type['memory_mb'],
- vcpus=instance_type['vcpus'],
- local_gb=instance_type['local_gb']))
+ if migration_ref['old_flavor_id'] != migration_ref['new_flavor_id']:
+ instance_type = self.db.instance_type_get_by_flavor_id(context,
+ migration_ref['new_flavor_id'])
+ self.db.instance_update(context, instance_ref.uuid,
+ dict(instance_type_id=instance_type['id'],
+ memory_mb=instance_type['memory_mb'],
+ vcpus=instance_type['vcpus'],
+ local_gb=instance_type['local_gb']))
+ resize_instance = True
instance_ref = self.db.instance_get_by_uuid(context,
instance_ref.uuid)
+
network_info = self._get_instance_nw_info(context, instance_ref)
- self.driver.finish_resize(context, instance_ref, disk_info,
- network_info)
+ self.driver.finish_migration(context, instance_ref, disk_info,
+ network_info, resize_instance)
self.db.migration_update(context, migration_id,
{'status': 'finished', })
diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py
index f09270b34..0b76841f0 100644
--- a/nova/tests/api/openstack/test_common.py
+++ b/nova/tests/api/openstack/test_common.py
@@ -20,6 +20,7 @@ Test suites for 'common' code used throughout the OpenStack HTTP API.
"""
import webob.exc
+import xml.dom.minidom as minidom
from webob import Request
@@ -265,3 +266,203 @@ class MiscFunctionsTest(test.TestCase):
expected = '1.0'
actual = common.get_version_from_href(fixture)
self.assertEqual(actual, expected)
+
+
+class MetadataXMLDeserializationTest(test.TestCase):
+
+ deserializer = common.MetadataXMLDeserializer()
+
+ def test_create(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key='123'>asdf</meta>
+ <meta key='567'>jkl;</meta>
+ </metadata>"""
+ output = self.deserializer.deserialize(request_body, 'create')
+ expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
+ self.assertEquals(output, expected)
+
+ def test_create_empty(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"/>"""
+ output = self.deserializer.deserialize(request_body, 'create')
+ expected = {"body": {"metadata": {}}}
+ self.assertEquals(output, expected)
+
+ def test_update_all(self):
+ request_body = """
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key='123'>asdf</meta>
+ <meta key='567'>jkl;</meta>
+ </metadata>"""
+ output = self.deserializer.deserialize(request_body, 'update_all')
+ expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
+ self.assertEquals(output, expected)
+
+ def test_update(self):
+ request_body = """
+ <meta xmlns="http://docs.openstack.org/compute/api/v1.1"
+ key='123'>asdf</meta>"""
+ output = self.deserializer.deserialize(request_body, 'update')
+ expected = {"body": {"meta": {"123": "asdf"}}}
+ self.assertEquals(output, expected)
+
+
+class MetadataXMLSerializationTest(test.TestCase):
+
+ def test_index(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ 'one': 'two',
+ 'three': 'four',
+ },
+ }
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="three">
+ four
+ </meta>
+ <meta key="one">
+ two
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_index_null(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ None: None,
+ },
+ }
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="None">
+ None
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_index_unicode(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ u'three': u'Jos\xe9',
+ },
+ }
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString(u"""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="three">
+ Jos\xe9
+ </meta>
+ </metadata>
+ """.encode("UTF-8").replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_show(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'meta': {
+ 'one': 'two',
+ },
+ }
+ output = serializer.serialize(fixture, 'show')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
+ two
+ </meta>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_update_all(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ 'key6': 'value6',
+ 'key4': 'value4',
+ },
+ }
+ output = serializer.serialize(fixture, 'update_all')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="key6">
+ value6
+ </meta>
+ <meta key="key4">
+ value4
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_update_item(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'meta': {
+ 'one': 'two',
+ },
+ }
+ output = serializer.serialize(fixture, 'update')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
+ two
+ </meta>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_create(self):
+ serializer = common.MetadataXMLSerializer()
+ fixture = {
+ 'metadata': {
+ 'key9': 'value9',
+ 'key2': 'value2',
+ 'key1': 'value1',
+ },
+ }
+ output = serializer.serialize(fixture, 'create')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
+ <meta key="key2">
+ value2
+ </meta>
+ <meta key="key9">
+ value9
+ </meta>
+ <meta key="key1">
+ value1
+ </meta>
+ </metadata>
+ """.replace(" ", ""))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_delete(self):
+ serializer = common.MetadataXMLSerializer()
+ output = serializer.serialize(None, 'delete')
+ self.assertEqual(output, '')
diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py
index d459c694f..bf2d0368f 100644
--- a/nova/tests/api/openstack/test_extensions.py
+++ b/nova/tests/api/openstack/test_extensions.py
@@ -109,8 +109,8 @@ class ExtensionControllerTest(unittest.TestCase):
'updated': '2011-01-22T13:25:27-06:00',
'description': 'The Fox In Socks Extension',
'alias': 'FOXNSOX',
- 'links': []
- }
+ 'links': [],
+ },
)
def test_get_extension_json(self):
@@ -127,8 +127,8 @@ class ExtensionControllerTest(unittest.TestCase):
"updated": "2011-01-22T13:25:27-06:00",
"description": "The Fox In Socks Extension",
"alias": "FOXNSOX",
- "links": []
- }
+ "links": [],
+ },
)
def test_list_extensions_xml(self):
@@ -342,15 +342,15 @@ class ExtensionsXMLSerializerTest(unittest.TestCase):
{
'rel': 'describedby',
'type': 'application/pdf',
- 'href': 'http://docs.rack.com/servers/api/ext/cs.pdf'
+ 'href': 'http://docs.rack.com/servers/api/ext/cs.pdf',
},
{
'rel': 'describedby',
'type': 'application/vnd.sun.wadl+xml',
- 'href': 'http://docs.rack.com/servers/api/ext/cs.wadl'
- }
- ]
- }
+ 'href': 'http://docs.rack.com/servers/api/ext/cs.wadl',
+ },
+ ],
+ },
}
xml = serializer.serialize(data, 'show')
@@ -382,14 +382,14 @@ class ExtensionsXMLSerializerTest(unittest.TestCase):
{
"rel": "describedby",
"type": "application/pdf",
- "href": "http://foo.com/api/ext/cs-pie.pdf"
+ "href": "http://foo.com/api/ext/cs-pie.pdf",
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
- "href": "http://foo.com/api/ext/cs-pie.wadl"
- }
- ]
+ "href": "http://foo.com/api/ext/cs-pie.wadl",
+ },
+ ],
},
{
"name": "Cloud Block Storage",
@@ -401,16 +401,16 @@ class ExtensionsXMLSerializerTest(unittest.TestCase):
{
"rel": "describedby",
"type": "application/pdf",
- "href": "http://foo.com/api/ext/cs-cbs.pdf"
+ "href": "http://foo.com/api/ext/cs-cbs.pdf",
},
{
"rel": "describedby",
"type": "application/vnd.sun.wadl+xml",
- "href": "http://foo.com/api/ext/cs-cbs.wadl"
- }
- ]
- }
- ]
+ "href": "http://foo.com/api/ext/cs-cbs.wadl",
+ },
+ ],
+ },
+ ],
}
xml = serializer.serialize(data, 'index')
diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py
index 31ca18497..c9137cc24 100644
--- a/nova/tests/api/openstack/test_image_metadata.py
+++ b/nova/tests/api/openstack/test_image_metadata.py
@@ -19,7 +19,6 @@ import json
import stubout
import unittest
import webob
-import xml.dom.minidom as minidom
from nova import flags
@@ -252,203 +251,3 @@ class ImageMetaDataTest(test.TestCase):
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(400, res.status_int)
-
-
-class ImageMetadataXMLDeserializationTest(test.TestCase):
-
- deserializer = openstack.image_metadata.ImageMetadataXMLDeserializer()
-
- def test_create(self):
- request_body = """
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key='123'>asdf</meta>
- <meta key='567'>jkl;</meta>
- </metadata>"""
- output = self.deserializer.deserialize(request_body, 'create')
- expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
- self.assertEquals(output, expected)
-
- def test_create_empty(self):
- request_body = """
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1"/>"""
- output = self.deserializer.deserialize(request_body, 'create')
- expected = {"body": {"metadata": {}}}
- self.assertEquals(output, expected)
-
- def test_update_all(self):
- request_body = """
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key='123'>asdf</meta>
- <meta key='567'>jkl;</meta>
- </metadata>"""
- output = self.deserializer.deserialize(request_body, 'update_all')
- expected = {"body": {"metadata": {"123": "asdf", "567": "jkl;"}}}
- self.assertEquals(output, expected)
-
- def test_update(self):
- request_body = """
- <meta xmlns="http://docs.openstack.org/compute/api/v1.1"
- key='123'>asdf</meta>"""
- output = self.deserializer.deserialize(request_body, 'update')
- expected = {"body": {"meta": {"123": "asdf"}}}
- self.assertEquals(output, expected)
-
-
-class ImageMetadataXMLSerializationTest(test.TestCase):
-
- def test_index(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- 'one': 'two',
- 'three': 'four',
- },
- }
- output = serializer.serialize(fixture, 'index')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="three">
- four
- </meta>
- <meta key="one">
- two
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_index_null(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- None: None,
- },
- }
- output = serializer.serialize(fixture, 'index')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="None">
- None
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_index_unicode(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- u'three': u'Jos\xe9',
- },
- }
- output = serializer.serialize(fixture, 'index')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString(u"""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="three">
- Jos\xe9
- </meta>
- </metadata>
- """.encode("UTF-8").replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_show(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'meta': {
- 'one': 'two',
- },
- }
- output = serializer.serialize(fixture, 'show')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
- two
- </meta>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_update_all(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- 'key6': 'value6',
- 'key4': 'value4',
- },
- }
- output = serializer.serialize(fixture, 'update_all')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="key6">
- value6
- </meta>
- <meta key="key4">
- value4
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_update_item(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'meta': {
- 'one': 'two',
- },
- }
- output = serializer.serialize(fixture, 'update')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <meta xmlns="http://docs.openstack.org/compute/api/v1.1" key="one">
- two
- </meta>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_create(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- fixture = {
- 'metadata': {
- 'key9': 'value9',
- 'key2': 'value2',
- 'key1': 'value1',
- },
- }
- output = serializer.serialize(fixture, 'create')
- actual = minidom.parseString(output.replace(" ", ""))
-
- expected = minidom.parseString("""
- <metadata xmlns="http://docs.openstack.org/compute/api/v1.1">
- <meta key="key2">
- value2
- </meta>
- <meta key="key9">
- value9
- </meta>
- <meta key="key1">
- value1
- </meta>
- </metadata>
- """.replace(" ", ""))
-
- self.assertEqual(expected.toxml(), actual.toxml())
-
- def test_delete(self):
- serializer = openstack.image_metadata.ImageMetadataXMLSerializer()
- output = serializer.serialize(None, 'delete')
- self.assertEqual(output, '')
diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py
index 8a3fe681a..6c3d531e3 100644
--- a/nova/tests/api/openstack/test_limits.py
+++ b/nova/tests/api/openstack/test_limits.py
@@ -920,7 +920,7 @@ class LimitsViewBuilderV11Test(test.TestCase):
"verb": "POST",
"remaining": 2,
"unit": "MINUTE",
- "resetTime": 1311272226
+ "resetTime": 1311272226,
},
{
"URI": "*/servers",
@@ -929,7 +929,7 @@ class LimitsViewBuilderV11Test(test.TestCase):
"verb": "POST",
"remaining": 10,
"unit": "DAY",
- "resetTime": 1311272226
+ "resetTime": 1311272226,
},
]
self.absolute_limits = {
@@ -954,7 +954,7 @@ class LimitsViewBuilderV11Test(test.TestCase):
"verb": "POST",
"remaining": 2,
"unit": "MINUTE",
- "next-available": "2011-07-21T18:17:06Z"
+ "next-available": "2011-07-21T18:17:06Z",
},
]
},
@@ -967,7 +967,7 @@ class LimitsViewBuilderV11Test(test.TestCase):
"verb": "POST",
"remaining": 10,
"unit": "DAY",
- "next-available": "2011-07-21T18:17:06Z"
+ "next-available": "2011-07-21T18:17:06Z",
},
]
},
@@ -989,7 +989,7 @@ class LimitsViewBuilderV11Test(test.TestCase):
expected_limits = {
"limits": {
"rate": [],
- "absolute": {}
+ "absolute": {},
}
}
@@ -1022,7 +1022,7 @@ class LimitsXMLSerializationTest(test.TestCase):
"verb": "POST",
"remaining": 2,
"unit": "MINUTE",
- "next-available": "2011-12-15T22:42:45Z"
+ "next-available": "2011-12-15T22:42:45Z",
},
]
},
@@ -1083,7 +1083,7 @@ class LimitsXMLSerializationTest(test.TestCase):
fixture = {
"limits": {
"rate": [],
- "absolute": {}
+ "absolute": {},
}
}
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index 4ca79434f..4027ef829 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -16,6 +16,7 @@
# under the License.
import base64
+import datetime
import json
import unittest
from xml.dom import minidom
@@ -172,8 +173,8 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
instance = {
"id": int(id),
- "created_at": "2010-10-10T12:00:00Z",
- "updated_at": "2010-11-11T11:00:00Z",
+ "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
+ "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
"admin_pass": "",
"user_id": user_id,
"project_id": "",
@@ -399,6 +400,78 @@ class ServersTest(test.TestCase):
self.assertDictMatch(res_dict, expected_server)
+ def test_get_server_by_id_v1_1_xml(self):
+ image_bookmark = "http://localhost/images/10"
+ flavor_ref = "http://localhost/v1.1/flavors/1"
+ flavor_id = "1"
+ flavor_bookmark = "http://localhost/flavors/1"
+ server_href = "http://localhost/v1.1/servers/1"
+ server_bookmark = "http://localhost/servers/1"
+
+ public_ip = '192.168.0.3'
+ private_ip = '172.19.0.1'
+ interfaces = [
+ {
+ 'network': {'label': 'public'},
+ 'fixed_ips': [
+ {'address': public_ip},
+ ],
+ },
+ {
+ 'network': {'label': 'private'},
+ 'fixed_ips': [
+ {'address': private_ip},
+ ],
+ },
+ ]
+ new_return_server = return_server_with_attributes(
+ interfaces=interfaces)
+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
+
+ req = webob.Request.blank('/v1.1/servers/1')
+ req.headers['Accept'] = 'application/xml'
+ res = req.get_response(fakes.wsgi_app())
+ actual = minidom.parseString(res.body.replace(' ', ''))
+ expected_uuid = FAKE_UUID
+ expected_updated = "2010-11-11T11:00:00Z"
+ expected_created = "2010-10-10T12:00:00Z"
+ expected = minidom.parseString("""
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ name="server1"
+ updated="%(expected_updated)s"
+ created="%(expected_created)s"
+ hostId=""
+ status="BUILD"
+ progress="0">
+ <atom:link href="%(server_href)s" rel="self"/>
+ <atom:link href="%(server_bookmark)s" rel="bookmark"/>
+ <image id="10">
+ <atom:link rel="bookmark" href="%(image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="seq">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="public">
+ <ip version="4" addr="%(public_ip)s"/>
+ </network>
+ <network id="private">
+ <ip version="4" addr="%(private_ip)s"/>
+ </network>
+ </addresses>
+ </server>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
def test_get_server_with_active_status_by_id_v1_1(self):
image_bookmark = "http://localhost/images/10"
flavor_ref = "http://localhost/v1.1/flavors/1"
@@ -1048,8 +1121,8 @@ class ServersTest(test.TestCase):
'uuid': FAKE_UUID,
'instance_type': dict(inst_type),
'image_ref': image_ref,
- 'created_at': '2010-10-10T12:00:00Z',
- 'updated_at': '2010-11-11T11:00:00Z',
+ "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
+ "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
}
def server_update(context, id, params):
@@ -1099,6 +1172,7 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(16, len(server['adminPass']))
self.assertEqual('server_test', server['name'])
@@ -1106,7 +1180,6 @@ class ServersTest(test.TestCase):
self.assertEqual(2, server['flavorId'])
self.assertEqual(3, server['imageId'])
self.assertEqual(FAKE_UUID, server['uuid'])
- self.assertEqual(res.status_int, 200)
def test_create_instance(self):
self._test_create_instance_helper()
@@ -1279,7 +1352,12 @@ class ServersTest(test.TestCase):
'hello': 'world',
'open': 'stack',
},
- 'personality': {},
+ 'personality': [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "MQ==",
+ },
+ ],
},
}
@@ -1293,11 +1371,11 @@ class ServersTest(test.TestCase):
self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(16, len(server['adminPass']))
+ self.assertEqual(1, server['id'])
+ self.assertEqual(0, server['progress'])
self.assertEqual('server_test', server['name'])
self.assertEqual(expected_flavor, server['flavor'])
self.assertEqual(expected_image, server['image'])
- self.assertEqual(res.status_int, 200)
- #self.assertEqual(1, server['id'])
def test_create_instance_v1_1_invalid_flavor_href(self):
self._setup_for_create_instance()
@@ -1351,7 +1429,7 @@ class ServersTest(test.TestCase):
self._setup_for_create_instance()
image_id = "2"
- flavor_ref = 'http://localhost/flavors/3'
+ flavor_ref = 'http://localhost/v1.1/flavors/3'
expected_flavor = {
"id": "3",
"links": [
@@ -1385,10 +1463,10 @@ class ServersTest(test.TestCase):
res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(expected_flavor, server['flavor'])
self.assertEqual(expected_image, server['image'])
- self.assertEqual(res.status_int, 200)
def test_create_instance_with_admin_pass_v1_0(self):
self._setup_for_create_instance()
@@ -1411,7 +1489,7 @@ class ServersTest(test.TestCase):
self.assertNotEqual(res['server']['adminPass'],
body['server']['adminPass'])
- def test_create_instance_with_admin_pass_v1_1(self):
+ def test_create_instance_v1_1_admin_pass(self):
self._setup_for_create_instance()
image_href = 'http://localhost/v1.1/images/2'
@@ -1419,8 +1497,8 @@ class ServersTest(test.TestCase):
body = {
'server': {
'name': 'server_test',
- 'imageRef': image_href,
- 'flavorRef': flavor_ref,
+ 'imageRef': 3,
+ 'flavorRef': 3,
'adminPass': 'testpass',
},
}
@@ -1430,19 +1508,18 @@ class ServersTest(test.TestCase):
req.body = json.dumps(body)
req.headers['content-type'] = "application/json"
res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 200)
server = json.loads(res.body)['server']
self.assertEqual(server['adminPass'], body['server']['adminPass'])
- def test_create_instance_with_empty_admin_pass_v1_1(self):
+ def test_create_instance_v1_1_admin_pass_empty(self):
self._setup_for_create_instance()
- image_href = 'http://localhost/v1.1/images/2'
- flavor_ref = 'http://localhost/v1.1/flavors/3'
body = {
'server': {
'name': 'server_test',
- 'imageRef': image_href,
- 'flavorRef': flavor_ref,
+ 'imageRef': 3,
+ 'flavorRef': 3,
'adminPass': '',
},
}
@@ -2235,7 +2312,7 @@ class ServersTest(test.TestCase):
self.assertEqual(res_dict['server']['status'], 'SHUTOFF')
-class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
+class TestServerCreateRequestXMLDeserializerV10(unittest.TestCase):
def setUp(self):
self.deserializer = create_instance_helper.ServerXMLDeserializer()
@@ -2249,6 +2326,8 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
+ "metadata": {},
+ "personality": [],
}}
self.assertEquals(request['body'], expected)
@@ -2264,6 +2343,7 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
"imageId": "1",
"flavorId": "1",
"metadata": {},
+ "personality": [],
}}
self.assertEquals(request['body'], expected)
@@ -2278,6 +2358,7 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase):
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
+ "metadata": {},
"personality": [],
}}
self.assertEquals(request['body'], expected)
@@ -2515,18 +2596,188 @@ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""",
request = self.deserializer.deserialize(serial_request, 'create')
self.assertEqual(request['body'], expected)
- def test_request_xmlser_with_flavor_image_href(self):
+
+class TestServerCreateRequestXMLDeserializerV11(unittest.TestCase):
+
+ def setUp(self):
+ self.deserializer = create_instance_helper.ServerXMLDeserializer()
+
+ def test_minimal_request(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_admin_pass(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2"
+ adminPass="1234"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "adminPass": "1234",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_image_link(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="http://localhost:8774/v1.1/images/2"
+ flavorRef="3"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "http://localhost:8774/v1.1/images/2",
+ "flavorRef": "3",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_flavor_link(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="http://localhost:8774/v1.1/flavors/3"/>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "http://localhost:8774/v1.1/flavors/3",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_empty_metadata_personality(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2">
+ <metadata/>
+ <personality/>
+</server>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_multiple_metadata_items(self):
serial_request = """
- <server xmlns="http://docs.openstack.org/compute/api/v1.1"
- name="new-server-test"
- imageRef="http://localhost:8774/v1.1/images/1"
- flavorRef="http://localhost:8774/v1.1/flavors/1">
- </server>"""
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2">
+ <metadata>
+ <meta key="one">two</meta>
+ <meta key="open">snack</meta>
+ </metadata>
+</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
- self.assertEquals(request['body']["server"]["flavorRef"],
- "http://localhost:8774/v1.1/flavors/1")
- self.assertEquals(request['body']["server"]["imageRef"],
- "http://localhost:8774/v1.1/images/1")
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {"one": "two", "open": "snack"},
+ "personality": [],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_multiple_personality_files(self):
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ name="new-server-test"
+ imageRef="1"
+ flavorRef="2">
+ <personality>
+ <file path="/etc/banner.txt">MQ==</file>
+ <file path="/etc/hosts">Mg==</file>
+ </personality>
+</server>"""
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "1",
+ "flavorRef": "2",
+ "metadata": {},
+ "personality": [
+ {"path": "/etc/banner.txt", "contents": "MQ=="},
+ {"path": "/etc/hosts", "contents": "Mg=="},
+ ],
+ },
+ }
+ self.assertEquals(request['body'], expected)
+
+ def test_spec_request(self):
+ image_bookmark_link = "http://servers.api.openstack.org/1234/" + \
+ "images/52415800-8b69-11e0-9b19-734f6f006e54"
+ serial_request = """
+<server xmlns="http://docs.openstack.org/compute/api/v1.1"
+ imageRef="%s"
+ flavorRef="52415800-8b69-11e0-9b19-734f1195ff37"
+ name="new-server-test">
+ <metadata>
+ <meta key="My Server Name">Apache1</meta>
+ </metadata>
+ <personality>
+ <file path="/etc/banner.txt">Mg==</file>
+ </personality>
+</server>""" % (image_bookmark_link)
+ request = self.deserializer.deserialize(serial_request, 'create')
+ expected = {
+ "server": {
+ "name": "new-server-test",
+ "imageRef": "http://servers.api.openstack.org/1234/" + \
+ "images/52415800-8b69-11e0-9b19-734f6f006e54",
+ "flavorRef": "52415800-8b69-11e0-9b19-734f1195ff37",
+ "metadata": {"My Server Name": "Apache1"},
+ "personality": [
+ {
+ "path": "/etc/banner.txt",
+ "contents": "Mg==",
+ },
+ ],
+ },
+ }
+ self.assertEquals(request['body'], expected)
class TextAddressesXMLSerialization(test.TestCase):
@@ -2899,10 +3150,12 @@ class ServersViewBuilderV11Test(test.TestCase):
pass
def _get_instance(self):
+ created_at = datetime.datetime(2010, 10, 10, 12, 0, 0)
+ updated_at = datetime.datetime(2010, 11, 11, 11, 0, 0)
instance = {
"id": 1,
- "created_at": "2010-10-10T12:00:00Z",
- "updated_at": "2010-11-11T11:00:00Z",
+ "created_at": created_at,
+ "updated_at": updated_at,
"admin_pass": "",
"user_id": "",
"project_id": "",
@@ -2950,7 +3203,7 @@ class ServersViewBuilderV11Test(test.TestCase):
address_builder,
flavor_builder,
image_builder,
- base_url
+ base_url,
)
return view_builder
@@ -3106,12 +3359,12 @@ class ServersViewBuilderV11Test(test.TestCase):
},
"flavor": {
"id": "1",
- "links": [
- {
- "rel": "bookmark",
- "href": flavor_bookmark,
- },
- ],
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": flavor_bookmark,
+ },
+ ],
},
"addresses": {},
"metadata": {
@@ -3133,3 +3386,505 @@ class ServersViewBuilderV11Test(test.TestCase):
output = self.view_builder.build(self.instance, True)
self.assertDictMatch(output, expected_server)
+
+
+class ServerXMLSerializationTest(test.TestCase):
+
+ TIMESTAMP = "2010-10-11T10:30:22Z"
+ SERVER_HREF = 'http://localhost/v1.1/servers/123'
+ SERVER_BOOKMARK = 'http://localhost/servers/123'
+ IMAGE_BOOKMARK = 'http://localhost/images/5'
+ FLAVOR_BOOKMARK = 'http://localhost/flavors/1'
+
+ def setUp(self):
+ self.maxDiff = None
+ test.TestCase.setUp(self)
+
+ def test_show(self):
+ serializer = servers.ServerXMLSerializer()
+
+ fixture = {
+ "server": {
+ "id": 1,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 0,
+ "name": "test_server",
+ "status": "BUILD",
+ "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0',
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.IMAGE_BOOKMARK,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.FLAVOR_BOOKMARK,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ "network_two": [
+ {
+ "version": 4,
+ "addr": "67.23.10.139",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.139",
+ },
+ ],
+ },
+ "metadata": {
+ "Open": "Stack",
+ "Number": "1",
+ },
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ }
+ }
+
+ output = serializer.serialize(fixture, 'show')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected_server_href = self.SERVER_HREF
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_image_bookmark = self.IMAGE_BOOKMARK
+ expected_flavor_bookmark = self.FLAVOR_BOOKMARK
+ expected_now = self.TIMESTAMP
+ expected_uuid = FAKE_UUID
+ expected = minidom.parseString("""
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ name="test_server"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="BUILD"
+ progress="0">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Open">
+ Stack
+ </meta>
+ <meta key="Number">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ <network id="network_two">
+ <ip version="4" addr="67.23.10.139"/>
+ <ip version="6" addr="::babe:67.23.10.139"/>
+ </network>
+ </addresses>
+ </server>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_create(self):
+ serializer = servers.ServerXMLSerializer()
+
+ fixture = {
+ "server": {
+ "id": 1,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 0,
+ "name": "test_server",
+ "status": "BUILD",
+ "hostId": "e4d909c290d0fb1ca068ffaddf22cbd0",
+ "adminPass": "test_password",
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.IMAGE_BOOKMARK,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": self.FLAVOR_BOOKMARK,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ "network_two": [
+ {
+ "version": 4,
+ "addr": "67.23.10.139",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.139",
+ },
+ ],
+ },
+ "metadata": {
+ "Open": "Stack",
+ "Number": "1",
+ },
+ 'links': [
+ {
+ 'href': self.SERVER_HREF,
+ 'rel': 'self',
+ },
+ {
+ 'href': self.SERVER_BOOKMARK,
+ 'rel': 'bookmark',
+ },
+ ],
+ }
+ }
+
+ output = serializer.serialize(fixture, 'create')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected_server_href = self.SERVER_HREF
+ expected_server_bookmark = self.SERVER_BOOKMARK
+ expected_image_bookmark = self.IMAGE_BOOKMARK
+ expected_flavor_bookmark = self.FLAVOR_BOOKMARK
+ expected_now = self.TIMESTAMP
+ expected_uuid = FAKE_UUID
+ expected = minidom.parseString("""
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ name="test_server"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="BUILD"
+ adminPass="test_password"
+ progress="0">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Open">
+ Stack
+ </meta>
+ <meta key="Number">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ <network id="network_two">
+ <ip version="4" addr="67.23.10.139"/>
+ <ip version="6" addr="::babe:67.23.10.139"/>
+ </network>
+ </addresses>
+ </server>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_index(self):
+ serializer = servers.ServerXMLSerializer()
+
+ expected_server_href = 'http://localhost/v1.1/servers/1'
+ expected_server_bookmark = 'http://localhost/servers/1'
+ expected_server_href_2 = 'http://localhost/v1.1/servers/2'
+ expected_server_bookmark_2 = 'http://localhost/servers/2'
+ fixture = {"servers": [
+ {
+ "id": 1,
+ "name": "test_server",
+ 'links': [
+ {
+ 'href': expected_server_href,
+ 'rel': 'self',
+ },
+ {
+ 'href': expected_server_bookmark,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ {
+ "id": 2,
+ "name": "test_server_2",
+ 'links': [
+ {
+ 'href': expected_server_href_2,
+ 'rel': 'self',
+ },
+ {
+ 'href': expected_server_bookmark_2,
+ 'rel': 'bookmark',
+ },
+ ],
+ },
+ ]}
+
+ output = serializer.serialize(fixture, 'index')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <servers xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom">
+ <server id="1" name="test_server">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ </server>
+ <server id="2" name="test_server_2">
+ <atom:link href="%(expected_server_href_2)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark_2)s" rel="bookmark"/>
+ </server>
+ </servers>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
+
+ def test_detail(self):
+ serializer = servers.ServerXMLSerializer()
+
+ expected_server_href = 'http://localhost/v1.1/servers/1'
+ expected_server_bookmark = 'http://localhost/servers/1'
+ expected_image_bookmark = self.IMAGE_BOOKMARK
+ expected_flavor_bookmark = self.FLAVOR_BOOKMARK
+ expected_now = self.TIMESTAMP
+ expected_uuid = FAKE_UUID
+
+ expected_server_href_2 = 'http://localhost/v1.1/servers/2'
+ expected_server_bookmark_2 = 'http://localhost/servers/2'
+ fixture = {"servers": [
+ {
+ "id": 1,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 0,
+ "name": "test_server",
+ "status": "BUILD",
+ "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0',
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_image_bookmark,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_flavor_bookmark,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ },
+ "metadata": {
+ "Number": "1",
+ },
+ "links": [
+ {
+ "href": expected_server_href,
+ "rel": "self",
+ },
+ {
+ "href": expected_server_bookmark,
+ "rel": "bookmark",
+ },
+ ],
+ },
+ {
+ "id": 2,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 100,
+ "name": "test_server_2",
+ "status": "ACTIVE",
+ "hostId": 'e4d909c290d0fb1ca068ffaddf22cbd0',
+ "image": {
+ "id": "5",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_image_bookmark,
+ },
+ ],
+ },
+ "flavor": {
+ "id": "1",
+ "links": [
+ {
+ "rel": "bookmark",
+ "href": expected_flavor_bookmark,
+ },
+ ],
+ },
+ "addresses": {
+ "network_one": [
+ {
+ "version": 4,
+ "addr": "67.23.10.138",
+ },
+ {
+ "version": 6,
+ "addr": "::babe:67.23.10.138",
+ },
+ ],
+ },
+ "metadata": {
+ "Number": "2",
+ },
+ "links": [
+ {
+ "href": expected_server_href_2,
+ "rel": "self",
+ },
+ {
+ "href": expected_server_bookmark_2,
+ "rel": "bookmark",
+ },
+ ],
+ },
+ ]}
+
+ output = serializer.serialize(fixture, 'detail')
+ actual = minidom.parseString(output.replace(" ", ""))
+
+ expected = minidom.parseString("""
+ <servers xmlns="http://docs.openstack.org/compute/api/v1.1"
+ xmlns:atom="http://www.w3.org/2005/Atom">
+ <server id="1"
+ uuid="%(expected_uuid)s"
+ name="test_server"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="BUILD"
+ progress="0">
+ <atom:link href="%(expected_server_href)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Number">
+ 1
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ </addresses>
+ </server>
+ <server id="2"
+ uuid="%(expected_uuid)s"
+ name="test_server_2"
+ updated="%(expected_now)s"
+ created="%(expected_now)s"
+ hostId="e4d909c290d0fb1ca068ffaddf22cbd0"
+ status="ACTIVE"
+ progress="100">
+ <atom:link href="%(expected_server_href_2)s" rel="self"/>
+ <atom:link href="%(expected_server_bookmark_2)s" rel="bookmark"/>
+ <image id="5">
+ <atom:link rel="bookmark" href="%(expected_image_bookmark)s"/>
+ </image>
+ <flavor id="1">
+ <atom:link rel="bookmark" href="%(expected_flavor_bookmark)s"/>
+ </flavor>
+ <metadata>
+ <meta key="Number">
+ 2
+ </meta>
+ </metadata>
+ <addresses>
+ <network id="network_one">
+ <ip version="4" addr="67.23.10.138"/>
+ <ip version="6" addr="::babe:67.23.10.138"/>
+ </network>
+ </addresses>
+ </server>
+ </servers>
+ """.replace(" ", "") % (locals()))
+
+ self.assertEqual(expected.toxml(), actual.toxml())
diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py
index 4e8e85c7b..67b3c485a 100644
--- a/nova/tests/integrated/test_servers.py
+++ b/nova/tests/integrated/test_servers.py
@@ -305,5 +305,6 @@ class ServersTest(integrated_helpers._IntegratedTestBase):
# Cleanup
self._delete_server(server_id)
+
if __name__ == "__main__":
unittest.main()
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 0ede4f469..d82666689 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -420,7 +420,7 @@ class ComputeTestCase(test.TestCase):
def fake(*args, **kwargs):
pass
- self.stubs.Set(self.compute.driver, 'finish_resize', fake)
+ self.stubs.Set(self.compute.driver, 'finish_migration', fake)
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
context = self.context.elevated()
instance_id = self._create_instance()
@@ -531,8 +531,8 @@ class ComputeTestCase(test.TestCase):
def fake(*args, **kwargs):
pass
- self.stubs.Set(self.compute.driver, 'finish_resize', fake)
- self.stubs.Set(self.compute.driver, 'revert_resize', fake)
+ self.stubs.Set(self.compute.driver, 'finish_migration', fake)
+ self.stubs.Set(self.compute.driver, 'revert_migration', fake)
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info', fake)
self.compute.run_instance(self.context, instance_id)
diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py
index 107fd03e3..5560b489b 100644
--- a/nova/tests/test_db_api.py
+++ b/nova/tests/test_db_api.py
@@ -66,7 +66,7 @@ class DbApiTestCase(test.TestCase):
result = db.fixed_ip_get_all(self.context)
values = {'instance_type_id': FLAGS.default_instance_type,
'image_ref': FLAGS.vpn_image_id,
- 'project_id': self.project.id
+ 'project_id': self.project.id,
}
instance = db.instance_create(self.context, values)
result = db.instance_get_project_vpn(self.context, self.project.id)
@@ -76,7 +76,7 @@ class DbApiTestCase(test.TestCase):
result = db.fixed_ip_get_all(self.context)
values = {'instance_type_id': FLAGS.default_instance_type,
'image_ref': FLAGS.vpn_image_id,
- 'project_id': self.project.id
+ 'project_id': self.project.id,
}
instance = db.instance_create(self.context, values)
_setup_networking(instance.id)
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index d8462eb25..3cad9d1ed 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -239,7 +239,7 @@ class LibvirtConnTestCase(test.TestCase):
'mac_address': 'fake',
'ip_address': 'fake',
'dhcp_server': 'fake',
- 'extra_params': 'fake'
+ 'extra_params': 'fake',
}
# Creating mocks
diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py
index 7313508a6..909e65dd9 100644
--- a/nova/tests/test_vmwareapi.py
+++ b/nova/tests/test_vmwareapi.py
@@ -20,6 +20,7 @@ Test suite for VMWareAPI.
"""
from nova import db
+from nova import context
from nova import flags
from nova import test
from nova import utils
@@ -40,6 +41,7 @@ class VMWareAPIVMTestCase(test.TestCase):
def setUp(self):
super(VMWareAPIVMTestCase, self).setUp()
+ self.context = context.RequestContext('fake', 'fake', False)
self.flags(vmwareapi_host_ip='test_url',
vmwareapi_host_username='test_username',
vmwareapi_host_password='test_pass')
@@ -97,7 +99,7 @@ class VMWareAPIVMTestCase(test.TestCase):
"""Create and spawn the VM."""
self._create_instance_in_the_db()
self.type_data = db.instance_type_get_by_name(None, 'm1.large')
- self.conn.spawn(self.instance, self.network_info)
+ self.conn.spawn(self.context, self.instance, self.network_info)
self._check_vm_record()
def _check_vm_record(self):
@@ -159,14 +161,14 @@ class VMWareAPIVMTestCase(test.TestCase):
self._create_vm()
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
- self.conn.snapshot(self.instance, "Test-Snapshot")
+ self.conn.snapshot(self.context, self.instance, "Test-Snapshot")
info = self.conn.get_info(1)
self._check_vm_info(info, power_state.RUNNING)
def test_snapshot_non_existent(self):
self._create_instance_in_the_db()
- self.assertRaises(Exception, self.conn.snapshot, self.instance,
- "Test-Snapshot")
+ self.assertRaises(Exception, self.conn.snapshot, self.context,
+ self.instance, "Test-Snapshot")
def test_reboot(self):
self._create_vm()
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py
index bb1b88421..1a8ddadc4 100644
--- a/nova/tests/test_xenapi.py
+++ b/nova/tests/test_xenapi.py
@@ -786,8 +786,48 @@ class XenAPIMigrateInstance(test.TestCase):
conn = xenapi_conn.get_connection(False)
conn.migrate_disk_and_power_off(instance, '127.0.0.1')
- def test_finish_resize(self):
+ def test_finish_migrate(self):
instance = db.instance_create(self.context, self.values)
+ self.called = False
+
+ def fake_vdi_resize(*args, **kwargs):
+ self.called = True
+
+ self.stubs.Set(stubs.FakeSessionForMigrationTests,
+ "VDI_resize_online", fake_vdi_resize)
+ stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests)
+ stubs.stubout_loopingcall_start(self.stubs)
+ conn = xenapi_conn.get_connection(False)
+ network_info = [({'bridge': 'fa0', 'id': 0, 'injected': False},
+ {'broadcast': '192.168.0.255',
+ 'dns': ['192.168.0.1'],
+ 'gateway': '192.168.0.1',
+ 'gateway6': 'dead:beef::1',
+ 'ip6s': [{'enabled': '1',
+ 'ip': 'dead:beef::dcad:beff:feef:0',
+ 'netmask': '64'}],
+ 'ips': [{'enabled': '1',
+ 'ip': '192.168.0.100',
+ 'netmask': '255.255.255.0'}],
+ 'label': 'fake',
+ 'mac': 'DE:AD:BE:EF:00:00',
+ 'rxtx_cap': 3})]
+ conn.finish_migration(self.context, instance,
+ dict(base_copy='hurr', cow='durr'),
+ network_info, resize_instance=True)
+ self.assertEqual(self.called, True)
+
+ def test_finish_migrate_no_local_storage(self):
+ tiny_type_id = \
+ instance_types.get_instance_type_by_name('m1.tiny')['id']
+ self.values.update({'instance_type_id': tiny_type_id, 'local_gb': 0})
+ instance = db.instance_create(self.context, self.values)
+
+ def fake_vdi_resize(*args, **kwargs):
+ raise Exception("This shouldn't be called")
+
+ self.stubs.Set(stubs.FakeSessionForMigrationTests,
+ "VDI_resize_online", fake_vdi_resize)
stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests)
stubs.stubout_loopingcall_start(self.stubs)
conn = xenapi_conn.get_connection(False)
@@ -805,9 +845,40 @@ class XenAPIMigrateInstance(test.TestCase):
'label': 'fake',
'mac': 'DE:AD:BE:EF:00:00',
'rxtx_cap': 3})]
- conn.finish_resize(self.context, instance,
- dict(base_copy='hurr', cow='durr'),
- network_info)
+ conn.finish_migration(self.context, instance,
+ dict(base_copy='hurr', cow='durr'),
+ network_info, resize_instance=True)
+
+ def test_finish_migrate_no_resize_vdi(self):
+ instance = db.instance_create(self.context, self.values)
+
+ def fake_vdi_resize(*args, **kwargs):
+ raise Exception("This shouldn't be called")
+
+ self.stubs.Set(stubs.FakeSessionForMigrationTests,
+ "VDI_resize_online", fake_vdi_resize)
+ stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests)
+ stubs.stubout_loopingcall_start(self.stubs)
+ conn = xenapi_conn.get_connection(False)
+ network_info = [({'bridge': 'fa0', 'id': 0, 'injected': False},
+ {'broadcast': '192.168.0.255',
+ 'dns': ['192.168.0.1'],
+ 'gateway': '192.168.0.1',
+ 'gateway6': 'dead:beef::1',
+ 'ip6s': [{'enabled': '1',
+ 'ip': 'dead:beef::dcad:beff:feef:0',
+ 'netmask': '64'}],
+ 'ips': [{'enabled': '1',
+ 'ip': '192.168.0.100',
+ 'netmask': '255.255.255.0'}],
+ 'label': 'fake',
+ 'mac': 'DE:AD:BE:EF:00:00',
+ 'rxtx_cap': 3})]
+
+ # Resize instance would be determined by the compute call
+ conn.finish_migration(self.context, instance,
+ dict(base_copy='hurr', cow='durr'),
+ network_info, resize_instance=False)
class XenAPIDetermineDiskImageTestCase(test.TestCase):
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index 8e17d7540..4be847dc6 100644
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -65,7 +65,7 @@ class ComputeDriver(object):
# TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
- def spawn(self, context, instance, network_info,
+ def spawn(self, cxt, instance, network_info,
block_device_mapping=None):
"""Launch a VM for the specified instance"""
raise NotImplementedError()
@@ -131,15 +131,16 @@ class ComputeDriver(object):
# TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
- def snapshot(self, context, instance, image_id):
+ def snapshot(self, cxt, instance, image_id):
"""Create snapshot from a running VM instance."""
raise NotImplementedError()
- def finish_resize(self, context, instance, disk_info):
+ def finish_migration(self, cxt, instance, disk_info, network_info,
+ resize_instance):
"""Completes a resize, turning on the migrated instance"""
raise NotImplementedError()
- def revert_resize(self, instance):
+ def revert_migration(self, instance):
"""Reverts a resize, powering back on the instance"""
# TODO(Vek): Need to pass context in for access to auth_token
raise NotImplementedError()
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index f67c2309e..23aa603ef 100644
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -129,7 +129,7 @@ class FakeConnection(driver.ComputeDriver):
info_list.append(self._map_to_instance_info(instance))
return info_list
- def spawn(self, context, instance, network_info,
+ def spawn(self, cxt, instance, network_info,
block_device_mapping=None):
"""
Create a new instance/VM/domain on the virtualization platform.
@@ -154,7 +154,7 @@ class FakeConnection(driver.ComputeDriver):
fake_instance = FakeInstance(name, state)
self.instances[name] = fake_instance
- def snapshot(self, context, instance, name):
+ def snapshot(self, cxt, instance, name):
"""
Snapshots the specified instance.
diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py
index 8236b5a45..075594808 100644
--- a/nova/virt/hyperv.py
+++ b/nova/virt/hyperv.py
@@ -139,7 +139,7 @@ class HyperVConnection(driver.ComputeDriver):
return instance_infos
- def spawn(self, context, instance, network_info,
+ def spawn(self, cxt, instance, network_info,
block_device_mapping=None):
""" Create a new VM and start it."""
vm = self._lookup(instance.name)
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 471811b06..1e291000c 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -396,7 +396,7 @@ class LibvirtConnection(driver.ComputeDriver):
virt_dom.detachDevice(xml)
@exception.wrap_exception()
- def snapshot(self, context, instance, image_href):
+ def snapshot(self, cxt, instance, image_href):
"""Create snapshot from a running VM instance.
This command only works with qemu 0.14+, the qemu_img flag is
@@ -592,7 +592,7 @@ class LibvirtConnection(driver.ComputeDriver):
# NOTE(ilyaalekseyev): Implementation like in multinics
# for xenapi(tr3buchet)
@exception.wrap_exception()
- def spawn(self, context, instance, network_info,
+ def spawn(self, cxt, instance, network_info,
block_device_mapping=None):
xml = self.to_xml(instance, False, network_info=network_info,
block_device_mapping=block_device_mapping)
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 777c15736..ad354bc3a 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -89,7 +89,7 @@ class VMWareVMOps(object):
LOG.debug(_("Got total of %s instances") % str(len(lst_vm_names)))
return lst_vm_names
- def spawn(self, context, instance, network_info):
+ def spawn(self, cxt, instance, network_info):
"""
Creates a VM instance.
@@ -329,7 +329,7 @@ class VMWareVMOps(object):
LOG.debug(_("Powered on the VM instance %s") % instance.name)
_power_on_vm()
- def snapshot(self, context, instance, snapshot_name):
+ def snapshot(self, cxt, instance, snapshot_name):
"""
Create snapshot from a running VM instance.
Steps followed are:
diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py
index 3d209fa99..a26a02290 100644
--- a/nova/virt/vmwareapi_conn.py
+++ b/nova/virt/vmwareapi_conn.py
@@ -124,14 +124,14 @@ class VMWareESXConnection(driver.ComputeDriver):
"""List VM instances."""
return self._vmops.list_instances()
- def spawn(self, context, instance, network_info,
+ def spawn(self, cxt, instance, network_info,
block_device_mapping=None):
"""Create VM instance."""
- self._vmops.spawn(context, instance, network_info)
+ self._vmops.spawn(cxt, instance, network_info)
- def snapshot(self, context, instance, name):
+ def snapshot(self, cxt, instance, name):
"""Create snapshot from a running VM instance."""
- self._vmops.snapshot(context, instance, name)
+ self._vmops.snapshot(cxt, instance, name)
def reboot(self, instance, network_info):
"""Reboot VM instance."""
diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py
index b1b0ddd0c..14465d8b4 100644
--- a/nova/virt/xenapi/vm_utils.py
+++ b/nova/virt/xenapi/vm_utils.py
@@ -359,7 +359,7 @@ class VMHelper(HelperBase):
return os.path.join(FLAGS.xenapi_sr_base_path, sr_uuid)
@classmethod
- def upload_image(cls, context, session, instance, vdi_uuids, image_id):
+ def upload_image(cls, ctx, session, instance, vdi_uuids, image_id):
""" Requests that the Glance plugin bundle the specified VDIs and
push them into Glance using the specified human-friendly name.
"""
@@ -378,14 +378,14 @@ class VMHelper(HelperBase):
'glance_port': glance_port,
'sr_path': cls.get_sr_path(session),
'os_type': os_type,
- 'auth_token': getattr(context, 'auth_token', None)}
+ 'auth_token': getattr(ctx, 'auth_token', None)}
kwargs = {'params': pickle.dumps(params)}
task = session.async_call_plugin('glance', 'upload_vhd', kwargs)
session.wait_for_task(task, instance.id)
@classmethod
- def fetch_image(cls, context, session, instance_id, image, user, project,
+ def fetch_image(cls, ctx, session, instance_id, image, user, project,
image_type):
"""
image_type is interpreted as an ImageType instance
@@ -400,7 +400,7 @@ class VMHelper(HelperBase):
access = AuthManager().get_access_key(user, project)
if FLAGS.xenapi_image_service == 'glance':
- return cls._fetch_image_glance(context, session, instance_id,
+ return cls._fetch_image_glance(ctx, session, instance_id,
image, access, image_type)
else:
return cls._fetch_image_objectstore(session, instance_id, image,
@@ -408,7 +408,7 @@ class VMHelper(HelperBase):
image_type)
@classmethod
- def _fetch_image_glance_vhd(cls, context, session, instance_id, image,
+ def _fetch_image_glance_vhd(cls, ctx, session, instance_id, image,
access, image_type):
"""Tell glance to download an image and put the VHDs into the SR
@@ -431,7 +431,7 @@ class VMHelper(HelperBase):
'glance_port': glance_port,
'uuid_stack': uuid_stack,
'sr_path': cls.get_sr_path(session),
- 'auth_token': getattr(context, 'auth_token', None)}
+ 'auth_token': getattr(ctx, 'auth_token', None)}
kwargs = {'params': pickle.dumps(params)}
task = session.async_call_plugin('glance', 'download_vhd', kwargs)
@@ -457,7 +457,7 @@ class VMHelper(HelperBase):
return vdis
@classmethod
- def _fetch_image_glance_disk(cls, context, session, instance_id, image,
+ def _fetch_image_glance_disk(cls, ctx, session, instance_id, image,
access, image_type):
"""Fetch the image from Glance
@@ -477,7 +477,7 @@ class VMHelper(HelperBase):
sr_ref = safe_find_sr(session)
glance_client, image_id = nova.image.get_glance_client(image)
- glance_client.set_auth_token(getattr(context, 'auth_token', None))
+ glance_client.set_auth_token(getattr(ctx, 'auth_token', None))
meta, image_file = glance_client.get_image(image_id)
virtual_size = int(meta['size'])
vdi_size = virtual_size
@@ -592,7 +592,7 @@ class VMHelper(HelperBase):
return image_type
@classmethod
- def _fetch_image_glance(cls, context, session, instance_id, image, access,
+ def _fetch_image_glance(cls, ctx, session, instance_id, image, access,
image_type):
"""Fetch image from glance based on image type.
@@ -600,10 +600,10 @@ class VMHelper(HelperBase):
A list of dictionaries that describe VDIs, otherwise
"""
if image_type == ImageType.DISK_VHD:
- return cls._fetch_image_glance_vhd(context,
+ return cls._fetch_image_glance_vhd(ctx,
session, instance_id, image, access, image_type)
else:
- return cls._fetch_image_glance_disk(context,
+ return cls._fetch_image_glance_disk(ctx,
session, instance_id, image, access, image_type)
@classmethod
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index f7a800d58..e01ffa046 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -110,17 +110,19 @@ class VMOps(object):
instance_infos.append(instance_info)
return instance_infos
- def revert_resize(self, instance):
+ def revert_migration(self, instance):
vm_ref = VMHelper.lookup(self._session, instance.name)
self._start(instance, vm_ref)
- def finish_resize(self, context, instance, disk_info, network_info):
+ def finish_migration(self, ctx, instance, disk_info, network_info,
+ resize_instance):
vdi_uuid = self.link_disks(instance, disk_info['base_copy'],
disk_info['cow'])
- vm_ref = self._create_vm(context, instance,
+ vm_ref = self._create_vm(ctx, instance,
[dict(vdi_type='os', vdi_uuid=vdi_uuid)],
network_info)
- self.resize_instance(instance, vdi_uuid)
+ if resize_instance:
+ self.resize_instance(instance, vdi_uuid)
self._spawn(instance, vm_ref)
def _start(self, instance, vm_ref=None):
@@ -133,20 +135,20 @@ class VMOps(object):
LOG.debug(_("Starting instance %s"), instance.name)
self._session.call_xenapi('VM.start', vm_ref, False, False)
- def _create_disks(self, context, instance):
+ def _create_disks(self, ctx, instance):
user = AuthManager().get_user(instance.user_id)
project = AuthManager().get_project(instance.project_id)
disk_image_type = VMHelper.determine_disk_image_type(instance)
- vdis = VMHelper.fetch_image(context, self._session,
+ vdis = VMHelper.fetch_image(ctx, self._session,
instance.id, instance.image_ref, user, project,
disk_image_type)
return vdis
- def spawn(self, context, instance, network_info):
+ def spawn(self, ctx, instance, network_info):
vdis = None
try:
- vdis = self._create_disks(context, instance)
- vm_ref = self._create_vm(context, instance, vdis, network_info)
+ vdis = self._create_disks(ctx, instance)
+ vm_ref = self._create_vm(ctx, instance, vdis, network_info)
self._spawn(instance, vm_ref)
except (self.XenAPI.Failure, OSError, IOError) as spawn_error:
LOG.exception(_("instance %s: Failed to spawn"),
@@ -160,7 +162,7 @@ class VMOps(object):
"""Spawn a rescue instance."""
self.spawn(instance)
- def _create_vm(self, context, instance, vdis, network_info):
+ def _create_vm(self, ctx, instance, vdis, network_info):
"""Create VM instance."""
instance_name = instance.name
vm_ref = VMHelper.lookup(self._session, instance_name)
@@ -184,11 +186,11 @@ class VMOps(object):
ramdisk = None
try:
if instance.kernel_id:
- kernel = VMHelper.fetch_image(context, self._session,
+ kernel = VMHelper.fetch_image(ctx, self._session,
instance.id, instance.kernel_id, user, project,
ImageType.KERNEL)[0]
if instance.ramdisk_id:
- ramdisk = VMHelper.fetch_image(context, self._session,
+ ramdisk = VMHelper.fetch_image(ctx, self._session,
instance.id, instance.ramdisk_id, user, project,
ImageType.RAMDISK)[0]
# Create the VM ref and attach the first disk
@@ -440,10 +442,10 @@ class VMOps(object):
vm,
"start")
- def snapshot(self, context, instance, image_id):
+ def snapshot(self, ctx, instance, image_id):
"""Create snapshot from a running VM instance.
- :param context: request context
+ :param ctx: request context
:param instance: instance to be snapshotted
:param image_id: id of image to upload to
@@ -468,7 +470,7 @@ class VMOps(object):
try:
template_vm_ref, template_vdi_uuids = self._get_snapshot(instance)
# call plugin to ship snapshot off to glance
- VMHelper.upload_image(context,
+ VMHelper.upload_image(ctx,
self._session, instance, template_vdi_uuids, image_id)
finally:
if template_vm_ref:
@@ -569,18 +571,22 @@ class VMOps(object):
return new_cow_uuid
def resize_instance(self, instance, vdi_uuid):
- """Resize a running instance by changing it's RAM and disk size."""
+ """Resize a running instance by changing its RAM and disk size."""
#TODO(mdietz): this will need to be adjusted for swap later
#The new disk size must be in bytes
- new_disk_size = str(instance.local_gb * 1024 * 1024 * 1024)
- instance_name = instance.name
- instance_local_gb = instance.local_gb
- LOG.debug(_("Resizing VDI %(vdi_uuid)s for instance %(instance_name)s."
- " Expanding to %(instance_local_gb)d GB") % locals())
- vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
- self._session.call_xenapi('VDI.resize_online', vdi_ref, new_disk_size)
- LOG.debug(_("Resize instance %s complete") % (instance.name))
+ new_disk_size = instance.local_gb * 1024 * 1024 * 1024
+ if new_disk_size > 0:
+ instance_name = instance.name
+ instance_local_gb = instance.local_gb
+ LOG.debug(_("Resizing VDI %(vdi_uuid)s for instance"
+ "%(instance_name)s. Expanding to %(instance_local_gb)d"
+ " GB") % locals())
+ vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid)
+ # for an instance with no local storage
+ self._session.call_xenapi('VDI.resize_online', vdi_ref,
+ str(new_disk_size))
+ LOG.debug(_("Resize instance %s complete") % (instance.name))
def reboot(self, instance):
"""Reboot VM instance."""
diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py
index f191d13fa..9315c2f4a 100644
--- a/nova/virt/xenapi_conn.py
+++ b/nova/virt/xenapi_conn.py
@@ -187,22 +187,24 @@ class XenAPIConnection(driver.ComputeDriver):
def list_instances_detail(self):
return self._vmops.list_instances_detail()
- def spawn(self, context, instance, network_info,
+ def spawn(self, cxt, instance, network_info,
block_device_mapping=None):
"""Create VM instance"""
- self._vmops.spawn(context, instance, network_info)
+ self._vmops.spawn(cxt, instance, network_info)
- def revert_resize(self, instance):
+ def revert_migration(self, instance):
"""Reverts a resize, powering back on the instance"""
self._vmops.revert_resize(instance)
- def finish_resize(self, context, instance, disk_info, network_info):
+ def finish_migration(self, cxt, instance, disk_info, network_info,
+ resize_instance=False):
"""Completes a resize, turning on the migrated instance"""
- self._vmops.finish_resize(context, instance, disk_info, network_info)
+ self._vmops.finish_migration(cxt, instance, disk_info,
+ network_info, resize_instance)
- def snapshot(self, context, instance, image_id):
+ def snapshot(self, cxt, instance, image_id):
""" Create snapshot from a running VM instance """
- self._vmops.snapshot(context, instance, image_id)
+ self._vmops.snapshot(cxt, instance, image_id)
def reboot(self, instance, network_info):
"""Reboot VM instance"""