Support network_attach with more parameters

In before, the network_attach API supports only the 'network'
parameter. This patch adds three more parameter 'port' and
'fixed_ip'.

Change-Id: Ic7d3367f00b8cb034ee6d7d27962168e8cdc0a67
Closes-Bug: #1746654
This commit is contained in:
Hongbin Lu 2018-03-08 04:07:10 +00:00
parent 188ecf5fec
commit e5711229c7
7 changed files with 141 additions and 18 deletions

View File

@ -1026,7 +1026,9 @@ Response Codes
.. rest_parameters:: parameters.yaml
- container_ident: container_ident
- network: network
- network: network-query
- port: port-query
- fixed_ip: fixed_ip-query
Response
--------

View File

@ -56,6 +56,13 @@ exec_run:
in: query
required: false
type: boolean
fixed_ip-query:
description: |
Fixed IP addresses. If you request a specific fixed IP address without
a ``network``, the request returns a Bad Request (400) response code.
in: query
required: false
type: string
force:
description: |
Specify to delete container forcefully.
@ -70,16 +77,31 @@ height:
type: string
network:
description: |
Network to be detached of the container.
The ID or name of the network to be detached from the container.
in: query
required: true
type: string
network-query:
description: |
The ID or name of the network to be attached to the container.
in: query
required: false
type: string
new_name:
description: |
The new name for the container.
in: query
required: true
type: string
port-query:
description: |
The ID or name of the port for which you want to bind to the container.
The ``network`` and ``port`` parameters are mutually exclusive.
If you do not specify the ``port`` parameter, Zun will allocate a port
and bind the port to the container.
in: query
required: false
type: string
ps_args:
description: |
The arguments of ps command.

View File

@ -184,4 +184,34 @@ network_detach = {
'additionalProperties': False
}
network_attach = copy.deepcopy(network_detach)
network_attach = {
'type': 'object',
'properties': {
'network': {
'type': ['string'],
'minLength': 1,
'maxLength': 255,
},
'fixed_ip': {
'type': ['string'],
'oneOf': [
{'format': 'ipv4'},
{'format': 'ipv6'}
]
},
'port': {
'type': ['string'],
'maxLength': 255,
'minLength': 1,
}
},
'additionalProperties': False,
'oneOf': [
{
'required': ['network']
},
{
'required': ['port']
}
]
}

View File

@ -500,8 +500,7 @@ def build_requested_networks(context, nets):
'router:external':
network.get('router:external'),
'shared': network.get('shared'),
'v4-fixed-ip': '',
'v6-fixed-ip': '',
'fixed_ip': '',
'preserve_on_delete': True})
elif net.get('network'):
network = neutron_api.get_neutron_network(net['network'])
@ -510,9 +509,9 @@ def build_requested_networks(context, nets):
'router:external':
network.get('router:external'),
'shared': network.get('shared'),
'v4-fixed-ip':
net.get('v4-fixed-ip', ''),
'v6-fixed-ip':
'fixed_ip':
net.get('fixed_ip') or
net.get('v4-fixed-ip', '') or
net.get('v6-fixed-ip', ''),
'preserve_on_delete': False})
if not requested_networks:
@ -521,8 +520,7 @@ def build_requested_networks(context, nets):
neutron_net = neutron_api.get_available_network()
requested_networks.append({'network': neutron_net['id'],
'port': '',
'v4-fixed-ip': '',
'v6-fixed-ip': '',
'fixed_ip': '',
'preserve_on_delete': False})
check_external_network_attach(context, requested_networks)

View File

@ -229,8 +229,7 @@ class KuryrNetwork(network.Network):
'tenant_id': self.context.project_id,
'device_id': container.uuid,
}
ip_addr = requested_network.get("v4-fixed-ip") or requested_network.\
get("v6-fixed-ip")
ip_addr = requested_network.get("fixed_ip")
if ip_addr:
port_dict['fixed_ips'] = [{'ip_address': ip_addr}]
if security_groups is not None:

View File

