diff --git a/docs/vyos.vyos.vyos_vrrp_module.rst b/docs/vyos.vyos.vyos_vrrp_module.rst index 08d3387a..4794641f 100644 --- a/docs/vyos.vyos.vyos_vrrp_module.rst +++ b/docs/vyos.vyos.vyos_vrrp_module.rst @@ -1,2648 +1,2648 @@ .. _vyos.vyos.vyos_vrrp_module: ******************* vyos.vyos.vyos_vrrp ******************* **Manage VRRP and load balancer configuration on VyOS** Version added: 1.0.0 .. contents:: :local: :depth: 1 Synopsis -------- - This module configures VRRP groups, global VRRP parameters, VRRP sync groups, and LVS-style virtual servers on VyOS 1.4+. - Supports creation, modification, deletion, replacement, rendering, and parsing of VRRP-related configuration. Parameters ---------- .. raw:: html
Parameter Choices/Defaults Comments
config
dictionary
Full VRRP and virtual server configuration.
disable
boolean
    Choices:
  • no ←
  • yes
Disable all VRRP and L4-LB configuration under this module.
virtual_servers
list / elements=dictionary
List of load balancer virtual server (LVS) definitions.
address
string
Virtual IP address for the server.
algorithm
string
Load balancing algorithm used for dispatching connections.
- alias + delay_loop
- string - / required + integer
-
Unique identifier for the virtual server.
+
Delay loop interval in seconds.
- delay_loop + forward_method
- integer + string
+
    Choices: +
  • direct
  • +
  • nat
  • +
-
Delay loop interval in seconds.
+
Forwarding method used by LVS.
- forward_method + fwmark
string
-
    Choices: -
  • direct
  • -
  • nat
  • -
-
Forwarding method used by LVS.
+
Firewall mark for LVS traffic classification.
- fwmark + name
string + / required
-
Firewall mark for LVS traffic classification.
+
Unique identifier for the virtual server.
persistence_timeout
string
Client persistence timeout in seconds.
port
integer
TCP/UDP port provided by the virtual service.
protocol
string
    Choices:
  • tcp
  • udp
Transport protocol for the virtual server.
real_servers
list / elements=dictionary
Backend real servers behind the virtual service.
address
string / required
Real server IP address.
health_check_script
string
Path to health check script used for backend validation.
port
integer
Backend server port.
vrrp
dictionary
VRRP configuration including groups, global parameters, SNMP settings, and sync-groups.
global_parameters
dictionary
Global VRRP tuning parameters.
garp
dictionary
Gratuitous ARP related configuration.
interval
integer
GARP interval in seconds.
master_delay
integer
Delay before sending GARP as master.
master_refresh
integer
Refresh interval for master GARP announcements.
master_refresh_repeat
integer
Number of times to repeat refresh announcements.
master_repeat
integer
Number of GARP repeats when transitioning to master.
startup_delay
integer
Delay before VRRP starts after boot.
version
string
VRRP protocol version.
groups
list / elements=dictionary
VRRP instance configuration groups.
address
string
Virtual router IP address.
advertise_interval
integer
VRRP advertisement interval.
authentication
dictionary
VRRP group authentication options.
password
string
Authentication password.
type
string
Authentication type.
description
string
Text description for the VRRP group.
disable
boolean
    Choices:
  • no ←
  • yes
Disable this VRRP group.
excluded_address
string
IP address excluded from source checks.
garp
dictionary
GARP-specific settings for this group.
interval
integer
GARP interval.
master_delay
integer
GARP master delay.
master_refresh
integer
GARP master refresh interval.
master_refresh_repeat
integer
Repeated refresh sends.
master_repeat
integer
GARP repeat count.
health_check
dictionary
VRRP group health check options.
failure_count
integer
Allowed number of failed checks.
interval
integer
Health check interval.
ping
string
Host to ping for checks.
script
string
Script to execute for health checking.
hello_source_address
string
Source address for VRRP hello packets.
interface
string
Interface used by the VRRP group.
name
string / required
VRRP group name.
no_preempt
boolean
    Choices:
  • no
  • yes
Disable preemption.
peer_address
string
Peer VRRP router address.
preempt_delay
integer
Delay before taking master role.
priority
integer
VRRP priority (higher = preferred master).
rfc3768_compatibility
boolean
    Choices:
  • no
  • yes
Enable or disable RFC3768 compatibility mode.
track
dictionary
Track interface and VRRP behaviour.
exclude_vrrp_interface
boolean
    Choices:
  • no
  • yes
Exclude VRRP interface from tracking.
interface
string
Interface to track.
transition_script
dictionary
Scripts executed during VRRP state transitions.
backup
string
Path to backup script.
fault
string
Path to fault script.
master
string
Path to master script.
stop
string
Path to stop script.
vrid
integer / required
VRRP Virtual Router ID.
snmp
boolean
    Choices:
  • no
  • yes
Enable SNMP support for VRRP.
sync_groups
list / elements=dictionary
VRRP sync-groups for coordinated failover.
health_check
dictionary
Health check options for sync group.
failure_count
integer
Allowed number of failures.
interval
integer
Health check interval.
ping
string
Host to ping.
script
string
Script to run for health checking.
member
list / elements=string
List of VRRP groups participating in this sync group.
name
string / required
Sync-group name.
transition_script
dictionary
Transition scripts for sync group events.
backup
string
Backup state script.
fault
string
Fault state script.
master
string
Master state script.
stop
string
Stop state script.
running_config
string
Used only when state=parsed. Must contain the output of show configuration commands | grep high-availability.
state
string
    Choices:
  • deleted
  • merged ←
  • purged
  • replaced
  • gathered
  • rendered
  • parsed
Desired end state of the VRRP configuration.

