Remove SecurityGroup API extension
SecurityGroup API extension is not mentioned in Trove API doc. Security group information could be retrieved from Neutron. Change-Id: Ifb134eaada09ca4dc739eddb5772681b486cad93 Story: #2005366 Task: #30341
This commit is contained in:
parent
d98edf6798
commit
fe4c72807c
@ -40,7 +40,6 @@ trove.api.extensions =
|
||||
account = trove.extensions.routes.account:Account
|
||||
mgmt = trove.extensions.routes.mgmt:Mgmt
|
||||
mysql = trove.extensions.routes.mysql:Mysql
|
||||
security_group = trove.extensions.routes.security_group:Security_group
|
||||
|
||||
trove.guestagent.module.drivers =
|
||||
ping = trove.guestagent.module.drivers.ping_driver:PingDriver
|
||||
|
@ -1,60 +0,0 @@
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from trove.common import cfg
|
||||
from trove.common import extensions
|
||||
from trove.extensions.security_group import service
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
# The Extensions module from openstack common expects the classname of the
|
||||
# extension to be loaded to be the exact same as the filename, except with
|
||||
# a capital first letter. That's the reason this class has such a funky name.
|
||||
class Security_group(extensions.ExtensionDescriptor):
|
||||
|
||||
def get_name(self):
|
||||
return "SecurityGroup"
|
||||
|
||||
def get_description(self):
|
||||
return "Security Group related operations such as list \
|
||||
security groups and manage security group rules."
|
||||
|
||||
def get_alias(self):
|
||||
return "SecurityGroup"
|
||||
|
||||
def get_namespace(self):
|
||||
return "http://TBD"
|
||||
|
||||
def get_updated(self):
|
||||
return "2012-02-26T17:25:27-08:00"
|
||||
|
||||
def get_resources(self):
|
||||
resources = []
|
||||
|
||||
if CONF.trove_security_groups_support:
|
||||
security_groups = extensions.ResourceExtension(
|
||||
'{tenant_id}/security-groups',
|
||||
service.SecurityGroupController())
|
||||
resources.append(security_groups)
|
||||
|
||||
security_group_rules = extensions.ResourceExtension(
|
||||
'{tenant_id}/security-group-rules',
|
||||
service.SecurityGroupRuleController())
|
||||
resources.append(security_group_rules)
|
||||
|
||||
return resources
|
@ -1,160 +0,0 @@
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from trove.common import cfg
|
||||
from trove.common import exception
|
||||
from trove.common import wsgi
|
||||
from trove.datastore.models import DatastoreVersion
|
||||
from trove.extensions.security_group import models
|
||||
from trove.extensions.security_group import views
|
||||
from trove.instance import models as instance_models
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class SecurityGroupController(wsgi.Controller):
|
||||
"""Controller for security groups functionality."""
|
||||
|
||||
def index(self, req, tenant_id):
|
||||
"""Return all security groups tied to a particular tenant_id."""
|
||||
LOG.debug("Index() called with %s", tenant_id)
|
||||
|
||||
sec_groups = models.SecurityGroup().find_all(tenant_id=tenant_id,
|
||||
deleted=False)
|
||||
|
||||
# Construct the mapping from Security Groups to Security Group Rules
|
||||
rules_map = {g.id: g.get_rules() for g in sec_groups}
|
||||
|
||||
return wsgi.Result(
|
||||
views.SecurityGroupsView(sec_groups,
|
||||
rules_map,
|
||||
req, tenant_id).list(), 200)
|
||||
|
||||
def show(self, req, tenant_id, id):
|
||||
"""Return a single security group."""
|
||||
LOG.debug("Show() called with %(tenant_id)s, %(id)s",
|
||||
{'tenant_id': tenant_id, 'id': id})
|
||||
|
||||
sec_group = \
|
||||
models.SecurityGroup.get_security_group_by_id_or_instance_id(
|
||||
id, tenant_id)
|
||||
|
||||
return wsgi.Result(
|
||||
views.SecurityGroupView(sec_group,
|
||||
sec_group.get_rules(),
|
||||
req, tenant_id).show(), 200)
|
||||
|
||||
|
||||
class SecurityGroupRuleController(wsgi.Controller):
|
||||
"""Controller for security group rule functionality."""
|
||||
|
||||
def delete(self, req, tenant_id, id):
|
||||
LOG.debug("Delete Security Group Rule called %(tenant_id)s, %(id)s",
|
||||
{'tenant_id': tenant_id, 'id': id})
|
||||
|
||||
context = req.environ[wsgi.CONTEXT_KEY]
|
||||
sec_group_rule = models.SecurityGroupRule.find_by(id=id, deleted=False)
|
||||
sec_group = sec_group_rule.get_security_group(tenant_id)
|
||||
|
||||
if sec_group is None:
|
||||
LOG.error("Attempting to delete Group Rule that does not "
|
||||
"exist or does not belong to tenant %s", tenant_id)
|
||||
raise exception.Forbidden("Unauthorized")
|
||||
|
||||
sec_group_rule.delete(context, CONF.os_region_name)
|
||||
sec_group.save()
|
||||
return wsgi.Result(None, 204)
|
||||
|
||||
def create(self, req, body, tenant_id):
|
||||
LOG.debug("Creating a Security Group Rule for tenant '%s'", tenant_id)
|
||||
|
||||
context = req.environ[wsgi.CONTEXT_KEY]
|
||||
self._validate_create_body(body)
|
||||
|
||||
sec_group_id = body['security_group_rule']['group_id']
|
||||
sec_group = models.SecurityGroup.find_by(id=sec_group_id,
|
||||
tenant_id=tenant_id,
|
||||
deleted=False)
|
||||
instance_id = (models.SecurityGroupInstanceAssociation.
|
||||
get_instance_id_by_security_group_id(sec_group_id))
|
||||
db_info = instance_models.get_db_info(context, id=instance_id)
|
||||
manager = (DatastoreVersion.load_by_uuid(
|
||||
db_info.datastore_version_id).manager)
|
||||
tcp_ports = CONF.get(manager).tcp_ports
|
||||
udp_ports = CONF.get(manager).udp_ports
|
||||
|
||||
def _create_rules(sec_group, ports, protocol):
|
||||
rules = []
|
||||
try:
|
||||
for port_or_range in set(ports):
|
||||
from_, to_ = port_or_range[0], port_or_range[-1]
|
||||
rule = models.SecurityGroupRule.create_sec_group_rule(
|
||||
sec_group, protocol, from_, to_,
|
||||
body['security_group_rule']['cidr'], context,
|
||||
CONF.os_region_name)
|
||||
rules.append(rule)
|
||||
except (ValueError, AttributeError) as e:
|
||||
raise exception.BadRequest(message=str(e))
|
||||
return rules
|
||||
|
||||
tcp_rules = _create_rules(sec_group, tcp_ports, 'tcp')
|
||||
udp_rules = _create_rules(sec_group, udp_ports, 'udp')
|
||||
|
||||
sec_group.save()
|
||||
|
||||
all_rules = tcp_rules + udp_rules
|
||||
view = views.SecurityGroupRulesView(
|
||||
all_rules, req, tenant_id).create()
|
||||
return wsgi.Result(view, 201)
|
||||
|
||||
def _validate_create_body(self, body):
|
||||
try:
|
||||
body['security_group_rule']
|
||||
body['security_group_rule']['group_id']
|
||||
body['security_group_rule']['cidr']
|
||||
except KeyError as e:
|
||||
LOG.error("Create Security Group Rules Required field(s) "
|
||||
"- %s", e)
|
||||
raise exception.SecurityGroupRuleCreationError(
|
||||
"Required element/key - %s was not specified" % e)
|
||||
|
||||
schemas = {
|
||||
"type": "object",
|
||||
"name": "security_group_rule:create",
|
||||
"required": True,
|
||||
"properties": {
|
||||
"security_group_rule": {
|
||||
"type": "object",
|
||||
"required": True,
|
||||
"properties": {
|
||||
"cidr": {
|
||||
"type": "string",
|
||||
"required": True,
|
||||
"minLength": 9,
|
||||
"maxLength": 18
|
||||
},
|
||||
"group_id": {
|
||||
"type": "string",
|
||||
"required": True,
|
||||
"maxLength": 255
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def _base_url(req):
|
||||
return req.application_url
|
||||
|
||||
|
||||
class SecurityGroupView(object):
|
||||
|
||||
def __init__(self, secgroup, rules, req, tenant_id):
|
||||
self.secgroup = secgroup
|
||||
self.rules = rules
|
||||
self.request = req
|
||||
self.tenant_id = tenant_id
|
||||
|
||||
def _build_links(self):
|
||||
"""Build the links for the secgroup."""
|
||||
base_url = _base_url(self.request)
|
||||
href = os.path.join(base_url, self.tenant_id,
|
||||
"security-groups", str(self.secgroup['id']))
|
||||
links = [
|
||||
{
|
||||
'rel': 'self',
|
||||
'href': href
|
||||
}
|
||||
]
|
||||
return links
|
||||
|
||||
def _build_rules(self):
|
||||
rules = []
|
||||
|
||||
if self.rules is None:
|
||||
return rules
|
||||
|
||||
for rule in self.rules:
|
||||
rules.append({'id': str(rule['id']),
|
||||
'protocol': rule['protocol'],
|
||||
'from_port': rule['from_port'],
|
||||
'to_port': rule['to_port'],
|
||||
'cidr': rule['cidr'],
|
||||
})
|
||||
return rules
|
||||
|
||||
def data(self):
|
||||
return {"id": self.secgroup['id'],
|
||||
"name": self.secgroup['name'],
|
||||
"description": self.secgroup['description'],
|
||||
"instance_id": self.secgroup['instance_id'],
|
||||
"rules": self._build_rules(),
|
||||
"links": self._build_links(),
|
||||
"created": self.secgroup['created'],
|
||||
"updated": self.secgroup['updated']
|
||||
}
|
||||
|
||||
def show(self):
|
||||
return {"security_group": self.data()}
|
||||
|
||||
def create(self):
|
||||
return self.show()
|
||||
|
||||
|
||||
class SecurityGroupsView(object):
|
||||
|
||||
def __init__(self, secgroups, rules_dict, req, tenant_id):
|
||||
self.secgroups = secgroups
|
||||
self.rules = rules_dict
|
||||
self.request = req
|
||||
self.tenant_id = tenant_id
|
||||
|
||||
def list(self):
|
||||
groups_data = []
|
||||
|
||||
for secgroup in self.secgroups:
|
||||
rules = (self.rules[secgroup['id']]
|
||||
if self.rules is not None else None)
|
||||
groups_data.append(SecurityGroupView(secgroup,
|
||||
rules,
|
||||
self.request,
|
||||
self.tenant_id).data())
|
||||
|
||||
return {"security_groups": groups_data}
|
||||
|
||||
|
||||
class SecurityGroupRulesView(object):
|
||||
|
||||
def __init__(self, rules, req, tenant_id):
|
||||
self.rules = rules
|
||||
self.request = req
|
||||
self.tenant_id = tenant_id
|
||||
|
||||
def _build_create(self):
|
||||
views = []
|
||||
for rule in self.rules:
|
||||
to_append = {
|
||||
"id": rule.id,
|
||||
"security_group_id": rule.group_id,
|
||||
"protocol": rule.protocol,
|
||||
"from_port": rule.from_port,
|
||||
"to_port": rule.to_port,
|
||||
"cidr": rule.cidr,
|
||||
"created": rule.created
|
||||
}
|
||||
views.append(to_append)
|
||||
return {"security_group_rule": views}
|
||||
|
||||
def create(self):
|
||||
return self._build_create()
|
@ -34,7 +34,6 @@ from proboscis import before_class
|
||||
from proboscis.decorators import time_out
|
||||
from proboscis import SkipTest
|
||||
from proboscis import test
|
||||
import six
|
||||
from troveclient.compat import exceptions
|
||||
|
||||
from trove.common import cfg
|
||||
@ -44,11 +43,9 @@ from trove.datastore import models as datastore_models
|
||||
from trove import tests
|
||||
from trove.tests.config import CONFIG
|
||||
from trove.tests.util.check import AttrCheck
|
||||
from trove.tests.util.check import TypeCheck
|
||||
from trove.tests.util import create_dbaas_client
|
||||
from trove.tests.util import create_nova_client
|
||||
from trove.tests.util import dns_checker
|
||||
from trove.tests.util import event_simulator
|
||||
from trove.tests.util import iso_time
|
||||
from trove.tests.util import test_config
|
||||
from trove.tests.util.usage import create_usage_verifier
|
||||
@ -68,7 +65,6 @@ GROUP_USERS = "dbaas.api.users"
|
||||
GROUP_ROOT = "dbaas.api.root"
|
||||
GROUP_GUEST = "dbaas.guest.start.test"
|
||||
GROUP_DATABASES = "dbaas.api.databases"
|
||||
GROUP_SECURITY_GROUPS = "dbaas.api.security_groups"
|
||||
GROUP_CREATE_INSTANCE_FAILURE = "dbaas.api.failures"
|
||||
GROUP_QUOTAS = "dbaas.quotas"
|
||||
|
||||
@ -967,126 +963,6 @@ class WaitForGuestInstallationToFinish(object):
|
||||
"the instance at the end of the tests.")
|
||||
|
||||
|
||||
@test(depends_on_classes=[WaitForGuestInstallationToFinish],
|
||||
groups=[GROUP, GROUP_SECURITY_GROUPS])
|
||||
class SecurityGroupsTest(object):
|
||||
|
||||
@before_class
|
||||
def setUp(self):
|
||||
self.testSecurityGroup = dbaas.security_groups.get(
|
||||
instance_info.id)
|
||||
self.secGroupName = (
|
||||
"%s_%s" % (CONF.trove_security_group_name_prefix, instance_info.id)
|
||||
)
|
||||
self.secGroupDescription = "Security Group for %s" % instance_info.id
|
||||
|
||||
@test
|
||||
def test_created_security_group(self):
|
||||
assert_is_not_none(self.testSecurityGroup)
|
||||
with TypeCheck('SecurityGroup', self.testSecurityGroup) as secGrp:
|
||||
secGrp.has_field('id', six.string_types)
|
||||
secGrp.has_field('name', six.string_types)
|
||||
secGrp.has_field('description', six.string_types)
|
||||
secGrp.has_field('created', six.string_types)
|
||||
secGrp.has_field('updated', six.string_types)
|
||||
assert_equal(self.testSecurityGroup.name, self.secGroupName)
|
||||
assert_equal(self.testSecurityGroup.description,
|
||||
self.secGroupDescription)
|
||||
assert_equal(self.testSecurityGroup.created,
|
||||
self.testSecurityGroup.updated)
|
||||
|
||||
@test
|
||||
def test_list_security_group(self):
|
||||
securityGroupList = dbaas.security_groups.list()
|
||||
assert_is_not_none(securityGroupList)
|
||||
securityGroup = [x for x in securityGroupList
|
||||
if x.name in self.secGroupName]
|
||||
assert_is_not_none(securityGroup)
|
||||
|
||||
@test
|
||||
def test_get_security_group(self):
|
||||
securityGroup = dbaas.security_groups.get(self.testSecurityGroup.id)
|
||||
assert_is_not_none(securityGroup)
|
||||
assert_equal(securityGroup.name, self.secGroupName)
|
||||
assert_equal(securityGroup.description, self.secGroupDescription)
|
||||
assert_equal(securityGroup.instance_id, instance_info.id)
|
||||
|
||||
|
||||
@test(depends_on_classes=[SecurityGroupsTest],
|
||||
groups=[GROUP, GROUP_SECURITY_GROUPS])
|
||||
class SecurityGroupsRulesTest(object):
|
||||
|
||||
# Security group already have default rule
|
||||
# that is why 'delete'-test is not needed anymore
|
||||
|
||||
@before_class
|
||||
def setUp(self):
|
||||
self.testSecurityGroup = dbaas.security_groups.get(
|
||||
instance_info.id)
|
||||
self.secGroupName = (
|
||||
"%s_%s" % (CONF.trove_security_group_name_prefix, instance_info.id)
|
||||
)
|
||||
self.secGroupDescription = "Security Group for %s" % instance_info.id
|
||||
self.orig_allowable_empty_sleeps = (event_simulator.
|
||||
allowable_empty_sleeps)
|
||||
event_simulator.allowable_empty_sleeps = 2
|
||||
self.test_rule_id = None
|
||||
|
||||
@after_class
|
||||
def tearDown(self):
|
||||
(event_simulator.
|
||||
allowable_empty_sleeps) = self.orig_allowable_empty_sleeps
|
||||
|
||||
@test
|
||||
def test_create_security_group_rule(self):
|
||||
# Need to sleep to verify created/updated timestamps
|
||||
time.sleep(1)
|
||||
cidr = "1.2.3.4/16"
|
||||
self.testSecurityGroupRules = (
|
||||
dbaas.security_group_rules.create(
|
||||
group_id=self.testSecurityGroup.id,
|
||||
cidr=cidr))
|
||||
assert_not_equal(len(self.testSecurityGroupRules), 0)
|
||||
assert_is_not_none(self.testSecurityGroupRules)
|
||||
for rule in self.testSecurityGroupRules:
|
||||
assert_is_not_none(rule)
|
||||
assert_equal(rule['security_group_id'],
|
||||
self.testSecurityGroup.id)
|
||||
assert_is_not_none(rule['id'])
|
||||
assert_equal(rule['cidr'], cidr)
|
||||
assert_equal(rule['from_port'], 3306)
|
||||
assert_equal(rule['to_port'], 3306)
|
||||
assert_is_not_none(rule['created'])
|
||||
self.test_rule_id = rule['id']
|
||||
|
||||
if not CONFIG.fake_mode:
|
||||
group = dbaas.security_groups.get(
|
||||
self.testSecurityGroup.id)
|
||||
assert_not_equal(self.testSecurityGroup.created,
|
||||
group.updated)
|
||||
assert_not_equal(self.testSecurityGroup.updated,
|
||||
group.updated)
|
||||
|
||||
@test(depends_on=[test_create_security_group_rule])
|
||||
def test_delete_security_group_rule(self):
|
||||
# Need to sleep to verify created/updated timestamps
|
||||
time.sleep(1)
|
||||
group_before = dbaas.security_groups.get(
|
||||
self.testSecurityGroup.id)
|
||||
dbaas.security_group_rules.delete(self.test_rule_id)
|
||||
assert_equal(204, dbaas.last_http_code)
|
||||
|
||||
if not CONFIG.fake_mode:
|
||||
group = dbaas.security_groups.get(
|
||||
self.testSecurityGroup.id)
|
||||
assert_not_equal(group_before.created,
|
||||
group.updated)
|
||||
assert_not_equal(group_before.updated,
|
||||
group.updated)
|
||||
assert_not_equal(self.testSecurityGroup,
|
||||
group.updated)
|
||||
|
||||
|
||||
@test(depends_on_classes=[WaitForGuestInstallationToFinish],
|
||||
groups=[GROUP, GROUP_START], enabled=create_new_instance())
|
||||
class TestGuestProcess(object):
|
||||
|
@ -94,7 +94,6 @@ black_box_groups = [
|
||||
GROUP_SERVICES_INITIALIZE,
|
||||
instances.GROUP_START,
|
||||
instances.GROUP_QUOTAS,
|
||||
instances.GROUP_SECURITY_GROUPS,
|
||||
backups.GROUP,
|
||||
replication.GROUP,
|
||||
configurations.GROUP,
|
||||
|
@ -23,21 +23,18 @@ from trove.common import extensions
|
||||
from trove.extensions.routes.account import Account
|
||||
from trove.extensions.routes.mgmt import Mgmt
|
||||
from trove.extensions.routes.mysql import Mysql
|
||||
from trove.extensions.routes.security_group import Security_group
|
||||
from trove.tests.unittests import trove_testtools
|
||||
|
||||
DEFAULT_EXTENSION_MAP = {
|
||||
'Account': [Account, extensions.ExtensionDescriptor],
|
||||
'Mgmt': [Mgmt, extensions.ExtensionDescriptor],
|
||||
'MYSQL': [Mysql, extensions.ExtensionDescriptor],
|
||||
'SecurityGroup': [Security_group, extensions.ExtensionDescriptor]
|
||||
'MYSQL': [Mysql, extensions.ExtensionDescriptor]
|
||||
}
|
||||
|
||||
EP_TEXT = '''
|
||||
account = trove.extensions.routes.account:Account
|
||||
mgmt = trove.extensions.routes.mgmt:Mgmt
|
||||
mysql = trove.extensions.routes.mysql:Mysql
|
||||
security_group = trove.extensions.routes.security_group:Security_group
|
||||
invalid = trove.tests.unittests.api.common.test_extensions:InvalidExtension
|
||||
'''
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user