pull-up from trunk; fix problem obscuring context module with context param; fix conflicts and no-longer-skipped tests

This commit is contained in:
Kevin L. Mitchell
2011-07-29 18:59:33 +00:00
29 changed files with 1449 additions and 462 deletions

View File

@@ -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 ''

View File

@@ -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,26 +303,26 @@ 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"):
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")

View File

@@ -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)

View File

@@ -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')

View File

@@ -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):
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 = {

View File

@@ -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)

View File

@@ -165,9 +165,8 @@ 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 = {}
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)

View File

@@ -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:

View File

@@ -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,8 +845,11 @@ 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)
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,
@@ -854,12 +857,14 @@ class ComputeManager(manager.SchedulerDependentManager):
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', })

View File

@@ -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, '')

View File

@@ -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')

View File

@@ -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, '')

View File

@@ -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": {},
}
}

View File

@@ -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="http://localhost:8774/v1.1/images/1"
flavorRef="http://localhost:8774/v1.1/flavors/1">
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')
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": {},
"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="1"
flavorRef="2">
<metadata>
<meta key="one">two</meta>
<meta key="open">snack</meta>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
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
@@ -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())

View File

@@ -305,5 +305,6 @@ class ServersTest(integrated_helpers._IntegratedTestBase):
# Cleanup
self._delete_server(server_id)
if __name__ == "__main__":
unittest.main()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -786,8 +786,15 @@ 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)
@@ -805,9 +812,73 @@ class XenAPIMigrateInstance(test.TestCase):
'label': 'fake',
'mac': 'DE:AD:BE:EF:00:00',
'rxtx_cap': 3})]
conn.finish_resize(self.context, instance,
conn.finish_migration(self.context, instance,
dict(base_copy='hurr', cow='durr'),
network_info)
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)
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)
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):

View File

@@ -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()

View File

@@ -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.

View File

@@ -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)

View File

@@ -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)

View File

@@ -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:

View File

@@ -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."""

View File

@@ -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

View File

@@ -110,16 +110,18 @@ 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)
if resize_instance:
self.resize_instance(instance, vdi_uuid)
self._spawn(instance, vm_ref)
@@ -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,17 +571,21 @@ 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)
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())
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)
# 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):

View File

@@ -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"""