Merge "Create server with security group ID and name"

This commit is contained in:
Jenkins
2017-05-22 23:09:02 +00:00
committed by Gerrit Code Review
5 changed files with 168 additions and 4 deletions

View File

@@ -164,7 +164,7 @@ Create a new server
Create server with this flavor (name or ID) Create server with this flavor (name or ID)
.. option:: --security-group <security-group-name> .. option:: --security-group <security-group>
Security group to assign to this server (name or ID) Security group to assign to this server (name or ID)
(repeat option to set multiple groups) (repeat option to set multiple groups)

View File

@@ -407,7 +407,7 @@ class CreateServer(command.ShowOne):
) )
parser.add_argument( parser.add_argument(
'--security-group', '--security-group',
metavar='<security-group-name>', metavar='<security-group>',
action='append', action='append',
default=[], default=[],
help=_('Security group to assign to this server (name or ID) ' help=_('Security group to assign to this server (name or ID) '
@@ -695,6 +695,22 @@ class CreateServer(command.ShowOne):
# decide the default behavior. # decide the default behavior.
nics = [] nics = []
# Check security group exist and convert ID to name
security_group_names = []
if self.app.client_manager.is_network_endpoint_enabled():
network_client = self.app.client_manager.network
for each_sg in parsed_args.security_group:
sg = network_client.find_security_group(each_sg,
ignore_missing=False)
# Use security group ID to avoid multiple security group have
# same name in neutron networking backend
security_group_names.append(sg.id)
else:
# Handle nova-network case
for each_sg in parsed_args.security_group:
sg = compute_client.api.security_group_find(each_sg)
security_group_names.append(sg['name'])
hints = {} hints = {}
for hint in parsed_args.hint: for hint in parsed_args.hint:
key, _sep, value = hint.partition('=') key, _sep, value = hint.partition('=')
@@ -724,7 +740,7 @@ class CreateServer(command.ShowOne):
reservation_id=None, reservation_id=None,
min_count=parsed_args.min, min_count=parsed_args.min,
max_count=parsed_args.max, max_count=parsed_args.max,
security_groups=parsed_args.security_group, security_groups=security_group_names,
userdata=userdata, userdata=userdata,
key_name=parsed_args.key_name, key_name=parsed_args.key_name,
availability_zone=parsed_args.availability_zone, availability_zone=parsed_args.availability_zone,

View File

@@ -517,6 +517,52 @@ class ServerTests(common.ComputeTestCase):
self.assertIsNotNone(server['addresses']) self.assertIsNotNone(server['addresses'])
self.assertEqual('', server['addresses']) self.assertEqual('', server['addresses'])
def test_server_create_with_security_group(self):
"""Test server create with security group ID and name"""
if not self.haz_network:
# NOTE(dtroyer): As of Ocata release Nova forces nova-network to
# run in a cells v1 configuration. Security group
# and network functions currently do not work in
# the gate jobs so we have to skip this. It is
# known to work tested against a Mitaka nova-net
# DevStack without cells.
self.skipTest("No Network service present")
# Create two security group, use name and ID to create server
sg_name1 = uuid.uuid4().hex
security_group1 = json.loads(self.openstack(
'security group create -f json ' + sg_name1
))
self.addCleanup(self.openstack, 'security group delete ' + sg_name1)
sg_name2 = uuid.uuid4().hex
security_group2 = json.loads(self.openstack(
'security group create -f json ' + sg_name2
))
self.addCleanup(self.openstack, 'security group delete ' + sg_name2)
server_name = uuid.uuid4().hex
server = json.loads(self.openstack(
'server create -f json ' +
'--flavor ' + self.flavor_name + ' ' +
'--image ' + self.image_name + ' ' +
# Security group id is integer in nova-network, convert to string
'--security-group ' + str(security_group1['id']) + ' ' +
'--security-group ' + security_group2['name'] + ' ' +
self.network_arg + ' ' +
server_name
))
self.addCleanup(self.openstack, 'server delete --wait ' + server_name)
self.assertIsNotNone(server['id'])
self.assertEqual(server_name, server['name'])
self.assertIn(str(security_group1['id']), server['security_groups'])
self.assertIn(str(security_group2['id']), server['security_groups'])
self.wait_for_status(server_name, 'ACTIVE')
server = json.loads(self.openstack(
'server show -f json ' + server_name
))
self.assertIn(sg_name1, server['security_groups'])
self.assertIn(sg_name2, server['security_groups'])
def test_server_create_with_empty_network_option_latest(self): def test_server_create_with_empty_network_option_latest(self):
"""Test server create with empty network option in nova 2.latest.""" """Test server create with empty network option in nova 2.latest."""
server_name = uuid.uuid4().hex server_name = uuid.uuid4().hex

View File

@@ -25,6 +25,7 @@ from oslo_utils import timeutils
from openstackclient.compute.v2 import server from openstackclient.compute.v2 import server
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
from openstackclient.tests.unit.image.v2 import fakes as image_fakes from openstackclient.tests.unit.image.v2 import fakes as image_fakes
from openstackclient.tests.unit.network.v2 import fakes as network_fakes
from openstackclient.tests.unit import utils from openstackclient.tests.unit import utils
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
@@ -421,8 +422,16 @@ class TestServerCreate(TestServer):
# In base command class ShowOne in cliff, abstract method take_action() # In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of # returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown. # data to be shown.
fake_sg = network_fakes.FakeSecurityGroup.create_security_groups()
mock_find_sg = (
network_fakes.FakeSecurityGroup.get_security_groups(fake_sg)
)
self.app.client_manager.network.find_security_group = mock_find_sg
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
mock_find_sg.assert_called_once_with('securitygroup',
ignore_missing=False)
# Set expected values # Set expected values
kwargs = dict( kwargs = dict(
meta={'Beta': 'b'}, meta={'Beta': 'b'},
@@ -430,7 +439,7 @@ class TestServerCreate(TestServer):
reservation_id=None, reservation_id=None,
min_count=1, min_count=1,
max_count=1, max_count=1,
security_groups=['securitygroup'], security_groups=[fake_sg[0].id],
userdata=None, userdata=None,
key_name='keyname', key_name='keyname',
availability_zone=None, availability_zone=None,
@@ -450,6 +459,92 @@ class TestServerCreate(TestServer):
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist(), data) self.assertEqual(self.datalist(), data)
def test_server_create_with_not_exist_security_group(self):
arglist = [
'--image', 'image1',
'--flavor', 'flavor1',
'--key-name', 'keyname',
'--security-group', 'securitygroup',
'--security-group', 'not_exist_sg',
self.new_server.name,
]
verifylist = [
('image', 'image1'),
('flavor', 'flavor1'),
('key_name', 'keyname'),
('security_group', ['securitygroup', 'not_exist_sg']),
('server_name', self.new_server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
fake_sg = network_fakes.FakeSecurityGroup.create_security_groups(
count=1)
fake_sg.append(exceptions.NotFound(code=404))
mock_find_sg = (
network_fakes.FakeSecurityGroup.get_security_groups(fake_sg)
)
self.app.client_manager.network.find_security_group = mock_find_sg
self.assertRaises(exceptions.NotFound,
self.cmd.take_action,
parsed_args)
mock_find_sg.assert_called_with('not_exist_sg',
ignore_missing=False)
def test_server_create_with_security_group_in_nova_network(self):
arglist = [
'--image', 'image1',
'--flavor', 'flavor1',
'--key-name', 'keyname',
'--security-group', 'securitygroup',
self.new_server.name,
]
verifylist = [
('image', 'image1'),
('flavor', 'flavor1'),
('key_name', 'keyname'),
('security_group', ['securitygroup']),
('server_name', self.new_server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch.object(self.app.client_manager,
'is_network_endpoint_enabled',
return_value=False):
with mock.patch.object(self.app.client_manager.compute.api,
'security_group_find',
return_value={'name': 'fake_sg'}
) as mock_find:
columns, data = self.cmd.take_action(parsed_args)
mock_find.assert_called_once_with('securitygroup')
# Set expected values
kwargs = dict(
meta=None,
files={},
reservation_id=None,
min_count=1,
max_count=1,
security_groups=['fake_sg'],
userdata=None,
key_name='keyname',
availability_zone=None,
block_device_mapping_v2=[],
nics=[],
scheduler_hints={},
config_drive=None,
)
# ServerManager.create(name, image, flavor, **kwargs)
self.servers_mock.create.assert_called_with(
self.new_server.name,
self.image,
self.flavor,
**kwargs
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist(), data)
def test_server_create_with_network(self): def test_server_create_with_network(self):
arglist = [ arglist = [
'--image', 'image1', '--image', 'image1',

View File

@@ -0,0 +1,7 @@
---
fixes:
- |
Allow security groups in ``server create`` command to be specified by name or ID with
the ``--security-group`` option. This also checks that the security group exist before
creating the server.
[Bug `1687814 <https://bugs.launchpad.net/python-openstackclient/+bug/1687814>`_]