Examples -------- .. code-block:: yaml # Using merged # Before state # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # vyos@vyos:~$ - name: Merge provided configuration with device configuration vyos.vyos.vyos_vrrp: config: as_number: "65536" aggregate_address: - prefix: "203.0.113.0/24" as_set: true - prefix: "192.0.2.0/24" summary_only: true network: - address: "192.1.13.0/24" backdoor: true redistribute: - protocol: "kernel" metric: 45 - protocol: "connected" route_map: "map01" maximum_paths: - path: "ebgp" count: 20 - path: "ibgp" count: 55 timers: keepalive: 35 bgp_params: bestpath: as_path: "confed" compare_routerid: true default: no_ipv4_unicast: true router_id: "192.1.2.9" confederation: - peers: 20 - peers: 55 - identifier: 66 neighbor: - address: "192.0.2.25" disable_connected_check: true timers: holdtime: 30 keepalive: 10 - address: "203.0.113.5" attribute_unchanged: as_path: true med: true ebgp_multihop: 2 remote_as: 101 update_source: "192.0.2.25" - address: "5001::64" maximum_prefix: 34 distribute_list: - acl: 20 action: "export" - acl: 40 action: "import" state: merged # After State # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp system-as 65536 # set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' # set protocols bgp aggregate-address 203.0.113.0/24 'as-set' # set protocols bgp maximum-paths ebgp '20' # set protocols bgp maximum-paths ibgp '55' # set protocols bgp neighbor 192.0.2.25 'disable-connected-check' # set protocols bgp neighbor 192.0.2.25 timers holdtime '30' # set protocols bgp neighbor 192.0.2.25 timers keepalive '10' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' # set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' # set protocols bgp neighbor 203.0.113.5 remote-as '101' # set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' # set protocols bgp neighbor 5001::64 distribute-list export '20' # set protocols bgp neighbor 5001::64 distribute-list import '40' # set protocols bgp neighbor 5001::64 maximum-prefix '34' # set protocols bgp network 192.1.13.0/24 'backdoor' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp parameters bestpath 'compare-routerid' # set protocols bgp parameters confederation identifier '66' # set protocols bgp parameters confederation peers '20' # set protocols bgp parameters confederation peers '55' # set protocols bgp parameters default 'no-ipv4-unicast' # set protocols bgp parameters router-id '192.1.2.9' # set protocols bgp redistribute connected route-map 'map01' # set protocols bgp redistribute kernel metric '45' # set protocols bgp timers keepalive '35' # vyos@vyos:~$ # # # Module Execution: # # "after": { # "aggregate_address": [ # { # "prefix": "192.0.2.0/24", # "summary_only": true # }, # { # "prefix": "203.0.113.0/24", # "as_set": true # } # ], # "as_number": 65536, # "bgp_params": { # "bestpath": { # "as_path": "confed", # "compare_routerid": true # }, # "confederation": [ # { # "identifier": 66 # }, # { # "peers": 20 # }, # { # "peers": 55 # } # ], # "default": { # "no_ipv4_unicast": true # }, # "router_id": "192.1.2.9" # }, # "maximum_paths": [ # { # "count": 20, # "path": "ebgp" # }, # { # "count": 55, # "path": "ibgp" # } # ], # "neighbor": [ # { # "address": "192.0.2.25", # "disable_connected_check": true, # "timers": { # "holdtime": 30, # "keepalive": 10 # } # }, # { # "address": "203.0.113.5", # "attribute_unchanged": { # "as_path": true, # "med": true, # "next_hop": true # }, # "ebgp_multihop": 2, # "remote_as": 101, # "update_source": "192.0.2.25" # }, # { # "address": "5001::64", # "distribute_list": [ # { # "acl": 20, # "action": "export" # }, # { # "acl": 40, # "action": "import" # } # ], # "maximum_prefix": 34 # } # ], # "network": [ # { # "address": "192.1.13.0/24", # "backdoor": true # } # ], # "redistribute": [ # { # "protocol": "connected", # "route_map": "map01" # }, # { # "metric": 45, # "protocol": "kernel" # } # ], # "timers": { # "keepalive": 35 # } # }, # "before": {}, # "changed": true, # "commands": [ # "set protocols bgp neighbor 192.0.2.25 disable-connected-check", # "set protocols bgp neighbor 192.0.2.25 timers holdtime 30", # "set protocols bgp neighbor 192.0.2.25 timers keepalive 10", # "set protocols bgp neighbor 203.0.113.5 attribute-unchanged as-path", # "set protocols bgp neighbor 203.0.113.5 attribute-unchanged med", # "set protocols bgp neighbor 203.0.113.5 attribute-unchanged next-hop", # "set protocols bgp neighbor 203.0.113.5 ebgp-multihop 2", # "set protocols bgp neighbor 203.0.113.5 remote-as 101", # "set protocols bgp neighbor 203.0.113.5 update-source 192.0.2.25", # "set protocols bgp neighbor 5001::64 maximum-prefix 34", # "set protocols bgp neighbor 5001::64 distribute-list export 20", # "set protocols bgp neighbor 5001::64 distribute-list import 40", # "set protocols bgp redistribute kernel metric 45", # "set protocols bgp redistribute connected route-map map01", # "set protocols bgp network 192.1.13.0/24 backdoor", # "set protocols bgp aggregate-address 203.0.113.0/24 as-set", # "set protocols bgp aggregate-address 192.0.2.0/24 summary-only", # "set protocols bgp parameters bestpath as-path confed", # "set protocols bgp parameters bestpath compare-routerid", # "set protocols bgp parameters default no-ipv4-unicast", # "set protocols bgp parameters router-id 192.1.2.9", # "set protocols bgp parameters confederation peers 20", # "set protocols bgp parameters confederation peers 55", # "set protocols bgp parameters confederation identifier 66", # "set protocols bgp maximum-paths ebgp 20", # "set protocols bgp maximum-paths ibgp 55", # "set protocols bgp timers keepalive 35" # ], # Using replaced: # -------------- # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp system-as 65536 # set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' # set protocols bgp aggregate-address 203.0.113.0/24 'as-set' # set protocols bgp maximum-paths ebgp '20' # set protocols bgp maximum-paths ibgp '55' # set protocols bgp neighbor 192.0.2.25 'disable-connected-check' # set protocols bgp neighbor 192.0.2.25 timers holdtime '30' # set protocols bgp neighbor 192.0.2.25 timers keepalive '10' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' # set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' # set protocols bgp neighbor 203.0.113.5 remote-as '101' # set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' # set protocols bgp neighbor 5001::64 distribute-list export '20' # set protocols bgp neighbor 5001::64 distribute-list import '40' # set protocols bgp neighbor 5001::64 maximum-prefix '34' # set protocols bgp network 192.1.13.0/24 'backdoor' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp parameters bestpath 'compare-routerid' # set protocols bgp parameters confederation identifier '66' # set protocols bgp parameters confederation peers '20' # set protocols bgp parameters confederation peers '55' # set protocols bgp parameters default 'no-ipv4-unicast' # set protocols bgp parameters router-id '192.1.2.9' # set protocols bgp redistribute connected route-map 'map01' # set protocols bgp redistribute kernel metric '45' # set protocols bgp timers keepalive '35' # vyos@vyos:~$ - name: Replace vyos.vyos.vyos_vrrp: config: as_number: "65536" network: - address: "203.0.113.0/24" route_map: map01 redistribute: - protocol: "static" route_map: "map01" neighbor: - address: "192.0.2.40" advertisement_interval: 72 capability: orf: "receive" bgp_params: bestpath: as_path: "confed" state: replaced # After state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp system-as 65536 # set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' # set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' # set protocols bgp network 203.0.113.0/24 route-map 'map01' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ # # # Module Execution: # # "after": { # "as_number": 65536, # "bgp_params": { # "bestpath": { # "as_path": "confed" # } # }, # "neighbor": [ # { # "address": "192.0.2.40", # "advertisement_interval": 72, # "capability": { # "orf": "receive" # } # } # ], # "network": [ # { # "address": "203.0.113.0/24", # "route_map": "map01" # } # ], # "redistribute": [ # { # "protocol": "static", # "route_map": "map01" # } # ] # }, # "before": { # "aggregate_address": [ # { # "prefix": "192.0.2.0/24", # "summary_only": true # }, # { # "prefix": "203.0.113.0/24", # "as_set": true # } # ], # "as_number": 65536, # "bgp_params": { # "bestpath": { # "as_path": "confed", # "compare_routerid": true # }, # "confederation": [ # { # "identifier": 66 # }, # { # "peers": 20 # }, # { # "peers": 55 # } # ], # "default": { # "no_ipv4_unicast": true # }, # "router_id": "192.1.2.9" # }, # "maximum_paths": [ # { # "count": 20, # "path": "ebgp" # }, # { # "count": 55, # "path": "ibgp" # } # ], # "neighbor": [ # { # "address": "192.0.2.25", # "disable_connected_check": true, # "timers": { # "holdtime": 30, # "keepalive": 10 # } # }, # { # "address": "203.0.113.5", # "attribute_unchanged": { # "as_path": true, # "med": true, # "next_hop": true # }, # "ebgp_multihop": 2, # "remote_as": 101, # "update_source": "192.0.2.25" # }, # { # "address": "5001::64", # "distribute_list": [ # { # "acl": 20, # "action": "export" # }, # { # "acl": 40, # "action": "import" # } # ], # "maximum_prefix": 34 # } # ], # "network": [ # { # "address": "192.1.13.0/24", # "backdoor": true # } # ], # "redistribute": [ # { # "protocol": "connected", # "route_map": "map01" # }, # { # "metric": 45, # "protocol": "kernel" # } # ], # "timers": { # "keepalive": 35 # } # }, # "changed": true, # "commands": [ # "delete protocols bgp timers", # "delete protocols bgp maximum-paths ", # "delete protocols bgp maximum-paths ", # "delete protocols bgp parameters router-id 192.1.2.9", # "delete protocols bgp parameters default", # "delete protocols bgp parameters confederation", # "delete protocols bgp parameters bestpath compare-routerid", # "delete protocols bgp aggregate-address", # "delete protocols bgp network 192.1.13.0/24", # "delete protocols bgp redistribute kernel", # "delete protocols bgp redistribute kernel", # "delete protocols bgp redistribute connected", # "delete protocols bgp redistribute connected", # "delete protocols bgp neighbor 5001::64", # "delete protocols bgp neighbor 203.0.113.5", # "delete protocols bgp neighbor 192.0.2.25", # "set protocols bgp neighbor 192.0.2.40 advertisement-interval 72", # "set protocols bgp neighbor 192.0.2.40 capability orf prefix-list receive", # "set protocols bgp redistribute static route-map map01", # "set protocols bgp network 203.0.113.0/24 route-map map01" # ], # Using deleted: # ------------- # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp system-as 65536 # set protocols bgp neighbor 192.0.2.40 advertisement-interval '72' # set protocols bgp neighbor 192.0.2.40 capability orf prefix-list 'receive' # set protocols bgp network 203.0.113.0/24 route-map 'map01' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ - name: Delete configuration vyos.vyos.vyos_vrrp: config: as_number: "65536" state: deleted # After state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp '65536' # vyos@vyos:~$ # # # Module Execution: # # "after": { # "as_number": 65536 # }, # "before": { # "as_number": 65536, # "bgp_params": { # "bestpath": { # "as_path": "confed" # } # }, # "neighbor": [ # { # "address": "192.0.2.40", # "advertisement_interval": 72, # "capability": { # "orf": "receive" # } # } # ], # "network": [ # { # "address": "203.0.113.0/24", # "route_map": "map01" # } # ], # "redistribute": [ # { # "protocol": "static", # "route_map": "map01" # } # ] # }, # "changed": true, # "commands": [ # "delete protocols bgp neighbor 192.0.2.40", # "delete protocols bgp redistribute", # "delete protocols bgp network", # "delete protocols bgp parameters" # ], # Using purged: # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp system-as 65536 # set protocols bgp aggregate-address 192.0.2.0/24 'summary-only' # set protocols bgp aggregate-address 203.0.113.0/24 'as-set' # set protocols bgp maximum-paths ebgp '20' # set protocols bgp maximum-paths ibgp '55' # set protocols bgp neighbor 192.0.2.25 'disable-connected-check' # set protocols bgp neighbor 192.0.2.25 timers holdtime '30' # set protocols bgp neighbor 192.0.2.25 timers keepalive '10' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'as-path' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'med' # set protocols bgp neighbor 203.0.113.5 attribute-unchanged 'next-hop' # set protocols bgp neighbor 203.0.113.5 ebgp-multihop '2' # set protocols bgp neighbor 203.0.113.5 remote-as '101' # set protocols bgp neighbor 203.0.113.5 update-source '192.0.2.25' # set protocols bgp neighbor 5001::64 distribute-list export '20' # set protocols bgp neighbor 5001::64 distribute-list import '40' # set protocols bgp neighbor 5001::64 maximum-prefix '34' # set protocols bgp network 192.1.13.0/24 'backdoor' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp parameters bestpath 'compare-routerid' # set protocols bgp parameters confederation identifier '66' # set protocols bgp parameters confederation peers '20' # set protocols bgp parameters confederation peers '55' # set protocols bgp parameters default 'no-ipv4-unicast' # set protocols bgp parameters router-id '192.1.2.9' # set protocols bgp redistribute connected route-map 'map01' # set protocols bgp redistribute kernel metric '45' # set protocols bgp timers keepalive '35' # vyos@vyos:~$ - name: Purge configuration vyos.vyos.vyos_vrrp: config: as_number: "65536" state: purged # After state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # vyos@vyos:~$ # # Module Execution: # # "after": {}, # "before": { # "aggregate_address": [ # { # "prefix": "192.0.2.0/24", # "summary_only": true # }, # { # "prefix": "203.0.113.0/24", # "as_set": true # } # ], # "as_number": 65536, # "bgp_params": { # "bestpath": { # "as_path": "confed", # "compare_routerid": true # }, # "confederation": [ # { # "identifier": 66 # }, # { # "peers": 20 # }, # { # "peers": 55 # } # ], # "default": { # "no_ipv4_unicast": true # }, # "router_id": "192.1.2.9" # }, # "maximum_paths": [ # { # "count": 20, # "path": "ebgp" # }, # { # "count": 55, # "path": "ibgp" # } # ], # "neighbor": [ # { # "address": "192.0.2.25", # "disable_connected_check": true, # "timers": { # "holdtime": 30, # "keepalive": 10 # } # }, # { # "address": "203.0.113.5", # "attribute_unchanged": { # "as_path": true, # "med": true, # "next_hop": true # }, # "ebgp_multihop": 2, # "remote_as": 101, # "update_source": "192.0.2.25" # }, # { # "address": "5001::64", # "distribute_list": [ # { # "acl": 20, # "action": "export" # }, # { # "acl": 40, # "action": "import" # } # ], # "maximum_prefix": 34 # } # ], # "network": [ # { # "address": "192.1.13.0/24", # "backdoor": true # } # ], # "redistribute": [ # { # "protocol": "connected", # "route_map": "map01" # }, # { # "metric": 45, # "protocol": "kernel" # } # ], # "timers": { # "keepalive": 35 # } # }, # "changed": true, # "commands": [ # "delete protocols bgp 65536" # ], # Deleted in presence of address family under neighbors: # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp system-as 65536 # set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' # set protocols bgp neighbor 192.0.2.43 capability 'dynamic' # set protocols bgp neighbor 192.0.2.43 'disable-connected-check' # set protocols bgp neighbor 192.0.2.43 timers holdtime '30' # set protocols bgp neighbor 192.0.2.43 timers keepalive '10' # set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' # set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' # set protocols bgp network 203.0.113.0/24 route-map 'map01' # set protocols bgp parameters 'always-compare-med' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp parameters bestpath 'compare-routerid' # set protocols bgp parameters dampening half-life '33' # set protocols bgp parameters dampening max-suppress-time '20' # set protocols bgp parameters dampening re-use '60' # set protocols bgp parameters dampening start-suppress-time '5' # set protocols bgp parameters default 'no-ipv4-unicast' # set protocols bgp parameters distance global external '66' # set protocols bgp parameters distance global internal '20' # set protocols bgp parameters distance global local '10' # set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ ^C # vyos@vyos:~$ - name: Delete configuration vyos.vyos.vyos_vrrp: config: as_number: "65536" state: deleted # Module Execution: # # "changed": false, # "invocation": { # "module_args": { # "config": { # "aggregate_address": null, # "as_number": 65536, # "bgp_params": null, # "maximum_paths": null, # "neighbor": null, # "network": null, # "redistribute": null, # "timers": null # }, # "running_config": null, # "state": "deleted" # } # }, # "msg": "Use the _bgp_address_family module to delete the address_family under neighbor 203.0.113.0, before replacing/deleting the neighbor." # } # using gathered: # -------------- # Before state: # vyos@vyos:~$ show configuration commands | match "set protocols bgp" # set protocols bgp system-as 65536 # set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' # set protocols bgp neighbor 192.0.2.43 capability 'dynamic' # set protocols bgp neighbor 192.0.2.43 'disable-connected-check' # set protocols bgp neighbor 192.0.2.43 timers holdtime '30' # set protocols bgp neighbor 192.0.2.43 timers keepalive '10' # set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' # set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' # set protocols bgp network 203.0.113.0/24 route-map 'map01' # set protocols bgp parameters 'always-compare-med' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp parameters bestpath 'compare-routerid' # set protocols bgp parameters dampening half-life '33' # set protocols bgp parameters dampening max-suppress-time '20' # set protocols bgp parameters dampening re-use '60' # set protocols bgp parameters dampening start-suppress-time '5' # set protocols bgp parameters default 'no-ipv4-unicast' # set protocols bgp parameters distance global external '66' # set protocols bgp parameters distance global internal '20' # set protocols bgp parameters distance global local '10' # set protocols bgp redistribute static route-map 'map01' # vyos@vyos:~$ ^C - name: gather configs vyos.vyos.vyos_vrrp: state: gathered # Module Execution: # "gathered": { # "as_number": 65536, # "bgp_params": { # "always_compare_med": true, # "bestpath": { # "as_path": "confed", # "compare_routerid": true # }, # "default": { # "no_ipv4_unicast": true # }, # "distance": [ # { # "type": "external", # "value": 66 # }, # { # "type": "internal", # "value": 20 # }, # { # "type": "local", # "value": 10 # } # ] # }, # "neighbor": [ # { # "address": "192.0.2.43", # "advertisement_interval": 72, # "capability": { # "dynamic": true # }, # "disable_connected_check": true, # "timers": { # "holdtime": 30, # "keepalive": 10 # } # }, # { # "address": "203.0.113.0", # "capability": { # "orf": "receive" # } # } # ], # "network": [ # { # "address": "203.0.113.0/24", # "route_map": "map01" # } # ], # "redistribute": [ # { # "protocol": "static", # "route_map": "map01" # } # ] # }, # # Using parsed: # ------------ # parsed.cfg # set protocols bgp neighbor 192.0.2.43 advertisement-interval '72' # set protocols bgp neighbor 192.0.2.43 capability 'dynamic' # set protocols bgp neighbor 192.0.2.43 'disable-connected-check' # set protocols bgp neighbor 192.0.2.43 timers holdtime '30' # set protocols bgp neighbor 192.0.2.43 timers keepalive '10' # set protocols bgp neighbor 203.0.113.0 address-family 'ipv6-unicast' # set protocols bgp neighbor 203.0.113.0 capability orf prefix-list 'receive' # set protocols bgp network 203.0.113.0/24 route-map 'map01' # set protocols bgp parameters 'always-compare-med' # set protocols bgp parameters bestpath as-path 'confed' # set protocols bgp parameters bestpath 'compare-routerid' # set protocols bgp parameters dampening half-life '33' # set protocols bgp parameters dampening max-suppress-time '20' # set protocols bgp parameters dampening re-use '60' # set protocols bgp parameters dampening start-suppress-time '5' # set protocols bgp parameters default 'no-ipv4-unicast' # set protocols bgp parameters distance global external '66' # set protocols bgp parameters distance global internal '20' # set protocols bgp parameters distance global local '10' # set protocols bgp redistribute static route-map 'map01' - name: parse configs vyos.vyos.vyos_vrrp: running_config: "{{ lookup('file', './parsed.cfg') }}" state: parsed tags: - parsed # Module execution: # "parsed": { # "as_number": 65536, # "bgp_params": { # "always_compare_med": true, # "bestpath": { # "as_path": "confed", # "compare_routerid": true # }, # "default": { # "no_ipv4_unicast": true # }, # "distance": [ # { # "type": "external", # "value": 66 # }, # { # "type": "internal", # "value": 20 # }, # { # "type": "local", # "value": 10 # } # ] # }, # "neighbor": [ # { # "address": "192.0.2.43", # "advertisement_interval": 72, # "capability": { # "dynamic": true # }, # "disable_connected_check": true, # "timers": { # "holdtime": 30, # "keepalive": 10 # } # }, # { # "address": "203.0.113.0", # "capability": { # "orf": "receive" # } # } # ], # "network": [ # { # "address": "203.0.113.0/24", # "route_map": "map01" # } # ], # "redistribute": [ # { # "protocol": "static", # "route_map": "map01" # } # ] # } # # Using rendered: # -------------- - name: Render vyos.vyos.vyos_vrrp: config: as_number: "65536" network: - address: "203.0.113.0/24" route_map: map01 redistribute: - protocol: "static" route_map: "map01" bgp_params: always_compare_med: true dampening: start_suppress_time: 5 max_suppress_time: 20 half_life: 33 re_use: 60 distance: - type: "internal" value: 20 - type: "local" value: 10 - type: "external" value: 66 bestpath: as_path: "confed" compare_routerid: true default: no_ipv4_unicast: true neighbor: - address: "192.0.2.43" disable_connected_check: true advertisement_interval: 72 capability: dynamic: true timers: holdtime: 30 keepalive: 10 - address: "203.0.113.0" capability: orf: "receive" state: rendered # Module Execution: # "rendered": [ # "set protocols bgp neighbor 192.0.2.43 disable-connected-check", # "set protocols bgp neighbor 192.0.2.43 advertisement-interval 72", # "set protocols bgp neighbor 192.0.2.43 capability dynamic", # "set protocols bgp neighbor 192.0.2.43 timers holdtime 30", # "set protocols bgp neighbor 192.0.2.43 timers keepalive 10", # "set protocols bgp neighbor 203.0.113.0 capability orf prefix-list receive", # "set protocols bgp redistribute static route-map map01", # "set protocols bgp network 203.0.113.0/24 route-map map01", # "set protocols bgp parameters always-compare-med", # "set protocols bgp parameters dampening half-life 33", # "set protocols bgp parameters dampening max-suppress-time 20", # "set protocols bgp parameters dampening re-use 60", # "set protocols bgp parameters dampening start-suppress-time 5", # "set protocols bgp parameters distance global internal 20", # "set protocols bgp parameters distance global local 10", # "set protocols bgp parameters distance global external 66", # "set protocols bgp parameters bestpath as-path confed", # "set protocols bgp parameters bestpath compare-routerid", # "set protocols bgp parameters default no-ipv4-unicast" # ] Return Values ------------- Common return values are documented `here `_, the following are the fields unique to this module: .. raw:: html
Key Returned Description
after
dictionary
when changed
The resulting configuration after module execution.

