Merge "Remove SecurityGroup API extension"

This commit is contained in:
Zuul 2019-04-09 23:36:02 +00:00 committed by Gerrit Code Review
commit ddb839b4e4
7 changed files with 1 additions and 473 deletions

View File

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

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 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):

View File

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

View File

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