Example #1
0
 def set_commands(self, want, have):
     commands = []
     h1 = h2 = h3 = {}
     want = remove_empties(want)
     vrf_list = []
     if have:
         vrf_list = [h['vrf'] for h in have]
     if want['vrf'] in vrf_list and have != [{'vrf': '__global__'}]:
         for x in have:
             if x['vrf'] == want['vrf']:
                 h1 = x  # this has the 'have' dict with same vrf as want
         if 'address_families' in h1.keys():
             afi_list = [h['afi'] for h in h1['address_families']]
             for af in want['address_families']:
                 if af['afi'] in afi_list:
                     for x in h1['address_families']:
                         if x['afi'] == af['afi']:
                             h2 = x  # this has the have dict with same vrf and afi as want
                     dest_list = [h['dest'] for h in h2['routes']]
                     for ro in af['routes']:
                         # q(dest_list)
                         if ro['dest'] in dest_list:
                             for x in h2['routes']:
                                 if x['dest'] == ro['dest']:
                                     h3 = x  # this has the have dict with same vrf, afi and dest as want
                             next_hop_list = [h for h in h3['next_hops']]
                             for nh in ro['next_hops']:
                                 if 'interface' in nh.keys():
                                     nh['interface'] = normalize_interface(
                                         nh['interface'])
                                 if nh not in next_hop_list:
                                     # no match for next hop in have
                                     commands = self.set_next_hop(
                                         want, h2, nh, ro, commands)
                                     vrf_list.append(want['vrf'])
                         else:
                             # no match for dest
                             for nh in ro['next_hops']:
                                 commands = self.set_next_hop(
                                     want, h2, nh, ro, commands)
                 else:
                     # no match for afi
                     for ro in af['routes']:
                         for nh in ro['next_hops']:
                             commands = self.set_next_hop(
                                 want, af, nh, ro, commands)
     else:
         # no match for vrf
         vrf_list.append(want['vrf'])
         for af in want['address_families']:
             for ro in af['routes']:
                 for nh in ro['next_hops']:
                     commands = self.set_next_hop(want, af, nh, ro,
                                                  commands)
     return commands
    def execute_module(self):
        """ Execute the module
        :rtype: A dictionary
        :returns: The result from module execution
        """
        result = {'changed': False}
        commands = list()
        warnings = list()

        state = self._module.params['state']
        if 'overridden' in state:
            self._module.fail_json(
                msg='State <overridden> is invalid for this module.')
        if 'replaced' in state:
            self._module.fail_json(msg='State: <replaced> not yet supported')

        # When state is 'deleted', the module_params should not contain data
        # under the 'config' key
        if 'deleted' in state and self._module.params.get('config'):
            self._module.fail_json(
                msg='Remove config key from playbook when state is <deleted>')

        if self._module.params['config'] is None:
            self._module.params['config'] = {}
        # Normalize interface name.
        int = self._module.params['config'].get('source_interface')
        if int:
            self._module.params['config'][
                'source_interface'] = normalize_interface(int)

        existing_telemetry_facts = self.get_telemetry_facts()
        commands.extend(self.set_config(existing_telemetry_facts))
        if commands:
            if not self._module.check_mode:
                self.edit_config(commands)
                # TODO: edit_config is only available for network_cli. Once we
                # add support for httpapi, we will need to switch to load_config
                # or add support to httpapi for edit_config
                #
                # self._connection.load_config(commands)
            result['changed'] = True
        result['commands'] = commands

        changed_telemetry_facts = self.get_telemetry_facts()

        result['before'] = existing_telemetry_facts
        if result['changed']:
            result['after'] = changed_telemetry_facts

        result['warnings'] = warnings
        return result
Example #3
0
    def populate_structured_neighbors_lldp(self, data):
        objects = dict()
        data = data['TABLE_nbor']['ROW_nbor']

        if isinstance(data, dict):
            data = [data]

        for item in data:
            local_intf = normalize_interface(item['l_port_id'])
            objects[local_intf] = list()
            nbor = dict()
            nbor['port'] = item['port_id']
            nbor['host'] = nbor['sysname'] = item['chassis_id']
            objects[local_intf].append(nbor)

        return objects
