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:
Lingxian Kong 2019-04-05 09:41:55 +13:00
parent d98edf6798
commit fe4c72807c
7 changed files with 1 additions and 473 deletions

View File

@ -40,7 +40,6 @@ trove.api.extensions =
account = trove.extensions.routes.account:Account account = trove.extensions.routes.account:Account
mgmt = trove.extensions.routes.mgmt:Mgmt mgmt = trove.extensions.routes.mgmt:Mgmt
mysql = trove.extensions.routes.mysql:Mysql mysql = trove.extensions.routes.mysql:Mysql
security_group = trove.extensions.routes.security_group:Security_group
trove.guestagent.module.drivers = trove.guestagent.module.drivers =
ping = trove.guestagent.module.drivers.ping_driver:PingDriver ping = trove.guestagent.module.drivers.ping_driver:PingDriver

View File

@ -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

View File

@ -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
},
}
}
}
}

View File

@ -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()

View File

@ -34,7 +34,6 @@ from proboscis import before_class
from proboscis.decorators import time_out from proboscis.decorators import time_out
from proboscis import SkipTest from proboscis import SkipTest
from proboscis import test from proboscis import test
import six
from troveclient.compat import exceptions from troveclient.compat import exceptions
from trove.common import cfg from trove.common import cfg
@ -44,11 +43,9 @@ from trove.datastore import models as datastore_models
from trove import tests from trove import tests
from trove.tests.config import CONFIG from trove.tests.config import CONFIG
from trove.tests.util.check import AttrCheck 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_dbaas_client
from trove.tests.util import create_nova_client from trove.tests.util import create_nova_client
from trove.tests.util import dns_checker 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 iso_time
from trove.tests.util import test_config from trove.tests.util import test_config
from trove.tests.util.usage import create_usage_verifier from trove.tests.util.usage import create_usage_verifier
@ -68,7 +65,6 @@ GROUP_USERS = "dbaas.api.users"
GROUP_ROOT = "dbaas.api.root" GROUP_ROOT = "dbaas.api.root"
GROUP_GUEST = "dbaas.guest.start.test" GROUP_GUEST = "dbaas.guest.start.test"
GROUP_DATABASES = "dbaas.api.databases" GROUP_DATABASES = "dbaas.api.databases"
GROUP_SECURITY_GROUPS = "dbaas.api.security_groups"
GROUP_CREATE_INSTANCE_FAILURE = "dbaas.api.failures" GROUP_CREATE_INSTANCE_FAILURE = "dbaas.api.failures"
GROUP_QUOTAS = "dbaas.quotas" GROUP_QUOTAS = "dbaas.quotas"
@ -967,126 +963,6 @@ class WaitForGuestInstallationToFinish(object):
"the instance at the end of the tests.") "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], @test(depends_on_classes=[WaitForGuestInstallationToFinish],
groups=[GROUP, GROUP_START], enabled=create_new_instance()) groups=[GROUP, GROUP_START], enabled=create_new_instance())
class TestGuestProcess(object): class TestGuestProcess(object):

View File

@ -94,7 +94,6 @@ black_box_groups = [
GROUP_SERVICES_INITIALIZE, GROUP_SERVICES_INITIALIZE,
instances.GROUP_START, instances.GROUP_START,
instances.GROUP_QUOTAS, instances.GROUP_QUOTAS,
instances.GROUP_SECURITY_GROUPS,
backups.GROUP, backups.GROUP,
replication.GROUP, replication.GROUP,
configurations.GROUP, configurations.GROUP,

View File

@ -23,21 +23,18 @@ from trove.common import extensions
from trove.extensions.routes.account import Account from trove.extensions.routes.account import Account
from trove.extensions.routes.mgmt import Mgmt from trove.extensions.routes.mgmt import Mgmt
from trove.extensions.routes.mysql import Mysql from trove.extensions.routes.mysql import Mysql
from trove.extensions.routes.security_group import Security_group
from trove.tests.unittests import trove_testtools from trove.tests.unittests import trove_testtools
DEFAULT_EXTENSION_MAP = { DEFAULT_EXTENSION_MAP = {
'Account': [Account, extensions.ExtensionDescriptor], 'Account': [Account, extensions.ExtensionDescriptor],
'Mgmt': [Mgmt, extensions.ExtensionDescriptor], 'Mgmt': [Mgmt, extensions.ExtensionDescriptor],
'MYSQL': [Mysql, extensions.ExtensionDescriptor], 'MYSQL': [Mysql, extensions.ExtensionDescriptor]
'SecurityGroup': [Security_group, extensions.ExtensionDescriptor]
} }
EP_TEXT = ''' EP_TEXT = '''
account = trove.extensions.routes.account:Account account = trove.extensions.routes.account:Account
mgmt = trove.extensions.routes.mgmt:Mgmt mgmt = trove.extensions.routes.mgmt:Mgmt
mysql = trove.extensions.routes.mysql:Mysql mysql = trove.extensions.routes.mysql:Mysql
security_group = trove.extensions.routes.security_group:Security_group
invalid = trove.tests.unittests.api.common.test_extensions:InvalidExtension invalid = trove.tests.unittests.api.common.test_extensions:InvalidExtension
''' '''