def _check_for_duplicate_rules(self, context, security_group_id, new_security_group_rules): # First up, check for any duplicates in the new rules. new_rules_set = set() for i in new_security_group_rules: rule_key = self._rule_to_key(i['security_group_rule']) if rule_key in new_rules_set: raise ext_sg.DuplicateSecurityGroupRuleInPost(rule=i) new_rules_set.add(rule_key) # Now, let's make sure none of the new rules conflict with # existing rules; note that we do *not* store the db rules # in the set, as we assume they were already checked, # when added. sg = self.get_security_group(context, security_group_id) if sg: for i in sg['security_group_rules']: rule_key = self._rule_to_key(i) if rule_key in new_rules_set: raise ext_sg.SecurityGroupRuleExists(rule_id=i.get('id'))
def _check_for_duplicate_rules_in_db(self, context, security_group_rule): # Check in database if rule exists filters = self._make_security_group_rule_filter_dict( security_group_rule) db_rules = self.get_security_group_rules( context, filters, fields=security_group_rule['security_group_rule'].keys()) # Note(arosen): the call to get_security_group_rules wildcards # values in the filter that have a value of [None]. For # example, filters = {'remote_group_id': [None]} will return # all security group rules regardless of their value of # remote_group_id. Therefore it is not possible to do this # query unless the behavior of _get_collection() # is changed which cannot be because other methods are already # relying on this behavior. Therefore, we do the filtering # below to check for these corner cases. for db_rule in db_rules: # need to remove id from db_rule for matching if (security_group_rule['security_group_rule'] == db_rule): raise ext_sg.SecurityGroupRuleExists(id=id)
def _check_for_duplicate_rules_in_db(self, context, security_group_rule): # Check in database if rule exists filters = self._make_security_group_rule_filter_dict( security_group_rule) rule_dict = security_group_rule['security_group_rule'].copy() rule_dict.pop('description', None) keys = rule_dict.keys() fields = list(keys) + ['id'] if 'remote_ip_prefix' not in fields: fields += ['remote_ip_prefix'] db_rules = self.get_security_group_rules(context, filters, fields=fields) # Note(arosen): the call to get_security_group_rules wildcards # values in the filter that have a value of [None]. For # example, filters = {'remote_group_id': [None]} will return # all security group rules regardless of their value of # remote_group_id. Therefore it is not possible to do this # query unless the behavior of _get_collection() # is changed which cannot be because other methods are already # relying on this behavior. Therefore, we do the filtering # below to check for these corner cases. rule_dict.pop('id', None) sg_protocol = rule_dict.pop('protocol', None) remote_ip_prefix = rule_dict.pop('remote_ip_prefix', None) for db_rule in db_rules: rule_id = db_rule.pop('id', None) # remove protocol and match separately for number and type db_protocol = db_rule.pop('protocol', None) is_protocol_matching = ( self._get_ip_proto_name_and_num(db_protocol) == self._get_ip_proto_name_and_num(sg_protocol)) db_remote_ip_prefix = db_rule.pop('remote_ip_prefix', None) duplicate_ip_prefix = self._validate_duplicate_ip_prefix( remote_ip_prefix, db_remote_ip_prefix) if (is_protocol_matching and duplicate_ip_prefix and rule_dict == db_rule): raise ext_sg.SecurityGroupRuleExists(rule_id=rule_id)