Skip to content

Commit 108778c

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "api: Reject duplicate port IDs in server create" into stable/xena
2 parents f088ade + d4c92bc commit 108778c

File tree

3 files changed

+54
-14
lines changed

3 files changed

+54
-14
lines changed

nova/api/openstack/compute/servers.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ def _get_requested_networks(self, requested_networks):
409409

410410
networks = []
411411
network_uuids = []
412+
port_uuids = []
412413
for network in requested_networks:
413414
request = objects.NetworkRequest()
414415
try:
@@ -417,18 +418,31 @@ def _get_requested_networks(self, requested_networks):
417418
# it will use one of the available IP address from the network
418419
request.address = network.get('fixed_ip', None)
419420
request.port_id = network.get('port', None)
420-
421421
request.tag = network.get('tag', None)
422422

423423
if request.port_id:
424-
request.network_id = None
424+
if request.port_id in port_uuids:
425+
msg = _(
426+
"Port ID '%(port)s' was specified twice: you "
427+
"cannot attach a port multiple times."
428+
) % {
429+
"port": request.port_id,
430+
}
431+
raise exc.HTTPBadRequest(explanation=msg)
432+
425433
if request.address is not None:
426-
msg = _("Specified Fixed IP '%(addr)s' cannot be used "
427-
"with port '%(port)s': the two cannot be "
428-
"specified together.") % {
429-
"addr": request.address,
430-
"port": request.port_id}
434+
msg = _(
435+
"Specified Fixed IP '%(addr)s' cannot be used "
436+
"with port '%(port)s': the two cannot be "
437+
"specified together."
438+
) % {
439+
"addr": request.address,
440+
"port": request.port_id,
441+
}
431442
raise exc.HTTPBadRequest(explanation=msg)
443+
444+
request.network_id = None
445+
port_uuids.append(request.port_id)
432446
else:
433447
request.network_id = network['uuid']
434448
self._validate_network_id(

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -389,17 +389,36 @@ def test_requested_networks_with_and_duplicate_networks(self):
389389
(network, None, None, None, None, None)],
390390
res.as_tuples())
391391

392-
def test_requested_networks_enabled_conflict_on_fixed_ip(self):
393-
network = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
392+
def test_requested_networks_duplicate_ports(self):
393+
"""The same port can't be specified twice."""
394+
port = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
395+
requested_networks = [{'port': port}, {'port': port}]
396+
exc = self.assertRaises(
397+
webob.exc.HTTPBadRequest,
398+
self.controller._get_requested_networks,
399+
requested_networks,
400+
)
401+
self.assertIn(
402+
"Port ID 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee' was specified "
403+
"twice",
404+
str(exc),
405+
)
406+
407+
def test_requested_networks_conflict_on_fixed_ip(self):
408+
"""A fixed IP can't be specified at the same as a port ID."""
394409
port = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
395410
addr = '10.0.0.1'
396-
requested_networks = [{'uuid': network,
397-
'fixed_ip': addr,
398-
'port': port}]
399-
self.assertRaises(
411+
requested_networks = [{'fixed_ip': addr, 'port': port}]
412+
exc = self.assertRaises(
400413
webob.exc.HTTPBadRequest,
401414
self.controller._get_requested_networks,
402-
requested_networks)
415+
requested_networks,
416+
)
417+
self.assertIn(
418+
"Specified Fixed IP '10.0.0.1' cannot be used with port "
419+
"'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'",
420+
str(exc),
421+
)
403422

404423
def test_requested_networks_api_enabled_with_v2_subclass(self):
405424
network = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
fixes:
3+
- |
4+
The ``POST /servers`` (create server) API will now reject attempts to
5+
create a server with the same port specified multiple times. This was
6+
previously accepted by the API but the instance would fail to spawn and
7+
would instead transition to the error state.

0 commit comments

Comments
 (0)