diff options
| author | Dave Lapsley <dlapsley@nicira.com> | 2012-02-15 18:04:23 -0500 |
|---|---|---|
| committer | Dave Lapsley <dlapsley@nicira.com> | 2012-02-16 20:21:32 -0500 |
| commit | 269c0fca4d2dd78fecdd142047c5198b41c4e7d7 (patch) | |
| tree | e10be3457d207e5100134c3efd8db021e702dd70 | |
| parent | 31d1a423761ac2d68d227559f4e3f424487333be (diff) | |
| download | nova-269c0fca4d2dd78fecdd142047c5198b41c4e7d7.tar.gz nova-269c0fca4d2dd78fecdd142047c5198b41c4e7d7.tar.xz nova-269c0fca4d2dd78fecdd142047c5198b41c4e7d7.zip | |
Fix bug 933147 Security group trigger notifications.
Add a lightweight mechanism to allow security group trigger
notifications to be propagated to quantum security group handlers.
Add a global flag: "security_group_handler" to allow for runtime
selection of security group handler class.
Change-Id: I8a3768c26c97020071ad4e52d3a22d8898e72e9f
| -rw-r--r-- | nova/api/ec2/cloud.py | 14 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/security_groups.py | 14 | ||||
| -rw-r--r-- | nova/flags.py | 3 | ||||
| -rw-r--r-- | nova/network/manager.py | 5 | ||||
| -rw-r--r-- | nova/network/quantum/sg.py | 159 |
5 files changed, 193 insertions, 2 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 560a2d0dd..1a574ec6f 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -202,6 +202,7 @@ class CloudController(object): self.volume_api = volume.API() self.compute_api = compute.API(network_api=self.network_api, volume_api=self.volume_api) + self.sgh = utils.import_object(FLAGS.security_group_handler) def __str__(self): return 'CloudController' @@ -622,6 +623,7 @@ class CloudController(object): except KeyError: prevalues.append(kwargs) rule_id = None + rule_ids = [] for values in prevalues: rulesvalues = self._rule_args_to_dict(context, values) if not rulesvalues: @@ -634,11 +636,14 @@ class CloudController(object): values_for_rule) if rule_id: db.security_group_rule_destroy(context, rule_id) + rule_ids.append(rule_id) if rule_id: # NOTE(vish): we removed a rule, so refresh self.compute_api.trigger_security_group_rules_refresh( context, security_group_id=security_group['id']) + self.sgh.trigger_security_group_rule_destroy_refresh( + context, rule_ids) return True raise exception.EC2APIError(_("No rule for the specified parameters.")) @@ -685,15 +690,19 @@ class CloudController(object): raise exception.EC2APIError(_(err) % values_for_rule) postvalues.append(values_for_rule) + rule_ids = [] for values_for_rule in postvalues: security_group_rule = db.security_group_rule_create( context, values_for_rule) + rule_ids.append(security_group_rule['id']) if postvalues: self.compute_api.trigger_security_group_rules_refresh( context, security_group_id=security_group['id']) + self.sgh.trigger_security_group_rule_create_refresh( + context, rule_ids) return True raise exception.EC2APIError(_("No rule for the specified parameters.")) @@ -744,6 +753,8 @@ class CloudController(object): 'description': group_description} group_ref = db.security_group_create(context, group) + self.sgh.trigger_security_group_create_refresh(context, group) + return {'securityGroupSet': [self._format_security_group(context, group_ref)]} @@ -765,6 +776,9 @@ class CloudController(object): raise notfound(security_group_id=group_id) LOG.audit(_("Delete security group %s"), group_name, context=context) db.security_group_destroy(context, security_group.id) + + self.sgh.trigger_security_group_destroy_refresh(context, + security_group.id) return True def get_console_output(self, context, instance_id, **kwargs): diff --git a/nova/api/openstack/compute/contrib/security_groups.py b/nova/api/openstack/compute/contrib/security_groups.py index e1e5a47fe..d7e851468 100644 --- a/nova/api/openstack/compute/contrib/security_groups.py +++ b/nova/api/openstack/compute/contrib/security_groups.py @@ -179,6 +179,7 @@ class SecurityGroupController(object): def __init__(self): self.compute_api = compute.API() super(SecurityGroupController, self).__init__() + self.sgh = utils.import_object(FLAGS.security_group_handler) def _format_security_group_rule(self, context, rule): sg_rule = {} @@ -236,6 +237,8 @@ class SecurityGroupController(object): security_group = self._get_security_group(context, id) LOG.audit(_("Delete security group %s"), id, context=context) db.security_group_destroy(context, security_group.id) + self.sgh.trigger_security_group_destroy_refresh( + context, security_group.id) return webob.Response(status_int=202) @@ -290,6 +293,7 @@ class SecurityGroupController(object): 'name': group_name, 'description': group_description} group_ref = db.security_group_create(context, group) + self.sgh.trigger_security_group_create_refresh(context, group) return {'security_group': self._format_security_group(context, group_ref)} @@ -366,7 +370,8 @@ class SecurityGroupRulesController(SecurityGroupController): raise exc.HTTPBadRequest(explanation=msg) security_group_rule = db.security_group_rule_create(context, values) - + self.sgh.trigger_security_group_rule_create_refresh( + context, [security_group_rule['id']]) self.compute_api.trigger_security_group_rules_refresh(context, security_group_id=security_group['id']) @@ -495,6 +500,8 @@ class SecurityGroupRulesController(SecurityGroupController): LOG.audit(msg, security_group['name'], context=context) db.security_group_rule_destroy(context, rule['id']) + self.sgh.trigger_security_group_rule_destroy_refresh( + context, [rule['id']]) self.compute_api.trigger_security_group_rules_refresh(context, security_group_id=security_group['id']) @@ -505,6 +512,7 @@ class SecurityGroupActionController(wsgi.Controller): def __init__(self, *args, **kwargs): super(SecurityGroupActionController, self).__init__(*args, **kwargs) self.compute_api = compute.API() + self.sgh = utils.import_object(FLAGS.security_group_handler) @wsgi.action('addSecurityGroup') def _addSecurityGroup(self, req, id, body): @@ -528,6 +536,8 @@ class SecurityGroupActionController(wsgi.Controller): try: instance = self.compute_api.get(context, id) self.compute_api.add_security_group(context, instance, group_name) + self.sgh.trigger_instance_add_security_group_refresh( + context, instance, group_name) except exception.SecurityGroupNotFound as exp: raise exc.HTTPNotFound(explanation=unicode(exp)) except exception.InstanceNotFound as exp: @@ -560,6 +570,8 @@ class SecurityGroupActionController(wsgi.Controller): instance = self.compute_api.get(context, id) self.compute_api.remove_security_group(context, instance, group_name) + self.sgh.trigger_instance_remove_security_group_refresh( + context, instance, group_name) except exception.SecurityGroupNotFound as exp: raise exc.HTTPNotFound(explanation=unicode(exp)) except exception.InstanceNotFound as exp: diff --git a/nova/flags.py b/nova/flags.py index af490e287..4277d1eda 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -451,6 +451,9 @@ global_opts = [ cfg.StrOpt('volume_api_class', default='nova.volume.api.API', help='The volume API class to use'), + cfg.StrOpt('security_group_handler', + default='nova.network.quantum.sg.NullSecurityGroupHandler', + help='security group handler class') ] FLAGS.register_opts(global_opts) diff --git a/nova/network/manager.py b/nova/network/manager.py index fe6cfa07a..5ad14f839 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -685,6 +685,7 @@ class NetworkManager(manager.SchedulerDependentManager): self.floating_dns_manager = temp self.network_api = network_api.API() self.compute_api = compute_api.API() + self.sgh = utils.import_object(FLAGS.security_group_handler) # NOTE(tr3buchet: unless manager subclassing NetworkManager has # already imported ipam, import nova ipam here @@ -761,7 +762,9 @@ class NetworkManager(manager.SchedulerDependentManager): groups = instance_ref['security_groups'] group_ids = [group['id'] for group in groups] self.compute_api.trigger_security_group_members_refresh(admin_context, - group_ids) + group_ids) + self.sgh.trigger_security_group_members_refresh(admin_context, + group_ids) def get_floating_ips_by_fixed_address(self, context, fixed_address): # NOTE(jkoelker) This is just a stub function. Managers supporting diff --git a/nova/network/quantum/sg.py b/nova/network/quantum/sg.py new file mode 100644 index 000000000..93ba6be11 --- /dev/null +++ b/nova/network/quantum/sg.py @@ -0,0 +1,159 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 Nicira Networks, Inc +# 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. + +'''Implement Security Groups abstraction and API. + +The nova security_group_handler flag specifies which class is to be used +to implement the security group calls. + +The NullSecurityGroupHandler provides a "no-op" plugin that is loaded +by default and has no impact on current system behavior. In the future, +special purposes classes that inherit from SecurityGroupHandlerBase +will provide enhanced functionality and will be loadable via the +security_group_handler flag. +''' + +from nova import log as logging + + +LOG = logging.getLogger('nova.network.api.quantum.sg') + + +class SecurityGroupHandlerBase(object): + + def __init__(self): + raise NotImplementedError() + + def trigger_security_group_create_refresh(self, context, group): + '''Called when a rule is added to a security_group. + + :param context: the security context. + :param group: the new group added. group is a dictionary that contains + the following: user_id, project_id, name, description).''' + raise NotImplementedError() + + def trigger_security_group_destroy_refresh(self, context, + security_group_id): + '''Called when a rule is added to a security_group. + + :param context: the security context. + :param security_group_id: the security group identifier.''' + raise NotImplementedError() + + def trigger_security_group_rule_create_refresh(self, context, + rule_ids): + '''Called when a rule is added to a security_group. + + :param context: the security context. + :param rule_ids: a list of rule ids that have been affected.''' + raise NotImplementedError() + + def trigger_security_group_rule_destroy_refresh(self, context, + rule_ids): + '''Called when a rule is removed from a security_group. + + :param context: the security context. + :param rule_ids: a list of rule ids that have been affected.''' + raise NotImplementedError() + + def trigger_instance_add_security_group_refresh(self, context, instance, + group_name): + '''Called when a security group gains a new member. + + :param context: the security context. + :param instance: the instance to be associated. + :param group_name: the name of the security group to be associated.''' + raise NotImplementedError() + + def trigger_instance_remove_security_group_refresh(self, context, instance, + group_name): + '''Called when a security group loses a member. + + :param context: the security context. + :param instance: the instance to be associated. + :param group_name: the name of the security group to be associated.''' + raise NotImplementedError() + + def trigger_security_group_members_refresh(self, context, group_ids): + '''Called when a security group gains or loses a member. + + :param context: the security context. + :param group_ids: a list of security group identifiers.''' + raise NotImplementedError() + + +class NullSecurityGroupHandler(SecurityGroupHandlerBase): + + def __init__(self): + pass + + def trigger_security_group_create_refresh(self, context, group): + '''Called when a rule is added to a security_group. + + :param context: the security context. + :param group: the new group added. group is a dictionary that contains + the following: user_id, project_id, name, description).''' + pass + + def trigger_security_group_destroy_refresh(self, context, + security_group_id): + '''Called when a rule is added to a security_group. + + :param context: the security context. + :param security_group_id: the security group identifier.''' + pass + + def trigger_security_group_rule_create_refresh(self, context, + rule_ids): + '''Called when a rule is added to a security_group. + + :param context: the security context. + :param rule_ids: a list of rule ids that have been affected.''' + pass + + def trigger_security_group_rule_destroy_refresh(self, context, + rule_ids): + '''Called when a rule is removed from a security_group. + + :param context: the security context. + :param rule_ids: a list of rule ids that have been affected.''' + pass + + def trigger_instance_add_security_group_refresh(self, context, instance, + group_name): + '''Called when a security group gains a new member. + + :param context: the security context. + :param instance: the instance to be associated. + :param group_name: the name of the security group to be associated.''' + pass + + def trigger_instance_remove_security_group_refresh(self, context, instance, + group_name): + '''Called when a security group loses a member. + + :param context: the security context. + :param instance: the instance to be associated. + :param group_name: the name of the security group to be associated.''' + pass + + def trigger_security_group_members_refresh(self, context, group_ids): + '''Called when a security group gains or loses a member. + + :param context: the security context. + :param group_ids: a list of security group identifiers.''' + pass |
