Added handling of secgroup for service_instance module

Change-Id: If3cb5f7436142e4eb8829690117d15c3029ed9d2
Closes-Bug: #1314591
This commit is contained in:
Valeriy Ponomaryov 2014-05-12 07:59:08 -04:00 committed by vponomaryov
parent 625cea75cd
commit 45dc9bddc5
6 changed files with 198 additions and 13 deletions

View File

@ -260,7 +260,7 @@ function create_manila_service_image {
}
function create_manila_service_secgroup {
MANILA_SERVICE_SECGROUP="manila-service-secgroup"
MANILA_SERVICE_SECGROUP="manila-service"
# Create a secgroup
if ! nova secgroup-list | grep -q $MANILA_SERVICE_SECGROUP; then

View File

@ -24,3 +24,26 @@ STATUS_ACTIVATING = 'ACTIVATING'
STATUS_DEACTIVATING = 'DEACTIVATING'
SECURITY_SERVICES_ALLOWED_TYPES = ['active_directory', 'ldap', 'kerberos']
# Below represented ports are ranges (from, to)
CIFS_PORTS = (
("tcp", (445, 445)),
("tcp", (137, 139)),
("udp", (137, 139)),
("udp", (445, 445)),
)
NFS_PORTS = (
("tcp", (2049, 2049)),
("udp", (2049, 2049)),
)
SSH_PORTS = (
("tcp", (22, 22)),
)
PING_PORTS = (
("icmp", (-1, -1)),
)
SERVICE_INSTANCE_SECGROUP_DATA = CIFS_PORTS + \
NFS_PORTS + \
SSH_PORTS + \
PING_PORTS

View File

@ -129,6 +129,7 @@ def _untranslate_server_summary_view(server):
d['networks'] = server.networks
d['tenant_id'] = server.tenant_id
d['user_id'] = server.user_id
d['security_groups'] = server.security_groups
return d
@ -154,8 +155,9 @@ def translate_server_exception(method):
class API(base.Base):
"""API for interacting with novaclient."""
def server_create(self, context, name, image, flavor, key_name, user_data,
security_groups, block_device_mapping=None,
def server_create(self, context, name, image, flavor, key_name=None,
user_data=None, security_groups=None,
block_device_mapping=None,
block_device_mapping_v2=None, nics=None,
availability_zone=None, instance_count=1,
admin_pass=None):
@ -272,3 +274,25 @@ class API(base.Base):
def image_list(self, context):
return novaclient(context).images.list()
def add_security_group_to_server(self, context, server, security_group):
return novaclient(context).servers.add_security_group(server,
security_group)
def security_group_create(self, context, name, description=""):
return novaclient(context).security_groups.create(name, description)
def security_group_get(self, context, group_id):
return novaclient(context).security_groups.get(group_id)
def security_group_list(self, context, search_opts=None):
return novaclient(context).security_groups.list(search_opts)
def security_group_rule_create(self, context, parent_group_id,
ip_protocol=None, from_port=None,
to_port=None, cidr=None, group_id=None):
return novaclient(context).security_group_rules.create(
parent_group_id, ip_protocol, from_port, to_port, cidr, group_id)
def security_group_rule_delete(self, context, rule):
return novaclient(context).security_group_rules.delete(rule)

View File

@ -23,6 +23,7 @@ import time
from oslo.config import cfg
from manila.common import constants
from manila import compute
from manila import context
from manila import exception
@ -61,6 +62,10 @@ server_opts = [
cfg.IntOpt('max_time_to_build_instance',
default=300,
help="Maximum time to wait for creating service instance."),
cfg.StrOpt('service_instance_security_group',
default="manila-service",
help="Name of security group, that will be used for "
"service instance creation."),
cfg.IntOpt('service_instance_flavor_id',
default=100,
help="ID of flavor, that will be used for service instance "
@ -195,6 +200,43 @@ class ServiceInstanceManager(object):
LOG.error(msg)
raise exception.ServiceInstanceException(msg)
def _get_service_instance_security_group(self, context, name=None):
"""Searches for security group by name."""
if not (name or CONF.service_instance_security_group):
return None
if not name:
name = CONF.service_instance_security_group
s_groups = [s for s in self.compute_api.security_group_list(context)
if s.name == name]
if not s_groups:
return None
elif len(s_groups) > 1:
msg = _("Ambiguous security_groups.")
raise exception.ServiceInstanceException(msg)
else:
sg = s_groups[0]
return sg
def _create_service_instance_security_group(self, context,
name=None, description=None):
"""Creates and returns security_group for service vm."""
if not name:
name = CONF.service_instance_security_group
if not description:
description = "This security group is intended to "\
"be used by share service."
LOG.debug("Creating security group with name '%s'." % name)
sg = self.compute_api.security_group_create(context, name, description)
for protocol, ports in constants.SERVICE_INSTANCE_SECGROUP_DATA:
self.compute_api.security_group_rule_create(context,
parent_group_id=sg.id,
ip_protocol=protocol,
from_port=ports[0],
to_port=ports[1],
cidr="0.0.0.0/0",
)
return sg
def _ensure_server(self, context, server, update=False):
"""Ensures that server exists and active, otherwise deletes it."""
if not server:
@ -352,6 +394,10 @@ class ServiceInstanceManager(object):
raise exception.ServiceInstanceException(_('Neither service '
'instance password nor key are available.'))
security_group = self._get_service_instance_security_group(context)
if not security_group and CONF.service_instance_security_group:
security_group = self._create_service_instance_security_group(
context)
port = self._setup_network_for_instance(context,
share_network_id,
old_server_ip)
@ -363,13 +409,11 @@ class ServiceInstanceManager(object):
raise
service_instance = self.compute_api.server_create(context,
instance_name,
service_image_id,
CONF.service_instance_flavor_id,
key_name,
None,
None,
nics=[{'port-id': port['id']}])
name=instance_name,
image=service_image_id,
flavor=CONF.service_instance_flavor_id,
key_name=key_name,
nics=[{'port-id': port['id']}])
t = time.time()
while time.time() - t < CONF.max_time_to_build_instance:
@ -389,6 +433,12 @@ class ServiceInstanceManager(object):
_('Instance have not been spawned in %ss. Giving up.') %
CONF.max_time_to_build_instance)
if security_group:
LOG.debug("Adding security group "
"'%s' to server '%s'." % (security_group.id,
service_instance["id"]))
self.compute_api.add_security_group_to_server(context,
service_instance["id"], security_group.id)
service_instance['ip'] = self._get_server_ip(service_instance)
if not self._check_server_availability(service_instance):
raise exception.ServiceInstanceException(

View File

@ -60,6 +60,14 @@ class FakeImage(object):
setattr(self, key, value)
class FakeSecurityGroup(object):
def __init__(self, **kwargs):
self.id = kwargs.pop('id', 'fake_security_group_id')
self.name = kwargs.pop('name', 'fake_security_group_name')
for key, value in kwargs.items():
setattr(self, key, value)
class API(object):
"""Fake Compute API"""
def instance_volume_attach(self, ctx, server_id, volume_id, mount_path):
@ -94,3 +102,15 @@ class API(object):
def image_list(self, *args, **kwargs):
pass
def security_group_create(self, *args, **kwargs):
pass
def security_group_list(self, *args, **kwargs):
pass
def add_security_group_to_server(self, *args, **kwargs):
pass
def security_group_rule_create(self, *args, **kwargs):
pass

View File

@ -123,6 +123,65 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self.assertRaises(exception.ManilaException,
self._manager._get_server_ip, fake_server)
def test_get_security_group_name_is_unique(self):
fake_secgroup = fake_compute.FakeSecurityGroup()
self.stubs.Set(self._manager.compute_api, 'security_group_list',
mock.Mock(return_value=[fake_secgroup, ]))
result = self._manager._get_service_instance_security_group(
self._context, fake_secgroup.name)
self.assertEqual(result, fake_secgroup)
def test_get_security_group_name_is_absent(self):
self.stubs.Set(self._manager.compute_api, 'security_group_list',
mock.Mock(return_value=[]))
result = self._manager._get_service_instance_security_group(
self._context, "fake_absent_name")
self.assertEqual(result, None)
def test_get_security_group_name_not_unique(self):
fake_secgroup1 = fake_compute.FakeSecurityGroup()
fake_secgroup2 = fake_compute.FakeSecurityGroup()
self.stubs.Set(self._manager.compute_api, 'security_group_list',
mock.Mock(return_value=[fake_secgroup1,
fake_secgroup2, ]))
self.assertRaises(exception.ServiceInstanceException,
self._manager._get_service_instance_security_group,
self._context,
fake_secgroup1.name)
def test_get_security_group_name_not_provided_at_all(self):
fake_secgroup = fake_compute.FakeSecurityGroup(
name=CONF.service_instance_security_group)
self.stubs.Set(self._manager.compute_api, 'security_group_list',
mock.Mock(return_value=[fake_secgroup, ]))
default_option = CONF.service_instance_security_group
try:
CONF.service_instance_security_group = ""
result = self._manager._get_service_instance_security_group(
context=self._context, name="")
self.assertEqual(result, None)
finally:
CONF.service_instance_security_group = default_option
def test_get_security_group_name_not_provided(self):
fake_secgroup = fake_compute.FakeSecurityGroup(
name=CONF.service_instance_security_group)
self.stubs.Set(self._manager.compute_api, 'security_group_list',
mock.Mock(return_value=[fake_secgroup, ]))
result = self._manager._get_service_instance_security_group(
context=self._context, name=None)
self.assertEqual(result, fake_secgroup)
def test_create_security_group(self):
self.stubs.Set(self._manager.compute_api, 'security_group_create',
mock.Mock(return_value=mock.Mock()))
self.stubs.Set(self._manager.compute_api, 'security_group_rule_create',
mock.Mock(return_value=mock.Mock()))
result = self._manager._create_service_instance_security_group(
context=self._context, name="fake_name",
description="fake_description")
self._manager.compute_api.security_group_create.assert_called_once()
def test_get_service_instance(self):
fake_server = fake_compute.FakeServer()
self.stubs.Set(self._manager, '_ensure_server',
@ -358,6 +417,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
def test_create_service_instance(self):
fake_server = fake_compute.FakeServer()
fake_port = fake_network.FakePort()
fake_security_group = fake_compute.FakeSecurityGroup()
fake_instance_name = 'fake_instance_name'
sn_id = 'fake_sn_id'
self.stubs.Set(self._manager, '_get_service_image',
@ -373,6 +433,8 @@ class ServiceInstanceManagerTestCase(test.TestCase):
mock.Mock(return_value=fake_server))
self.stubs.Set(self._manager, '_get_server_ip',
mock.Mock(return_value='fake_ip'))
self.stubs.Set(self._manager, '_get_service_instance_security_group',
mock.Mock(return_value=fake_security_group))
self.stubs.Set(service_instance.socket, 'socket', mock.Mock())
self.stubs.Set(self._manager, '_get_service_instance_name',
mock.Mock(return_value=fake_instance_name))
@ -385,19 +447,22 @@ class ServiceInstanceManagerTestCase(test.TestCase):
self._manager._setup_connectivity_with_service_instances.\
assert_called_once()
self._manager.compute_api.server_create.assert_called_once_with(
self._context, fake_instance_name, 'fake_image_id',
CONF.service_instance_flavor_id, 'fake_key_name', None, None,
nics=[{'port-id': fake_port['id']}])
self._context, name=fake_instance_name, image='fake_image_id',
flavor=CONF.service_instance_flavor_id,
key_name='fake_key_name', nics=[{'port-id': fake_port['id']}])
service_instance.socket.socket.assert_called_once()
self.assertEqual(result, fake_server)
def test_create_service_instance_error(self):
fake_server = fake_compute.FakeServer(status='ERROR')
fake_port = fake_network.FakePort()
fake_security_group = fake_compute.FakeSecurityGroup()
self.stubs.Set(self._manager, '_get_service_image',
mock.Mock(return_value='fake_image_id'))
self.stubs.Set(self._manager, '_get_key',
mock.Mock(return_value='fake_key_name'))
self.stubs.Set(self._manager, '_get_service_instance_security_group',
mock.Mock(return_value=fake_security_group))
self.stubs.Set(self._manager, '_setup_network_for_instance',
mock.Mock(return_value=fake_port))
self.stubs.Set(self._manager,
@ -420,10 +485,13 @@ class ServiceInstanceManagerTestCase(test.TestCase):
def test_create_service_instance_failed_setup_connectivity(self):
fake_server = fake_compute.FakeServer(status='ERROR')
fake_port = fake_network.FakePort()
fake_security_group = fake_compute.FakeSecurityGroup()
self.stubs.Set(self._manager, '_get_service_image',
mock.Mock(return_value='fake_image_id'))
self.stubs.Set(self._manager, '_get_key',
mock.Mock(return_value='fake_key_name'))
self.stubs.Set(self._manager, '_get_service_instance_security_group',
mock.Mock(return_value=fake_security_group))
self.stubs.Set(self._manager, '_setup_network_for_instance',
mock.Mock(return_value=fake_port))
self.stubs.Set(self._manager,