1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 from neutronclient.common.exceptions import NotFound, Conflict
20 from snaps.config.security_group import (
21 SecurityGroupConfig, SecurityGroupRuleConfig)
22 from snaps.openstack.openstack_creator import OpenStackNetworkObject
23 from snaps.openstack.utils import neutron_utils
25 __author__ = 'spisarski'
27 logger = logging.getLogger('OpenStackSecurityGroup')
30 class OpenStackSecurityGroup(OpenStackNetworkObject):
32 Class responsible for managing a Security Group in OpenStack
35 def __init__(self, os_creds, sec_grp_settings):
37 Constructor - all parameters are required
38 :param os_creds: The credentials to connect with OpenStack
39 :param sec_grp_settings: The settings used to create a security group
41 super(self.__class__, self).__init__(os_creds)
43 self.sec_grp_settings = sec_grp_settings
45 # Attributes instantiated on create()
46 self.__security_group = None
48 # dict where the rule settings object is the key
53 Loads existing security group.
54 :return: the security group domain object
56 super(self.__class__, self).initialize()
58 self.__security_group = neutron_utils.get_security_group(
59 self._neutron, self._keystone,
60 sec_grp_settings=self.sec_grp_settings,
61 project_name=self._os_creds.project_name)
62 if self.__security_group:
64 existing_rules = neutron_utils.get_rules_by_security_group(
65 self._neutron, self.__security_group)
67 for existing_rule in existing_rules:
69 rule_setting = self.__get_setting_from_rule(existing_rule)
70 self.__rules[rule_setting] = existing_rule
72 self.__security_group = neutron_utils.get_security_group_by_id(
73 self._neutron, self.__security_group.id)
75 return self.__security_group
79 Responsible for creating the security group.
80 :return: the security group domain object
84 if not self.__security_group:
86 'Creating security group %s...' % self.sec_grp_settings.name)
88 self.__security_group = neutron_utils.create_security_group(
89 self._neutron, self._keystone, self.sec_grp_settings)
91 # Get the rules added for free
92 auto_rules = neutron_utils.get_rules_by_security_group(
93 self._neutron, self.__security_group)
96 for auto_rule in auto_rules:
97 auto_rule_setting = self.__generate_rule_setting(auto_rule)
98 self.__rules[auto_rule_setting] = auto_rule
101 # Create the custom rules
102 for sec_grp_rule_setting in self.sec_grp_settings.rule_settings:
104 custom_rule = neutron_utils.create_security_group_rule(
105 self._neutron, self._keystone, sec_grp_rule_setting,
106 self._os_creds.project_name)
107 self.__rules[sec_grp_rule_setting] = custom_rule
108 except Conflict as e:
109 logger.warn('Unable to create rule due to conflict - %s',
112 # Refresh security group object to reflect the new rules added
113 self.__security_group = neutron_utils.get_security_group_by_id(
114 self._neutron, self.__security_group.id)
116 return self.__security_group
118 def __generate_rule_setting(self, rule):
120 Creates a SecurityGroupRuleConfig object for a given rule
121 :param rule: the rule from which to create the
122 SecurityGroupRuleConfig object
123 :return: the newly instantiated SecurityGroupRuleConfig object
125 sec_grp = neutron_utils.get_security_group_by_id(
126 self._neutron, rule.security_group_id)
128 setting = SecurityGroupRuleConfig(
129 description=rule.description,
130 direction=rule.direction,
131 ethertype=rule.ethertype,
132 port_range_min=rule.port_range_min,
133 port_range_max=rule.port_range_max,
134 protocol=rule.protocol,
135 remote_group_id=rule.remote_group_id,
136 remote_ip_prefix=rule.remote_ip_prefix,
137 sec_grp_name=sec_grp.name)
142 Removes and deletes the rules then the security group.
144 for setting, rule in self.__rules.items():
146 neutron_utils.delete_security_group_rule(self._neutron, rule)
147 except NotFound as e:
148 logger.warning('Rule not found, cannot delete - ' + str(e))
150 self.__rules = dict()
152 if self.__security_group:
154 neutron_utils.delete_security_group(self._neutron,
155 self.__security_group)
156 except NotFound as e:
158 'Security Group not found, cannot delete - ' + str(e))
160 self.__security_group = None
162 super(self.__class__, self).clean()
164 def get_security_group(self):
166 Returns the OpenStack security group object
169 return self.__security_group
173 Returns the associated rules
178 def add_rule(self, rule_setting):
180 Adds a rule to this security group
181 :param rule_setting: the rule configuration
183 rule_setting.sec_grp_name = self.sec_grp_settings.name
184 new_rule = neutron_utils.create_security_group_rule(
185 self._neutron, self._keystone, rule_setting,
186 self._os_creds.project_name)
187 self.__rules[rule_setting] = new_rule
188 self.sec_grp_settings.rule_settings.append(rule_setting)
190 def remove_rule(self, rule_id=None, rule_setting=None):
192 Removes a rule to this security group by id, name, or rule_setting
194 :param rule_id: the rule's id
195 :param rule_setting: the rule's setting object
197 rule_to_remove = None
198 if rule_id or rule_setting:
200 rule_to_remove = neutron_utils.get_rule_by_id(
201 self._neutron, self.__security_group, rule_id)
203 rule_to_remove = self.__rules.get(rule_setting)
206 neutron_utils.delete_security_group_rule(self._neutron,
208 rule_setting = self.__get_setting_from_rule(rule_to_remove)
210 self.__rules.pop(rule_setting)
212 logger.warning('Rule setting is None, cannot remove rule')
214 def __get_setting_from_rule(self, rule):
216 Returns the associated RuleSetting object for a given rule
217 :param rule: the Rule object
218 :return: the associated RuleSetting object or None
220 for rule_setting in self.sec_grp_settings.rule_settings:
221 if rule_setting.rule_eq(rule):
226 class SecurityGroupSettings(SecurityGroupConfig):
228 Class to hold the configuration settings required for creating OpenStack
229 SecurityGroup objects
230 deprecated - use snaps.config.security_group.SecurityGroupConfig instead
233 def __init__(self, **kwargs):
234 from warnings import warn
235 warn('Use snaps.config.security_group.SecurityGroupConfig instead',
237 super(self.__class__, self).__init__(**kwargs)
240 class Direction(enum.Enum):
243 deprecated - use snaps.config.security_group.Direction
249 class Protocol(enum.Enum):
252 deprecated - use snaps.config.security_group.Protocol
280 class Ethertype(enum.Enum):
283 deprecated - use snaps.config.security_group.Ethertype
289 class SecurityGroupRuleSettings(SecurityGroupRuleConfig):
291 Class to hold the configuration settings required for creating OpenStack
292 SecurityGroupRule objects
293 deprecated - use snaps.config.security_group.SecurityGroupRuleConfig
297 def __init__(self, **kwargs):
298 from warnings import warn
299 warn('Use snaps.config.security_group.SecurityGroupRuleConfig instead',
301 super(self.__class__, self).__init__(**kwargs)