trove/trove/extensions/security_group/models.py

255 lines
9.4 KiB
Python

# 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.
#
"""
Model classes for Security Groups and Security Group Rules on instances.
"""
from oslo_log import log as logging
from trove.common import cfg
from trove.common import exception
from trove.common.i18n import _
from trove.common.models import NetworkRemoteModelBase
from trove.db.models import DatabaseModelBase
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
def persisted_models():
return {
'security_group': SecurityGroup,
'security_group_rule': SecurityGroupRule,
'security_group_instance_association':
SecurityGroupInstanceAssociation,
}
class SecurityGroup(DatabaseModelBase):
_data_fields = ['id', 'name', 'description', 'user', 'tenant_id',
'created', 'updated', 'deleted', 'deleted_at']
@property
def instance_id(self):
return SecurityGroupInstanceAssociation\
.get_instance_id_by_security_group_id(self.id)
@classmethod
def create_sec_group(cls, name, description, context, region_name):
try:
remote_sec_group = RemoteSecurityGroup.create(
name, description, context, region_name)
if not remote_sec_group:
raise exception.SecurityGroupCreationError(
_("Failed to create Security Group."))
else:
return cls.create(
id=remote_sec_group.data()['id'],
name=name,
description=description,
user=context.user,
tenant_id=context.tenant)
except exception.SecurityGroupCreationError:
LOG.exception("Failed to create remote security group.")
raise
@classmethod
def create_for_instance(cls, instance_id, context, region_name):
# Create a new security group
name = "%s_%s" % (CONF.trove_security_group_name_prefix, instance_id)
description = _("Security Group for %s") % instance_id
sec_group = cls.create_sec_group(name, description, context,
region_name)
# Currently this locked down by default, since we don't create any
# default security group rules for the security group.
# Create security group instance association
SecurityGroupInstanceAssociation.create(
security_group_id=sec_group["id"],
instance_id=instance_id)
return sec_group
@classmethod
def get_security_group_by_id_or_instance_id(self, id, tenant_id):
try:
return SecurityGroup.find_by(id=id,
tenant_id=tenant_id,
deleted=False)
except exception.ModelNotFoundError:
return SecurityGroupInstanceAssociation.\
get_security_group_by_instance_id(id)
def get_rules(self):
return SecurityGroupRule.find_all(group_id=self.id,
deleted=False)
def delete(self, context, region_name):
try:
sec_group_rules = self.get_rules()
if sec_group_rules:
for rule in sec_group_rules:
rule.delete(context, region_name)
RemoteSecurityGroup.delete(self.id, context, region_name)
super(SecurityGroup, self).delete()
except exception.TroveError:
LOG.exception('Failed to delete security group.')
raise exception.TroveError("Failed to delete Security Group")
@classmethod
def delete_for_instance(cls, instance_id, context, region_name):
try:
association = SecurityGroupInstanceAssociation.find_by(
instance_id=instance_id,
deleted=False)
if association:
sec_group = association.get_security_group()
if sec_group:
sec_group.delete(context, region_name)
association.delete()
except (exception.ModelNotFoundError,
exception.TroveError):
LOG.info('Security Group with id: %(id)s '
'already had been deleted',
{'id': instance_id})
class SecurityGroupRule(DatabaseModelBase):
_data_fields = ['id', 'parent_group_id', 'protocol', 'from_port',
'to_port', 'cidr', 'group_id', 'created', 'updated',
'deleted', 'deleted_at']
@classmethod
def create_sec_group_rule(cls, sec_group, protocol, from_port,
to_port, cidr, context, region_name):
try:
remote_rule_id = RemoteSecurityGroup.add_rule(
sec_group_id=sec_group['id'],
protocol=protocol,
from_port=from_port,
to_port=to_port,
cidr=cidr,
context=context,
region_name=region_name)
if not remote_rule_id:
raise exception.SecurityGroupRuleCreationError(
"Failed to create Remote Security Group Rule")
else:
# Create db record
return cls.create(
id=remote_rule_id,
protocol=protocol,
from_port=from_port,
to_port=to_port,
cidr=cidr,
group_id=sec_group['id'])
except exception.SecurityGroupRuleCreationError:
LOG.exception("Failed to create remote security group rule.")
raise
def get_security_group(self, tenant_id):
return SecurityGroup.find_by(id=self.group_id,
tenant_id=tenant_id,
deleted=False)
def delete(self, context, region_name):
try:
# Delete Remote Security Group Rule
RemoteSecurityGroup.delete_rule(self.id, context, region_name)
super(SecurityGroupRule, self).delete()
except exception.TroveError:
LOG.exception('Failed to delete remote security group rule.')
raise exception.SecurityGroupRuleDeletionError(
"Failed to delete Remote Security Group Rule")
class SecurityGroupInstanceAssociation(DatabaseModelBase):
_data_fields = ['id', 'security_group_id', 'instance_id',
'created', 'updated', 'deleted', 'deleted_at']
def get_security_group(self):
return SecurityGroup.find_by(id=self.security_group_id,
deleted=False)
@classmethod
def get_security_group_by_instance_id(cls, id):
association = SecurityGroupInstanceAssociation.find_by(
instance_id=id,
deleted=False)
return association.get_security_group()
@classmethod
def get_instance_id_by_security_group_id(cls, secgroup_id):
association = SecurityGroupInstanceAssociation.find_by(
security_group_id=secgroup_id,
deleted=False)
return association.instance_id
class RemoteSecurityGroup(NetworkRemoteModelBase):
_data_fields = ['id', 'name', 'description', 'rules']
def __init__(self, security_group=None, id=None, context=None,
region_name=None):
if id is None and security_group is None:
msg = _("Security Group does not have id defined!")
raise exception.InvalidModelError(msg)
elif security_group is None:
driver = self.get_driver(context,
region_name or CONF.os_region_name)
self._data_object = driver.get_sec_group_by_id(group_id=id)
else:
self._data_object = security_group
@classmethod
def create(cls, name, description, context, region_name):
"""Creates a new Security Group."""
driver = cls.get_driver(context, region_name)
sec_group = driver.create_security_group(
name=name, description=description)
return RemoteSecurityGroup(security_group=sec_group)
@classmethod
def delete(cls, sec_group_id, context, region_name):
"""Deletes a Security Group."""
driver = cls.get_driver(context, region_name)
driver.delete_security_group(sec_group_id)
@classmethod
def add_rule(cls, sec_group_id, protocol, from_port,
to_port, cidr, context, region_name):
"""Adds a new rule to an existing security group."""
driver = cls.get_driver(context, region_name)
sec_group_rule = driver.add_security_group_rule(
sec_group_id, protocol, from_port, to_port, cidr)
return sec_group_rule.id
@classmethod
def delete_rule(cls, sec_group_rule_id, context, region_name):
"""Deletes a rule from an existing security group."""
driver = cls.get_driver(context, region_name)
driver.delete_security_group_rule(sec_group_rule_id)