nova/nova/tests/api/openstack/test_servers.py

3864 lines
141 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010-2011 OpenStack LLC.
# All Rights Reserved.
#
# 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.
import base64
import datetime
import json
import unittest
from xml.dom import minidom
import webob
from nova import context
from nova import db
from nova import exception
from nova import test
from nova import utils
import nova.api.openstack
from nova.api.openstack import create_instance_helper
from nova.api.openstack import servers
from nova.api.openstack import wsgi
import nova.compute.api
from nova.compute import instance_types
from nova.compute import power_state
import nova.db.api
import nova.scheduler.api
from nova.db.sqlalchemy.models import Instance
from nova.db.sqlalchemy.models import InstanceMetadata
import nova.image.fake
import nova.rpc
from nova.tests.api.openstack import common
from nova.tests.api.openstack import fakes
FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
def fake_gen_uuid():
return FAKE_UUID
def return_server_by_id(context, id):
return stub_instance(id)
def return_server_by_uuid(context, uuid):
id = 1
return stub_instance(id, uuid=uuid)
def return_virtual_interface_by_instance(interfaces):
def _return_virtual_interface_by_instance(context, instance_id):
return interfaces
return _return_virtual_interface_by_instance
def return_virtual_interface_instance_nonexistant(interfaces):
def _return_virtual_interface_by_instance(context, instance_id):
raise exception.InstanceNotFound(instance_id=instance_id)
return _return_virtual_interface_by_instance
def return_server_with_attributes(**kwargs):
def _return_server(context, id):
return stub_instance(id, **kwargs)
return _return_server
def return_server_with_addresses(private, public):
def _return_server(context, id):
return stub_instance(id, private_address=private,
public_addresses=public)
return _return_server
def return_server_with_power_state(power_state):
def _return_server(context, id):
return stub_instance(id, power_state=power_state)
return _return_server
def return_server_with_uuid_and_power_state(power_state):
def _return_server(context, id):
return stub_instance(id, uuid=FAKE_UUID, power_state=power_state)
return _return_server
def return_servers(context, *args, **kwargs):
return [stub_instance(i, 'fake', 'fake') for i in xrange(5)]
def return_servers_by_reservation(context, reservation_id=""):
return [stub_instance(i, reservation_id) for i in xrange(5)]
def return_servers_by_reservation_empty(context, reservation_id=""):
return []
def return_servers_from_child_zones_empty(*args, **kwargs):
return []
def return_servers_from_child_zones(*args, **kwargs):
class Server(object):
pass
zones = []
for zone in xrange(3):
servers = []
for server_id in xrange(5):
server = Server()
server._info = stub_instance(server_id, reservation_id="child")
servers.append(server)
zones.append(("Zone%d" % zone, servers))
return zones
def return_security_group(context, instance_id, security_group_id):
pass
def instance_update(context, instance_id, values):
return stub_instance(instance_id, name=values.get('display_name'))
def instance_addresses(context, instance_id):
return None
def stub_instance(id, user_id='fake', project_id='fake', private_address=None,
public_addresses=None, host=None, power_state=0,
reservation_id="", uuid=FAKE_UUID, image_ref="10",
flavor_id="1", interfaces=None, name=None):
metadata = []
metadata.append(InstanceMetadata(key='seq', value=id))
if interfaces is None:
interfaces = []
inst_type = instance_types.get_instance_type_by_flavor_id(int(flavor_id))
if public_addresses is None:
public_addresses = list()
if host is not None:
host = str(host)
# ReservationID isn't sent back, hack it in there.
server_name = name or "server%s" % id
if reservation_id != "":
server_name = "reservation_%s" % (reservation_id, )
instance = {
"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": user_id,
"project_id": project_id,
"image_ref": image_ref,
"kernel_id": "",
"ramdisk_id": "",
"launch_index": 0,
"key_name": "",
"key_data": "",
"state": power_state,
"state_description": "",
"memory_mb": 0,
"vcpus": 0,
"local_gb": 0,
"hostname": "",
"host": host,
"instance_type": dict(inst_type),
"user_data": "",
"reservation_id": reservation_id,
"mac_address": "",
"scheduled_at": utils.utcnow(),
"launched_at": utils.utcnow(),
"terminated_at": utils.utcnow(),
"availability_zone": "",
"display_name": server_name,
"display_description": "",
"locked": False,
"metadata": metadata,
"uuid": uuid,
"virtual_interfaces": interfaces}
instance["fixed_ips"] = {
"address": private_address,
"floating_ips": [{"address":ip} for ip in public_addresses]}
return instance
def fake_compute_api(cls, req, id):
return True
def find_host(self, context, instance_id):
return "nova"
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 ServersTest(test.TestCase):
def setUp(self):
self.maxDiff = None
super(ServersTest, self).setUp()
self.flags(verbose=True)
fakes.stub_out_networking(self.stubs)
fakes.stub_out_rate_limiting(self.stubs)
fakes.stub_out_key_pair_funcs(self.stubs)
fakes.stub_out_image_service(self.stubs)
self.stubs.Set(utils, 'gen_uuid', fake_gen_uuid)
self.stubs.Set(nova.db.api, 'instance_get_all_by_filters',
return_servers)
self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id)
self.stubs.Set(nova.db, 'instance_get_by_uuid',
return_server_by_uuid)
self.stubs.Set(nova.db.api, 'instance_get_all_by_project',
return_servers)
self.stubs.Set(nova.db.api, 'instance_add_security_group',
return_security_group)
self.stubs.Set(nova.db.api, 'instance_update', instance_update)
self.stubs.Set(nova.db.api, 'instance_get_fixed_addresses',
instance_addresses)
self.stubs.Set(nova.db.api, 'instance_get_floating_address',
instance_addresses)
self.stubs.Set(nova.compute.API, 'pause', fake_compute_api)
self.stubs.Set(nova.compute.API, 'unpause', fake_compute_api)
self.stubs.Set(nova.compute.API, 'suspend', fake_compute_api)
self.stubs.Set(nova.compute.API, 'resume', fake_compute_api)
self.stubs.Set(nova.compute.API, "get_diagnostics", fake_compute_api)
self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api)
self.webreq = common.webob_factory('/v1.0/servers')
def test_get_server_by_id(self):
req = webob.Request.blank('/v1.0/servers/1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['name'], 'server1')
def test_get_server_by_uuid(self):
"""
The steps involved with resolving a UUID are pretty complicated;
here's what's happening in this scenario:
1. Show is calling `routing_get`
2. `routing_get` is wrapped by `reroute_compute` which does the work
of resolving requests to child zones.
3. `reroute_compute` looks up the UUID by hitting the stub
(returns_server_by_uuid)
4. Since the stub return that the record exists, `reroute_compute`
considers the request to be 'zone local', so it replaces the UUID
in the argument list with an integer ID and then calls the inner
function ('get').
5. The call to `get` hits the other stub 'returns_server_by_id` which
has the UUID set to FAKE_UUID
So, counterintuitively, we call `get` twice on the `show` command.
"""
req = webob.Request.blank('/v1.0/servers/%s' % FAKE_UUID)
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['uuid'], FAKE_UUID)
self.assertEqual(res_dict['server']['name'], 'server1')
def test_get_server_by_id_v1_1(self):
image_bookmark = "http://localhost/images/10"
flavor_ref = "http://localhost/v1.1/flavors/1"
flavor_id = "1"
flavor_bookmark = "http://localhost/flavors/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')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
expected_server = {
"server": {
"id": 1,
"uuid": FAKE_UUID,
"updated": "2010-11-11T11:00:00Z",
"created": "2010-10-10T12:00:00Z",
"progress": 0,
"name": "server1",
"status": "BUILD",
"hostId": '',
"image": {
"id": "10",
"links": [
{
"rel": "bookmark",
"href": image_bookmark,
},
],
},
"flavor": {
"id": "1",
"links": [
{
"rel": "bookmark",
"href": flavor_bookmark,
},
],
},
"addresses": {
"public": [
{
"version": 4,
"addr": public_ip,
},
],
"private": [
{
"version": 4,
"addr": private_ip,
},
],
},
"metadata": {
"seq": "1",
},
"links": [
{
"rel": "self",
#FIXME(wwolf) Do we want the links to be id or uuid?
"href": "http://localhost/v1.1/servers/1",
},
{
"rel": "bookmark",
"href": "http://localhost/servers/1",
},
],
}
}
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"
flavor_id = "1"
flavor_bookmark = "http://localhost/flavors/1"
private_ip = "192.168.0.3"
public_ip = "1.2.3.4"
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, power_state=1)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.1/servers/1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
expected_server = {
"server": {
"id": 1,
"uuid": FAKE_UUID,
"updated": "2010-11-11T11:00:00Z",
"created": "2010-10-10T12:00:00Z",
"progress": 100,
"name": "server1",
"status": "ACTIVE",
"hostId": '',
"image": {
"id": "10",
"links": [
{
"rel": "bookmark",
"href": image_bookmark,
},
],
},
"flavor": {
"id": "1",
"links": [
{
"rel": "bookmark",
"href": flavor_bookmark,
},
],
},
"addresses": {
"public": [
{
"version": 4,
"addr": public_ip,
},
],
"private": [
{
"version": 4,
"addr": private_ip,
},
],
},
"metadata": {
"seq": "1",
},
"links": [
{
"rel": "self",
"href": "http://localhost/v1.1/servers/1",
},
{
"rel": "bookmark",
"href": "http://localhost/servers/1",
},
],
}
}
self.assertDictMatch(res_dict, expected_server)
def test_get_server_with_id_image_ref_by_id_v1_1(self):
image_ref = "10"
image_bookmark = "http://localhost/images/10"
flavor_ref = "http://localhost/v1.1/flavors/1"
flavor_id = "1"
flavor_bookmark = "http://localhost/flavors/1"
private_ip = "192.168.0.3"
public_ip = "1.2.3.4"
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, power_state=1, image_ref=image_ref,
flavor_id=flavor_id)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.1/servers/1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
expected_server = {
"server": {
"id": 1,
"uuid": FAKE_UUID,
"updated": "2010-11-11T11:00:00Z",
"created": "2010-10-10T12:00:00Z",
"progress": 100,
"name": "server1",
"status": "ACTIVE",
"hostId": '',
"image": {
"id": "10",
"links": [
{
"rel": "bookmark",
"href": image_bookmark,
},
],
},
"flavor": {
"id": "1",
"links": [
{
"rel": "bookmark",
"href": flavor_bookmark,
},
],
},
"addresses": {
"public": [
{
"version": 4,
"addr": public_ip,
},
],
"private": [
{
"version": 4,
"addr": private_ip,
},
],
},
"metadata": {
"seq": "1",
},
"links": [
{
"rel": "self",
"href": "http://localhost/v1.1/servers/1",
},
{
"rel": "bookmark",
"href": "http://localhost/servers/1",
},
],
}
}
self.assertDictMatch(res_dict, expected_server)
def test_get_server_by_id_with_addresses_xml(self):
private = "192.168.0.3"
public = ["1.2.3.4"]
new_return_server = return_server_with_addresses(private, public)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1')
req.headers['Accept'] = 'application/xml'
res = req.get_response(fakes.wsgi_app())
dom = minidom.parseString(res.body)
server = dom.childNodes[0]
self.assertEquals(server.nodeName, 'server')
self.assertEquals(server.getAttribute('id'), '1')
self.assertEquals(server.getAttribute('name'), 'server1')
(public,) = server.getElementsByTagName('public')
(ip,) = public.getElementsByTagName('ip')
self.assertEquals(ip.getAttribute('addr'), '1.2.3.4')
(private,) = server.getElementsByTagName('private')
(ip,) = private.getElementsByTagName('ip')
self.assertEquals(ip.getAttribute('addr'), '192.168.0.3')
def test_get_server_by_id_with_addresses(self):
private = "192.168.0.3"
public = ["1.2.3.4"]
new_return_server = return_server_with_addresses(private, public)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['name'], 'server1')
addresses = res_dict['server']['addresses']
self.assertEqual(len(addresses["public"]), len(public))
self.assertEqual(addresses["public"][0], public[0])
self.assertEqual(len(addresses["private"]), 1)
self.assertEqual(addresses["private"][0], private)
def test_get_server_addresses_v1_0(self):
private = '192.168.0.3'
public = ['1.2.3.4']
new_return_server = return_server_with_addresses(private, public)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1/ips')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict, {
'addresses': {'public': public, 'private': [private]}})
def test_get_server_addresses_xml_v1_0(self):
private_expected = "192.168.0.3"
public_expected = ["1.2.3.4"]
new_return_server = return_server_with_addresses(private_expected,
public_expected)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1/ips')
req.headers['Accept'] = 'application/xml'
res = req.get_response(fakes.wsgi_app())
dom = minidom.parseString(res.body)
(addresses,) = dom.childNodes
self.assertEquals(addresses.nodeName, 'addresses')
(public,) = addresses.getElementsByTagName('public')
(ip,) = public.getElementsByTagName('ip')
self.assertEquals(ip.getAttribute('addr'), public_expected[0])
(private,) = addresses.getElementsByTagName('private')
(ip,) = private.getElementsByTagName('ip')
self.assertEquals(ip.getAttribute('addr'), private_expected)
def test_get_server_addresses_public_v1_0(self):
private = "192.168.0.3"
public = ["1.2.3.4"]
new_return_server = return_server_with_addresses(private, public)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1/ips/public')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict, {'public': public})
def test_get_server_addresses_private_v1_0(self):
private = "192.168.0.3"
public = ["1.2.3.4"]
new_return_server = return_server_with_addresses(private, public)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1/ips/private')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict, {'private': [private]})
def test_get_server_addresses_public_xml_v1_0(self):
private = "192.168.0.3"
public = ["1.2.3.4"]
new_return_server = return_server_with_addresses(private, public)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1/ips/public')
req.headers['Accept'] = 'application/xml'
res = req.get_response(fakes.wsgi_app())
dom = minidom.parseString(res.body)
(public_node,) = dom.childNodes
self.assertEquals(public_node.nodeName, 'public')
(ip,) = public_node.getElementsByTagName('ip')
self.assertEquals(ip.getAttribute('addr'), public[0])
def test_get_server_addresses_private_xml_v1_0(self):
private = "192.168.0.3"
public = ["1.2.3.4"]
new_return_server = return_server_with_addresses(private, public)
self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
req = webob.Request.blank('/v1.0/servers/1/ips/private')
req.headers['Accept'] = 'application/xml'
res = req.get_response(fakes.wsgi_app())
dom = minidom.parseString(res.body)
(private_node,) = dom.childNodes
self.assertEquals(private_node.nodeName, 'private')
(ip,) = private_node.getElementsByTagName('ip')
self.assertEquals(ip.getAttribute('addr'), private)
def test_get_server_by_id_with_addresses_v1_1(self):
self.flags(use_ipv6=True)
interfaces = [
{
'network': {'label': 'network_1'},
'fixed_ips': [
{'address': '192.168.0.3'},
{'address': '192.168.0.4'},
],
},
{
'network': {'label': 'network_2'},
'fixed_ips': [
{'address': '172.19.0.1'},
{'address': '172.19.0.2'},
],
'fixed_ipv6': '2001:4860::12',
},
]
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')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['name'], 'server1')
addresses = res_dict['server']['addresses']
expected = {
'network_1': [
{'addr': '192.168.0.3', 'version': 4},
{'addr': '192.168.0.4', 'version': 4},
],
'network_2': [
{'addr': '172.19.0.1', 'version': 4},
{'addr': '172.19.0.2', 'version': 4},
{'addr': '2001:4860::12', 'version': 6},
],
}
self.assertEqual(addresses, expected)
def test_get_server_by_id_with_addresses_v1_1_ipv6_disabled(self):
self.flags(use_ipv6=False)
interfaces = [
{
'network': {'label': 'network_1'},
'fixed_ips': [
{'address': '192.168.0.3'},
{'address': '192.168.0.4'},
],
},
{
'network': {'label': 'network_2'},
'fixed_ips': [
{'address': '172.19.0.1'},
{'address': '172.19.0.2'},
],
'fixed_ipv6': '2001:4860::12',
},
]
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')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['name'], 'server1')
addresses = res_dict['server']['addresses']
expected = {
'network_1': [
{'addr': '192.168.0.3', 'version': 4},
{'addr': '192.168.0.4', 'version': 4},
],
'network_2': [
{'addr': '172.19.0.1', 'version': 4},
{'addr': '172.19.0.2', 'version': 4},
],
}
self.assertEqual(addresses, expected)
def test_get_server_addresses_v1_1(self):
self.flags(use_ipv6=True)
interfaces = [
{
'network': {'label': 'network_1'},
'fixed_ips': [
{'address': '192.168.0.3'},
{'address': '192.168.0.4'},
],
},
{
'network': {'label': 'network_2'},
'fixed_ips': [
{
'address': '172.19.0.1',
'floating_ips': [
{'address': '1.2.3.4'},
],
},
{'address': '172.19.0.2'},
],
'fixed_ipv6': '2001:4860::12',
},
]
_return_vifs = return_virtual_interface_by_instance(interfaces)
self.stubs.Set(nova.db.api,
'virtual_interface_get_by_instance',
_return_vifs)
req = webob.Request.blank('/v1.1/servers/1/ips')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
expected = {
'addresses': {
'network_1': [
{'version': 4, 'addr': '192.168.0.3'},
{'version': 4, 'addr': '192.168.0.4'},
],
'network_2': [
{'version': 4, 'addr': '172.19.0.1'},
{'version': 4, 'addr': '1.2.3.4'},
{'version': 4, 'addr': '172.19.0.2'},
{'version': 6, 'addr': '2001:4860::12'},
],
},
}
self.assertEqual(res_dict, expected)
def test_get_server_addresses_single_network_v1_1(self):
self.flags(use_ipv6=True)
interfaces = [
{
'network': {'label': 'network_1'},
'fixed_ips': [
{'address': '192.168.0.3'},
{'address': '192.168.0.4'},
],
},
{
'network': {'label': 'network_2'},
'fixed_ips': [
{
'address': '172.19.0.1',
'floating_ips': [
{'address': '1.2.3.4'},
],
},
{'address': '172.19.0.2'},
],
'fixed_ipv6': '2001:4860::12',
},
]
_return_vifs = return_virtual_interface_by_instance(interfaces)
self.stubs.Set(nova.db.api,
'virtual_interface_get_by_instance',
_return_vifs)
req = webob.Request.blank('/v1.1/servers/1/ips/network_2')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
expected = {
'network_2': [
{'version': 4, 'addr': '172.19.0.1'},
{'version': 4, 'addr': '1.2.3.4'},
{'version': 4, 'addr': '172.19.0.2'},
{'version': 6, 'addr': '2001:4860::12'},
],
}
self.assertEqual(res_dict, expected)
def test_get_server_addresses_nonexistant_network_v1_1(self):
_return_vifs = return_virtual_interface_by_instance([])
self.stubs.Set(nova.db.api,
'virtual_interface_get_by_instance',
_return_vifs)
req = webob.Request.blank('/v1.1/servers/1/ips/network_0')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
def test_get_server_addresses_nonexistant_server_v1_1(self):
_return_vifs = return_virtual_interface_instance_nonexistant([])
self.stubs.Set(nova.db.api,
'virtual_interface_get_by_instance',
_return_vifs)
req = webob.Request.blank('/v1.1/servers/600/ips')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
def test_get_server_list(self):
req = webob.Request.blank('/v1.0/servers')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(len(res_dict['servers']), 5)
i = 0
for s in res_dict['servers']:
self.assertEqual(s['id'], i)
self.assertEqual(s['name'], 'server%d' % i)
self.assertEqual(s.get('imageId', None), None)
i += 1
def test_get_server_list_with_reservation_id(self):
self.stubs.Set(nova.db.api, 'instance_get_all_by_reservation',
return_servers_by_reservation)
self.stubs.Set(nova.scheduler.api, 'call_zone_method',
return_servers_from_child_zones)
req = webob.Request.blank('/v1.0/servers?reservation_id=foo')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
i = 0
for s in res_dict['servers']:
if '_is_precooked' in s:
self.assertEqual(s.get('reservation_id'), 'child')
else:
self.assertEqual(s.get('name'), 'server%d' % i)
i += 1
def test_get_server_list_with_reservation_id_empty(self):
self.stubs.Set(nova.db.api, 'instance_get_all_by_reservation',
return_servers_by_reservation_empty)
self.stubs.Set(nova.scheduler.api, 'call_zone_method',
return_servers_from_child_zones_empty)
req = webob.Request.blank('/v1.0/servers/detail?reservation_id=foo')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
i = 0
for s in res_dict['servers']:
if '_is_precooked' in s:
self.assertEqual(s.get('reservation_id'), 'child')
else:
self.assertEqual(s.get('name'), 'server%d' % i)
i += 1
def test_get_server_list_with_reservation_id_details(self):
self.stubs.Set(nova.db.api, 'instance_get_all_by_reservation',
return_servers_by_reservation)
self.stubs.Set(nova.scheduler.api, 'call_zone_method',
return_servers_from_child_zones)
req = webob.Request.blank('/v1.0/servers/detail?reservation_id=foo')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
i = 0
for s in res_dict['servers']:
if '_is_precooked' in s:
self.assertEqual(s.get('reservation_id'), 'child')
else:
self.assertEqual(s.get('name'), 'server%d' % i)
i += 1
def test_get_server_list_v1_1(self):
req = webob.Request.blank('/v1.1/servers')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
self.assertEqual(len(res_dict['servers']), 5)
for i, s in enumerate(res_dict['servers']):
self.assertEqual(s['id'], i)
self.assertEqual(s['name'], 'server%d' % i)
self.assertEqual(s.get('image', None), None)
expected_links = [
{
"rel": "self",
"href": "http://localhost/v1.1/servers/%s" % s['id'],
},
{
"rel": "bookmark",
"href": "http://localhost/servers/%s" % s['id'],
},
]
self.assertEqual(s['links'], expected_links)
def test_get_servers_with_limit(self):
req = webob.Request.blank('/v1.0/servers?limit=3')
res = req.get_response(fakes.wsgi_app())
servers = json.loads(res.body)['servers']
self.assertEqual([s['id'] for s in servers], [0, 1, 2])
req = webob.Request.blank('/v1.0/servers?limit=aaa')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
self.assertTrue('limit' in res.body)
def test_get_servers_with_offset(self):
req = webob.Request.blank('/v1.0/servers?offset=2')
res = req.get_response(fakes.wsgi_app())
servers = json.loads(res.body)['servers']
self.assertEqual([s['id'] for s in servers], [2, 3, 4])
req = webob.Request.blank('/v1.0/servers?offset=aaa')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
self.assertTrue('offset' in res.body)
def test_get_servers_with_limit_and_offset(self):
req = webob.Request.blank('/v1.0/servers?limit=2&offset=1')
res = req.get_response(fakes.wsgi_app())
servers = json.loads(res.body)['servers']
self.assertEqual([s['id'] for s in servers], [1, 2])
def test_get_servers_with_bad_limit(self):
req = webob.Request.blank('/v1.0/servers?limit=asdf&offset=1')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
self.assertTrue(res.body.find('limit param') > -1)
def test_get_servers_with_bad_offset(self):
req = webob.Request.blank('/v1.0/servers?limit=2&offset=asdf')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
self.assertTrue(res.body.find('offset param') > -1)
def test_get_servers_with_marker(self):
req = webob.Request.blank('/v1.1/servers?marker=2')
res = req.get_response(fakes.wsgi_app())
servers = json.loads(res.body)['servers']
self.assertEqual([s['name'] for s in servers], ["server3", "server4"])
def test_get_servers_with_limit_and_marker(self):
req = webob.Request.blank('/v1.1/servers?limit=2&marker=1')
res = req.get_response(fakes.wsgi_app())
servers = json.loads(res.body)['servers']
self.assertEqual([s['name'] for s in servers], ['server2', 'server3'])
def test_get_servers_with_bad_marker(self):
req = webob.Request.blank('/v1.1/servers?limit=2&marker=asdf')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
self.assertTrue(res.body.find('marker param') > -1)
def test_get_servers_with_bad_option_v1_0(self):
# 1.0 API ignores unknown options
def fake_get_all(compute_self, context, search_opts=None):
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
req = webob.Request.blank('/v1.0/servers?unknownoption=whee')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_with_bad_option_v1_1(self):
# 1.1 API also ignores unknown options
def fake_get_all(compute_self, context, search_opts=None):
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
req = webob.Request.blank('/v1.1/servers?unknownoption=whee')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_allows_image_v1_1(self):
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
self.assertTrue('image' in search_opts)
self.assertEqual(search_opts['image'], '12345')
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
self.flags(allow_admin_api=False)
req = webob.Request.blank('/v1.1/servers?image=12345')
res = req.get_response(fakes.wsgi_app())
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_allows_flavor_v1_1(self):
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
self.assertTrue('flavor' in search_opts)
# flavor is an integer ID
self.assertEqual(search_opts['flavor'], '12345')
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
self.flags(allow_admin_api=False)
req = webob.Request.blank('/v1.1/servers?flavor=12345')
res = req.get_response(fakes.wsgi_app())
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_allows_status_v1_1(self):
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
self.assertTrue('state' in search_opts)
self.assertEqual(set(search_opts['state']),
set([power_state.RUNNING, power_state.BLOCKED]))
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
self.flags(allow_admin_api=False)
req = webob.Request.blank('/v1.1/servers?status=active')
res = req.get_response(fakes.wsgi_app())
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_invalid_status_v1_1(self):
"""Test getting servers by invalid status"""
self.flags(allow_admin_api=False)
req = webob.Request.blank('/v1.1/servers?status=running')
res = req.get_response(fakes.wsgi_app())
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 400)
self.assertTrue(res.body.find('Invalid server status') > -1)
def test_get_servers_allows_name_v1_1(self):
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
self.assertTrue('name' in search_opts)
self.assertEqual(search_opts['name'], 'whee.*')
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
self.flags(allow_admin_api=False)
req = webob.Request.blank('/v1.1/servers?name=whee.*')
res = req.get_response(fakes.wsgi_app())
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_unknown_or_admin_options1(self):
"""Test getting servers by admin-only or unknown options.
This tests when admin_api is off. Make sure the admin and
unknown options are stripped before they get to
compute_api.get_all()
"""
self.flags(allow_admin_api=False)
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
# Allowed by user
self.assertTrue('name' in search_opts)
self.assertTrue('status' in search_opts)
# Allowed only by admins with admin API on
self.assertFalse('ip' in search_opts)
self.assertFalse('unknown_option' in search_opts)
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
req = webob.Request.blank('/v1.1/servers?%s' % query_str)
# Request admin context
context = nova.context.RequestContext('testuser', 'testproject',
is_admin=True)
res = req.get_response(fakes.wsgi_app(fake_auth_context=context))
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_unknown_or_admin_options2(self):
"""Test getting servers by admin-only or unknown options.
This tests when admin_api is on, but context is a user.
Make sure the admin and unknown options are stripped before
they get to compute_api.get_all()
"""
self.flags(allow_admin_api=True)
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
# Allowed by user
self.assertTrue('name' in search_opts)
self.assertTrue('status' in search_opts)
# Allowed only by admins with admin API on
self.assertFalse('ip' in search_opts)
self.assertFalse('unknown_option' in search_opts)
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
req = webob.Request.blank('/v1.1/servers?%s' % query_str)
# Request admin context
context = nova.context.RequestContext('testuser', 'testproject',
is_admin=False)
res = req.get_response(fakes.wsgi_app(fake_auth_context=context))
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_unknown_or_admin_options3(self):
"""Test getting servers by admin-only or unknown options.
This tests when admin_api is on and context is admin.
All options should be passed through to compute_api.get_all()
"""
self.flags(allow_admin_api=True)
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
# Allowed by user
self.assertTrue('name' in search_opts)
self.assertTrue('status' in search_opts)
# Allowed only by admins with admin API on
self.assertTrue('ip' in search_opts)
self.assertTrue('unknown_option' in search_opts)
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
query_str = "name=foo&ip=10.*&status=active&unknown_option=meow"
req = webob.Request.blank('/v1.1/servers?%s' % query_str)
# Request admin context
context = nova.context.RequestContext('testuser', 'testproject',
is_admin=True)
res = req.get_response(fakes.wsgi_app(fake_auth_context=context))
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_admin_allows_ip_v1_1(self):
"""Test getting servers by ip with admin_api enabled and
admin context
"""
self.flags(allow_admin_api=True)
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
self.assertTrue('ip' in search_opts)
self.assertEqual(search_opts['ip'], '10\..*')
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
req = webob.Request.blank('/v1.1/servers?ip=10\..*')
# Request admin context
context = nova.context.RequestContext('testuser', 'testproject',
is_admin=True)
res = req.get_response(fakes.wsgi_app(fake_auth_context=context))
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def test_get_servers_admin_allows_ip6_v1_1(self):
"""Test getting servers by ip6 with admin_api enabled and
admin context
"""
self.flags(allow_admin_api=True)
def fake_get_all(compute_self, context, search_opts=None):
self.assertNotEqual(search_opts, None)
self.assertTrue('ip6' in search_opts)
self.assertEqual(search_opts['ip6'], 'ffff.*')
return [stub_instance(100)]
self.stubs.Set(nova.compute.API, 'get_all', fake_get_all)
req = webob.Request.blank('/v1.1/servers?ip6=ffff.*')
# Request admin context
context = nova.context.RequestContext('testuser', 'testproject',
is_admin=True)
res = req.get_response(fakes.wsgi_app(fake_auth_context=context))
# The following assert will fail if either of the asserts in
# fake_get_all() fail
self.assertEqual(res.status_int, 200)
servers = json.loads(res.body)['servers']
self.assertEqual(len(servers), 1)
self.assertEqual(servers[0]['id'], 100)
def _setup_for_create_instance(self):
"""Shared implementation for tests below that create instance"""
def instance_create(context, inst):
inst_type = instance_types.get_instance_type_by_flavor_id(3)
image_ref = 'http://localhost/images/2'
return {'id': 1,
'display_name': 'server_test',
'uuid': FAKE_UUID,
'instance_type': dict(inst_type),
'image_ref': image_ref,
"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):
return instance_create(context, id)
def fake_method(*args, **kwargs):
pass
def project_get_networks(context, user_id):
return dict(id='1', host='localhost')
def queue_get_for(context, *args):
return 'network_topic'
def kernel_ramdisk_mapping(*args, **kwargs):
return (1, 1)
def image_id_from_hash(*args, **kwargs):
return 2
self.stubs.Set(nova.db.api, 'project_get_networks',
project_get_networks)
self.stubs.Set(nova.db.api, 'instance_create', instance_create)
self.stubs.Set(nova.rpc, 'cast', fake_method)
self.stubs.Set(nova.rpc, 'call', fake_method)
self.stubs.Set(nova.db.api, 'instance_update',
server_update)
self.stubs.Set(nova.db.api, 'queue_get_for', queue_get_for)
self.stubs.Set(nova.network.manager.VlanManager, 'allocate_fixed_ip',
fake_method)
self.stubs.Set(
nova.api.openstack.create_instance_helper.CreateInstanceHelper,
"_get_kernel_ramdisk_from_image", kernel_ramdisk_mapping)
self.stubs.Set(nova.compute.api.API, "_find_host", find_host)
def _test_create_instance_helper(self):
self._setup_for_create_instance()
body = dict(server=dict(
name='server_test', imageId=3, flavorId=2,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = webob.Request.blank('/v1.0/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
server = json.loads(res.body)['server']
self.assertEqual(16, len(server['adminPass']))
self.assertEqual('server_test', server['name'])
self.assertEqual(1, server['id'])
self.assertEqual(2, server['flavorId'])
self.assertEqual(3, server['imageId'])
self.assertEqual(FAKE_UUID, server['uuid'])
def test_create_instance(self):
self._test_create_instance_helper()
def test_create_instance_has_uuid(self):
"""Tests at the db-layer instead of API layer since that's where the
UUID is generated
"""
ctxt = context.RequestContext(1, 1)
values = {}
instance = nova.db.api.instance_create(ctxt, values)
expected = FAKE_UUID
self.assertEqual(instance['uuid'], expected)
def test_create_instance_via_zones(self):
"""Server generated ReservationID"""
self._setup_for_create_instance()
self.flags(allow_admin_api=True)
body = dict(server=dict(
name='server_test', imageId=3, flavorId=2,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = webob.Request.blank('/v1.0/zones/boot')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
reservation_id = json.loads(res.body)['reservation_id']
self.assertEqual(res.status_int, 200)
self.assertNotEqual(reservation_id, "")
self.assertNotEqual(reservation_id, None)
self.assertTrue(len(reservation_id) > 1)
def test_create_instance_via_zones_with_resid(self):
"""User supplied ReservationID"""
self._setup_for_create_instance()
self.flags(allow_admin_api=True)
body = dict(server=dict(
name='server_test', imageId=3, flavorId=2,
metadata={'hello': 'world', 'open': 'stack'},
personality={}, reservation_id='myresid'))
req = webob.Request.blank('/v1.0/zones/boot')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
reservation_id = json.loads(res.body)['reservation_id']
self.assertEqual(res.status_int, 200)
self.assertEqual(reservation_id, "myresid")
def test_create_instance_no_key_pair(self):
fakes.stub_out_key_pair_funcs(self.stubs, have_key_pair=False)
self._test_create_instance_helper()
def test_create_instance_no_name(self):
self._setup_for_create_instance()
body = {
'server': {
'imageId': 3,
'flavorId': 1,
'metadata': {
'hello': 'world',
'open': 'stack',
},
'personality': {},
},
}
req = webob.Request.blank('/v1.0/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_instance_nonstring_name(self):
self._setup_for_create_instance()
body = {
'server': {
'name': 12,
'imageId': 3,
'flavorId': 1,
'metadata': {
'hello': 'world',
'open': 'stack',
},
'personality': {},
},
}
req = webob.Request.blank('/v1.0/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_instance_no_server_entity(self):
self._setup_for_create_instance()
body = {}
req = webob.Request.blank('/v1.0/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 422)
def test_create_instance_whitespace_name(self):
self._setup_for_create_instance()
body = {
'server': {
'name': ' ',
'imageId': 3,
'flavorId': 1,
'metadata': {
'hello': 'world',
'open': 'stack',
},
'personality': {},
},
}
req = webob.Request.blank('/v1.0/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_instance_v1_1(self):
self._setup_for_create_instance()
# proper local hrefs must start with 'http://localhost/v1.1/'
image_href = 'http://localhost/v1.1/images/2'
flavor_ref = 'http://localhost/flavors/3'
expected_flavor = {
"id": "3",
"links": [
{
"rel": "bookmark",
"href": 'http://localhost/flavors/3',
},
],
}
expected_image = {
"id": "2",
"links": [
{
"rel": "bookmark",
"href": 'http://localhost/images/2',
},
],
}
body = {
'server': {
'name': 'server_test',
'imageRef': image_href,
'flavorRef': flavor_ref,
'metadata': {
'hello': 'world',
'open': 'stack',
},
'personality': [
{
"path": "/etc/banner.txt",
"contents": "MQ==",
},
],
},
}
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
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'])
def test_create_instance_v1_1_invalid_flavor_href(self):
self._setup_for_create_instance()
image_href = 'http://localhost/v1.1/images/2'
flavor_ref = 'http://localhost/v1.1/flavors/asdf'
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_instance_v1_1_invalid_flavor_id_int(self):
self._setup_for_create_instance()
image_href = 'http://localhost/v1.1/images/2'
flavor_ref = -1
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_instance_v1_1_bad_flavor_href(self):
self._setup_for_create_instance()
image_href = 'http://localhost/v1.1/images/2'
flavor_ref = 'http://localhost/v1.1/flavors/17'
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_instance_v1_1_bad_href(self):
self._setup_for_create_instance()
image_href = 'http://localhost/v1.1/images/asdf'
flavor_ref = 'http://localhost/v1.1/flavors/3'
body = dict(server=dict(
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
metadata={'hello': 'world', 'open': 'stack'},
personality={}))
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_create_instance_v1_1_local_href(self):
self._setup_for_create_instance()
image_id = "2"
flavor_ref = 'http://localhost/v1.1/flavors/3'
expected_flavor = {
"id": "3",
"links": [
{
"rel": "bookmark",
"href": 'http://localhost/flavors/3',
},
],
}
expected_image = {
"id": "2",
"links": [
{
"rel": "bookmark",
"href": 'http://localhost/images/2',
},
],
}
body = {
'server': {
'name': 'server_test',
'imageRef': image_id,
'flavorRef': flavor_ref,
},
}
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers["content-type"] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
server = json.loads(res.body)['server']
self.assertEqual(expected_flavor, server['flavor'])
self.assertEqual(expected_image, server['image'])
def test_create_instance_with_admin_pass_v1_0(self):
self._setup_for_create_instance()
body = {
'server': {
'name': 'test-server-create',
'imageId': 3,
'flavorId': 1,
'adminPass': 'testpass',
},
}
req = webob.Request.blank('/v1.0/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers['content-type'] = "application/json"
res = req.get_response(fakes.wsgi_app())
res = json.loads(res.body)
self.assertNotEqual(res['server']['adminPass'],
body['server']['adminPass'])
def test_create_instance_v1_1_admin_pass(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': 3,
'flavorRef': 3,
'adminPass': 'testpass',
},
}
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers['content-type'] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
server = json.loads(res.body)['server']
self.assertEqual(server['adminPass'], body['server']['adminPass'])
def test_create_instance_v1_1_admin_pass_empty(self):
self._setup_for_create_instance()
body = {
'server': {
'name': 'server_test',
'imageRef': 3,
'flavorRef': 3,
'adminPass': '',
},
}
req = webob.Request.blank('/v1.1/servers')
req.method = 'POST'
req.body = json.dumps(body)
req.headers['content-type'] = "application/json"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_update_server_no_body(self):
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'PUT'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_update_nonstring_name(self):
""" Confirm that update is filtering params """
inst_dict = dict(name=12, adminPass='bacon')
self.body = json.dumps(dict(server=inst_dict))
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'PUT'
req.content_type = "application/json"
req.body = self.body
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_update_whitespace_name(self):
""" Confirm that update is filtering params """
inst_dict = dict(name=' ', adminPass='bacon')
self.body = json.dumps(dict(server=inst_dict))
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'PUT'
req.content_type = "application/json"
req.body = self.body
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_update_null_name(self):
""" Confirm that update is filtering params """
inst_dict = dict(name='', adminPass='bacon')
self.body = json.dumps(dict(server=inst_dict))
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'PUT'
req.content_type = "application/json"
req.body = self.body
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_update_server_v1_0(self):
inst_dict = dict(name='server_test', adminPass='bacon')
self.body = json.dumps(dict(server=inst_dict))
def server_update(context, id, params):
filtered_dict = dict(display_name='server_test')
self.assertEqual(params, filtered_dict)
return filtered_dict
self.stubs.Set(nova.db.api, 'instance_update',
server_update)
self.stubs.Set(nova.compute.api.API, "_find_host", find_host)
mock_method = MockSetAdminPassword()
self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'PUT'
req.content_type = "application/json"
req.body = self.body
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 204)
self.assertEqual(mock_method.instance_id, '1')
self.assertEqual(mock_method.password, 'bacon')
def test_update_server_no_body_v1_1(self):
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'PUT'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 400)
def test_update_server_name_v1_1(self):
self.stubs.Set(nova.db.api, 'instance_get',
return_server_with_attributes(name='server_test'))
req = webob.Request.blank('/v1.1/servers/1')
req.method = 'PUT'
req.content_type = 'application/json'
req.body = json.dumps({'server': {'name': 'server_test'}})
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['name'], 'server_test')
def test_update_server_adminPass_ignored_v1_1(self):
inst_dict = dict(name='server_test', adminPass='bacon')
self.body = json.dumps(dict(server=inst_dict))
def server_update(context, id, params):
filtered_dict = dict(display_name='server_test')
self.assertEqual(params, filtered_dict)
return filtered_dict
self.stubs.Set(nova.db.api, 'instance_update', server_update)
self.stubs.Set(nova.db.api, 'instance_get',
return_server_with_attributes(name='server_test'))
req = webob.Request.blank('/v1.1/servers/1')
req.method = 'PUT'
req.content_type = "application/json"
req.body = self.body
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['id'], 1)
self.assertEqual(res_dict['server']['name'], 'server_test')
def test_create_backup_schedules(self):
req = webob.Request.blank('/v1.0/servers/1/backup_schedule')
req.method = 'POST'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_delete_backup_schedules(self):
req = webob.Request.blank('/v1.0/servers/1/backup_schedule/1')
req.method = 'DELETE'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_get_server_backup_schedules(self):
req = webob.Request.blank('/v1.0/servers/1/backup_schedule')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_get_server_backup_schedule(self):
req = webob.Request.blank('/v1.0/servers/1/backup_schedule/1')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 501)
def test_server_backup_schedule_deprecated_v1_1(self):
req = webob.Request.blank('/v1.1/servers/1/backup_schedule')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
def test_get_all_server_details_xml_v1_0(self):
req = webob.Request.blank('/v1.0/servers/detail')
req.headers['Accept'] = 'application/xml'
res = req.get_response(fakes.wsgi_app())
dom = minidom.parseString(res.body)
for i, server in enumerate(dom.getElementsByTagName('server')):
self.assertEqual(server.getAttribute('id'), str(i))
self.assertEqual(server.getAttribute('hostId'), '')
self.assertEqual(server.getAttribute('name'), 'server%d' % i)
self.assertEqual(server.getAttribute('imageId'), '10')
self.assertEqual(server.getAttribute('status'), 'BUILD')
(meta,) = server.getElementsByTagName('meta')
self.assertEqual(meta.getAttribute('key'), 'seq')
self.assertEqual(meta.firstChild.data.strip(), str(i))
def test_get_all_server_details_v1_0(self):
req = webob.Request.blank('/v1.0/servers/detail')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
for i, s in enumerate(res_dict['servers']):
self.assertEqual(s['id'], i)
self.assertEqual(s['hostId'], '')
self.assertEqual(s['name'], 'server%d' % i)
self.assertEqual(s['imageId'], 10)
self.assertEqual(s['flavorId'], 1)
self.assertEqual(s['status'], 'BUILD')
self.assertEqual(s['metadata']['seq'], str(i))
def test_get_all_server_details_v1_1(self):
expected_flavor = {
"id": "1",
"links": [
{
"rel": "bookmark",
"href": 'http://localhost/flavors/1',
},
],
}
expected_image = {
"id": "10",
"links": [
{
"rel": "bookmark",
"href": 'http://localhost/images/10',
},
],
}
req = webob.Request.blank('/v1.1/servers/detail')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
for i, s in enumerate(res_dict['servers']):
self.assertEqual(s['id'], i)
self.assertEqual(s['hostId'], '')
self.assertEqual(s['name'], 'server%d' % i)
self.assertEqual(s['image'], expected_image)
self.assertEqual(s['flavor'], expected_flavor)
self.assertEqual(s['status'], 'BUILD')
self.assertEqual(s['metadata']['seq'], str(i))
def test_get_all_server_details_with_host(self):
'''
We want to make sure that if two instances are on the same host, then
they return the same hostId. If two instances are on different hosts,
they should return different hostId's. In this test, there are 5
instances - 2 on one host and 3 on another.
'''
def return_servers_with_host(context, *args, **kwargs):
return [stub_instance(i, 'fake', 'fake', None, None, i % 2)
for i in xrange(5)]
self.stubs.Set(nova.db.api, 'instance_get_all_by_filters',
return_servers_with_host)
req = webob.Request.blank('/v1.0/servers/detail')
res = req.get_response(fakes.wsgi_app())
res_dict = json.loads(res.body)
server_list = res_dict['servers']
host_ids = [server_list[0]['hostId'], server_list[1]['hostId']]
self.assertTrue(host_ids[0] and host_ids[1])
self.assertNotEqual(host_ids[0], host_ids[1])
for i, s in enumerate(res_dict['servers']):
self.assertEqual(s['id'], i)
self.assertEqual(s['hostId'], host_ids[i % 2])
self.assertEqual(s['name'], 'server%d' % i)
self.assertEqual(s['imageId'], 10)
self.assertEqual(s['flavorId'], 1)
def test_server_pause(self):
self.flags(allow_admin_api=True)
req = webob.Request.blank('/v1.0/servers/1/pause')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
def test_server_unpause(self):
self.flags(allow_admin_api=True)
req = webob.Request.blank('/v1.0/servers/1/unpause')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
def test_server_suspend(self):
self.flags(allow_admin_api=True)
req = webob.Request.blank('/v1.0/servers/1/suspend')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
def test_server_resume(self):
self.flags(allow_admin_api=True)
req = webob.Request.blank('/v1.0/servers/1/resume')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
def test_server_reset_network(self):
self.flags(allow_admin_api=True)
req = webob.Request.blank('/v1.0/servers/1/reset_network')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
def test_server_inject_network_info(self):
self.flags(allow_admin_api=True)
req = webob.Request.blank(
'/v1.0/servers/1/inject_network_info')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 202)
def test_server_diagnostics(self):
self.flags(allow_admin_api=False)
req = webob.Request.blank("/v1.0/servers/1/diagnostics")
req.method = "GET"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
def test_server_actions(self):
self.flags(allow_admin_api=False)
req = webob.Request.blank("/v1.0/servers/1/actions")
req.method = "GET"
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 404)
def test_delete_server_instance(self):
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'DELETE'
self.server_delete_called = False
def instance_destroy_mock(context, id):
self.server_delete_called = True
self.stubs.Set(nova.db.api, 'instance_destroy',
instance_destroy_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status, '202 Accepted')
self.assertEqual(self.server_delete_called, True)
def test_rescue_accepted(self):
self.flags(allow_admin_api=True)
body = {}
self.called = False
def rescue_mock(*args, **kwargs):
self.called = True
self.stubs.Set(nova.compute.api.API, 'rescue', rescue_mock)
req = webob.Request.blank('/v1.0/servers/1/rescue')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(self.called, True)
self.assertEqual(res.status_int, 202)
def test_rescue_raises_handled(self):
self.flags(allow_admin_api=True)
body = {}
def rescue_mock(*args, **kwargs):
raise Exception('Who cares?')
self.stubs.Set(nova.compute.api.API, 'rescue', rescue_mock)
req = webob.Request.blank('/v1.0/servers/1/rescue')
req.method = 'POST'
req.content_type = 'application/json'
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 422)
def test_delete_server_instance_v1_1(self):
req = webob.Request.blank('/v1.1/servers/1')
req.method = 'DELETE'
self.server_delete_called = False
def instance_destroy_mock(context, id):
self.server_delete_called = True
self.stubs.Set(nova.db.api, 'instance_destroy',
instance_destroy_mock)
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 204)
self.assertEqual(self.server_delete_called, True)
def test_shutdown_status(self):
new_server = return_server_with_power_state(power_state.SHUTDOWN)
self.stubs.Set(nova.db.api, 'instance_get', new_server)
req = webob.Request.blank('/v1.0/servers/1')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['status'], 'SHUTDOWN')
def test_shutoff_status(self):
new_server = return_server_with_power_state(power_state.SHUTOFF)
self.stubs.Set(nova.db.api, 'instance_get', new_server)
req = webob.Request.blank('/v1.0/servers/1')
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 200)
res_dict = json.loads(res.body)
self.assertEqual(res_dict['server']['status'], 'SHUTOFF')
class TestServerCreateRequestXMLDeserializerV10(unittest.TestCase):
def setUp(self):
self.deserializer = create_instance_helper.ServerXMLDeserializer()
def test_minimal_request(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1"/>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"server": {
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
"metadata": {},
"personality": [],
}}
self.assertEquals(request['body'], expected)
def test_request_with_empty_metadata(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata/>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"server": {
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
"metadata": {},
"personality": [],
}}
self.assertEquals(request['body'], expected)
def test_request_with_empty_personality(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality/>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"server": {
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
"metadata": {},
"personality": [],
}}
self.assertEquals(request['body'], expected)
def test_request_with_empty_metadata_and_personality(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata/>
<personality/>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"server": {
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
"metadata": {},
"personality": [],
}}
self.assertEquals(request['body'], expected)
def test_request_with_empty_metadata_and_personality_reversed(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality/>
<metadata/>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"server": {
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
"metadata": {},
"personality": [],
}}
self.assertEquals(request['body'], expected)
def test_request_with_one_personality(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality>
<file path="/etc/conf">aabbccdd</file>
</personality>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = [{"path": "/etc/conf", "contents": "aabbccdd"}]
self.assertEquals(request['body']["server"]["personality"], expected)
def test_request_with_two_personalities(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality><file path="/etc/conf">aabbccdd</file>
<file path="/etc/sudoers">abcd</file></personality></server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = [{"path": "/etc/conf", "contents": "aabbccdd"},
{"path": "/etc/sudoers", "contents": "abcd"}]
self.assertEquals(request['body']["server"]["personality"], expected)
def test_request_second_personality_node_ignored(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality>
<file path="/etc/conf">aabbccdd</file>
</personality>
<personality>
<file path="/etc/ignoreme">anything</file>
</personality>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = [{"path": "/etc/conf", "contents": "aabbccdd"}]
self.assertEquals(request['body']["server"]["personality"], expected)
def test_request_with_one_personality_missing_path(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality><file>aabbccdd</file></personality></server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = [{"contents": "aabbccdd"}]
self.assertEquals(request['body']["server"]["personality"], expected)
def test_request_with_one_personality_empty_contents(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality><file path="/etc/conf"></file></personality></server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = [{"path": "/etc/conf", "contents": ""}]
self.assertEquals(request['body']["server"]["personality"], expected)
def test_request_with_one_personality_empty_contents_variation(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<personality><file path="/etc/conf"/></personality></server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = [{"path": "/etc/conf", "contents": ""}]
self.assertEquals(request['body']["server"]["personality"], expected)
def test_request_with_one_metadata(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta key="alpha">beta</meta>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"alpha": "beta"}
self.assertEquals(request['body']["server"]["metadata"], expected)
def test_request_with_two_metadata(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta key="alpha">beta</meta>
<meta key="foo">bar</meta>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"alpha": "beta", "foo": "bar"}
self.assertEquals(request['body']["server"]["metadata"], expected)
def test_request_with_metadata_missing_value(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta key="alpha"></meta>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"alpha": ""}
self.assertEquals(request['body']["server"]["metadata"], expected)
def test_request_with_two_metadata_missing_value(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta key="alpha"/>
<meta key="delta"/>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"alpha": "", "delta": ""}
self.assertEquals(request['body']["server"]["metadata"], expected)
def test_request_with_metadata_missing_key(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta>beta</meta>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"": "beta"}
self.assertEquals(request['body']["server"]["metadata"], expected)
def test_request_with_two_metadata_missing_key(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta>beta</meta>
<meta>gamma</meta>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"": "gamma"}
self.assertEquals(request['body']["server"]["metadata"], expected)
def test_request_with_metadata_duplicate_key(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta key="foo">bar</meta>
<meta key="foo">baz</meta>
</metadata>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {"foo": "baz"}
self.assertEquals(request['body']["server"]["metadata"], expected)
def test_canonical_request_from_docs(self):
serial_request = """
<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"
name="new-server-test" imageId="1" flavorId="1">
<metadata>
<meta key="My Server Name">Apache1</meta>
</metadata>
<personality>
<file path="/etc/banner.txt">\
ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp\
dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k\
IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs\
c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g\
QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo\
ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv\
dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy\
c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6\
b25zLiINCg0KLVJpY2hhcmQgQmFjaA==</file>
</personality>
</server>"""
expected = {"server": {
"name": "new-server-test",
"imageId": "1",
"flavorId": "1",
"metadata": {
"My Server Name": "Apache1",
},
"personality": [
{
"path": "/etc/banner.txt",
"contents": """\
ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp\
dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k\
IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs\
c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g\
QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo\
ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv\
dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy\
c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6\
b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""",
},
],
}}
request = self.deserializer.deserialize(serial_request, 'create')
self.assertEqual(request['body'], expected)
class TestServerCreateRequestXMLDeserializerV11(test.TestCase):
def setUp(self):
super(TestServerCreateRequestXMLDeserializerV11, self).setUp()
self.deserializer = create_instance_helper.ServerXMLDeserializerV11()
def test_minimal_request(self):
serial_request = """
<server xmlns="http://docs.openstack.org/compute/api/v1.1"
name="new-server-test"
imageRef="1"
flavorRef="2"/>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {
"server": {
"name": "new-server-test",
"imageRef": "1",
"flavorRef": "2",
},
}
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",
},
}
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",
},
}
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",
},
}
self.assertEquals(request['body'], expected)
def test_empty_metadata_personality(self):
serial_request = """
<server xmlns="http://docs.openstack.org/compute/api/v1.1"
name="new-server-test"
imageRef="1"
flavorRef="2">
<metadata/>
<personality/>
</server>"""
request = self.deserializer.deserialize(serial_request, 'create')
expected = {
"server": {
"name": "new-server-test",
"imageRef": "1",
"flavorRef": "2",
"metadata": {},
"personality": [],
},
}
self.assertEquals(request['body'], expected)
def test_multiple_metadata_items(self):
serial_request = """
<server xmlns="http://docs.openstack.org/compute/api/v1.1"
name="new-server-test"
imageRef="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"},
},
}
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",
"personality": [
{"path": "/etc/banner.txt", "contents": "MQ=="},
{"path": "/etc/hosts", "contents": "Mg=="},
],
},
}
self.assertDictMatch(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 TestAddressesXMLSerialization(test.TestCase):
serializer = nova.api.openstack.ips.IPXMLSerializer()
def test_show(self):
fixture = {
'network_2': [
{'addr': '192.168.0.1', 'version': 4},
{'addr': 'fe80::beef', 'version': 6},
],
}
output = self.serializer.serialize(fixture, 'show')
actual = minidom.parseString(output.replace(" ", ""))
expected = minidom.parseString("""
<network xmlns="http://docs.openstack.org/compute/api/v1.1"
id="network_2">
<ip version="4" addr="192.168.0.1"/>
<ip version="6" addr="fe80::beef"/>
</network>
""".replace(" ", ""))
self.assertEqual(expected.toxml(), actual.toxml())
def test_index(self):
fixture = {
'addresses': {
'network_1': [
{'addr': '192.168.0.3', 'version': 4},
{'addr': '192.168.0.5', 'version': 4},
],
'network_2': [
{'addr': '192.168.0.1', 'version': 4},
{'addr': 'fe80::beef', 'version': 6},
],
},
}
output = self.serializer.serialize(fixture, 'index')
actual = minidom.parseString(output.replace(" ", ""))
expected = minidom.parseString("""
<addresses xmlns="http://docs.openstack.org/compute/api/v1.1">
<network id="network_2">
<ip version="4" addr="192.168.0.1"/>
<ip version="6" addr="fe80::beef"/>
</network>
<network id="network_1">
<ip version="4" addr="192.168.0.3"/>
<ip version="4" addr="192.168.0.5"/>
</network>
</addresses>
""".replace(" ", ""))
self.assertEqual(expected.toxml(), actual.toxml())
class TestServerInstanceCreation(test.TestCase):
def setUp(self):
super(TestServerInstanceCreation, self).setUp()
fakes.stub_out_image_service(self.stubs)
fakes.stub_out_key_pair_funcs(self.stubs)
def _setup_mock_compute_api_for_personality(self):
class MockComputeAPI(nova.compute.API):
def __init__(self):
self.injected_files = None
def create(self, *args, **kwargs):
if 'injected_files' in kwargs:
self.injected_files = kwargs['injected_files']
else:
self.injected_files = None
return [{'id': '1234', 'display_name': 'fakeinstance',
'uuid': FAKE_UUID}]
def set_admin_password(self, *args, **kwargs):
pass
def make_stub_method(canned_return):
def stub_method(*args, **kwargs):
return canned_return
return stub_method
compute_api = MockComputeAPI()
self.stubs.Set(nova.compute, 'API', make_stub_method(compute_api))
self.stubs.Set(
nova.api.openstack.create_instance_helper.CreateInstanceHelper,
'_get_kernel_ramdisk_from_image', make_stub_method((1, 1)))
return compute_api
def _create_personality_request_dict(self, personality_files):
server = {}
server['name'] = 'new-server-test'
server['imageId'] = 1
server['flavorId'] = 1
if personality_files is not None:
personalities = []
for path, contents in personality_files:
personalities.append({'path': path, 'contents': contents})
server['personality'] = personalities
return {'server': server}
def _get_create_request_json(self, body_dict):
req = webob.Request.blank('/v1.0/servers')
req.headers['Content-Type'] = 'application/json'
req.method = 'POST'
req.body = json.dumps(body_dict)
return req
def _run_create_instance_with_mock_compute_api(self, request):
compute_api = self._setup_mock_compute_api_for_personality()
response = request.get_response(fakes.wsgi_app())
return compute_api, response
def _format_xml_request_body(self, body_dict):
server = body_dict['server']
body_parts = []
body_parts.extend([
'<?xml version="1.0" encoding="UTF-8"?>',
'<server xmlns="http://docs.rackspacecloud.com/servers/api/v1.0"',
' name="%s" imageId="%s" flavorId="%s">' % (
server['name'], server['imageId'], server['flavorId'])])
if 'metadata' in server:
metadata = server['metadata']
body_parts.append('<metadata>')
for item in metadata.iteritems():
body_parts.append('<meta key="%s">%s</meta>' % item)
body_parts.append('</metadata>')
if 'personality' in server:
personalities = server['personality']
body_parts.append('<personality>')
for file in personalities:
item = (file['path'], file['contents'])
body_parts.append('<file path="%s">%s</file>' % item)
body_parts.append('</personality>')
body_parts.append('</server>')
return ''.join(body_parts)
def _get_create_request_xml(self, body_dict):
req = webob.Request.blank('/v1.0/servers')
req.content_type = 'application/xml'
req.accept = 'application/xml'
req.method = 'POST'
req.body = self._format_xml_request_body(body_dict)
return req
def _create_instance_with_personality_json(self, personality):
body_dict = self._create_personality_request_dict(personality)
request = self._get_create_request_json(body_dict)
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
return request, response, compute_api.injected_files
def _create_instance_with_personality_xml(self, personality):
body_dict = self._create_personality_request_dict(personality)
request = self._get_create_request_xml(body_dict)
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
return request, response, compute_api.injected_files
def test_create_instance_with_no_personality(self):
request, response, injected_files = \
self._create_instance_with_personality_json(personality=None)
self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [])
def test_create_instance_with_no_personality_xml(self):
request, response, injected_files = \
self._create_instance_with_personality_xml(personality=None)
self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [])
def test_create_instance_with_personality(self):
path = '/my/file/path'
contents = '#!/bin/bash\necho "Hello, World!"\n'
b64contents = base64.b64encode(contents)
personality = [(path, b64contents)]
request, response, injected_files = \
self._create_instance_with_personality_json(personality)
self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [(path, contents)])
def test_create_instance_with_personality_xml(self):
path = '/my/file/path'
contents = '#!/bin/bash\necho "Hello, World!"\n'
b64contents = base64.b64encode(contents)
personality = [(path, b64contents)]
request, response, injected_files = \
self._create_instance_with_personality_xml(personality)
self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [(path, contents)])
def test_create_instance_with_personality_no_path(self):
personality = [('/remove/this/path',
base64.b64encode('my\n\file\ncontents'))]
body_dict = self._create_personality_request_dict(personality)
del body_dict['server']['personality'][0]['path']
request = self._get_create_request_json(body_dict)
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
self.assertEquals(response.status_int, 400)
self.assertEquals(compute_api.injected_files, None)
def _test_create_instance_with_personality_no_path_xml(self):
personality = [('/remove/this/path',
base64.b64encode('my\n\file\ncontents'))]
body_dict = self._create_personality_request_dict(personality)
request = self._get_create_request_xml(body_dict)
request.body = request.body.replace(' path="/remove/this/path"', '')
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
self.assertEquals(response.status_int, 400)
self.assertEquals(compute_api.injected_files, None)
def test_create_instance_with_personality_no_contents(self):
personality = [('/test/path',
base64.b64encode('remove\nthese\ncontents'))]
body_dict = self._create_personality_request_dict(personality)
del body_dict['server']['personality'][0]['contents']
request = self._get_create_request_json(body_dict)
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
self.assertEquals(response.status_int, 400)
self.assertEquals(compute_api.injected_files, None)
def test_create_instance_with_personality_not_a_list(self):
personality = [('/test/path', base64.b64encode('test\ncontents\n'))]
body_dict = self._create_personality_request_dict(personality)
body_dict['server']['personality'] = \
body_dict['server']['personality'][0]
request = self._get_create_request_json(body_dict)
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
self.assertEquals(response.status_int, 400)
self.assertEquals(compute_api.injected_files, None)
def test_create_instance_with_personality_with_non_b64_content(self):
path = '/my/file/path'
contents = '#!/bin/bash\necho "Oh no!"\n'
personality = [(path, contents)]
request, response, injected_files = \
self._create_instance_with_personality_json(personality)
self.assertEquals(response.status_int, 400)
self.assertEquals(injected_files, None)
def test_create_instance_with_null_personality(self):
personality = None
body_dict = self._create_personality_request_dict(personality)
body_dict['server']['personality'] = None
request = self._get_create_request_json(body_dict)
compute_api, response = \
self._run_create_instance_with_mock_compute_api(request)
self.assertEquals(response.status_int, 202)
def test_create_instance_with_three_personalities(self):
files = [
('/etc/sudoers', 'ALL ALL=NOPASSWD: ALL\n'),
('/etc/motd', 'Enjoy your root access!\n'),
('/etc/dovecot.conf', 'dovecot\nconfig\nstuff\n'),
]
personality = []
for path, content in files:
personality.append((path, base64.b64encode(content)))
request, response, injected_files = \
self._create_instance_with_personality_json(personality)
self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, files)
def test_create_instance_personality_empty_content(self):
path = '/my/file/path'
contents = ''
personality = [(path, contents)]
request, response, injected_files = \
self._create_instance_with_personality_json(personality)
self.assertEquals(response.status_int, 202)
self.assertEquals(injected_files, [(path, contents)])
def test_create_instance_admin_pass_json(self):
request, response, dummy = \
self._create_instance_with_personality_json(None)
self.assertEquals(response.status_int, 202)
response = json.loads(response.body)
self.assertTrue('adminPass' in response['server'])
self.assertEqual(16, len(response['server']['adminPass']))
def test_create_instance_admin_pass_xml(self):
request, response, dummy = \
self._create_instance_with_personality_xml(None)
self.assertEquals(response.status_int, 202)
dom = minidom.parseString(response.body)
server = dom.childNodes[0]
self.assertEquals(server.nodeName, 'server')
self.assertEqual(16, len(server.getAttribute('adminPass')))
class TestGetKernelRamdiskFromImage(test.TestCase):
"""
If we're building from an AMI-style image, we need to be able to fetch the
kernel and ramdisk associated with the machine image. This information is
stored with the image metadata and return via the ImageService.
These tests ensure that we parse the metadata return the ImageService
correctly and that we handle failure modes appropriately.
"""
def test_status_not_active(self):
"""We should only allow fetching of kernel and ramdisk information if
we have a 'fully-formed' image, aka 'active'
"""
image_meta = {'id': 1, 'status': 'queued'}
self.assertRaises(exception.Invalid, self._get_k_r, image_meta)
def test_not_ami(self):
"""Anything other than ami should return no kernel and no ramdisk"""
image_meta = {'id': 1, 'status': 'active', 'container_format': 'vhd'}
kernel_id, ramdisk_id = self._get_k_r(image_meta)
self.assertEqual(kernel_id, None)
self.assertEqual(ramdisk_id, None)
def test_ami_no_kernel(self):
"""If an ami is missing a kernel it should raise NotFound"""
image_meta = {'id': 1, 'status': 'active', 'container_format': 'ami',
'properties': {'ramdisk_id': 1}}
self.assertRaises(exception.NotFound, self._get_k_r, image_meta)
def test_ami_no_ramdisk(self):
"""If an ami is missing a ramdisk it should raise NotFound"""
image_meta = {'id': 1, 'status': 'active', 'container_format': 'ami',
'properties': {'kernel_id': 1}}
self.assertRaises(exception.NotFound, self._get_k_r, image_meta)
def test_ami_kernel_ramdisk_present(self):
"""Return IDs if both kernel and ramdisk are present"""
image_meta = {'id': 1, 'status': 'active', 'container_format': 'ami',
'properties': {'kernel_id': 1, 'ramdisk_id': 2}}
kernel_id, ramdisk_id = self._get_k_r(image_meta)
self.assertEqual(kernel_id, 1)
self.assertEqual(ramdisk_id, 2)
@staticmethod
def _get_k_r(image_meta):
"""Rebinding function to a shorter name for convenience"""
kernel_id, ramdisk_id = create_instance_helper.CreateInstanceHelper. \
_do_get_kernel_ramdisk_from_image(image_meta)
return kernel_id, ramdisk_id
class ServersViewBuilderV11Test(test.TestCase):
def setUp(self):
self.instance = self._get_instance()
self.view_builder = self._get_view_builder()
def tearDown(self):
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": created_at,
"updated_at": updated_at,
"admin_pass": "",
"user_id": "",
"project_id": "",
"image_ref": "5",
"kernel_id": "",
"ramdisk_id": "",
"launch_index": 0,
"key_name": "",
"key_data": "",
"state": 0,
"state_description": "",
"memory_mb": 0,
"vcpus": 0,
"local_gb": 0,
"hostname": "",
"host": "",
"instance_type": {
"flavorid": 1,
},
"user_data": "",
"reservation_id": "",
"mac_address": "",
"scheduled_at": utils.utcnow(),
"launched_at": utils.utcnow(),
"terminated_at": utils.utcnow(),
"availability_zone": "",
"display_name": "test_server",
"display_description": "",
"locked": False,
"metadata": [],
#"address": ,
#"floating_ips": [{"address":ip} for ip in public_addresses]}
"uuid": "deadbeef-feed-edee-beef-d0ea7beefedd"}
return instance
def _get_view_builder(self):
base_url = "http://localhost/v1.1"
views = nova.api.openstack.views
address_builder = views.addresses.ViewBuilderV11()
flavor_builder = views.flavors.ViewBuilderV11(base_url)
image_builder = views.images.ViewBuilderV11(base_url)
view_builder = nova.api.openstack.views.servers.ViewBuilderV11(
address_builder,
flavor_builder,
image_builder,
base_url)
return view_builder
def test_build_server(self):
expected_server = {
"server": {
"id": 1,
"uuid": self.instance['uuid'],
"name": "test_server",
"links": [
{
"rel": "self",
"href": "http://localhost/v1.1/servers/1",
},
{
"rel": "bookmark",
"href": "http://localhost/servers/1",
},
],
}
}
output = self.view_builder.build(self.instance, False)
self.assertDictMatch(output, expected_server)
def test_build_server_detail(self):
image_bookmark = "http://localhost/images/5"
flavor_bookmark = "http://localhost/flavors/1"
expected_server = {
"server": {
"id": 1,
"uuid": self.instance['uuid'],
"updated": "2010-11-11T11:00:00Z",
"created": "2010-10-10T12:00:00Z",
"progress": 0,
"name": "test_server",
"status": "BUILD",
"hostId": '',
"image": {
"id": "5",
"links": [
{
"rel": "bookmark",
"href": image_bookmark,
},
],
},
"flavor": {
"id": "1",
"links": [
{
"rel": "bookmark",
"href": flavor_bookmark,
},
],
},
"addresses": {},
"metadata": {},
"links": [
{
"rel": "self",
"href": "http://localhost/v1.1/servers/1",
},
{
"rel": "bookmark",
"href": "http://localhost/servers/1",
},
],
}
}
output = self.view_builder.build(self.instance, True)
self.assertDictMatch(output, expected_server)
def test_build_server_detail_active_status(self):
#set the power state of the instance to running
self.instance['state'] = 1
image_bookmark = "http://localhost/images/5"
flavor_bookmark = "http://localhost/flavors/1"
expected_server = {
"server": {
"id": 1,
"uuid": self.instance['uuid'],
"updated": "2010-11-11T11:00:00Z",
"created": "2010-10-10T12:00:00Z",
"progress": 100,
"name": "test_server",
"status": "ACTIVE",
"hostId": '',
"image": {
"id": "5",
"links": [
{
"rel": "bookmark",
"href": image_bookmark,
},
],
},
"flavor": {
"id": "1",
"links": [
{
"rel": "bookmark",
"href": flavor_bookmark,
},
],
},
"addresses": {},
"metadata": {},
"links": [
{
"rel": "self",
"href": "http://localhost/v1.1/servers/1",
},
{
"rel": "bookmark",
"href": "http://localhost/servers/1",
},
],
}
}
output = self.view_builder.build(self.instance, True)
self.assertDictMatch(output, expected_server)
def test_build_server_detail_with_metadata(self):
metadata = []
metadata.append(InstanceMetadata(key="Open", value="Stack"))
metadata.append(InstanceMetadata(key="Number", value=1))
self.instance['metadata'] = metadata
image_bookmark = "http://localhost/images/5"
flavor_bookmark = "http://localhost/flavors/1"
expected_server = {
"server": {
"id": 1,
"uuid": self.instance['uuid'],
"updated": "2010-11-11T11:00:00Z",
"created": "2010-10-10T12:00:00Z",
"progress": 0,
"name": "test_server",
"status": "BUILD",
"hostId": '',
"image": {
"id": "5",
"links": [
{
"rel": "bookmark",
"href": image_bookmark,
},
],
},
"flavor": {
"id": "1",
"links": [
{
"rel": "bookmark",
"href": flavor_bookmark,
},
],
},
"addresses": {},
"metadata": {
"Open": "Stack",
"Number": "1",
},
"links": [
{
"rel": "self",
"href": "http://localhost/v1.1/servers/1",
},
{
"rel": "bookmark",
"href": "http://localhost/servers/1",
},
],
}
}
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())
def test_update(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, 'update')
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())