1c6fdc9aec
This change adds a new microversion to expose virtual device tags for volumes and ports attached to a server. Implements blueprint expose-virtual-device-tags-in-rest-api Change-Id: I09420ff7134874dfe4dc399931c7740e81ecc2d0
271 lines
11 KiB
Python
271 lines
11 KiB
Python
# Copyright 2012 Nebula, Inc.
|
|
# Copyright 2013 IBM Corp.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from nova import exception
|
|
from nova.network import api as network_api
|
|
from nova import objects
|
|
from nova.tests.functional.api_sample_tests import test_servers
|
|
from nova.tests.unit import fake_network_cache_model
|
|
|
|
|
|
class AttachInterfacesSampleJsonTest(test_servers.ServersSampleBase):
|
|
sample_dir = 'os-attach-interfaces'
|
|
|
|
def setUp(self):
|
|
super(AttachInterfacesSampleJsonTest, self).setUp()
|
|
|
|
def fake_list_ports(self, *args, **kwargs):
|
|
uuid = kwargs.get('device_id', None)
|
|
if not uuid:
|
|
raise exception.InstanceNotFound(instance_id=None)
|
|
port_data = {
|
|
"id": "ce531f90-199f-48c0-816c-13e38010b442",
|
|
"network_id": "3cb9bc59-5699-4588-a4b1-b87f96708bc6",
|
|
"admin_state_up": True,
|
|
"status": "ACTIVE",
|
|
"mac_address": "fa:16:3e:4c:2c:30",
|
|
"fixed_ips": [
|
|
{
|
|
"ip_address": "192.168.1.3",
|
|
"subnet_id": "f8a6e8f8-c2ec-497c-9f23-da9616de54ef"
|
|
}
|
|
],
|
|
"device_id": uuid,
|
|
}
|
|
ports = {'ports': [port_data]}
|
|
return ports
|
|
|
|
def fake_show_port(self, context, port_id=None):
|
|
if not port_id:
|
|
raise exception.PortNotFound(port_id=None)
|
|
port_data = {
|
|
"id": port_id,
|
|
"network_id": "3cb9bc59-5699-4588-a4b1-b87f96708bc6",
|
|
"admin_state_up": True,
|
|
"status": "ACTIVE",
|
|
"mac_address": "fa:16:3e:4c:2c:30",
|
|
"fixed_ips": [
|
|
{
|
|
"ip_address": "192.168.1.3",
|
|
"subnet_id": "f8a6e8f8-c2ec-497c-9f23-da9616de54ef"
|
|
}
|
|
],
|
|
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
|
}
|
|
port = {'port': port_data}
|
|
return port
|
|
|
|
def fake_attach_interface(self, context, instance,
|
|
network_id, port_id,
|
|
requested_ip='192.168.1.3', tag=None):
|
|
if not network_id:
|
|
network_id = "fake_net_uuid"
|
|
if not port_id:
|
|
port_id = "fake_port_uuid"
|
|
vif = fake_network_cache_model.new_vif()
|
|
vif['id'] = port_id
|
|
vif['network']['id'] = network_id
|
|
vif['network']['subnets'][0]['ips'][0] = requested_ip
|
|
return vif
|
|
|
|
def fake_detach_interface(self, context, instance, port_id):
|
|
pass
|
|
|
|
self.stub_out('nova.network.api.API.list_ports', fake_list_ports)
|
|
self.stub_out('nova.network.api.API.show_port', fake_show_port)
|
|
self.stub_out('nova.compute.api.API.attach_interface',
|
|
fake_attach_interface)
|
|
self.stub_out('nova.compute.api.API.detach_interface',
|
|
fake_detach_interface)
|
|
self.flags(timeout=30, group='neutron')
|
|
|
|
def generalize_subs(self, subs, vanilla_regexes):
|
|
subs['subnet_id'] = vanilla_regexes['uuid']
|
|
subs['net_id'] = vanilla_regexes['uuid']
|
|
subs['port_id'] = vanilla_regexes['uuid']
|
|
subs['mac_addr'] = '(?:[a-f0-9]{2}:){5}[a-f0-9]{2}'
|
|
subs['ip_address'] = vanilla_regexes['ip']
|
|
return subs
|
|
|
|
def _get_subs(self):
|
|
"""Allows sub-classes to override the subs dict used for verification.
|
|
"""
|
|
return {
|
|
'ip_address': '192.168.1.3',
|
|
'subnet_id': 'f8a6e8f8-c2ec-497c-9f23-da9616de54ef',
|
|
'mac_addr': 'fa:16:3e:4c:2c:30',
|
|
'net_id': '3cb9bc59-5699-4588-a4b1-b87f96708bc6',
|
|
'port_id': 'ce531f90-199f-48c0-816c-13e38010b442',
|
|
'port_state': 'ACTIVE'
|
|
}
|
|
|
|
def test_list_interfaces(self):
|
|
instance_uuid = self._post_server()
|
|
response = self._do_get('servers/%s/os-interface'
|
|
% instance_uuid)
|
|
subs = self._get_subs()
|
|
self._verify_response('attach-interfaces-list-resp', subs,
|
|
response, 200)
|
|
|
|
def _stub_show_for_instance(self, instance_uuid, port_id):
|
|
show_port = network_api.API().show_port(None, port_id)
|
|
show_port['port']['device_id'] = instance_uuid
|
|
self.stub_out('nova.network.api.API.show_port',
|
|
lambda *a, **k: show_port)
|
|
|
|
def test_show_interfaces(self):
|
|
instance_uuid = self._post_server()
|
|
port_id = 'ce531f90-199f-48c0-816c-13e38010b442'
|
|
self._stub_show_for_instance(instance_uuid, port_id)
|
|
response = self._do_get('servers/%s/os-interface/%s' %
|
|
(instance_uuid, port_id))
|
|
subs = self._get_subs()
|
|
self._verify_response('attach-interfaces-show-resp', subs,
|
|
response, 200)
|
|
|
|
def test_create_interfaces(self, instance_uuid=None):
|
|
if instance_uuid is None:
|
|
instance_uuid = self._post_server()
|
|
subs = self._get_subs()
|
|
self._stub_show_for_instance(instance_uuid, subs['port_id'])
|
|
response = self._do_post('servers/%s/os-interface'
|
|
% instance_uuid,
|
|
'attach-interfaces-create-req', subs)
|
|
self._verify_response('attach-interfaces-create-resp', subs,
|
|
response, 200)
|
|
|
|
def test_create_interfaces_with_net_id_and_fixed_ips(self,
|
|
instance_uuid=None):
|
|
if instance_uuid is None:
|
|
instance_uuid = self._post_server()
|
|
subs = self._get_subs()
|
|
self._stub_show_for_instance(instance_uuid, subs['port_id'])
|
|
response = self._do_post('servers/%s/os-interface'
|
|
% instance_uuid,
|
|
'attach-interfaces-create-net_id-req', subs)
|
|
self._verify_response('attach-interfaces-create-resp', subs,
|
|
response, 200)
|
|
|
|
def test_delete_interfaces(self):
|
|
instance_uuid = self._post_server()
|
|
port_id = 'ce531f90-199f-48c0-816c-13e38010b442'
|
|
response = self._do_delete('servers/%s/os-interface/%s' %
|
|
(instance_uuid, port_id))
|
|
self.assertEqual(202, response.status_code)
|
|
self.assertEqual('', response.text)
|
|
|
|
|
|
class AttachInterfacesSampleV249JsonTest(test_servers.ServersSampleBase):
|
|
sample_dir = 'os-attach-interfaces'
|
|
microversion = '2.49'
|
|
scenarios = [('v2_49', {'api_major_version': 'v2.1'})]
|
|
|
|
def setUp(self):
|
|
super(AttachInterfacesSampleV249JsonTest, self).setUp()
|
|
|
|
def fake_show_port(self, context, port_id=None):
|
|
if not port_id:
|
|
raise exception.PortNotFound(port_id=None)
|
|
port_data = {
|
|
"id": port_id,
|
|
"network_id": "3cb9bc59-5699-4588-a4b1-b87f96708bc6",
|
|
"admin_state_up": True,
|
|
"status": "ACTIVE",
|
|
"mac_address": "fa:16:3e:4c:2c:30",
|
|
"fixed_ips": [
|
|
{
|
|
"ip_address": "192.168.1.3",
|
|
"subnet_id": "f8a6e8f8-c2ec-497c-9f23-da9616de54ef"
|
|
}
|
|
],
|
|
"device_id": 'bece68a3-2f8b-4e66-9092-244493d6aba7',
|
|
}
|
|
port = {'port': port_data}
|
|
return port
|
|
|
|
def fake_attach_interface(self, context, instance,
|
|
network_id, port_id,
|
|
requested_ip='192.168.1.3', tag=None):
|
|
if not network_id:
|
|
network_id = "fake_net_uuid"
|
|
if not port_id:
|
|
port_id = "fake_port_uuid"
|
|
vif = fake_network_cache_model.new_vif()
|
|
vif['id'] = port_id
|
|
vif['network']['id'] = network_id
|
|
vif['network']['subnets'][0]['ips'][0] = requested_ip
|
|
vif['tag'] = tag
|
|
return vif
|
|
|
|
self.stub_out('nova.network.api.API.show_port', fake_show_port)
|
|
self.stub_out('nova.compute.api.API.attach_interface',
|
|
fake_attach_interface)
|
|
|
|
def _stub_show_for_instance(self, instance_uuid, port_id):
|
|
show_port = network_api.API().show_port(None, port_id)
|
|
show_port['port']['device_id'] = instance_uuid
|
|
self.stub_out('nova.network.api.API.show_port',
|
|
lambda *a, **k: show_port)
|
|
|
|
def test_create_interfaces(self, instance_uuid=None):
|
|
if instance_uuid is None:
|
|
instance_uuid = self._post_server()
|
|
subs = {
|
|
'net_id': '3cb9bc59-5699-4588-a4b1-b87f96708bc6',
|
|
'port_id': 'ce531f90-199f-48c0-816c-13e38010b442',
|
|
'subnet_id': 'f8a6e8f8-c2ec-497c-9f23-da9616de54ef',
|
|
'ip_address': '192.168.1.3',
|
|
'port_state': 'ACTIVE',
|
|
'mac_addr': 'fa:16:3e:4c:2c:30',
|
|
}
|
|
self._stub_show_for_instance(instance_uuid, subs['port_id'])
|
|
response = self._do_post('servers/%s/os-interface'
|
|
% instance_uuid,
|
|
'attach-interfaces-create-req', subs)
|
|
self._verify_response('attach-interfaces-create-resp', subs,
|
|
response, 200)
|
|
|
|
|
|
class AttachInterfacesSampleV270JsonTest(AttachInterfacesSampleJsonTest):
|
|
"""Tests for the 2.70 microversion in the os-interface API
|
|
which returns the 'tag' field in response bodies to GET and POST methods.
|
|
"""
|
|
microversion = '2.70'
|
|
scenarios = [('v2_70', {'api_major_version': 'v2.1'})]
|
|
|
|
def setUp(self):
|
|
super(AttachInterfacesSampleV270JsonTest, self).setUp()
|
|
port_id = 'ce531f90-199f-48c0-816c-13e38010b442'
|
|
|
|
def fake_virtual_interface_list_by_instance_uuid(*args, **kwargs):
|
|
return objects.VirtualInterfaceList(objects=[
|
|
objects.VirtualInterface(
|
|
# All these tests care about is the uuid and tag.
|
|
uuid=port_id, tag='public')])
|
|
|
|
def fake_virtual_interface_get_by_uuid(*args, **kwargs):
|
|
return objects.VirtualInterface(uuid=port_id, tag='public')
|
|
|
|
self.stub_out('nova.objects.VirtualInterface.get_by_uuid',
|
|
fake_virtual_interface_get_by_uuid)
|
|
self.stub_out('nova.objects.VirtualInterfaceList.get_by_instance_uuid',
|
|
fake_virtual_interface_list_by_instance_uuid)
|
|
|
|
def _get_subs(self):
|
|
subs = super(AttachInterfacesSampleV270JsonTest, self)._get_subs()
|
|
# 2.70 adds the tag parameter to the request and response.
|
|
subs['tag'] = 'public'
|
|
return subs
|