def _clear_config(name, want, have): commands = [] for key, value in iteritems(have): if value is None: continue if key in ('receive', 'transmit') and want.get(key) is None: commands.append("lldp {0}".format(key)) elif key == 'tlv_select': for tlv, stat in iteritems(value): if stat: commands.append("no lldp tlv-select {0}".format( tlv.replace('_', '-'))) elif key == 'med_tlv_select': for tlv, stat in iteritems(value): if tlv == 'inventory_management': commands.append("no lldp med-tlv-select {0}".format( tlv.replace('_', '-'))) else: commands.append("lldp med-tlv-select {0}".format( tlv.replace('_', '-'))) if commands: commands.insert(0, "interface {0}".format(name)) return commands
def _state_overridden(self, want, have): """ The command generator when state is overridden :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] for name, want_dict in iteritems(want): kwargs = { 'self': self, 'want': { name: want[name] }, 'have': { name: have.get(name, {}) } } commands.extend(self._state_replaced(**kwargs)) to_delete = {} for name, have_dict in iteritems(have): if name not in want and name != 'manager': to_delete.update({name: have_dict}) commands.extend(self._clear_config(to_delete, have)) return commands
def _set_config(name, want, have): commands = [] for key, value in iteritems(want): if value is None: continue if key in ('receive', 'transmit'): if have.get(key, True) != value: prefix = "" if value else "no " commands.append("{0}lldp {1}".format(prefix, key)) elif key == 'tlv_select': for tlv, stat in iteritems(value): if stat is None: continue if have.get(key, {}).get(tlv, False) != stat: prefix = "" if stat else "no " commands.append("{0}lldp tlv-select {1}".format( prefix, tlv.replace('_', '-'))) elif key == 'med_tlv_select': for tlv, stat in iteritems(value): if stat is None: continue have_stat = have.get(key, {}).get(tlv, True) if tlv != 'inventory_management' \ else have.get(key, {}).get(tlv, False) if have_stat != stat: prefix = "" if stat else "no " commands.append("{0}lldp med-tlv-select {1}".format( prefix, tlv.replace('_', '-'))) if commands: commands.insert(0, "interface {0}".format(name)) return commands
def _state_deleted(self, want, have): """ The command generator when state is deleted :rtype: A list :returns: the commands necessary to remove the current configuration of the provided objects """ commands = [] if want: for vlan_id, value in iteritems(want): commands.extend(_clear_config(vlan_id, have)) else: for vlan_id, value in iteritems(have): commands.extend(_clear_config(vlan_id, have)) return commands
def _clear_config(self, to_delete, have): # clear config commands = [] for name, value in iteritems(to_delete): if name != 'manager' and name in have: commands.append('no username {}'.format(name)) return commands
def _set_config(self, want, have): # set config commands = [] for name, value in iteritems(want): if name not in have and (not value.get('configured_password') and not value.get('hashed_password')): self._module.fail_json(msg='Password is required.') if value.get('configured_password') and value.get( 'hashed_password'): self._module.fail_json( msg= 'configured_password and hashed_password are mutually exclusive.' ) privilege = value['privilege'] if value['privilege'] else have.get( name, {}).get('privilege', 1) if value.get('configured_password'): commands.append('username {} privilege {} password {}'.format( name, privilege, value['configured_password'])) elif value.get('hashed_password'): commands.append( 'username {} privilege {} password 8 {}'.format( name, privilege, value['hashed_password'])) elif privilege != have[name]['privilege']: commands.append('username {} privilege {}'.format( name, privilege)) return commands
def generate_addrfam_commands(want, have): commands = [] want = param_list_to_dict(want, unique_key='vrf') if have: have = param_list_to_dict(have, unique_key='vrf') else: have = dict() for vrf, stats in iteritems(want): vrf_commands = [] if stats.get('redistribute'): vrf_commands.extend( generate_redistribute_commands( stats['redistribute'], have.get(vrf, {}).get('redistribute', []))) if stats.get('networks'): network_commands = generate_network_commands( stats['networks'], have.get(vrf, {}).get('networks', [])) vrf_commands.extend(network_commands) if stats.get('neighbors'): neighbor_commands = generate_af_neighbor_commands( stats['neighbors'], have.get(vrf, {}).get('neighbors')) vrf_commands.extend(neighbor_commands) if vrf_commands or vrf not in have: vrf_commands.insert(0, 'address-family ipv4 vrf {}'.format(vrf)) vrf_commands.append('exit-address-family') commands.extend(vrf_commands) return commands
def _state_replaced(self, want, have): """ The command generator when state is replaced :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] for name, want_dict in iteritems(want): kwargs = {'self': self, 'want': {name: want[name]}, 'have': have} commands.extend(self._state_merged(**kwargs)) for name, have_dict in iteritems(have): if name not in want: commands.extend(_clear_config(name)) return commands
def generate_neighbor_commands(want, have): commands = [] w_neighbors = param_list_to_dict(want, unique_key='neighbor') if have: h_neighbors = param_list_to_dict(have, unique_key='neighbor') else: h_neighbors = dict() diff = dict_diff(h_neighbors, w_neighbors) for w_neighbor, stats in iteritems(diff): if w_neighbor not in h_neighbors: commands.append('neighbor {} remote-as {}'.format( w_neighbor, stats['remote_as'])) for key, value in iteritems(stats): if key == 'remote_as' or value is None: continue if key == 'enabled': if value is False and value != h_neighbors.get(w_neighbor).get( 'enabled', True): commands.append('neighbor {} shutdown'.format(w_neighbor)) if value and value != h_neighbors.get(w_neighbor).get( 'enabled', True): commands.append( 'no neighbor {} shutdown'.format(w_neighbor)) elif key == 'timers': if value.get('connect'): commands.append('neighbor {} timers connect {}'.format( w_neighbor, value['connect'])) else: if value.get('keepalive') is None or value.get( 'holdtime') is None: raise ValueError( 'keepalive and holdtime required together') commands.append('neighbor {} timers {} {}'.format( w_neighbor, value['keepalive'], value['holdtime'])) else: commands.append('neighbor {} {} {}'.format( w_neighbor, key.replace('_', '-'), value)) return commands
def _state_deleted(self, want, have): """ The command generator when state is deleted :rtype: A list :returns: the commands necessary to remove the current configuration of the provided objects """ commands = [] if not want: for name, have_dict in iteritems(have): commands.extend(_clear_config(name, dict(), have_dict)) else: for name, want_dict in iteritems(want): if name in have: have_dict = have[name] commands.extend(_clear_config(name, dict(), have_dict)) return commands
def _set_config(self, want, have): # Set LLDP global config commands = [] self.validate_tx(want, have) for key, value in iteritems(want): if value is not None and have.get(key) != value: commands.append(self.get_command(key, value=value)) return commands
def _clear_config(self, want, have): # clear LLDP global config commands = [] defaults = get_lldp_defaults() for key, value in iteritems(have): if value != defaults[key] and want.get(key) is None: commands.append(self.get_command(key, value=False)) return commands
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) multiplier = re.search(r'lldp holdtime-multiplier (\d+)', conf, re.M) if multiplier: config['holdtime_multiplier'] = multiplier.group(1) notif_int = re.search(r'lldp notification-interval (\d+)', conf, re.M) if notif_int: config['notification_interval'] = notif_int.group(1) reinit = re.search(r'lldp reinit (\d+)', conf, re.M) if reinit: config['reinit'] = reinit.group(1) timer = re.search(r'lldp timer (\d+)', conf, re.M) if timer: config['timer'] = timer.group(1) tx_delay = re.search(r'lldp tx-delay (\d+)', conf, re.M) if tx_delay: config['tx_delay'] = tx_delay.group(1) port_type = re.search(r'lldp port-number-type (\S+)', conf, re.M) if port_type: config['port_number_type'] = port_type.group(1) faststart_count = re.search(r'lldp faststart-count (\d+)', conf, re.M) if faststart_count: config['faststart_count'] = faststart_count.group(1) non_strict_check = re.search(r'lldp non-strict-med-tlv-order-check', conf, re.M) if non_strict_check: config['non_strict_med_tlv_order_check'] = True enabled = re.search(r'lldp run', conf, re.M) if enabled: config['enabled'] = True defaults = get_lldp_defaults() for key, value in utils.iteritems(config): if not value: config[key] = defaults[key] return utils.remove_empties(config)
def _state_merged(self, want, have): """ The command generator when state is merged :rtype: A list :returns: the commands necessary to merge the provided into the current configuration """ commands = [] diff = dict_diff(have, want) for vlan_id, value in iteritems(diff): commands.extend(_set_config(vlan_id, value)) return commands
def _state_replaced(self, want, have): """ The command generator when state is replaced :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] diff = dict_diff(have, want) for vlan_id, value in iteritems(diff): commands.extend(_clear_config(vlan_id, have)) commands.extend(_set_config(vlan_id, value)) return commands
def _state_deleted(self, want, have): """ The command generator when state is deleted :rtype: A list :returns: the commands necessary to remove the current configuration of the provided objects """ commands = [] if not want: for key, value in iteritems(have): commands.extend(_clear_config(key, dict(), value)) else: for key, value in iteritems(want): want_dict = dict(name=key) if key in have: have_dict = have[key] diff = dict_diff(want_dict, have_dict) commands.extend(_clear_config(key, want_dict, diff)) return commands
def generate_af_neighbor_commands(want, have): commands = [] w_neighbors = param_list_to_dict(want, unique_key='neighbor') if have: h_neighbors = param_list_to_dict(have, unique_key='neighbor') else: h_neighbors = dict() diff = dict_diff(h_neighbors, w_neighbors) for w_neighbor, stats in iteritems(diff): if w_neighbor not in h_neighbors: commands.append('neighbor {} remote-as {}'.format( w_neighbor, stats['remote_as'])) for key, value in iteritems(stats): if key == 'remote_as' or value is None: continue if key == 'maximum_prefix': commands.append('neighbor {} maximum-prefix {}'.format( w_neighbor, value)) elif key == 'prefix_list_in': commands.append('neighbor {} prefix-list {} in'.format( w_neighbor, value)) elif key == 'prefix_list_out': commands.append('neighbor {} prefix-list {} out'.format( w_neighbor, value)) else: if value and value != h_neighbors.get(w_neighbor, {}).get( key, False): commands.append('neighbor {} {}'.format( w_neighbor, key.replace('_', '-'), value)) elif not value and value != h_neighbors.get( w_neighbor, {}).get(key, False): commands.append('no neighbor {} {}'.format( w_neighbor, key.replace('_', '-'), value)) return commands
def _state_overridden(self, want, have): """ The command generator when state is overridden :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] commands.extend(self._state_replaced(self, want, have)) for name, value in iteritems(have): if name not in want: commands.extend(_clear_config(name, value)) return commands
def _state_merged(self, want, have): """ The command generator when state is merged :rtype: A list :returns: the commands necessary to merge the provided into the current configuration """ commands = [] for name, want_dict in iteritems(want): if name in have: have_dict = have[name] commands.extend(_set_config(name, want_dict, have_dict)) return commands
def _state_replaced(self, want, have): """ The command generator when state is replaced :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] for name, value in iteritems(want): if name in have: to_clear = dict_diff(value, have[name]) commands.extend(_clear_config(name, to_clear)) to_set = dict_diff(have[name], value) commands.extend(_set_config(name, to_set)) return remove_duplicate_interface(commands)
def _state_overridden(self, want, have): """ The command generator when state is overridden :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] for name, have_dict in iteritems(have): p_have = {name: have_dict} if name in want: p_want = {name: want[name]} commands.extend(self._state_replaced(self, p_want, p_have)) else: commands.extend(self._state_deleted(self, dict(), p_have)) return commands
def _state_replaced(self, want, have): """ The command generator when state is replaced :rtype: A list :returns: the commands necessary to migrate the current configuration to the desired configuration """ commands = [] for name, want_dict in iteritems(want): if name in have: have_dict = have[name] diff = dict_diff(want_dict, have_dict) commands.extend(_clear_config(name, want_dict, diff)) commands.extend( _set_config(name, want_dict, have_dict, self._module)) return remove_duplicate_interface(commands)