Example #4
0
    def set_config(self, existing_interfaces_facts):
        """ Collect the configuration from the args passed to the module,
            collect the current configuration (as a dict from facts)

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        config = self._module.params.get('config')
        want = []
        if config:
            for w in config:
                w.update({'name': normalize_interface(w['name'])})
                want.append(remove_empties(w))
        have = existing_interfaces_facts
        resp = self.set_state(want, have)
        return to_list(resp)
Example #5
0
    def set_config(self, existing_lag_interfaces_facts):
        """ Collect the configuration from the args passed to the module,
            collect the current configuration (as a dict from facts)

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        want = self._module.params.get('config')
        if want:
            for w in want:
                w.update(remove_empties(w))
                if 'members' in w and w['members']:
                    for item in w['members']:
                        item.update({'member': normalize_interface(item['member'])})
        have = existing_lag_interfaces_facts
        resp = self.set_state(want, have)
        return to_list(resp)
    def get_members(self, id, connection):
        """
        Returns members associated with a channel-group

        :param name: The channel group
        :rtype: list
        :returns: Members
        """
        members = []
        data = connection.get('show port-channel summary')
        match = re.search(r'{0} (.+)(|\n)'.format(id), data)
        if match:
            interfaces = re.search(r'Eth\d(.+)$', match.group())
            if interfaces:
                for i in interfaces.group().split():
                    if get_interface_type(i[:-3]) != 'unknown':
                        members.append(normalize_interface(i[:-3]))

        return members
    def set_config(self, existing_lacp_interfaces_facts):
        """ Collect the configuration from the args passed to the module,
            collect the current configuration (as a dict from facts)

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        config = self._module.params.get('config')
        want = []
        if config:
            for w in config:
                if get_interface_type(w['name']) not in ('portchannel', 'ethernet'):
                    self._module.fail_json(msg='This module works with either portchannel or ethernet')
                w.update({'name': normalize_interface(w['name'])})
                want.append(remove_empties(w))
        have = existing_lacp_interfaces_facts
        resp = self.set_state(want, have)
        return to_list(resp)
Example #8
0
 def add_commands(self, want):
     command = ''
     params = want.keys()
     pref = vrf = ip = intf = name = tag = track = ''
     if 'admin_distance' in params:
         pref = str(want['admin_distance']) + ' '
     if 'track' in params:
         track = 'track ' + str(want['track']) + ' '
     if 'dest_vrf' in params:
         vrf = 'vrf ' + str(want['dest_vrf']) + ' '
     if 'forward_router_address' in params:
         ip = want['forward_router_address'] + ' '
     if 'interface' in params:
         intf = normalize_interface(want['interface']) + ' '
     if 'route_name' in params:
         name = 'name ' + str(want['route_name']) + ' '
     if 'tag' in params:
         tag = 'tag ' + str(want['tag']) + ' '
     command = intf + ip + vrf + name + tag + track + pref
     return command
Example #9
0
    def set_config(self, existing_l3_interfaces_facts):
        """ Collect the configuration from the args passed to the module,
            collect the current configuration (as a dict from facts)

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        config = self._module.params.get('config')
        want = []
        if config:
            for w in config:
                w.update({'name': normalize_interface(w['name'])})
                if get_interface_type(w['name']) == 'management':
                    self._module.fail_json(msg="The 'management' interface is not allowed to be managed by this module")
                want.append(remove_empties(w))
        have = deepcopy(existing_l3_interfaces_facts)
        self.init_check_existing(have)
        resp = self.set_state(want, have)
        return to_list(resp)
Example #10
0
    def populate_neighbors(self, data):
        objects = dict()
        # if there are no neighbors the show command returns
        # ERROR: No neighbour information
        if data.startswith('ERROR'):
            return dict()

        regex = re.compile(r'(\S+)\s+(\S+)\s+\d+\s+\w+\s+(\S+)')

        for item in data.split('\n')[4:-1]:
            match = regex.match(item)
            if match:
                nbor = dict()
                nbor['host'] = nbor['sysname'] = match.group(1)
                nbor['port'] = match.group(3)
                local_intf = normalize_interface(match.group(2))
                if local_intf not in objects:
                    objects[local_intf] = []
                objects[local_intf].append(nbor)

        return objects
Example #11
0
    def render_config(self, spec, conf):
        """
        Render config as dictionary structure and delete keys
          from spec for null values

        :param spec: The facts tree, generated from the argspec
        :param conf: The configuration
        :rtype: dictionary
        :returns: The generated config
        """
        config = deepcopy(spec)
        name = conf[0].strip()
        config['name'] = normalize_interface(name)
        config['access_groups'] = []
        v4 = {'afi': 'ipv4', 'acls': []}
        v6 = {'afi': 'ipv6', 'acls': []}
        for c in conf[1:]:
            if c:
                acl4 = re.search(r'ip( port)? access-group (\w*) (\w*)', c)
                acl6 = re.search(r'ipv6( port)? traffic-filter (\w*) (\w*)', c)
                if acl4:
                    acl = {
                        'name': acl4.group(2).strip(),
                        'direction': acl4.group(3).strip()
                    }
                    if acl4.group(1):
                        acl.update({'port': True})
                    v4['acls'].append(acl)
                elif acl6:
                    acl = {'name': acl6.group(2), 'direction': acl6.group(3)}
                    if acl6.group(1):
                        acl.update({'port': True})
                    v6['acls'].append(acl)

        if len(v4['acls']) > 0:
            config['access_groups'].append(v4)
        if len(v6['acls']) > 0:
            config['access_groups'].append(v6)

        return utils.remove_empties(config)
Example #12
0
    def set_config(self, existing_interfaces_facts, default_intf_list):
        """ Collect the configuration from the args passed to the module,
            collect the current configuration (as a dict from facts)

        :rtype: A list
        :returns: the commands necessary to migrate the current configuration
                  to the desired configuration
        """
        config = self._module.params.get('config')
        want = []
        if config:
            for w in config:
                w.update({'name': normalize_interface(w['name'])})
                want.append(remove_empties(w))
        have = deepcopy(existing_interfaces_facts)
        for i in want:
            # 'have' does not include objects from the default_interfaces list.
            # Add any 'want' names from default_interfaces to the 'have' list.
            if i['name'] in default_intf_list:
                have.append({'name': i['name']})
        resp = self.set_state(want, have)
        return to_list(resp)