Sample:
This output will always be in the same format as the module argspec.
before
dictionary
when state is merged, replaced, overridden, deleted or purged
The configuration prior to the module execution.

Sample:
This output will always be in the same format as the module argspec.
commands
list
when state is merged, replaced, overridden, deleted or purged
The set of commands pushed to the remote device.

Sample:
['set protocols bgp redistribute static route-map map01', 'set protocols bgp network 203.0.113.0/24 route-map map01', 'set protocols bgp parameters always-compare-med']
gathered
list
when state is gathered
Facts about the network resource gathered from the remote device as structured data.

Sample:
This output will always be in the same format as the module argspec.
parsed
list
when state is parsed
The device native config provided in running_config option parsed into structured data as per module argspec.

Sample:
This output will always be in the same format as the module argspec.
rendered
list
when state is rendered
The provided configuration in the task rendered in device-native format (offline).

Sample:
['set protocols bgp redistribute static route-map map01', 'set protocols bgp network 203.0.113.0/24 route-map map01', 'set protocols bgp parameters always-compare-med']


Status ------ Authors ~~~~~~~ - Evgeny Molotkov (@omnom62) diff --git a/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py b/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py index 7e00a2f8..07ea64b1 100644 --- a/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py +++ b/plugins/module_utils/network/vyos/argspec/vrrp/vrrp.py @@ -1,191 +1,191 @@ # -*- coding: utf-8 -*- # Copyright 2024 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type ############################################# # WARNING # ############################################# # # This file is auto generated by the # cli_rm_builder. # # Manually editing this file is not advised. # # To update the argspec make the desired changes # in the module docstring and re-run # cli_rm_builder. # ############################################# """ The arg spec for the vyos_vrrp module """ class VrrpArgs(object): # pylint: disable=R0903 """The arg spec for the vyos_vrrp module""" argument_spec = { "config": { "type": "dict", "required": False, "options": { "disable": {"type": "bool", "default": False}, "virtual_servers": { "type": "list", "elements": "dict", "options": { - "alias": {"type": "str", "required": True}, + "name": {"type": "str", "required": True}, "address": {"type": "str"}, "algorithm": {"type": "str"}, "delay_loop": {"type": "int"}, "forward_method": {"type": "str", "choices": ["direct", "nat"]}, "fwmark": {"type": "str"}, "persistence_timeout": {"type": "str"}, "port": {"type": "int"}, "protocol": {"type": "str", "choices": ["tcp", "udp"]}, "real_servers": { "type": "list", "elements": "dict", "options": { "address": {"type": "str", "required": True}, "port": {"type": "int"}, "health_check_script": {"type": "str"}, }, }, }, }, "vrrp": { "type": "dict", "options": { "global_parameters": { "type": "dict", "options": { "garp": { "type": "dict", "options": { "interval": {"type": "int"}, "master_delay": {"type": "int"}, "master_refresh": {"type": "int"}, "master_refresh_repeat": {"type": "int"}, "master_repeat": {"type": "int"}, }, }, "startup_delay": {"type": "int"}, "version": {"type": "str"}, }, }, "groups": { "type": "list", "elements": "dict", "options": { "name": {"type": "str", "required": True}, "address": {"type": "str"}, "advertise_interval": {"type": "int"}, "authentication": { "type": "dict", "options": { "password": {"type": "str", "no_log": True}, "type": {"type": "str"}, }, }, "description": {"type": "str"}, "disable": {"type": "bool", "default": False}, "excluded_address": {"type": "str"}, "garp": { "type": "dict", "options": { "interval": {"type": "int"}, "master_delay": {"type": "int"}, "master_refresh": {"type": "int"}, "master_refresh_repeat": {"type": "int"}, "master_repeat": {"type": "int"}, }, }, "health_check": { "type": "dict", "options": { "failure_count": {"type": "int"}, "interval": {"type": "int"}, "ping": {"type": "str"}, "script": {"type": "str"}, }, }, "hello_source_address": {"type": "str"}, "interface": {"type": "str"}, "no_preempt": {"type": "bool"}, "peer_address": {"type": "str"}, "preempt_delay": {"type": "int"}, "priority": {"type": "int"}, "rfc3768_compatibility": {"type": "bool"}, "track": { "type": "dict", "options": { "exclude_vrrp_interface": {"type": "bool"}, "interface": {"type": "str"}, }, }, "transition_script": { "type": "dict", "options": { "backup": {"type": "str"}, "fault": {"type": "str"}, "master": {"type": "str"}, "stop": {"type": "str"}, }, }, "vrid": {"type": "int", "required": True}, }, }, "snmp": {"type": "bool"}, "sync_groups": { "type": "list", "elements": "dict", "options": { "name": {"type": "str", "required": True}, "health_check": { "type": "dict", "options": { "failure_count": {"type": "int"}, "interval": {"type": "int"}, "ping": {"type": "str"}, "script": {"type": "str"}, }, }, "member": {"type": "list", "elements": "str"}, "transition_script": { "type": "dict", "options": { "backup": {"type": "str"}, "fault": {"type": "str"}, "master": {"type": "str"}, "stop": {"type": "str"}, }, }, }, }, }, }, }, }, "state": { "type": "str", "choices": [ "deleted", "merged", "purged", "replaced", "gathered", "rendered", "parsed", ], "default": "merged", }, "running_config": {"type": "str"}, } # pylint: disable=C0301 diff --git a/plugins/module_utils/network/vyos/config/vrrp/vrrp.py b/plugins/module_utils/network/vyos/config/vrrp/vrrp.py index 14b077ca..eb0bac21 100644 --- a/plugins/module_utils/network/vyos/config/vrrp/vrrp.py +++ b/plugins/module_utils/network/vyos/config/vrrp/vrrp.py @@ -1,377 +1,395 @@ # # -*- coding: utf-8 -*- # Copyright 2021 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # from __future__ import absolute_import, division, print_function __metaclass__ = type """ The vyos_vrrp config file. It is in this file where the current configuration (as dict) is compared to the provided configuration (as dict) and the command set necessary to bring the current configuration to its desired end-state is created. """ from copy import deepcopy from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( ResourceModule, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import Facts from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.vrrp import ( VrrpTemplate, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import combine from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import ( LooseVersion, ) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version # from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( # dict_merge, # get_from_dict, # ) class Vrrp(ResourceModule): """ The vyos_vrrp config class """ def __init__(self, module): super(Vrrp, self).__init__( empty_fact_val={}, facts_module=Facts(module), module=module, resource="vrrp", tmplt=VrrpTemplate(), ) self.parsers = [ "disable", ] def _validate_template(self): version = get_os_version(self._module) if LooseVersion(version) >= LooseVersion("1.4"): self._tmplt = VrrpTemplate() else: self._module.fail_json(msg="VRRP is not supported in this version of VyOS") def parse(self): """override parse to check template""" self._validate_template() return super().parse() def get_parser(self, name): """get_parsers""" self._validate_template() return super().get_parser(name) def execute_module(self): """Execute the module :rtype: A dictionary :returns: The result from module execution """ if self.state not in ["parsed", "gathered"]: self.generate_commands() self.run_commands() return self.result def generate_commands(self): """Generate configuration commands to send based on want, have and desired state. """ wantd = {} haved = {} wantd = deepcopy(self.want) haved = deepcopy(self.have) for entry in wantd, haved: # self._module.fail_json(msg="Before normalize_vrrp_groups - entry: " + str(entry)) self._vrrp_groups_list_to_dict(entry) self._virtual_servers_list_to_dict(entry) # self._module.fail_json(msg="Normalise - want: " + str(wantd) + " (((()))) have: " + str(haved)) # if state is merged, merge want onto have and then compare if self.state in ["merged"]: wantd = combine(haved, wantd, recursive=True) # self._module.fail_json(msg="Want: " + str(wantd) + "**** H: " + str(haved)) # if state is deleted, delete and empty out wantd # if self.state == "deleted": # w = deepcopy(wantd) # if w == {} and haved != {}: # self.commands = ["delete vrrp"] # return # for k, want in w.items(): # if not (k in haved and haved[k]): # del wantd[k] # else: # if isinstance(want, list): # for entry in want: # wname = entry.get("name") # haved["instances"] = [ # i for i in haved.get("instances", []) if i.get("name") != wname # ] # self.commands.append("delete vrrp name {}".format(wname)) # else: # self.commands.append("delete vrrp {}".format(k.replace("_", "-"))) # del wantd[k] # # if self.state == "overridden": # w = deepcopy(wantd) # h = deepcopy(haved) # for k, want in w.items(): # if k in haved anzd haved[k] != want: # if isinstance(want, list): # for entry in want: # wname = entry.get("name") # hdict = next( # (inst for inst in haved["instances"] if inst["name"] == wname), # None, # ) # if entry != hdict: # # self._module.fail_json(msg="Want: " + str(entry) + "**** H: " + str(hdict)) # haved["instances"] = [ # i for i in haved.get("instances", []) if i.get("name") != wname # ] # self.commands.append("delete vrrp name {}".format(wname)) # self.commands.append("commit") # for k, want in wantd.items(): if k == "vrrp": self._compare_vrrp(want, haved.get(k, {})) if k == "virtual_servers": # self._module.fail_json(msg="VSERVERS: " + str(want) + " ---- " + str(haved.get(k, {}))) self._compare_vsrvs(want, haved.get(k, {})) # self._module.fail_json(msg=str(want) + " +++ " + str(haved.pop(k, {}))) self.compare( parsers=self.parsers, want={k: want}, have={k: haved.pop(k, {})}, ) self._module.fail_json(msg=self.commands) def _compare_vsrvs(self, want, have): """Compare virtual servers of VRRP.py""" vs_parsers = [ - "virtual_servers", - # "virtual_servers.real_servers", + # "virtual_servers", + "virtual_servers.real_servers", ] + # test = { + # "virtual_servers": { + # "name": "s2", + # "real_servers": { + # "10.10.10.2": { + # "name": "10.10.10.2", + # "port": 443 + # } + # } + # } + # } + # self._module.fail_json(msg=self.extract_named_leafs(test)) + # self._module.fail_json(msg=self.extract_leaf_items({"virtual_servers": want})) + # self._module.fail_json(msg=self.extract_leaf_items(test)) + # for vs in self.extract_named_leafs(want): + # self._module.fail_json(msg="virtual_server: " + str(vs)) + want = { + "name": "s1", + "real_servers": {"10.10.10.2": {"address": "10.10.10.2", "port": 443}}, + } + # self._module.fail_json(msg="want: " + str(want) + "**** have: " + str(have)) self.compare( parsers=vs_parsers, want={"virtual_servers": want}, - have={"virtual_servers": have}, + have={"virtual_servers": {}}, ) def _compare_vrrp(self, want, have): """Compare the instances of VRRP""" vrrp_parsers = [ "vrrp.snmp", - # "vrrp.sync_groups.member", - # "vrrp.sync_groups.health_check", - # "vrrp.sync_groups.transition_script", "vrrp.global_parameters.garp", "vrrp.global_parameters", - "vrrp.groups.garp", "vrrp.groups", - # "vrrp.group.aunthentication", - # "vrrp.group.transition_script", - # "vrrp.groups.health_check", - # "vrrp.group.track", - # "vrrp.group.transition_script", + "vrrp.groups.garp", + "vrrp.groups.authentication", + "vrrp.groups.transition_script", + "vrrp.groups.health_check", + "vrrp.groups.track", + # "vrrp.groups.excluded_addresses", ] - # self._module.fail_json(msg="Conf: " + str(want) + " <*****************> " + str(have)) - - for wvrrp in self.extract_leaf_items(want): - self._module.fail_json(msg="WV: " + str(wvrrp)) - - # "vrrp": { - # "groups": { - # "name": "g2", - # "interface": "eth1", - # "address": "2.2.2.2", - # "disable": False, - # "no_preempt": False, - # "vrid": 11, - # "garp": { - # "interval": 21, - # "master_delay": 6, - # "master_refresh": 51, - # "master_refresh_repeat": 101, - # "master_repeat": 4, - # }, + # self._module.fail_json(msg="Want: " + str(want) + "**** have: " + str(have)) + # self._module.fail_json(msg=self.extract_leaf_items(want)) + # want = { + # "groups": { + # "transition_script": { + # "stop": "/config/scripts/vrrp_stop.sh" # }, - # }, + # "name": "g1" + # } # } - - # have = { - # "vrrp": { - # "groups": { - # "name": "g2", - # "interface": "eth1", - # "address": "2.2.2.2", - # "disable": False, - # "no_preempt": False, - # "vrid": 11, - # "garp": { - # "interval": 22, - # "master_delay": 6, - # "master_refresh": 51, - # "master_refresh_repeat": 101, - # "master_repeat": 4, - # }, - # }, - # }, - # } - # want = { - # "vrrp": { - # "groups": { - # "name": "g2", - # "garp": { - # "interval": 21, - # }, - # }, - # }, - # } - - # have = { - # "vrrp": { - # "groups": { - # "name": "g2", - # "garp": { - # "interval": 22, - # }, - # }, - # }, - # } - - want = { - "vrrp": { - "global_parameters": { - "garp": { - "interval": 32, - }, - }, - }, - } - have = { - "vrrp": { - "global_parameters": { - "garp": { - "interval": 31, - }, - }, - }, - } - - self.compare(parsers=vrrp_parsers, want=want, have=have) + # self.compare(parsers=vrrp_parsers, want={"vrrp": want}, have={"vrrp": {}}) + for pair in self.extract_leaf_items(want): + self.compare(parsers=vrrp_parsers, want={"vrrp": pair}, have={"vrrp": {}}) # self.compare(parsers=vrrp_parsers, want={"vrrp": want}, have={"vrrp": have}) def _vrrp_groups_list_to_dict(self, data): vrrp = data.get("vrrp", {}) groups = vrrp.get("groups") # Nothing to do if not groups: return data # Already dict-based if isinstance(groups, dict): return data # Must be list → convert it if isinstance(groups, list): new_groups = {} for item in groups: name = item.get("name") if not name: continue new_groups[name] = item data["vrrp"]["groups"] = new_groups return data # Unexpected shape → leave as-is return data def _virtual_servers_list_to_dict(self, data): vss = data.get("virtual_servers") if not vss: return data # Already normalized dict → return untouched if isinstance(vss, dict): return data # List → convert if isinstance(vss, list): new_vss = {} for item in vss: # Skip non-dict items if not isinstance(item, dict): continue - alias = item.get("alias") + alias = item.get("name") if not alias: continue new_vss[alias] = item data["virtual_servers"] = new_vss return data # Anything else → leave unchanged return data + # def extract_leaf_items(self, data, path=None, parent_name=None): + # """ + # Recursively extract leaf items from a nested dict. + # - If a dict has a 'name', include it in each output. + # - Only emit leaves that are not 'name' itself. + # - Returns a list of one-leaf nested dicts. + # """ + # path = path or [] + # results = [] + + # if isinstance(data, dict): + # current_name = data.get("name", parent_name) + + # for k, v in data.items(): + # if k == "name": + # continue + # results.extend(self.extract_leaf_items(v, path + [k], current_name)) + # return results + + # # ----- LEAF ----- + # leaf_key = path[-1] + # top_key = path[0] + + # # Build only the required nesting (skip top_key and name-holder) + # subkeys = path[2:] # e.g. ['garp','interval'] or ['master_repeat'] + + # # base leaf: do NOT wrap leaf again + # nested = {leaf_key: data} + + # # wrap parents except leaf_key + # for p in reversed(subkeys[:-1]): # all except the leaf + # nested = {p: nested} + + # # top-level wrap + # if parent_name: + # out = {top_key: {"name": parent_name}} + # out[top_key].update(nested) + # else: + # out = {top_key: nested} + + # results.append(out) + # return results + def extract_leaf_items(self, data, path=None, parent_name=None): """ Recursively extract leaf items from a nested dict. - If a dict has a 'name', include it in each output. - Only emit leaves that are not 'name' itself. - Returns a list of one-leaf nested dicts. """ path = path or [] results = [] if isinstance(data, dict): current_name = data.get("name", parent_name) + for k, v in data.items(): if k == "name": continue results.extend(self.extract_leaf_items(v, path + [k], current_name)) + return results + + # ---------------- LEAF CASE ---------------- + leaf_key = path[-1] # e.g. "type" + top_key = path[0] # e.g. "groups" + + # keys after the name-holder: + # groups → g1 → authentication → type → subkeys = ['authentication','type'] + subkeys = path[2:] + + # base leaf (NO extra wrapper) + nested = {leaf_key: data} + + # wrap all parents except the leaf key + for p in reversed(subkeys[:-1]): # keep only intermediate keys + nested = {p: nested} + + # add top-level + if parent_name: + out = {top_key: {"name": parent_name}} + out[top_key].update(nested) else: - # leaf node - leaf_key = path[-1] - top_key = path[0] - - if parent_name is not None: - # parent has a name → include it - out = {top_key: {"name": parent_name, leaf_key: data}} - else: - # generic leaf - leaf = {leaf_key: data} - for p in reversed(path[:-1]): - leaf = {p: leaf} - out = leaf - - results.append(out) + out = {top_key: nested} + results.append(out) return results + + def extract_named_leafs(self, data, parent_name=None, prefix_key=None): + results = [] + + if isinstance(data, dict): + current_name = data.get("name", parent_name) + + for k, v in data.items(): + if k == "name": + continue + + # recurse + leaves = self.extract_named_leafs(v, current_name, k) + results.extend(leaves) + + return results + + # leaf value reached + item = {"name": parent_name, prefix_key: data} + return [item] diff --git a/plugins/module_utils/network/vyos/rm_templates/vrrp.py b/plugins/module_utils/network/vyos/rm_templates/vrrp.py index db768fea..67da9db9 100644 --- a/plugins/module_utils/network/vyos/rm_templates/vrrp.py +++ b/plugins/module_utils/network/vyos/rm_templates/vrrp.py @@ -1,743 +1,706 @@ # -*- coding: utf-8 -*- # Copyright 2021 Red Hat # GNU General Public License v3.0+ # (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type """ -The Bgp_global parser templates file. This contains +The Vrrp parser templates file. This contains a list of parser definitions and associated functions that facilitates both facts gathering and native command generation for the given network resource. """ import re -# from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( NetworkTemplate, ) -# def _tmplt_vsrvs(config_data): -# config_data = config_data["virtual_servers"] -# command = [] -# cmd = "high-availability virtual-server".format(**config_data) -# command = [str(cmd)] -# # if "mode" in config_data: -# # mode_cmd = cmd + " mode {mode}".format(**config_data) -# # command.append(mode_cmd) -# # if "seclevel" in config_data: -# # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) -# # command.append(sec_cmd) -# # if "view" in config_data: -# # view_cmd = cmd + " view {view}".format(**config_data) -# # command.append(view_cmd) -# return command - - def _tmplt_vsrvs(config_data): vs = config_data["virtual_servers"] command = [] - for alias, item in vs.items(): - cmd = f"set high-availability virtual-server {alias}" + for name, item in vs.items(): + cmd = f"set high-availability virtual-server {name}" for key, value in item.items(): - if key == "alias" or isinstance(value, list) or value is None: + if key == "name" or isinstance(value, list) or value is None: continue command.append(f"{cmd} {key.replace('_', '-')} {value}") return command def _tmplt_vsrvs_rsrv(config_data): - config_data = config_data["virtual_servers"]["real_servers"] - command = [] + config_data = config_data["virtual_servers"] + command = ["test"] # cmd = "service snmp v3 group {group}".format(**config_data) # if "mode" in config_data: # mode_cmd = cmd + " mode {mode}".format(**config_data) # command.append(mode_cmd) # if "seclevel" in config_data: # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) # command.append(sec_cmd) # if "view" in config_data: # view_cmd = cmd + " view {view}".format(**config_data) # command.append(view_cmd) return command def _tmplt_sgroup_hc(config_data): config_data = config_data["sync-group"]["health-check"] command = [] cmd = "high-availability vrrp sync-group health-check {health_check}".format(**config_data) if "failure_count" in config_data: failure_count_cmd = cmd + " failure-count {failure_count}".format(**config_data) command.append(failure_count_cmd) if "interval" in config_data: interval_cmd = cmd + " interval {interval}".format(**config_data) command.append(interval_cmd) if "ping" in config_data: ping_cmd = cmd + " ping {ping}".format(**config_data) command.append(ping_cmd) if "script" in config_data: script_cmd = cmd + " script {script}".format(**config_data) command.append(script_cmd) return command def _tmplt_sgroup_ts(config_data): config_data = config_data["sync-group"]["transition-script"] command = [] cmd = "high-availability vrrp sync-group transition-script {transition_script}".format( **config_data, ) if "backup" in config_data: backup_cmd = cmd + " backup {backup}".format(**config_data) command.append(backup_cmd) if "fault" in config_data: fault_cmd = cmd + " fault {fault}".format(**config_data) command.append(fault_cmd) if "master" in config_data: master_cmd = cmd + " master {master}".format(**config_data) command.append(master_cmd) if "stop" in config_data: stop_cmd = cmd + " stop {stop}".format(**config_data) command.append(stop_cmd) return command def _tmplt_vrrp_gp(config_data): config_data = config_data["vrrp"]["global_parameters"] command = [] cmd = "high-availability vrrp global-parameters" if "version" in config_data: version_cmd = cmd + " version {version}".format(**config_data) command.append(version_cmd) if "startup_delay" in config_data: startup_delay_cmd = cmd + " startup-delay {startup_delay}".format(**config_data) command.append(startup_delay_cmd) return command def _tmplt_vrrp_gp_garp(config_data): config_data = config_data["vrrp"]["global_parameters"]["garp"] command = [] cmd = "high-availability vrrp global-parameters garp" if "interval" in config_data: interval_cmd = cmd + " interval {interval}".format(**config_data) command.append(interval_cmd) if "master_delay" in config_data: master_delay_cmd = cmd + " master-delay {master_delay}".format(**config_data) command.append(master_delay_cmd) if "master_refresh" in config_data: master_refresh_cmd = cmd + " master-refresh {master_refresh}".format(**config_data) command.append(master_refresh_cmd) if "master_refresh_repeat" in config_data: master_refresh_repeat_cmd = cmd + " master-refresh-repeat {master_refresh_repeat}".format( **config_data, ) command.append(master_refresh_repeat_cmd) if "master_repeat" in config_data: master_repeat_cmd = cmd + " master-repeat {master_repeat}".format(**config_data) command.append(master_repeat_cmd) return command def _tmplt_vrrp_group(config_data): config_data = config_data["vrrp"]["groups"] command = [] cmd = "high-availability vrrp group {name}".format(**config_data) for key, value in config_data.items(): if key == "name" or isinstance(value, dict) or value is None: continue if isinstance(value, bool) and value is not None: command.append(f"{cmd} {key.replace('_', '-')}") command.append(f"{cmd} {key.replace('_', '-')} {value}") return command def _tmplt_vrrp_group_garp(config_data): config_data = config_data["vrrp"]["groups"] command = [] cmd = "high-availability vrrp group {name}".format(**config_data) config_data = config_data["garp"] for key, value in config_data.items(): if value is not None: command.append(cmd + " garp " + f"{key.replace('_', '-')} {value}") return command def _tmplt_vrrp_group_auth(config_data): - config_data = config_data["vrrp"]["group"] + config_data = config_data["vrrp"]["groups"] command = [] cmd = "high-availability vrrp group {name}".format(**config_data) config_data = config_data["authentication"] for key, value in config_data.items(): if value is not None: command.append(cmd + " authentication " + f"{key.replace('_', '-')} {value}") return command -def _tmplt_vrrp_group_track(config_data): - config_data = config_data["vrrp"]["group"]["track"] +def _tmplt_vrrp_group_ts(config_data): + config_data = config_data["vrrp"]["groups"] command = [] - # cmd = "service snmp v3 group {group}".format(**config_data) - # if "mode" in config_data: - # mode_cmd = cmd + " mode {mode}".format(**config_data) - # command.append(mode_cmd) - # if "seclevel" in config_data: - # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) - # command.append(sec_cmd) - # if "view" in config_data: - # view_cmd = cmd + " view {view}".format(**config_data) - # command.append(view_cmd) + cmd = "high-availability vrrp group {name}".format(**config_data) + config_data = config_data["transition_script"] + for key, value in config_data.items(): + if value is not None: + command.append(cmd + " transition-script " + f"{key.replace('_', '-')} {value}") return command def _tmplt_vrrp_group_hc(config_data): - config_data = config_data["vrrp"]["group"]["health-check"] + config_data = config_data["vrrp"]["groups"] command = [] - # cmd = "service snmp v3 group {group}".format(**config_data) - # if "mode" in config_data: - # mode_cmd = cmd + " mode {mode}".format(**config_data) - # command.append(mode_cmd) - # if "seclevel" in config_data: - # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) - # command.append(sec_cmd) - # if "view" in config_data: - # view_cmd = cmd + " view {view}".format(**config_data) - # command.append(view_cmd) + cmd = "high-availability vrrp group {name}".format(**config_data) + config_data = config_data["health_check"] + for key, value in config_data.items(): + if value is not None: + command.append(cmd + " health-check " + f"{key.replace('_', '-')} {value}") return command -def _tmplt_vrrp_group_ts(config_data): - config_data = config_data["vrrp"]["group"]["transcription-script"] +def _tmplt_vrrp_group_track(config_data): + config_data = config_data["vrrp"]["groups"] command = [] - # cmd = "service snmp v3 group {group}".format(**config_data) - # if "mode" in config_data: - # mode_cmd = cmd + " mode {mode}".format(**config_data) - # command.append(mode_cmd) - # if "seclevel" in config_data: - # sec_cmd = cmd + " seclevel {seclevel}".format(**config_data) - # command.append(sec_cmd) - # if "view" in config_data: - # view_cmd = cmd + " view {view}".format(**config_data) - # command.append(view_cmd) + cmd = "high-availability vrrp group {name}".format(**config_data) + config_data = config_data["track"] + for key, value in config_data.items(): + if value is not None: + command.append(cmd + " track " + f"{key.replace('_', '-')} {value}") return command class VrrpTemplate(NetworkTemplate): def __init__(self, lines=None, module=None): prefix = {"set": "set", "remove": "delete"} super(VrrpTemplate, self).__init__( lines=lines, tmplt=self, prefix=prefix, module=module, ) # fmt: off PARSERS = [ { "name": "disable", "getval": re.compile( r""" ^set \shigh-availability \s(?Pdisable) $""", re.VERBOSE, ), "setval": "high-availability disable", "result": { "disable": "{{ True if disable is defined }}", }, }, { "name": "virtual_servers", "getval": re.compile( r""" ^set\shigh-availability\svirtual-server - \s+(?P\S+) + \s+(?P\S+) (?:\s+address\s+(?P
\S+))? (?:\s+algorithm\s+(?P\S+))? (?:\s+delay-loop\s+(?P\S+))? (?:\s+forward-method\s+(?P\S+))? (?:\s+fwmark\s+(?P\S+))? (?:\s+persistence-timeout\s+(?P\S+))? (?:\s+port\s+(?P\S+))? (?:\s+protocol\s+(?P\S+))? $ """, re.VERBOSE, ), "setval": _tmplt_vsrvs, - # "setval": "virtual-server", "result": { "virtual_servers": { - "{{ alias }}": { - "alias": "{{ alias }}", + "{{ name }}": { + "name": "{{ name }}", "address": "{{ address if address is defined else None }}", "algorithm": "{{ algorithm if algorithm is defined else None }}", "delay_loop": "{{ delay_loop if delay_loop is defined else None }}", "forward_method": "{{ forward_method if forward_method is defined else None }}", "fwmark": "{{ fwmark if fwmark is defined else None }}", "persistence_timeout": "{{ persistence_timeout if persistence_timeout is defined else None }}", "port": "{{ port if port is defined else None }}", "protocol": "{{ protocol if protocol is defined else None }}", }, }, }, }, { "name": "virtual_servers.real_servers", "getval": re.compile( r""" ^set\shigh-availability\svirtual-server - \s+(?P\S+) + \s+(?P\S+) \sreal-server \s+(?P
\S+) (?:\s+port\s+(?P\S+))? (?:\s+health-check\sscript\s+(?P\S+))? (?:\s+connection-timeout\s+(?P\S+))? $ """, re.VERBOSE, ), "setval": _tmplt_vsrvs_rsrv, # "compval": "global_parameters.garp.master_refersh_repeat", "result": { "virtual_servers": { - "{{ alias }}": { - "alias": "{{ alias }}", + "{{ name }}": { + "name": "{{ name }}", "real_servers": { "{{ address }}": { "address": "{{ address }}", "port": "{{ port if port is defined else None }}", "health_check_script": "{{ hcscript if hcscript is defined else None }}", "connection_timeout": "{{ cont if cont is defined else None }}", }, }, }, }, }, }, # { # "name": "vrrp.sync_groups.member", # "getval": re.compile( # r""" # ^set\shigh-availability\svrrp\ssync-group # \s+(?P\S+) # \smember # \s+(?P\S+) # $ # """, # re.VERBOSE, # ), # "setval": "set high-availability vrrp sync-group {{sgname}} member {{member}}", # "result": { # "vrrp": { # "sync_groups": { # "{{ sgname }}": { # "name": "{{ sgname }}", # "member": [ # "{{ member }}" # ], # }, # }, # }, # }, # }, # { # "name": "vrrp.sync_groups.member", # "getval": re.compile( # r""" # ^set\shigh-availability\svrrp\ssync-group # \s+(?P\S+) # \smember # \s+(?P\S+) # $ # """, # re.VERBOSE, # ), # "setval": "set high-availability vrrp sync-group {{sgname}} member {{member}}", # "result": { # "vrrp": { # "sync_groups": [ # { # "name": "{{ sgname }}", # "member": ["{{ member }}"], # }, # ], # }, # }, # }, { "name": "vrrp.sync_groups.health_check", "getval": re.compile( r""" ^set\shigh-availability\svrrp\ssync-group \s+(?P\S+) \shealth-check (?:\s+failure-count\s+(?P\S+)) ?(?:\s+interval\s+(?P\S+)) ?(?:\s+ping\s+(?P\S+)) ?(?:\s+script\s+(?P