Merge "Support network_attach with more parameters"

This commit is contained in:
Zuul 2018-06-03 04:45:31 +00:00 committed by Gerrit Code Review
commit 15e29a81f2
7 changed files with 141 additions and 18 deletions

View File

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

View File

@ -56,6 +56,13 @@ exec_run:
in: query in: query
required: false required: false
type: boolean 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: force:
description: | description: |
Specify to delete container forcefully. Specify to delete container forcefully.
@ -70,16 +77,31 @@ height:
type: string type: string
network: network:
description: | description: |
Network to be detached of the container. The ID or name of the network to be detached from the container.
in: query in: query
required: true required: true
type: string 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: new_name:
description: | description: |
The new name for the container. The new name for the container.
in: query in: query
required: true required: true
type: string 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: ps_args:
description: | description: |
The arguments of ps command. The arguments of ps command.

View File

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

View File

@ -229,8 +229,7 @@ class KuryrNetwork(network.Network):
'tenant_id': self.context.project_id, 'tenant_id': self.context.project_id,
'device_id': container.uuid, 'device_id': container.uuid,
} }
ip_addr = requested_network.get("v4-fixed-ip") or requested_network.\ ip_addr = requested_network.get("fixed_ip")
get("v6-fixed-ip")
if ip_addr: if ip_addr:
port_dict['fixed_ips'] = [{'ip_address': ip_addr}] port_dict['fixed_ips'] = [{'ip_address': ip_addr}]
if security_groups is not None: 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, "use an ID to be more specific." % security_group_to_add,
response.json['errors'][0]['detail']) 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.network.neutron.NeutronAPI.get_neutron_network')
@patch('zun.compute.api.API.network_detach') @patch('zun.compute.api.API.network_detach')
@patch('zun.objects.Container.get_by_uuid') @patch('zun.objects.Container.get_by_uuid')

View File

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