@ -1811,6 +1811,81 @@ class TestContainerController(api_base.FunctionalTest):
"use an ID to be more specific." % security_group_to_add,
response.json['errors'][0]['detail'])
@patch('zun.network.neutron.NeutronAPI.get_neutron_network')
@patch('zun.compute.api.API.network_attach')
@patch('zun.objects.Container.get_by_uuid')
def test_network_attach(self, mock_by_uuid, mock_attach, mock_get_network):
built_requested_network = {
'network': 'fake-net-id',
'port': '',
'router:external': False,
'shared': False,
'fixed_ip': '',
'preserve_on_delete': False}
query = 'network=private'
self._test_network_attach(mock_by_uuid, mock_attach, mock_get_network,
query, built_requested_network)
mock_get_network.assert_called_once_with('private')
@patch('zun.network.neutron.NeutronAPI.get_neutron_network')
@patch('zun.compute.api.API.network_attach')
@patch('zun.objects.Container.get_by_uuid')
def test_network_attach_with_fixed_ip(self, mock_by_uuid, mock_attach,
mock_get_network):
built_requested_network = {
'network': 'fake-net-id',
'port': '',
'router:external': False,
'shared': False,
'fixed_ip': '10.0.0.3',
'preserve_on_delete': False}
query = 'network=private&fixed_ip=10.0.0.3'
self._test_network_attach(mock_by_uuid, mock_attach, mock_get_network,
query, built_requested_network)
mock_get_network.assert_called_once_with('private')
@patch('zun.network.neutron.NeutronAPI.get_neutron_port')
@patch('zun.network.neutron.NeutronAPI.ensure_neutron_port_usable')
@patch('zun.network.neutron.NeutronAPI.get_neutron_network')
@patch('zun.compute.api.API.network_attach')
@patch('zun.objects.Container.get_by_uuid')
def test_network_attach_with_port(self, mock_by_uuid, mock_attach,
mock_get_network,
mock_ensure, mock_get_port):
mock_get_port.return_value = {
'id': 'fake-port-id',
'network_id': 'fake-net-id',
}
built_requested_network = {
'network': 'fake-net-id',
'port': 'fake-port-id',
'router:external': False,
'shared': False,
'fixed_ip': '',
'preserve_on_delete': True}
query = 'port=fake-port'
self._test_network_attach(mock_by_uuid, mock_attach, mock_get_network,
query, built_requested_network)
mock_get_port.assert_called_once_with('fake-port')
mock_get_network.assert_called_once_with('fake-net-id')
def _test_network_attach(self, mock_by_uuid, mock_attach, mock_get_network,
query, built_requested_network):
test_container = utils.get_test_container()
test_container_obj = objects.Container(self.context, **test_container)
mock_by_uuid.return_value = test_container_obj
container_uuid = test_container.get('uuid')
fake_network = {'id': 'fake-net-id',
'router:external': False,
'shared': False}
mock_get_network.return_value = fake_network
url = '/v1/containers/%s/%s?%s' % (container_uuid, 'network_attach',
query)
response = self.post(url)
self.assertEqual(200, response.status_int)
mock_attach.assert_called_once_with(mock.ANY, test_container_obj,
built_requested_network)
@patch('zun.network.neutron.NeutronAPI.get_neutron_network')
@patch('zun.compute.api.API.network_detach')
@patch('zun.objects.Container.get_by_uuid')

View File

@ -798,8 +798,7 @@ class TestDockerDriver(base.DriverTestCase):
mock_list.return_value = {'network': 'network'}
requested_network = {'network': 'network',
'port': '',
'v4-fixed-ip': '',
'v6-fixed-ip': '',
'fixed_ip': '',
'preserve_on_delete': False}
self.driver.network_attach(self.context, mock_container,
requested_network)
@ -814,8 +813,7 @@ class TestDockerDriver(base.DriverTestCase):
mock_container.addresses = {'already-attached-net': []}
requested_network = {'network': 'already-attached-net',
'port': '',
'v4-fixed-ip': '',
'v6-fixed-ip': '',
'fixed_ip': '',
'preserve_on_delete': False}
self.assertRaises(exception.ZunException,
self.driver.network_attach,
@ -837,8 +835,7 @@ class TestDockerDriver(base.DriverTestCase):
mock_get_sec_group_id.return_value = test_sec_group_id
requested_network = {'network': 'network',
'port': '',
'v4-fixed-ip': '',
'v6-fixed-ip': '',
'fixed_ip': '',
'preserve_on_delete': False}
self.driver.network_attach(self.context, mock_container,
requested_network)