summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Lamar <brian.lamar@rackspace.com>2011-08-24 13:16:37 -0400
committerBrian Lamar <brian.lamar@rackspace.com>2011-08-24 13:16:37 -0400
commitc34c9a008f1314de6eeb41b1f57b6056a3f951f6 (patch)
tree810454c78a3a917e7e29248db296b2f2f79e04eb
parent64f946a6a0a6e08d7046ab98776928abe24f8d93 (diff)
parentbde2e876034219b614395ccd66cb45b0e23d348f (diff)
Merged trunk and fixed conflicts.
-rw-r--r--nova/api/openstack/servers.py29
-rw-r--r--nova/compute/api.py11
-rw-r--r--nova/compute/manager.py8
-rw-r--r--nova/ipv6/account_identifier.py6
-rw-r--r--nova/ipv6/rfc2462.py4
-rw-r--r--nova/tests/api/openstack/test_server_actions.py137
-rw-r--r--nova/tests/api/openstack/test_servers.py135
-rw-r--r--nova/tests/test_compute.py5
-rw-r--r--nova/tests/test_ipv6.py38
-rw-r--r--nova/tests/test_versions.py61
10 files changed, 387 insertions, 47 deletions
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index c5fdda1cf..e0dd9bdb1 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -602,8 +602,10 @@ class ControllerV10(Controller):
LOG.debug(msg)
raise exc.HTTPBadRequest(explanation=msg)
+ password = utils.generate_password(16)
+
try:
- self.compute_api.rebuild(context, instance_id, image_id)
+ self.compute_api.rebuild(context, instance_id, image_id, password)
except exception.RebuildRequiresActiveInstance:
msg = _("Instance %s must be active to rebuild.") % instance_id
raise exc.HTTPConflict(explanation=msg)
@@ -738,14 +740,25 @@ class ControllerV11(Controller):
self._validate_metadata(metadata)
self._decode_personalities(personalities)
+ password = info["rebuild"].get("adminPass",
+ utils.generate_password(16))
+
try:
- self.compute_api.rebuild(context, instance_id, image_href, name,
- metadata, personalities)
+ self.compute_api.rebuild(context, instance_id, image_href,
+ password, name=name, metadata=metadata,
+ files_to_inject=personalities)
except exception.RebuildRequiresActiveInstance:
msg = _("Instance %s must be active to rebuild.") % instance_id
raise exc.HTTPConflict(explanation=msg)
+ except exception.InstanceNotFound:
+ msg = _("Instance %s could not be found") % instance_id
+ raise exc.HTTPNotFound(explanation=msg)
- return webob.Response(status_int=202)
+ instance = self.compute_api.routing_get(context, instance_id)
+ view = self._build_view(request, instance, is_detail=True)
+ view['server']['adminPass'] = password
+
+ return view
@common.check_snapshots_enabled
def _action_create_image(self, input_dict, req, instance_id):
@@ -812,6 +825,9 @@ class HeadersSerializer(wsgi.ResponseHeadersSerializer):
def delete(self, response, data):
response.status_int = 204
+ def action(self, response, data):
+ response.status_int = 202
+
class ServerXMLSerializer(wsgi.XMLDictSerializer):
@@ -933,6 +949,11 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer):
node.setAttribute('adminPass', server_dict['server']['adminPass'])
return self.to_xml_string(node, True)
+ def action(self, server_dict):
+ #NOTE(bcwaldon): We need a way to serialize actions individually. This
+ # assumes all actions return a server entity
+ return self.create(server_dict)
+
def update(self, server_dict):
xml_doc = minidom.Document()
node = self._server_to_xml_detailed(xml_doc,
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 7ed41fbbc..960d28bd0 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -57,15 +57,15 @@ def generate_default_hostname(instance):
"""Default function to generate a hostname given an instance reference."""
display_name = instance['display_name']
if display_name is None:
- return 'server_%d' % (instance['id'],)
+ return 'server-%d' % (instance['id'],)
table = ''
deletions = ''
for i in xrange(256):
c = chr(i)
if ('a' <= c <= 'z') or ('0' <= c <= '9') or (c == '-'):
table += c
- elif c == ' ':
- table += '_'
+ elif c in " _":
+ table += '-'
elif ('A' <= c <= 'Z'):
table += c.lower()
else:
@@ -1041,8 +1041,8 @@ class API(base.Base):
self._cast_compute_message('reboot_instance', context, instance_id)
@scheduler_api.reroute_compute("rebuild")
- def rebuild(self, context, instance_id, image_href, name=None,
- metadata=None, files_to_inject=None):
+ def rebuild(self, context, instance_id, image_href, admin_password,
+ name=None, metadata=None, files_to_inject=None):
"""Rebuild the given instance with the provided metadata."""
instance = db.api.instance_get(context, instance_id)
name = name or instance["display_name"]
@@ -1065,6 +1065,7 @@ class API(base.Base):
task_state=task_states.REBUILDING)
rebuild_params = {
+ "new_pass": admin_password,
"image_ref": image_href,
"injected_files": files_to_inject,
}
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 0a1dc13be..7697e8e6c 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -525,6 +525,7 @@ class ComputeManager(manager.SchedulerDependentManager):
:param context: `nova.RequestContext` object
:param instance_id: Instance identifier (integer)
:param image_ref: Image identifier (href or integer)
+ :param new_pass: password to set on rebuilt instance
"""
context = context.elevated()
@@ -552,13 +553,18 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_ref.image_ref = image_ref
instance_ref.injected_files = kwargs.get('injected_files', [])
network_info = self.network_api.get_instance_nw_info(context,
- instance_ref)
+ instance_ref)
+ bd_mapping = self._setup_block_device_mapping(context, instance_id)
self._instance_update(context,
instance_id,
vm_state=vm_states.REBUILDING,
task_state=task_states.SPAWN)
+ # pull in new password here since the original password isn't in the db
+ instance_ref.admin_pass = kwargs.get('new_pass',
+ utils.generate_password(FLAGS.password_length))
+
self.driver.spawn(context, instance_ref, network_info, bd_mapping)
current_power_state = self._get_power_state(context, instance_ref)
diff --git a/nova/ipv6/account_identifier.py b/nova/ipv6/account_identifier.py
index 258678f0a..27bb01988 100644
--- a/nova/ipv6/account_identifier.py
+++ b/nova/ipv6/account_identifier.py
@@ -34,8 +34,12 @@ def to_global(prefix, mac, project_id):
mac_addr = netaddr.IPAddress(int_addr)
maskIP = netaddr.IPNetwork(prefix).ip
return (project_hash ^ static_num ^ mac_addr | maskIP).format()
- except TypeError:
+ except netaddr.AddrFormatError:
raise TypeError(_('Bad mac for to_global_ipv6: %s') % mac)
+ except TypeError:
+ raise TypeError(_('Bad prefix for to_global_ipv6: %s') % prefix)
+ except NameError:
+ raise TypeError(_('Bad project_id for to_global_ipv6: %s') % project_id)
def to_mac(ipv6_address):
diff --git a/nova/ipv6/rfc2462.py b/nova/ipv6/rfc2462.py
index 0074efe98..acf42d201 100644
--- a/nova/ipv6/rfc2462.py
+++ b/nova/ipv6/rfc2462.py
@@ -30,8 +30,10 @@ def to_global(prefix, mac, project_id):
maskIP = netaddr.IPNetwork(prefix).ip
return (mac64_addr ^ netaddr.IPAddress('::0200:0:0:0') | maskIP).\
format()
- except TypeError:
+ except netaddr.AddrFormatError:
raise TypeError(_('Bad mac for to_global_ipv6: %s') % mac)
+ except TypeError:
+ raise TypeError(_('Bad prefix for to_global_ipv6: %s') % prefix)
def to_mac(ipv6_address):
diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py
index bfbc77c96..0cbbe271d 100644
--- a/nova/tests/api/openstack/test_server_actions.py
+++ b/nova/tests/api/openstack/test_server_actions.py
@@ -1,4 +1,5 @@
import base64
+import datetime
import json
import stubout
@@ -6,9 +7,11 @@ import webob
from nova import context
from nova import utils
+from nova import exception
from nova import flags
from nova.api.openstack import create_instance_helper
from nova.compute import vm_states
+from nova.compute import instance_types
import nova.db.api
from nova import test
from nova.tests.api.openstack import common
@@ -19,47 +22,46 @@ FLAGS = flags.FLAGS
def return_server_by_id(context, id):
- return _get_instance()
+ return stub_instance(id)
def instance_update(context, instance_id, kwargs):
- return _get_instance()
+ return stub_instance(instance_id)
-def return_server_with_state(vm_state, task_state=None):
+def return_server_with_attributes(**kwargs):
def _return_server(context, id):
- instance = _get_instance()
- instance['vm_state'] = vm_state
- instance['task_state'] = task_state
- return instance
+ return stub_instance(id, **kwargs)
return _return_server
+def return_server_with_state(vm_state, task_state=None)
+ return return_server_with_attributes(vm_state=vm_state,
+ task_state=task_state)
+
+
def return_server_with_uuid_and_state(vm_state, task_state=None):
def _return_server(context, id):
return return_server_with_state(vm_state, task_state)
return _return_server
-class MockSetAdminPassword(object):
- def __init__(self):
- self.instance_id = None
- self.password = None
-
- def __call__(self, context, instance_id, password):
- self.instance_id = instance_id
- self.password = password
+def stub_instance(id, metadata=None, image_ref="10", flavor_id="1", name=None):
+ if metadata is not None:
+ metadata_items = [{'key':k, 'value':v} for k, v in metadata.items()]
+ else:
+ metadata_items = [{'key':'seq', 'value':id}]
+ inst_type = instance_types.get_instance_type_by_flavor_id(int(flavor_id))
-def _get_instance():
instance = {
- "id": 1,
- "created_at": "2010-10-10 12:00:00",
- "updated_at": "2010-11-11 11:00:00",
+ "id": int(id),
+ "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
+ "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
"admin_pass": "",
- "user_id": "",
- "project_id": "",
- "image_ref": "5",
+ "user_id": "fake",
+ "project_id": "fake",
+ "image_ref": image_ref,
"kernel_id": "",
"ramdisk_id": "",
"launch_index": 0,
@@ -72,9 +74,7 @@ def _get_instance():
"local_gb": 0,
"hostname": "",
"host": "",
- "instance_type": {
- "flavorid": 1,
- },
+ "instance_type": dict(inst_type),
"user_data": "",
"reservation_id": "",
"mac_address": "",
@@ -82,17 +82,34 @@ def _get_instance():
"launched_at": utils.utcnow(),
"terminated_at": utils.utcnow(),
"availability_zone": "",
- "display_name": "test_server",
+ "display_name": name or "server%s" % id,
"display_description": "",
"locked": False,
- "metadata": [],
- #"address": ,
- #"floating_ips": [{"address":ip} for ip in public_addresses]}
- "uuid": "deadbeef-feed-edee-beef-d0ea7beefedd"}
+ "metadata": metadata_items,
+ "access_ip_v4": "",
+ "access_ip_v6": "",
+ "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
+ "virtual_interfaces": [],
+ }
+
+ instance["fixed_ips"] = {
+ "address": '192.168.0.1',
+ "floating_ips": [],
+ }
return instance
+class MockSetAdminPassword(object):
+ def __init__(self):
+ self.instance_id = None
+ self.password = None
+
+ def __call__(self, context, instance_id, password):
+ self.instance_id = instance_id
+ self.password = password
+
+
class ServerActionsTest(test.TestCase):
def setUp(self):
@@ -599,6 +616,9 @@ class ServerActionsTestV11(test.TestCase):
self.assertEqual(res.status_int, 400)
def test_server_rebuild_accepted_minimum(self):
+ new_return_server = return_server_with_attributes(image_ref='2')
+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
+
body = {
"rebuild": {
"imageRef": "http://localhost/images/2",
@@ -612,6 +632,9 @@ class ServerActionsTestV11(test.TestCase):
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
+ body = json.loads(res.body)
+ self.assertEqual(body['server']['image']['id'], '2')
+ self.assertEqual(len(body['server']['adminPass']), 16)
def test_server_rebuild_rejected_when_building(self):
body = {
@@ -635,12 +658,15 @@ class ServerActionsTestV11(test.TestCase):
self.assertEqual(res.status_int, 409)
def test_server_rebuild_accepted_with_metadata(self):
+ metadata = {'new': 'metadata'}
+
+ new_return_server = return_server_with_attributes(metadata=metadata)
+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
+
body = {
"rebuild": {
"imageRef": "http://localhost/images/2",
- "metadata": {
- "new": "metadata",
- },
+ "metadata": metadata,
},
}
@@ -651,6 +677,8 @@ class ServerActionsTestV11(test.TestCase):
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
+ body = json.loads(res.body)
+ self.assertEqual(body['server']['metadata'], metadata)
def test_server_rebuild_accepted_with_bad_metadata(self):
body = {
@@ -720,6 +748,49 @@ class ServerActionsTestV11(test.TestCase):
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
+ body = json.loads(res.body)
+ self.assertTrue('personality' not in body['server'])
+
+ def test_server_rebuild_admin_pass(self):
+ new_return_server = return_server_with_attributes(image_ref='2')
+ self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
+
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ "adminPass": "asdf",
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/fake/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 202)
+ body = json.loads(res.body)
+ self.assertEqual(body['server']['image']['id'], '2')
+ self.assertEqual(body['server']['adminPass'], 'asdf')
+
+ def test_server_rebuild_server_not_found(self):
+ def server_not_found(self, instance_id):
+ raise exception.InstanceNotFound(instance_id=instance_id)
+ self.stubs.Set(nova.db.api, 'instance_get', server_not_found)
+
+ body = {
+ "rebuild": {
+ "imageRef": "http://localhost/images/2",
+ },
+ }
+
+ req = webob.Request.blank('/v1.1/fake/servers/1/action')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ req.body = json.dumps(body)
+
+ res = req.get_response(fakes.wsgi_app())
+ self.assertEqual(res.status_int, 404)
def test_resize_server(self):
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index dc4e73508..3905e4f7a 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -4594,3 +4594,138 @@ class ServerXMLSerializationTest(test.TestCase):
str(ip['version']))
self.assertEqual(str(ip_elem.get('addr')),
str(ip['addr']))
+
+ def test_action(self):
+ serializer = servers.ServerXMLSerializer()
+
+ fixture = {
+ "server": {
+ "id": 1,
+ "uuid": FAKE_UUID,
+ 'created': self.TIMESTAMP,
+ 'updated': self.TIMESTAMP,
+ "progress": 0,
+ "name": "test_server",
+ "status": "BUILD",
+ "accessIPv4": "1.2.3.4",
+ "accessIPv6": "fead::1234",
+ "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, 'action')
+ root = etree.XML(output)
+ xmlutil.validate_schema(root, 'server')
+
+ 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
+ server_dict = fixture['server']
+
+ for key in ['name', 'id', 'uuid', 'created', 'accessIPv4',
+ 'updated', 'progress', 'status', 'hostId',
+ 'accessIPv6', 'adminPass']:
+ self.assertEqual(root.get(key), str(server_dict[key]))
+
+ link_nodes = root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 2)
+ for i, link in enumerate(server_dict['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ metadata_root = root.find('{0}metadata'.format(NS))
+ metadata_elems = metadata_root.findall('{0}meta'.format(NS))
+ self.assertEqual(len(metadata_elems), 2)
+ for i, metadata_elem in enumerate(metadata_elems):
+ (meta_key, meta_value) = server_dict['metadata'].items()[i]
+ self.assertEqual(str(metadata_elem.get('key')), str(meta_key))
+ self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
+
+ image_root = root.find('{0}image'.format(NS))
+ self.assertEqual(image_root.get('id'), server_dict['image']['id'])
+ link_nodes = image_root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 1)
+ for i, link in enumerate(server_dict['image']['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ flavor_root = root.find('{0}flavor'.format(NS))
+ self.assertEqual(flavor_root.get('id'), server_dict['flavor']['id'])
+ link_nodes = flavor_root.findall('{0}link'.format(ATOMNS))
+ self.assertEqual(len(link_nodes), 1)
+ for i, link in enumerate(server_dict['flavor']['links']):
+ for key, value in link.items():
+ self.assertEqual(link_nodes[i].get(key), value)
+
+ addresses_root = root.find('{0}addresses'.format(NS))
+ addresses_dict = server_dict['addresses']
+ network_elems = addresses_root.findall('{0}network'.format(NS))
+ self.assertEqual(len(network_elems), 2)
+ for i, network_elem in enumerate(network_elems):
+ network = addresses_dict.items()[i]
+ self.assertEqual(str(network_elem.get('id')), str(network[0]))
+ ip_elems = network_elem.findall('{0}ip'.format(NS))
+ for z, ip_elem in enumerate(ip_elems):
+ ip = network[1][z]
+ self.assertEqual(str(ip_elem.get('version')),
+ str(ip['version']))
+ self.assertEqual(str(ip_elem.get('addr')),
+ str(ip['addr']))
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index cb6a6f54a..766a7da9b 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -176,8 +176,9 @@ class ComputeTestCase(test.TestCase):
db.instance_destroy(self.context, instance_id)
def test_default_hostname_generator(self):
- cases = [(None, 'server_1'), ('Hello, Server!', 'hello_server'),
- ('<}\x1fh\x10e\x08l\x02l\x05o\x12!{>', 'hello')]
+ cases = [(None, 'server-1'), ('Hello, Server!', 'hello-server'),
+ ('<}\x1fh\x10e\x08l\x02l\x05o\x12!{>', 'hello'),
+ ('hello_server', 'hello-server')]
for display_name, hostname in cases:
ref = self.compute_api.create(self.context,
instance_types.get_default_instance_type(), None,
diff --git a/nova/tests/test_ipv6.py b/nova/tests/test_ipv6.py
index d123df6f1..04c1b5598 100644
--- a/nova/tests/test_ipv6.py
+++ b/nova/tests/test_ipv6.py
@@ -40,6 +40,25 @@ class IPv6RFC2462TestCase(test.TestCase):
mac = ipv6.to_mac('2001:db8::216:3eff:fe33:4455')
self.assertEquals(mac, '00:16:3e:33:44:55')
+ def test_to_global_with_bad_mac(self):
+ bad_mac = '02:16:3e:33:44:5Z'
+ self.assertRaises(TypeError, ipv6.to_global,
+ '2001:db8::', bad_mac, 'test')
+
+ def test_to_global_with_bad_prefix(self):
+ bad_prefix = '82'
+ self.assertRaises(TypeError, ipv6.to_global,
+ bad_prefix,
+ '2001:db8::216:3eff:fe33:4455',
+ 'test')
+
+ def test_to_global_with_bad_project(self):
+ bad_project = 'non-existent-project-name'
+ self.assertRaises(TypeError, ipv6.to_global,
+ '2001:db8::',
+ '2001:db8::a94a:8fe5:ff33:4455',
+ bad_project)
+
class IPv6AccountIdentiferTestCase(test.TestCase):
"""Unit tests for IPv6 account_identifier backend operations."""
@@ -55,3 +74,22 @@ class IPv6AccountIdentiferTestCase(test.TestCase):
def test_to_mac(self):
mac = ipv6.to_mac('2001:db8::a94a:8fe5:ff33:4455')
self.assertEquals(mac, '02:16:3e:33:44:55')
+
+ def test_to_global_with_bad_mac(self):
+ bad_mac = '02:16:3e:33:44:5X'
+ self.assertRaises(TypeError, ipv6.to_global,
+ '2001:db8::', bad_mac, 'test')
+
+ def test_to_global_with_bad_prefix(self):
+ bad_prefix = '78'
+ self.assertRaises(TypeError, ipv6.to_global,
+ bad_prefix,
+ '2001:db8::a94a:8fe5:ff33:4455',
+ 'test')
+
+ def test_to_global_with_bad_project(self):
+ bad_project = 'non-existent-project-name'
+ self.assertRaises(TypeError, ipv6.to_global,
+ '2001:db8::',
+ '2001:db8::a94a:8fe5:ff33:4455',
+ bad_project)
diff --git a/nova/tests/test_versions.py b/nova/tests/test_versions.py
new file mode 100644
index 000000000..4621b042b
--- /dev/null
+++ b/nova/tests/test_versions.py
@@ -0,0 +1,61 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Ken Pepple
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+from nova import exception
+from nova import test
+from nova import utils
+from nova import version
+
+
+class VersionTestCase(test.TestCase):
+ """Test cases for Versions code"""
+ def setUp(self):
+ """setup test with unchanging values"""
+ super(VersionTestCase, self).setUp()
+ self.version = version
+ self.version.FINAL = False
+ self.version.NOVA_VERSION = ['2012', '10']
+ self.version.YEAR, self.version.COUNT = self.version.NOVA_VERSION
+ self.version.version_info = {'branch_nick': u'LOCALBRANCH',
+ 'revision_id': 'LOCALREVISION',
+ 'revno': 0}
+
+ def test_version_string_is_good(self):
+ """Ensure version string works"""
+ self.assertEqual("2012.10-dev", self.version.version_string())
+
+ def test_canonical_version_string_is_good(self):
+ """Ensure canonical version works"""
+ self.assertEqual("2012.10", self.version.canonical_version_string())
+
+ def test_final_version_strings_are_identical(self):
+ """Ensure final version strings match only at release"""
+ self.assertNotEqual(self.version.canonical_version_string(),
+ self.version.version_string())
+ self.version.FINAL = True
+ self.assertEqual(self.version.canonical_version_string(),
+ self.version.version_string())
+
+ def test_vcs_version_string_is_good(self):
+ """Ensure uninstalled code generates local """
+ self.assertEqual("LOCALBRANCH:LOCALREVISION",
+ self.version.vcs_version_string())
+
+ def test_version_string_with_vcs_is_good(self):
+ """Ensure uninstalled code get version string"""
+ self.assertEqual("2012.10-LOCALBRANCH:LOCALREVISION",
+ self.version.version_string_with_vcs())