Merge "Merge extended server attributes extension response"
This commit is contained in:
commit
cccba02be8
@ -1,105 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""The Extended Server Attributes API extension."""
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack import wsgi
|
||||
from nova import compute
|
||||
from nova.policies import extended_server_attributes as esa_policies
|
||||
from nova.policies import servers as servers_policies
|
||||
|
||||
|
||||
class ExtendedServerAttributesController(wsgi.Controller):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ExtendedServerAttributesController, self).__init__(*args,
|
||||
**kwargs)
|
||||
self.compute_api = compute.API()
|
||||
|
||||
def _extend_server(self, context, server, instance, req):
|
||||
key = "OS-EXT-SRV-ATTR:hypervisor_hostname"
|
||||
server[key] = instance.node
|
||||
|
||||
properties = ['host', 'name']
|
||||
if api_version_request.is_supported(req, min_version='2.3'):
|
||||
# NOTE(mriedem): These will use the OS-EXT-SRV-ATTR prefix below
|
||||
# and that's OK for microversion 2.3 which is being compatible
|
||||
# with v2.0 for the ec2 API split out from Nova. After this,
|
||||
# however, new microversions should not be using the
|
||||
# OS-EXT-SRV-ATTR prefix.
|
||||
properties += ['reservation_id', 'launch_index',
|
||||
'hostname', 'kernel_id', 'ramdisk_id',
|
||||
'root_device_name', 'user_data']
|
||||
for attr in properties:
|
||||
if attr == 'name':
|
||||
key = "OS-EXT-SRV-ATTR:instance_%s" % attr
|
||||
else:
|
||||
# NOTE(mriedem): Nothing after microversion 2.3 should use the
|
||||
# OS-EXT-SRV-ATTR prefix for the attribute key name.
|
||||
key = "OS-EXT-SRV-ATTR:%s" % attr
|
||||
server[key] = instance[attr]
|
||||
|
||||
def _server_host_status(self, context, server, instance, req):
|
||||
host_status = self.compute_api.get_instance_host_status(instance)
|
||||
server['host_status'] = host_status
|
||||
|
||||
@wsgi.extends
|
||||
def show(self, req, resp_obj, id):
|
||||
context = req.environ['nova.context']
|
||||
authorize_extend = False
|
||||
authorize_host_status = False
|
||||
if context.can(esa_policies.BASE_POLICY_NAME, fatal=False):
|
||||
authorize_extend = True
|
||||
if (api_version_request.is_supported(req, min_version='2.16') and
|
||||
context.can(servers_policies.SERVERS % 'show:host_status',
|
||||
fatal=False)):
|
||||
authorize_host_status = True
|
||||
if authorize_extend or authorize_host_status:
|
||||
server = resp_obj.obj['server']
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'show' method.
|
||||
if authorize_extend:
|
||||
self._extend_server(context, server, db_instance, req)
|
||||
if authorize_host_status:
|
||||
self._server_host_status(context, server, db_instance, req)
|
||||
|
||||
@wsgi.extends
|
||||
def detail(self, req, resp_obj):
|
||||
context = req.environ['nova.context']
|
||||
authorize_extend = False
|
||||
authorize_host_status = False
|
||||
if context.can(esa_policies.BASE_POLICY_NAME, fatal=False):
|
||||
authorize_extend = True
|
||||
if (api_version_request.is_supported(req, min_version='2.16') and
|
||||
context.can(servers_policies.SERVERS % 'show:host_status',
|
||||
fatal=False)):
|
||||
authorize_host_status = True
|
||||
if authorize_extend or authorize_host_status:
|
||||
servers = list(resp_obj.obj['servers'])
|
||||
# NOTE(dinesh-bhor): Skipping fetching of instances from cache as
|
||||
# servers list can be empty if invalid status is provided to the
|
||||
# core API 'detail' method.
|
||||
if servers:
|
||||
instances = req.get_db_instances()
|
||||
if authorize_host_status:
|
||||
host_statuses = (
|
||||
self.compute_api.get_instances_host_statuses(
|
||||
instances.values()))
|
||||
for server in servers:
|
||||
if authorize_extend:
|
||||
instance = instances[server['id']]
|
||||
self._extend_server(context, server, instance, req)
|
||||
if authorize_host_status:
|
||||
server['host_status'] = host_statuses[server['id']]
|
@ -34,7 +34,6 @@ from nova.api.openstack.compute import consoles
|
||||
from nova.api.openstack.compute import create_backup
|
||||
from nova.api.openstack.compute import deferred_delete
|
||||
from nova.api.openstack.compute import evacuate
|
||||
from nova.api.openstack.compute import extended_server_attributes
|
||||
from nova.api.openstack.compute import extended_status
|
||||
from nova.api.openstack.compute import extended_volumes
|
||||
from nova.api.openstack.compute import extension_info
|
||||
@ -267,7 +266,6 @@ security_group_rules_controller = functools.partial(_create_controller,
|
||||
server_controller = functools.partial(_create_controller,
|
||||
servers.ServersController,
|
||||
[
|
||||
extended_server_attributes.ExtendedServerAttributesController,
|
||||
extended_status.ExtendedStatusController,
|
||||
extended_volumes.ExtendedVolumesController,
|
||||
hide_server_addresses.Controller,
|
||||
|
@ -719,7 +719,9 @@ class ServersController(wsgi.Controller):
|
||||
return self._view_builder.show(req, instance,
|
||||
extend_address=False,
|
||||
show_AZ=False,
|
||||
show_config_drive=False)
|
||||
show_config_drive=False,
|
||||
show_extended_attr=False,
|
||||
show_host_status=False)
|
||||
except exception.InstanceNotFound:
|
||||
msg = _("Instance could not be found")
|
||||
raise exc.HTTPNotFound(explanation=msg)
|
||||
@ -985,7 +987,9 @@ class ServersController(wsgi.Controller):
|
||||
|
||||
view = self._view_builder.show(req, instance, extend_address=False,
|
||||
show_AZ=False,
|
||||
show_config_drive=False)
|
||||
show_config_drive=False,
|
||||
show_extended_attr=False,
|
||||
show_host_status=False)
|
||||
|
||||
# Add on the admin_password attribute since the view doesn't do it
|
||||
# unless instance passwords are disabled
|
||||
|
@ -22,10 +22,13 @@ from nova.api.openstack.compute.views import addresses as views_addresses
|
||||
from nova.api.openstack.compute.views import flavors as views_flavors
|
||||
from nova.api.openstack.compute.views import images as views_images
|
||||
from nova import availability_zones as avail_zone
|
||||
from nova import compute
|
||||
from nova import context as nova_context
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova.policies import extended_server_attributes as esa_policies
|
||||
from nova.policies import flavor_extra_specs as fes_policies
|
||||
from nova.policies import servers as servers_policies
|
||||
from nova import utils
|
||||
|
||||
|
||||
@ -61,6 +64,7 @@ class ViewBuilder(common.ViewBuilder):
|
||||
self._address_builder = views_addresses.ViewBuilder()
|
||||
self._image_builder = views_images.ViewBuilder()
|
||||
self._flavor_builder = views_flavors.ViewBuilder()
|
||||
self.compute_api = compute.API()
|
||||
|
||||
def create(self, request, instance):
|
||||
"""View that should be returned when an instance is created."""
|
||||
@ -78,7 +82,8 @@ class ViewBuilder(common.ViewBuilder):
|
||||
},
|
||||
}
|
||||
|
||||
def basic(self, request, instance, show_extra_specs=False):
|
||||
def basic(self, request, instance, show_extra_specs=False,
|
||||
show_extended_attr=None, show_host_status=None):
|
||||
"""Generic, non-detailed view of an instance."""
|
||||
return {
|
||||
"server": {
|
||||
@ -111,7 +116,8 @@ class ViewBuilder(common.ViewBuilder):
|
||||
return sorted(list(set(self._show_expected_attrs + expected_attrs)))
|
||||
|
||||
def show(self, request, instance, extend_address=True,
|
||||
show_extra_specs=None, show_AZ=True, show_config_drive=True):
|
||||
show_extra_specs=None, show_AZ=True, show_config_drive=True,
|
||||
show_extended_attr=None, show_host_status=None):
|
||||
"""Detailed view of a single instance."""
|
||||
ip_v4 = instance.get('access_ip_v4')
|
||||
ip_v6 = instance.get('access_ip_v6')
|
||||
@ -161,8 +167,8 @@ class ViewBuilder(common.ViewBuilder):
|
||||
if server["server"]["status"] in self._progress_statuses:
|
||||
server["server"]["progress"] = instance.get("progress", 0)
|
||||
|
||||
context = request.environ['nova.context']
|
||||
if show_AZ:
|
||||
context = request.environ['nova.context']
|
||||
az = avail_zone.get_instance_availability_zone(context, instance)
|
||||
# NOTE(mriedem): The OS-EXT-AZ prefix should not be used for new
|
||||
# attributes after v2.1. They are only in v2.1 for backward compat
|
||||
@ -172,6 +178,40 @@ class ViewBuilder(common.ViewBuilder):
|
||||
if show_config_drive:
|
||||
server["server"]["config_drive"] = instance["config_drive"]
|
||||
|
||||
if show_extended_attr is None:
|
||||
show_extended_attr = context.can(
|
||||
esa_policies.BASE_POLICY_NAME, fatal=False)
|
||||
if show_extended_attr:
|
||||
server["server"][
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname"] = instance.node
|
||||
|
||||
properties = ['host', 'name']
|
||||
if api_version_request.is_supported(request, min_version='2.3'):
|
||||
# NOTE(mriedem): These will use the OS-EXT-SRV-ATTR prefix
|
||||
# below and that's OK for microversion 2.3 which is being
|
||||
# compatible with v2.0 for the ec2 API split out from Nova.
|
||||
# After this, however, new microversions should not be using
|
||||
# the OS-EXT-SRV-ATTR prefix.
|
||||
properties += ['reservation_id', 'launch_index',
|
||||
'hostname', 'kernel_id', 'ramdisk_id',
|
||||
'root_device_name', 'user_data']
|
||||
for attr in properties:
|
||||
if attr == 'name':
|
||||
key = "OS-EXT-SRV-ATTR:instance_%s" % attr
|
||||
else:
|
||||
# NOTE(mriedem): Nothing after microversion 2.3 should use
|
||||
# the OS-EXT-SRV-ATTR prefix for the attribute key name.
|
||||
key = "OS-EXT-SRV-ATTR:%s" % attr
|
||||
server["server"][key] = instance[attr]
|
||||
if (api_version_request.is_supported(request, min_version='2.16')):
|
||||
if show_host_status is None:
|
||||
show_host_status = context.can(
|
||||
servers_policies.SERVERS % 'show:host_status', fatal=False)
|
||||
if show_host_status:
|
||||
host_status = self.compute_api.get_instance_host_status(
|
||||
instance)
|
||||
server["server"]['host_status'] = host_status
|
||||
|
||||
if api_version_request.is_supported(request, min_version="2.9"):
|
||||
server["server"]["locked"] = (True if instance["locked_by"]
|
||||
else False)
|
||||
@ -209,11 +249,20 @@ class ViewBuilder(common.ViewBuilder):
|
||||
fatal=False)
|
||||
else:
|
||||
show_extra_specs = False
|
||||
|
||||
context = request.environ['nova.context']
|
||||
show_extended_attr = context.can(
|
||||
esa_policies.BASE_POLICY_NAME, fatal=False)
|
||||
show_host_status = False
|
||||
if (api_version_request.is_supported(request, min_version='2.16')):
|
||||
show_host_status = context.can(
|
||||
servers_policies.SERVERS % 'show:host_status', fatal=False)
|
||||
return self._list_view(self.show, request, instances, coll_name,
|
||||
show_extra_specs)
|
||||
show_extra_specs,
|
||||
show_extended_attr=show_extended_attr,
|
||||
show_host_status=show_host_status)
|
||||
|
||||
def _list_view(self, func, request, servers, coll_name, show_extra_specs):
|
||||
def _list_view(self, func, request, servers, coll_name, show_extra_specs,
|
||||
show_extended_attr=None, show_host_status=None):
|
||||
"""Provide a view for a list of servers.
|
||||
|
||||
:param func: Function used to format the server data
|
||||
@ -221,10 +270,16 @@ class ViewBuilder(common.ViewBuilder):
|
||||
:param servers: List of servers in dictionary format
|
||||
:param coll_name: Name of collection, used to generate the next link
|
||||
for a pagination query
|
||||
:param show_extended_attr: If the server extended attributes should be
|
||||
included in the response dict.
|
||||
:param show_host_status: If the host status should be included in
|
||||
the response dict.
|
||||
:returns: Server data in dictionary format
|
||||
"""
|
||||
server_list = [func(request, server,
|
||||
show_extra_specs=show_extra_specs)["server"]
|
||||
show_extra_specs=show_extra_specs,
|
||||
show_extended_attr=show_extended_attr,
|
||||
show_host_status=show_host_status)["server"]
|
||||
for server in servers]
|
||||
servers_links = self._get_collection_links(request,
|
||||
servers,
|
||||
|
@ -1,246 +0,0 @@
|
||||
# Copyright 2011 OpenStack Foundation
|
||||
# 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 mock
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from nova.api.openstack import wsgi as os_wsgi
|
||||
from nova import compute
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova import test
|
||||
from nova.tests.unit.api.openstack import fakes
|
||||
|
||||
|
||||
NAME_FMT = cfg.CONF.instance_name_template
|
||||
UUID1 = '00000000-0000-0000-0000-000000000001'
|
||||
UUID2 = '00000000-0000-0000-0000-000000000002'
|
||||
UUID3 = '00000000-0000-0000-0000-000000000003'
|
||||
UUID4 = '00000000-0000-0000-0000-000000000004'
|
||||
UUID5 = '00000000-0000-0000-0000-000000000005'
|
||||
|
||||
|
||||
def fake_services(host):
|
||||
service_list = [objects.Service(id=0, host=host, forced_down=True,
|
||||
binary='nova-compute')]
|
||||
return objects.ServiceList(objects=service_list)
|
||||
|
||||
|
||||
def fake_compute_get(*args, **kwargs):
|
||||
return fakes.stub_instance_obj(
|
||||
None, 1, uuid=UUID3, host="host-fake",
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID4, ramdisk_id=UUID5,
|
||||
display_name="hostname-1",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
services=fake_services("host-fake"))
|
||||
|
||||
|
||||
def fake_compute_get_all(*args, **kwargs):
|
||||
inst_list = [
|
||||
fakes.stub_instance_obj(
|
||||
None, 1, uuid=UUID1, host="host-1", node="node-1",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID4, ramdisk_id=UUID5,
|
||||
display_name="hostname-1",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
services=fake_services("host-1")),
|
||||
fakes.stub_instance_obj(
|
||||
None, 2, uuid=UUID2, host="host-2", node="node-2",
|
||||
reservation_id="r-2", launch_index=1,
|
||||
kernel_id=UUID4, ramdisk_id=UUID5,
|
||||
display_name="hostname-2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
services=fake_services("host-2")),
|
||||
]
|
||||
return objects.InstanceList(objects=inst_list)
|
||||
|
||||
|
||||
class ExtendedServerAttributesTestV21(test.TestCase):
|
||||
content_type = 'application/json'
|
||||
prefix = 'OS-EXT-SRV-ATTR:'
|
||||
fake_url = '/v2/fake'
|
||||
wsgi_api_version = os_wsgi.DEFAULT_API_VERSION
|
||||
|
||||
def setUp(self):
|
||||
super(ExtendedServerAttributesTestV21, self).setUp()
|
||||
fakes.stub_out_nw_api(self)
|
||||
fakes.stub_out_secgroup_api(self)
|
||||
self.stub_out('nova.compute.api.API.get', fake_compute_get)
|
||||
self.stub_out('nova.compute.api.API.get_all', fake_compute_get_all)
|
||||
self.stub_out('nova.db.api.instance_get_by_uuid', fake_compute_get)
|
||||
|
||||
def _make_request(self, url):
|
||||
req = fakes.HTTPRequest.blank(url)
|
||||
req.headers['Accept'] = self.content_type
|
||||
req.headers = {os_wsgi.API_VERSION_REQUEST_HEADER:
|
||||
'compute %s' % self.wsgi_api_version}
|
||||
res = req.get_response(
|
||||
fakes.wsgi_app_v21())
|
||||
return res
|
||||
|
||||
def _get_server(self, body):
|
||||
return jsonutils.loads(body).get('server')
|
||||
|
||||
def _get_servers(self, body):
|
||||
return jsonutils.loads(body).get('servers')
|
||||
|
||||
def assertServerAttributes(self, server, host, node, instance_name):
|
||||
self.assertEqual(server.get('%shost' % self.prefix), host)
|
||||
self.assertEqual(server.get('%sinstance_name' % self.prefix),
|
||||
instance_name)
|
||||
self.assertEqual(server.get('%shypervisor_hostname' % self.prefix),
|
||||
node)
|
||||
|
||||
def test_show(self):
|
||||
url = self.fake_url + '/servers/%s' % UUID3
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertServerAttributes(self._get_server(res.body),
|
||||
host='host-fake',
|
||||
node='node-fake',
|
||||
instance_name=NAME_FMT % 1)
|
||||
|
||||
def test_detail(self):
|
||||
url = self.fake_url + '/servers/detail'
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
for i, server in enumerate(self._get_servers(res.body)):
|
||||
self.assertServerAttributes(server,
|
||||
host='host-%s' % (i + 1),
|
||||
node='node-%s' % (i + 1),
|
||||
instance_name=NAME_FMT % (i + 1))
|
||||
|
||||
@mock.patch.object(compute.api.API, 'get_all')
|
||||
def test_detail_empty_instance_list_invalid_status(self,
|
||||
mock_get_all_method):
|
||||
mock_get_all_method.return_value = objects.InstanceList(objects=[])
|
||||
|
||||
url = "%s%s" % (self.fake_url, '/servers/detail?status=invalid_status')
|
||||
res = self._make_request(url)
|
||||
# check status code 200 with empty instance list
|
||||
self.assertEqual(200, res.status_int)
|
||||
self.assertEqual(0, len(self._get_servers(res.body)))
|
||||
|
||||
def test_no_instance_passthrough_404(self):
|
||||
|
||||
def fake_compute_get(*args, **kwargs):
|
||||
raise exception.InstanceNotFound(instance_id='fake')
|
||||
|
||||
self.stub_out('nova.compute.api.API.get', fake_compute_get)
|
||||
url = self.fake_url + '/servers/70f6db34-de8d-4fbd-aafb-4065bdfa6115'
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 404)
|
||||
|
||||
|
||||
class ExtendedServerAttributesTestV23(ExtendedServerAttributesTestV21):
|
||||
wsgi_api_version = '2.3'
|
||||
|
||||
def assertServerAttributes(self, server, host, node, instance_name,
|
||||
reservation_id, launch_index, kernel_id,
|
||||
ramdisk_id, hostname, root_device_name,
|
||||
user_data):
|
||||
super(ExtendedServerAttributesTestV23, self).assertServerAttributes(
|
||||
server, host, node, instance_name)
|
||||
self.assertEqual(server.get('%sreservation_id' % self.prefix),
|
||||
reservation_id)
|
||||
self.assertEqual(server.get('%slaunch_index' % self.prefix),
|
||||
launch_index)
|
||||
self.assertEqual(server.get('%skernel_id' % self.prefix),
|
||||
kernel_id)
|
||||
self.assertEqual(server.get('%sramdisk_id' % self.prefix),
|
||||
ramdisk_id)
|
||||
self.assertEqual(server.get('%shostname' % self.prefix),
|
||||
hostname)
|
||||
self.assertEqual(server.get('%sroot_device_name' % self.prefix),
|
||||
root_device_name)
|
||||
self.assertEqual(server.get('%suser_data' % self.prefix),
|
||||
user_data)
|
||||
|
||||
def test_show(self):
|
||||
url = self.fake_url + '/servers/%s' % UUID3
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertServerAttributes(self._get_server(res.body),
|
||||
host='host-fake',
|
||||
node='node-fake',
|
||||
instance_name=NAME_FMT % 1,
|
||||
reservation_id="r-1",
|
||||
launch_index=0,
|
||||
kernel_id=UUID4,
|
||||
ramdisk_id=UUID5,
|
||||
hostname="hostname-1",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata")
|
||||
|
||||
def test_detail(self):
|
||||
url = self.fake_url + '/servers/detail'
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
for i, server in enumerate(self._get_servers(res.body)):
|
||||
self.assertServerAttributes(server,
|
||||
host='host-%s' % (i + 1),
|
||||
node='node-%s' % (i + 1),
|
||||
instance_name=NAME_FMT % (i + 1),
|
||||
reservation_id="r-%s" % (i + 1),
|
||||
launch_index=i,
|
||||
kernel_id=UUID4,
|
||||
ramdisk_id=UUID5,
|
||||
hostname="hostname-%s" % (i + 1),
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata")
|
||||
|
||||
|
||||
class ExtendedServerAttributesTestV216(ExtendedServerAttributesTestV21):
|
||||
wsgi_api_version = '2.16'
|
||||
|
||||
def assertServerAttributes(self, server, host, node, instance_name,
|
||||
host_status):
|
||||
super(ExtendedServerAttributesTestV216, self).assertServerAttributes(
|
||||
server, host, node, instance_name)
|
||||
self.assertEqual(server.get('host_status'), host_status)
|
||||
|
||||
def test_show(self):
|
||||
url = self.fake_url + '/servers/%s' % UUID3
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
self.assertServerAttributes(self._get_server(res.body),
|
||||
host='host-fake',
|
||||
node='node-fake',
|
||||
instance_name=NAME_FMT % 1,
|
||||
host_status="DOWN")
|
||||
|
||||
def test_detail(self):
|
||||
url = self.fake_url + '/servers/detail'
|
||||
res = self._make_request(url)
|
||||
|
||||
self.assertEqual(res.status_int, 200)
|
||||
for i, server in enumerate(self._get_servers(res.body)):
|
||||
self.assertServerAttributes(server,
|
||||
host='host-%s' % (i + 1),
|
||||
node='node-%s' % (i + 1),
|
||||
instance_name=NAME_FMT % (i + 1),
|
||||
host_status="DOWN")
|
@ -73,6 +73,9 @@ CONF = nova.conf.CONF
|
||||
|
||||
FAKE_UUID = fakes.FAKE_UUID
|
||||
|
||||
UUID1 = '00000000-0000-0000-0000-000000000001'
|
||||
UUID2 = '00000000-0000-0000-0000-000000000002'
|
||||
|
||||
INSTANCE_IDS = {FAKE_UUID: 1}
|
||||
FIELDS = instance_obj.INSTANCE_DEFAULT_FIELDS
|
||||
|
||||
@ -159,7 +162,7 @@ class ControllerTest(test.TestCase):
|
||||
self.flags(use_ipv6=False)
|
||||
fakes.stub_out_key_pair_funcs(self)
|
||||
fake.stub_out_image_service(self)
|
||||
return_server = fakes.fake_compute_get(availability_zone='nova')
|
||||
return_server = fakes.fake_compute_get(id=2, availability_zone='nova')
|
||||
return_servers = fakes.fake_compute_get_all()
|
||||
# Server sort keys extension is enabled in v21 so sort data is passed
|
||||
# to the instance API and the sorted DB API is invoked
|
||||
@ -379,6 +382,9 @@ class ServersControllerTest(ControllerTest):
|
||||
"accessIPv6": '',
|
||||
"OS-EXT-AZ:availability_zone": "nova",
|
||||
"config_drive": None,
|
||||
"OS-EXT-SRV-ATTR:host": None,
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": None,
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000002",
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,8 +401,6 @@ class ServersControllerTest(ControllerTest):
|
||||
image_bookmark,
|
||||
flavor_bookmark,
|
||||
progress=0)
|
||||
expected_server['server']['name'] = 'server1'
|
||||
expected_server['server']['metadata']['seq'] = '1'
|
||||
self.assertThat(res_dict, matchers.DictMatches(expected_server))
|
||||
|
||||
def test_get_server_empty_az(self):
|
||||
@ -411,15 +415,12 @@ class ServersControllerTest(ControllerTest):
|
||||
image_bookmark = "http://localhost/fake/images/10"
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, vm_state=vm_states.ACTIVE, progress=100,
|
||||
availability_zone='nova')
|
||||
|
||||
req = self.req('/fake/servers/%s' % FAKE_UUID)
|
||||
res_dict = self.controller.show(req, FAKE_UUID)
|
||||
expected_server = self._get_server_data_dict(FAKE_UUID,
|
||||
image_bookmark,
|
||||
flavor_bookmark)
|
||||
flavor_bookmark,
|
||||
progress=0)
|
||||
self.assertThat(res_dict, matchers.DictMatches(expected_server))
|
||||
self.mock_get.assert_called_once_with(
|
||||
req.environ['nova.context'], FAKE_UUID,
|
||||
@ -427,21 +428,15 @@ class ServersControllerTest(ControllerTest):
|
||||
'numa_topology'])
|
||||
|
||||
def test_get_server_with_id_image_ref_by_id(self):
|
||||
image_ref = "10"
|
||||
image_bookmark = "http://localhost/fake/images/10"
|
||||
flavor_id = "1"
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, vm_state=vm_states.ACTIVE, image_ref=image_ref,
|
||||
flavor_id=flavor_id, progress=100,
|
||||
availability_zone='nova')
|
||||
|
||||
req = self.req('/fake/servers/%s' % FAKE_UUID)
|
||||
res_dict = self.controller.show(req, FAKE_UUID)
|
||||
expected_server = self._get_server_data_dict(FAKE_UUID,
|
||||
image_bookmark,
|
||||
flavor_bookmark)
|
||||
flavor_bookmark,
|
||||
progress=0)
|
||||
|
||||
self.assertThat(res_dict, matchers.DictMatches(expected_server))
|
||||
self.mock_get.assert_called_once_with(
|
||||
@ -1435,9 +1430,104 @@ class ServersControllerTest(ControllerTest):
|
||||
self.assertIn('servers', self.controller.detail(req))
|
||||
|
||||
|
||||
class ServersControllerTestV23(ServersControllerTest):
|
||||
wsgi_api_version = '2.3'
|
||||
|
||||
def setUp(self):
|
||||
super(ServersControllerTestV23, self).setUp()
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
|
||||
def _get_server_data_dict(self, uuid, image_bookmark, flavor_bookmark,
|
||||
status="ACTIVE", progress=100):
|
||||
server_dict = super(ServersControllerTestV23,
|
||||
self)._get_server_data_dict(uuid,
|
||||
image_bookmark,
|
||||
flavor_bookmark,
|
||||
status,
|
||||
progress)
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:hostname"] = "server2"
|
||||
server_dict['server'][
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname"] = "node-fake"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:kernel_id"] = UUID1
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:launch_index"] = 0
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:ramdisk_id"] = UUID2
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:reservation_id"] = "r-1"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:root_device_name"] = "/dev/vda"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:user_data"] = "userdata"
|
||||
return server_dict
|
||||
|
||||
def test_show(self):
|
||||
image_bookmark = "http://localhost/fake/images/10"
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
|
||||
req = self.req('/fake/servers/%s' % FAKE_UUID)
|
||||
res_dict = self.controller.show(req, FAKE_UUID)
|
||||
|
||||
expected_server = self._get_server_data_dict(FAKE_UUID,
|
||||
image_bookmark,
|
||||
flavor_bookmark,
|
||||
progress=0)
|
||||
self.assertThat(res_dict, matchers.DictMatches(expected_server))
|
||||
|
||||
def test_detail(self):
|
||||
def fake_get_all(context, search_opts=None,
|
||||
limit=None, marker=None,
|
||||
expected_attrs=None, sort_keys=None, sort_dirs=None):
|
||||
obj_list = []
|
||||
for i in range(2):
|
||||
server = fakes.stub_instance_obj(context,
|
||||
id=2, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
obj_list.append(server)
|
||||
return objects.InstanceList(objects=obj_list)
|
||||
|
||||
self.mock_get_all.side_effect = None
|
||||
self.mock_get_all.return_value = fake_get_all(context)
|
||||
|
||||
req = self.req('/fake/servers/detail')
|
||||
servers_list = self.controller.detail(req)
|
||||
image_bookmark = "http://localhost/fake/images/10"
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
expected_server = self._get_server_data_dict(FAKE_UUID,
|
||||
image_bookmark,
|
||||
flavor_bookmark,
|
||||
progress=0)
|
||||
|
||||
self.assertIn(expected_server['server'], servers_list['servers'])
|
||||
|
||||
|
||||
class ServersControllerTestV29(ServersControllerTest):
|
||||
wsgi_api_version = '2.9'
|
||||
|
||||
def setUp(self):
|
||||
super(ServersControllerTestV29, self).setUp()
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
|
||||
def _get_server_data_dict(self, uuid, image_bookmark, flavor_bookmark,
|
||||
status="ACTIVE", progress=100):
|
||||
server_dict = super(ServersControllerTestV29,
|
||||
@ -1447,6 +1537,15 @@ class ServersControllerTestV29(ServersControllerTest):
|
||||
status,
|
||||
progress)
|
||||
server_dict['server']['locked'] = False
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:hostname"] = "server2"
|
||||
server_dict['server'][
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname"] = "node-fake"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:kernel_id"] = UUID1
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:launch_index"] = 0
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:ramdisk_id"] = UUID2
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:reservation_id"] = "r-1"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:root_device_name"] = "/dev/vda"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:user_data"] = "userdata"
|
||||
return server_dict
|
||||
|
||||
def _test_get_server_with_lock(self, locked_by):
|
||||
@ -1454,6 +1553,13 @@ class ServersControllerTestV29(ServersControllerTest):
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, locked_by=locked_by, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
|
||||
req = self.req('/fake/servers/%s' % FAKE_UUID)
|
||||
@ -1484,7 +1590,16 @@ class ServersControllerTestV29(ServersControllerTest):
|
||||
s2_locked):
|
||||
self.mock_get_all.side_effect = None
|
||||
self.mock_get_all.return_value = fake_instance_get_all_with_locked(
|
||||
context, [s1_locked, s2_locked])
|
||||
context, [s1_locked, s2_locked],
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
|
||||
req = self.req('/fake/servers/detail')
|
||||
servers_list = self.controller.detail(req)
|
||||
# Check that each returned server has the same 'locked' value
|
||||
@ -1525,9 +1640,111 @@ class ServersControllerTestV29(ServersControllerTest):
|
||||
self.assertNotIn(key, search_opts)
|
||||
|
||||
|
||||
class ServersControllerTestV216(ServersControllerTest):
|
||||
wsgi_api_version = '2.16'
|
||||
|
||||
def setUp(self):
|
||||
super(ServersControllerTestV216, self).setUp()
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
self.useFixture(fixtures.MockPatchObject(
|
||||
compute_api.API, 'get_instance_host_status',
|
||||
return_value='UP')).mock
|
||||
|
||||
def _get_server_data_dict(self, uuid, image_bookmark, flavor_bookmark,
|
||||
status="ACTIVE", progress=100):
|
||||
server_dict = super(ServersControllerTestV216,
|
||||
self)._get_server_data_dict(uuid,
|
||||
image_bookmark,
|
||||
flavor_bookmark,
|
||||
status,
|
||||
progress)
|
||||
server_dict['server']['locked'] = False
|
||||
server_dict['server']["host_status"] = "UP"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:hostname"] = "server2"
|
||||
server_dict['server'][
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname"] = "node-fake"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:kernel_id"] = UUID1
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:launch_index"] = 0
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:ramdisk_id"] = UUID2
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:reservation_id"] = "r-1"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:root_device_name"] = "/dev/vda"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:user_data"] = "userdata"
|
||||
|
||||
return server_dict
|
||||
|
||||
def test_show(self):
|
||||
image_bookmark = "http://localhost/fake/images/10"
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
req = self.req('/fake/servers/%s' % FAKE_UUID)
|
||||
res_dict = self.controller.show(req, FAKE_UUID)
|
||||
expected_server = self._get_server_data_dict(FAKE_UUID,
|
||||
image_bookmark,
|
||||
flavor_bookmark,
|
||||
progress=0)
|
||||
self.assertThat(res_dict, matchers.DictMatches(expected_server))
|
||||
|
||||
def test_detail(self):
|
||||
def fake_get_all(context, search_opts=None,
|
||||
limit=None, marker=None,
|
||||
expected_attrs=None, sort_keys=None, sort_dirs=None):
|
||||
obj_list = []
|
||||
for i in range(2):
|
||||
server = fakes.stub_instance_obj(context,
|
||||
id=2, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
obj_list.append(server)
|
||||
return objects.InstanceList(objects=obj_list)
|
||||
|
||||
self.mock_get_all.side_effect = None
|
||||
self.mock_get_all.return_value = fake_get_all(context)
|
||||
|
||||
req = self.req('/fake/servers/detail')
|
||||
servers_list = self.controller.detail(req)
|
||||
image_bookmark = "http://localhost/fake/images/10"
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
expected_server = self._get_server_data_dict(FAKE_UUID,
|
||||
image_bookmark,
|
||||
flavor_bookmark,
|
||||
progress=0)
|
||||
|
||||
self.assertIn(expected_server['server'], servers_list['servers'])
|
||||
|
||||
|
||||
class ServersControllerTestV219(ServersControllerTest):
|
||||
wsgi_api_version = '2.19'
|
||||
|
||||
def setUp(self):
|
||||
super(ServersControllerTestV219, self).setUp()
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
self.useFixture(fixtures.MockPatchObject(
|
||||
compute_api.API, 'get_instance_host_status',
|
||||
return_value='UP')).mock
|
||||
|
||||
def _get_server_data_dict(self, uuid, image_bookmark, flavor_bookmark,
|
||||
status="ACTIVE", progress=100, description=None):
|
||||
server_dict = super(ServersControllerTestV219,
|
||||
@ -1538,6 +1755,17 @@ class ServersControllerTestV219(ServersControllerTest):
|
||||
progress)
|
||||
server_dict['server']['locked'] = False
|
||||
server_dict['server']['description'] = description
|
||||
server_dict['server']["host_status"] = "UP"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:hostname"] = "server2"
|
||||
server_dict['server'][
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname"] = "node-fake"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:kernel_id"] = UUID1
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:launch_index"] = 0
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:ramdisk_id"] = UUID2
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:reservation_id"] = "r-1"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:root_device_name"] = "/dev/vda"
|
||||
server_dict['server']["OS-EXT-SRV-ATTR:user_data"] = "userdata"
|
||||
|
||||
return server_dict
|
||||
|
||||
def _test_get_server_with_description(self, description):
|
||||
@ -1545,6 +1773,13 @@ class ServersControllerTestV219(ServersControllerTest):
|
||||
flavor_bookmark = "http://localhost/fake/flavors/2"
|
||||
self.mock_get.side_effect = fakes.fake_compute_get(
|
||||
id=2, display_description=description, uuid=FAKE_UUID,
|
||||
node="node-fake",
|
||||
reservation_id="r-1", launch_index=0,
|
||||
kernel_id=UUID1, ramdisk_id=UUID2,
|
||||
display_name="server2",
|
||||
root_device_name="/dev/vda",
|
||||
user_data="userdata",
|
||||
metadata={"seq": "2"},
|
||||
availability_zone='nova')
|
||||
|
||||
req = self.req('/fake/servers/%s' % FAKE_UUID)
|
||||
@ -2088,8 +2323,19 @@ class ServersControllerRebuildInstanceTest(ControllerTest):
|
||||
body = self.controller._action_rebuild(self.req, FAKE_UUID,
|
||||
body=body).obj
|
||||
|
||||
self.assertNotIn('OS-EXT-AZ:availability_zone', body['server'])
|
||||
self.assertNotIn('config_drive', body['server'])
|
||||
get_only_fields = ['OS-EXT-AZ:availability_zone', 'config_drive',
|
||||
'OS-EXT-SRV-ATTR:host',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname',
|
||||
'OS-EXT-SRV-ATTR:instance_name',
|
||||
'OS-EXT-SRV-ATTR:hostname'
|
||||
'OS-EXT-SRV-ATTR:kernel_id',
|
||||
'OS-EXT-SRV-ATTR:launch_index',
|
||||
'OS-EXT-SRV-ATTR:ramdisk_id',
|
||||
'OS-EXT-SRV-ATTR:reservation_id',
|
||||
'OS-EXT-SRV-ATTR:root_device_name',
|
||||
'OS-EXT-SRV-ATTR:user_data', 'host_status']
|
||||
for field in get_only_fields:
|
||||
self.assertNotIn(field, body['server'])
|
||||
|
||||
@mock.patch.object(compute_api.API, 'start')
|
||||
def test_start(self, mock_start):
|
||||
@ -2684,8 +2930,19 @@ class ServersControllerUpdateTest(ControllerTest):
|
||||
body = {'server': {'name': 'server_test'}}
|
||||
req = self._get_request(body)
|
||||
res_dict = self.controller.update(req, FAKE_UUID, body=body)
|
||||
self.assertNotIn('OS-EXT-AZ:availability_zone', res_dict['server'])
|
||||
self.assertNotIn('config_drive', res_dict['server'])
|
||||
get_only_fields = ['OS-EXT-AZ:availability_zone', 'config_drive',
|
||||
'OS-EXT-SRV-ATTR:host',
|
||||
'OS-EXT-SRV-ATTR:hypervisor_hostname',
|
||||
'OS-EXT-SRV-ATTR:instance_name',
|
||||
'OS-EXT-SRV-ATTR:hostname'
|
||||
'OS-EXT-SRV-ATTR:kernel_id',
|
||||
'OS-EXT-SRV-ATTR:launch_index',
|
||||
'OS-EXT-SRV-ATTR:ramdisk_id',
|
||||
'OS-EXT-SRV-ATTR:reservation_id',
|
||||
'OS-EXT-SRV-ATTR:root_device_name',
|
||||
'OS-EXT-SRV-ATTR:user_data', 'host_status']
|
||||
for field in get_only_fields:
|
||||
self.assertNotIn(field, res_dict['server'])
|
||||
|
||||
def test_update_server_name_too_long(self):
|
||||
body = {'server': {'name': 'x' * 256}}
|
||||
@ -5996,6 +6253,9 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
"accessIPv6": '',
|
||||
"OS-EXT-AZ:availability_zone": "nova",
|
||||
"config_drive": None,
|
||||
"OS-EXT-SRV-ATTR:host": None,
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": None,
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
}
|
||||
}
|
||||
|
||||
@ -6077,6 +6337,9 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
"accessIPv6": '',
|
||||
"OS-EXT-AZ:availability_zone": "nova",
|
||||
"config_drive": None,
|
||||
"OS-EXT-SRV-ATTR:host": None,
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": None,
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
}
|
||||
}
|
||||
|
||||
@ -6257,6 +6520,9 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
"accessIPv6": '',
|
||||
"OS-EXT-AZ:availability_zone": "nova",
|
||||
"config_drive": None,
|
||||
"OS-EXT-SRV-ATTR:host": None,
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": None,
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
}
|
||||
}
|
||||
|
||||
@ -6335,6 +6601,9 @@ class ServersViewBuilderTest(test.TestCase):
|
||||
"accessIPv6": '',
|
||||
"OS-EXT-AZ:availability_zone": "nova",
|
||||
"config_drive": None,
|
||||
"OS-EXT-SRV-ATTR:host": None,
|
||||
"OS-EXT-SRV-ATTR:hypervisor_hostname": None,
|
||||
"OS-EXT-SRV-ATTR:instance_name": "instance-00000001",
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user