# Copyright 2013 VMware, 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. from oslo_log import log import six from vmware_nsx.common import nsx_utils LOG = log.getLogger(__name__) # Protocol number look up for supported protocols protocol_num_look_up = {'tcp': 6, 'icmp': 1, 'udp': 17, 'ipv6-icmp': 58} def _convert_to_nsx_rule(session, cluster, rule, with_id=False): """Converts a Neutron security group rule to the NSX format. This routine also replaces Neutron IDs with NSX UUIDs. """ nsx_rule = {} params = ['remote_ip_prefix', 'protocol', 'remote_group_id', 'port_range_min', 'port_range_max', 'ethertype'] if with_id: params.append('id') for param in params: value = rule.get(param) if param not in rule: nsx_rule[param] = value elif not value: pass elif param == 'remote_ip_prefix': nsx_rule['ip_prefix'] = rule['remote_ip_prefix'] elif param == 'remote_group_id': nsx_rule['profile_uuid'] = nsx_utils.get_nsx_security_group_id( session, cluster, rule['remote_group_id']) elif param == 'protocol': try: nsx_rule['protocol'] = int(rule['protocol']) except (ValueError, TypeError): nsx_rule['protocol'] = ( protocol_num_look_up[rule['protocol']]) else: nsx_rule[param] = value return nsx_rule def _convert_to_nsx_rules(session, cluster, rules, with_id=False): """Converts a list of Neutron security group rules to the NSX format.""" nsx_rules = {'logical_port_ingress_rules': [], 'logical_port_egress_rules': []} for direction in ['logical_port_ingress_rules', 'logical_port_egress_rules']: for rule in rules[direction]: nsx_rules[direction].append( _convert_to_nsx_rule(session, cluster, rule, with_id)) return nsx_rules def get_security_group_rules_nsx_format(session, cluster, security_group_rules, with_id=False): """Convert neutron security group rules into NSX format. This routine splits Neutron security group rules into two lists, one for ingress rules and the other for egress rules. """ def fields(rule): _fields = ['remote_ip_prefix', 'remote_group_id', 'protocol', 'port_range_min', 'port_range_max', 'protocol', 'ethertype'] if with_id: _fields.append('id') return dict((k, v) for k, v in six.iteritems(rule) if k in _fields) ingress_rules = [] egress_rules = [] for rule in security_group_rules: if rule.get('souce_group_id'): rule['remote_group_id'] = nsx_utils.get_nsx_security_group_id( session, cluster, rule['remote_group_id']) if rule['direction'] == 'ingress': ingress_rules.append(fields(rule)) elif rule['direction'] == 'egress': egress_rules.append(fields(rule)) rules = {'logical_port_ingress_rules': egress_rules, 'logical_port_egress_rules': ingress_rules} return _convert_to_nsx_rules(session, cluster, rules, with_id) def merge_security_group_rules_with_current(session, cluster, new_rules, current_rules): merged_rules = get_security_group_rules_nsx_format( session, cluster, current_rules) for new_rule in new_rules: rule = new_rule['security_group_rule'] if rule['direction'] == 'ingress': merged_rules['logical_port_egress_rules'].append( _convert_to_nsx_rule(session, cluster, rule)) elif rule['direction'] == 'egress': merged_rules['logical_port_ingress_rules'].append( _convert_to_nsx_rule(session, cluster, rule)) return merged_rules def remove_security_group_with_id_and_id_field(rules, rule_id): """Remove rule by rule_id. This function receives all of the current rule associated with a security group and then removes the rule that matches the rule_id. In addition it removes the id field in the dict with each rule since that should not be passed to nsx. """ for rule_direction in rules.values(): item_to_remove = None for port_rule in rule_direction: if port_rule['id'] == rule_id: item_to_remove = port_rule else: # remove key from dictionary for NSX del port_rule['id'] if item_to_remove: rule_direction.remove(item_to_remove)