1#!/usr/bin/python
2#
3# This file is part of Ansible
4#
5# Ansible is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ansible is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17#
18
19ANSIBLE_METADATA = {'metadata_version': '1.1',
20                    'status': ['preview'],
21                    'supported_by': 'community'}
22
23DOCUMENTATION = '''
24---
25module: ce_bgp_af
26version_added: "2.4"
27short_description: Manages BGP Address-family configuration on HUAWEI CloudEngine switches.
28description:
29    - Manages BGP Address-family configurations on HUAWEI CloudEngine switches.
30author:
31    - wangdezhuang (@QijunPan)
32notes:
33  - This module requires the netconf system service be enabled on the remote device being managed.
34  - Recommended connection is C(netconf).
35  - This module also works with C(local) connections for legacy playbooks.
36options:
37    state:
38        description:
39            - Specify desired state of the resource.
40        default: present
41        choices: ['present','absent']
42    vrf_name:
43        description:
44            - Name of a BGP instance. The name is a case-sensitive string of characters.
45              The BGP instance can be used only after the corresponding VPN instance is created.
46              The value is a string of 1 to 31 case-sensitive characters.
47        required: true
48    af_type:
49        description:
50            - Address family type of a BGP instance.
51        required: true
52        choices: ['ipv4uni','ipv4multi', 'ipv4vpn', 'ipv6uni', 'ipv6vpn', 'evpn']
53    max_load_ibgp_num:
54        description:
55            - Specify the maximum number of equal-cost IBGP routes.
56              The value is an integer ranging from 1 to 65535.
57    ibgp_ecmp_nexthop_changed:
58        description:
59            - If the value is true, the next hop of an advertised route is changed to the advertiser itself in IBGP
60              load-balancing scenarios.
61              If the value is false, the next hop of an advertised route is not changed to the advertiser itself in
62              IBGP load-balancing scenarios.
63        choices: ['no_use','true','false']
64        default: no_use
65    max_load_ebgp_num:
66        description:
67            - Specify the maximum number of equal-cost EBGP routes.
68              The value is an integer ranging from 1 to 65535.
69    ebgp_ecmp_nexthop_changed:
70        description:
71            - If the value is true, the next hop of an advertised route is changed to the advertiser itself in EBGP
72              load-balancing scenarios.
73              If the value is false, the next hop of an advertised route is not changed to the advertiser itself in
74              EBGP load-balancing scenarios.
75        choices: ['no_use','true','false']
76        default: no_use
77    maximum_load_balance:
78        description:
79            - Specify the maximum number of equal-cost routes in the BGP routing table.
80              The value is an integer ranging from 1 to 65535.
81    ecmp_nexthop_changed:
82        description:
83            - If the value is true, the next hop of an advertised route is changed to the advertiser itself in BGP
84              load-balancing scenarios.
85              If the value is false, the next hop of an advertised route is not changed to the advertiser itself
86              in BGP load-balancing scenarios.
87        choices: ['no_use','true','false']
88        default: no_use
89    default_local_pref:
90        description:
91            - Set the Local-Preference attribute. The value is an integer.
92              The value is an integer ranging from 0 to 4294967295.
93    default_med:
94        description:
95            - Specify the Multi-Exit-Discriminator (MED) of BGP routes.
96              The value is an integer ranging from 0 to 4294967295.
97    default_rt_import_enable:
98        description:
99            - If the value is true, importing default routes to the BGP routing table is allowed.
100              If the value is false, importing default routes to the BGP routing table is not allowed.
101        choices: ['no_use','true','false']
102        default: no_use
103    router_id:
104        description:
105            - ID of a router that is in IPv4 address format.
106              The value is a string of 0 to 255 characters.
107              The value is in dotted decimal notation.
108    vrf_rid_auto_sel:
109        description:
110            - If the value is true, VPN BGP instances are enabled to automatically select router IDs.
111              If the value is false, VPN BGP instances are disabled from automatically selecting router IDs.
112        choices: ['no_use','true','false']
113        default: no_use
114    nexthop_third_party:
115        description:
116            - If the value is true, the third-party next hop function is enabled.
117              If the value is false, the third-party next hop function is disabled.
118        choices: ['no_use','true','false']
119        default: no_use
120    summary_automatic:
121        description:
122            - If the value is true, automatic aggregation is enabled for locally imported routes.
123              If the value is false, automatic aggregation is disabled for locally imported routes.
124        choices: ['no_use','true','false']
125        default: no_use
126    auto_frr_enable:
127        description:
128            - If the value is true, BGP auto FRR is enabled.
129              If the value is false, BGP auto FRR is disabled.
130        choices: ['no_use','true','false']
131        default: no_use
132    load_balancing_as_path_ignore:
133        description:
134            - Load balancing as path ignore.
135        choices: ['no_use','true','false']
136        default: no_use
137    rib_only_enable:
138        description:
139            - If the value is true, BGP routes cannot be advertised to the IP routing table.
140              If the value is false, Routes preferred by BGP are advertised to the IP routing table.
141        choices: ['no_use','true','false']
142        default: no_use
143    rib_only_policy_name:
144        description:
145            - Specify the name of a routing policy.
146              The value is a string of 1 to 40 characters.
147    active_route_advertise:
148        description:
149            - If the value is true, BGP is enabled to advertise only optimal routes in the RM to peers.
150              If the value is false, BGP is not enabled to advertise only optimal routes in the RM to peers.
151        choices: ['no_use','true','false']
152        default: no_use
153    as_path_neglect:
154        description:
155            - If the value is true, the AS path attribute is ignored when BGP selects an optimal route.
156              If the value is false, the AS path attribute is not ignored when BGP selects an optimal route.
157              An AS path with a smaller length has a higher priority.
158        choices: ['no_use','true','false']
159        default: no_use
160    med_none_as_maximum:
161        description:
162            - If the value is true, when BGP selects an optimal route, the system uses 4294967295 as the
163              MED value of a route if the route's attribute does not carry a MED value.
164              If the value is false, the system uses 0 as the MED value of a route if the route's attribute
165              does not carry a MED value.
166        choices: ['no_use','true','false']
167        default: no_use
168    router_id_neglect:
169        description:
170            - If the value is true, the router ID attribute is ignored when BGP selects the optimal route.
171              If the value is false, the router ID attribute is not ignored when BGP selects the optimal route.
172        choices: ['no_use','true','false']
173        default: no_use
174    igp_metric_ignore:
175        description:
176            - If the value is true, the metrics of next-hop IGP routes are not compared when BGP selects
177              an optimal route.
178              If the value is false, the metrics of next-hop IGP routes are not compared when BGP selects
179              an optimal route.
180              A route with a smaller metric has a higher priority.
181        choices: ['no_use','true','false']
182        default: no_use
183    always_compare_med:
184        description:
185            - If the value is true, the MEDs of routes learned from peers in different autonomous systems
186              are compared when BGP selects an optimal route.
187              If the value is false, the MEDs of routes learned from peers in different autonomous systems
188              are not compared when BGP selects an optimal route.
189        choices: ['no_use','true','false']
190        default: no_use
191    determin_med:
192        description:
193            - If the value is true, BGP deterministic-MED is enabled.
194              If the value is false, BGP deterministic-MED is disabled.
195        choices: ['no_use','true','false']
196        default: no_use
197    preference_external:
198        description:
199            - Set the protocol priority of EBGP routes.
200              The value is an integer ranging from 1 to 255.
201    preference_internal:
202        description:
203            - Set the protocol priority of IBGP routes.
204              The value is an integer ranging from 1 to 255.
205    preference_local:
206        description:
207            - Set the protocol priority of a local BGP route.
208              The value is an integer ranging from 1 to 255.
209    prefrence_policy_name:
210        description:
211            - Set a routing policy to filter routes so that a configured priority is applied to
212              the routes that match the specified policy.
213              The value is a string of 1 to 40 characters.
214    reflect_between_client:
215        description:
216            - If the value is true, route reflection is enabled between clients.
217              If the value is false, route reflection is disabled between clients.
218        choices: ['no_use','true','false']
219        default: no_use
220    reflector_cluster_id:
221        description:
222            - Set a cluster ID. Configuring multiple RRs in a cluster can enhance the stability of the network.
223              The value is an integer ranging from 1 to 4294967295.
224    reflector_cluster_ipv4:
225        description:
226            - Set a cluster ipv4 address. The value is expressed in the format of an IPv4 address.
227    rr_filter_number:
228        description:
229            - Set the number of the extended community filter supported by an RR group.
230              The value is a string of 1 to 51 characters.
231    policy_vpn_target:
232        description:
233            - If the value is true, VPN-Target filtering function is performed for received VPN routes.
234              If the value is false, VPN-Target filtering function is not performed for received VPN routes.
235        choices: ['no_use','true','false']
236        default: no_use
237    next_hop_sel_depend_type:
238        description:
239            - Next hop select depend type.
240        choices: ['default','dependTunnel', 'dependIp']
241        default: default
242    nhp_relay_route_policy_name:
243        description:
244            - Specify the name of a route-policy for route iteration.
245              The value is a string of 1 to 40 characters.
246    ebgp_if_sensitive:
247        description:
248            - If the value is true, after the fast EBGP interface awareness function is enabled,
249              EBGP sessions on an interface are deleted immediately when the interface goes Down.
250              If the value is false, after the fast EBGP interface awareness function is enabled,
251              EBGP sessions on an interface are not deleted immediately when the interface goes Down.
252        choices: ['no_use','true','false']
253        default: no_use
254    reflect_chg_path:
255        description:
256            - If the value is true, the route reflector is enabled to modify route path attributes
257              based on an export policy.
258              If the value is false, the route reflector is disabled from modifying route path attributes
259              based on an export policy.
260        choices: ['no_use','true','false']
261        default: no_use
262    add_path_sel_num:
263        description:
264            - Number of Add-Path routes.
265              The value is an integer ranging from 2 to 64.
266    route_sel_delay:
267        description:
268            - Route selection delay.
269              The value is an integer ranging from 0 to 3600.
270    allow_invalid_as:
271        description:
272            - Allow routes with BGP origin AS validation result Invalid to be selected.
273              If the value is true, invalid routes can participate in route selection.
274              If the value is false, invalid routes cannot participate in route selection.
275        choices: ['no_use','true','false']
276        default: no_use
277    policy_ext_comm_enable:
278        description:
279            - If the value is true, modifying extended community attributes is allowed.
280              If the value is false, modifying extended community attributes is not allowed.
281        choices: ['no_use','true','false']
282        default: no_use
283    supernet_uni_adv:
284        description:
285            - If the value is true, the function to advertise supernetwork unicast routes is enabled.
286              If the value is false, the function to advertise supernetwork unicast routes is disabled.
287        choices: ['no_use','true','false']
288        default: no_use
289    supernet_label_adv:
290        description:
291            - If the value is true, the function to advertise supernetwork label is enabled.
292              If the value is false, the function to advertise supernetwork label is disabled.
293        choices: ['no_use','true','false']
294        default: no_use
295    ingress_lsp_policy_name:
296        description:
297            - Ingress lsp policy name.
298    originator_prior:
299        description:
300            - Originator prior.
301        choices: ['no_use','true','false']
302        default: no_use
303    lowest_priority:
304        description:
305            - If the value is true, enable reduce priority to advertise route.
306              If the value is false, disable reduce priority to advertise route.
307        choices: ['no_use','true','false']
308        default: no_use
309    relay_delay_enable:
310        description:
311            - If the value is true, relay delay enable.
312              If the value is false, relay delay disable.
313        choices: ['no_use','true','false']
314        default: no_use
315    import_protocol:
316        description:
317            - Routing protocol from which routes can be imported.
318        choices: ['direct', 'ospf', 'isis', 'static', 'rip', 'ospfv3', 'ripng']
319    import_process_id:
320        description:
321            - Process ID of an imported routing protocol.
322              The value is an integer ranging from 0 to 4294967295.
323    network_address:
324        description:
325            - Specify the IP address advertised by BGP.
326              The value is a string of 0 to 255 characters.
327    mask_len:
328        description:
329            - Specify the mask length of an IP address.
330              The value is an integer ranging from 0 to 128.
331'''
332
333EXAMPLES = '''
334- name: CloudEngine BGP address family test
335  hosts: cloudengine
336  connection: local
337  gather_facts: no
338  vars:
339    cli:
340      host: "{{ inventory_hostname }}"
341      port: "{{ ansible_ssh_port }}"
342      username: "{{ username }}"
343      password: "{{ password }}"
344      transport: cli
345  tasks:
346  - name: "Config BGP Address_Family"
347    ce_bgp_af:
348      state: present
349      vrf_name: js
350      af_type: ipv4uni
351      provider: "{{ cli }}"
352  - name: "Undo BGP Address_Family"
353    ce_bgp_af:
354      state: absent
355      vrf_name: js
356      af_type: ipv4uni
357      provider: "{{ cli }}"
358  - name: "Config import route"
359    ce_bgp_af:
360      state: present
361      vrf_name: js
362      af_type: ipv4uni
363      import_protocol: ospf
364      import_process_id: 123
365      provider: "{{ cli }}"
366  - name: "Undo import route"
367    ce_bgp_af:
368      state: absent
369      vrf_name: js
370      af_type: ipv4uni
371      import_protocol: ospf
372      import_process_id: 123
373      provider: "{{ cli }}"
374  - name: "Config network route"
375    ce_bgp_af:
376      state: present
377      vrf_name: js
378      af_type: ipv4uni
379      network_address: 1.1.1.1
380      mask_len: 24
381      provider: "{{ cli }}"
382  - name: "Undo network route"
383    ce_bgp_af:
384      state: absent
385      vrf_name: js
386      af_type: ipv4uni
387      network_address: 1.1.1.1
388      mask_len: 24
389      provider: "{{ cli }}"
390'''
391
392RETURN = '''
393changed:
394    description: check to see if a change was made on the device
395    returned: always
396    type: bool
397    sample: true
398proposed:
399    description: k/v pairs of parameters passed into module
400    returned: always
401    type: dict
402    sample: {"af_type": "ipv4uni",
403             "state": "present", "vrf_name": "js"}
404existing:
405    description: k/v pairs of existing aaa server
406    returned: always
407    type: dict
408    sample: {}
409end_state:
410    description: k/v pairs of aaa params after module execution
411    returned: always
412    type: dict
413    sample: {"af_type": "ipv4uni", "vrf_name": "js"}
414updates:
415    description: command sent to the device
416    returned: always
417    type: list
418    sample: ["ipv4-family vpn-instance js"]
419'''
420
421import re
422from ansible.module_utils.basic import AnsibleModule
423from ansible.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, ce_argument_spec, check_ip_addr
424
425# get bgp address family
426CE_GET_BGP_ADDRESS_FAMILY_HEADER = """
427    <filter type="subtree">
428      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
429        <bgpcomm>
430          <bgpVrfs>
431            <bgpVrf>
432              <vrfName>%s</vrfName>
433              <bgpVrfAFs>
434                <bgpVrfAF>
435                  <afType>%s</afType>
436"""
437CE_GET_BGP_ADDRESS_FAMILY_TAIL = """
438                </bgpVrfAF>
439              </bgpVrfAFs>
440            </bgpVrf>
441          </bgpVrfs>
442        </bgpcomm>
443      </bgp>
444    </filter>
445"""
446
447# merge bgp address family
448CE_MERGE_BGP_ADDRESS_FAMILY_HEADER = """
449    <config>
450      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
451        <bgpcomm>
452          <bgpVrfs>
453            <bgpVrf>
454              <vrfName>%s</vrfName>
455              <bgpVrfAFs>
456                <bgpVrfAF operation="merge">
457                  <afType>%s</afType>
458"""
459CE_MERGE_BGP_ADDRESS_FAMILY_TAIL = """
460                </bgpVrfAF>
461              </bgpVrfAFs>
462            </bgpVrf>
463          </bgpVrfs>
464        </bgpcomm>
465      </bgp>
466    </config>
467"""
468
469# create bgp address family
470CE_CREATE_BGP_ADDRESS_FAMILY_HEADER = """
471    <config>
472      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
473        <bgpcomm>
474          <bgpVrfs>
475            <bgpVrf>
476              <vrfName>%s</vrfName>
477              <bgpVrfAFs>
478                <bgpVrfAF operation="merge">
479                  <afType>%s</afType>
480"""
481CE_CREATE_BGP_ADDRESS_FAMILY_TAIL = """
482                </bgpVrfAF>
483              </bgpVrfAFs>
484            </bgpVrf>
485          </bgpVrfs>
486        </bgpcomm>
487      </bgp>
488    </config>
489"""
490
491# delete bgp address family
492CE_DELETE_BGP_ADDRESS_FAMILY_HEADER = """
493    <config>
494      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
495        <bgpcomm>
496          <bgpVrfs>
497            <bgpVrf>
498              <vrfName>%s</vrfName>
499              <bgpVrfAFs>
500                <bgpVrfAF operation="delete">
501                  <afType>%s</afType>
502"""
503CE_DELETE_BGP_ADDRESS_FAMILY_TAIL = """
504                </bgpVrfAF>
505              </bgpVrfAFs>
506            </bgpVrf>
507          </bgpVrfs>
508        </bgpcomm>
509      </bgp>
510    </config>
511"""
512
513# get bgp import route
514CE_GET_BGP_IMPORT_AND_NETWORK_ROUTE = """
515    <filter type="subtree">
516      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
517        <bgpcomm>
518          <bgpVrfs>
519            <bgpVrf>
520              <vrfName>%s</vrfName>
521              <bgpVrfAFs>
522                <bgpVrfAF>
523                  <afType>%s</afType>
524                  <importRoutes>
525                    <importRoute>
526                      <importProtocol></importProtocol>
527                      <importProcessId></importProcessId>
528                    </importRoute>
529                  </importRoutes>
530                  <networkRoutes>
531                    <networkRoute>
532                      <networkAddress></networkAddress>
533                      <maskLen></maskLen>
534                    </networkRoute>
535                  </networkRoutes>
536                </bgpVrfAF>
537              </bgpVrfAFs>
538            </bgpVrf>
539          </bgpVrfs>
540        </bgpcomm>
541      </bgp>
542    </filter>
543"""
544
545# merge bgp import route
546CE_MERGE_BGP_IMPORT_ROUTE_HEADER = """
547    <config>
548      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
549        <bgpcomm>
550          <bgpVrfs>
551            <bgpVrf>
552              <vrfName>%s</vrfName>
553              <bgpVrfAFs>
554                <bgpVrfAF>
555                  <afType>%s</afType>
556                  <importRoutes>
557                    <importRoute operation="merge">
558                      <importProtocol>%s</importProtocol>
559                      <importProcessId>%s</importProcessId>
560"""
561CE_MERGE_BGP_IMPORT_ROUTE_TAIL = """
562                    </importRoute>
563                  </importRoutes>
564                </bgpVrfAF>
565              </bgpVrfAFs>
566            </bgpVrf>
567          </bgpVrfs>
568        </bgpcomm>
569      </bgp>
570    </config>
571"""
572
573# create bgp import route
574CE_CREATE_BGP_IMPORT_ROUTE = """
575    <config>
576      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
577        <bgpcomm>
578          <bgpVrfs>
579            <bgpVrf>
580              <vrfName>%s</vrfName>
581              <bgpVrfAFs>
582                <bgpVrfAF>
583                  <afType>%s</afType>
584                  <importRoutes>
585                    <importRoute operation="create">
586                      <importProtocol>%s</importProtocol>
587                      <importProcessId>%s</importProcessId>
588                    </importRoute>
589                  </importRoutes>
590                </bgpVrfAF>
591              </bgpVrfAFs>
592            </bgpVrf>
593          </bgpVrfs>
594        </bgpcomm>
595      </bgp>
596    </config>
597"""
598
599# delete bgp import route
600CE_DELETE_BGP_IMPORT_ROUTE = """
601    <config>
602      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
603        <bgpcomm>
604          <bgpVrfs>
605            <bgpVrf>
606              <vrfName>%s</vrfName>
607              <bgpVrfAFs>
608                <bgpVrfAF>
609                  <afType>%s</afType>
610                  <importRoutes>
611                    <importRoute operation="delete">
612                      <importProtocol>%s</importProtocol>
613                      <importProcessId>%s</importProcessId>
614                    </importRoute>
615                  </importRoutes>
616                </bgpVrfAF>
617              </bgpVrfAFs>
618            </bgpVrf>
619          </bgpVrfs>
620        </bgpcomm>
621      </bgp>
622    </config>
623"""
624
625# get bgp network route
626CE_GET_BGP_NETWORK_ROUTE_HEADER = """
627    <filter type="subtree">
628      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
629        <bgpcomm>
630          <bgpVrfs>
631            <bgpVrf>
632              <vrfName>%s</vrfName>
633              <bgpVrfAFs>
634                <bgpVrfAF>
635                  <afType>%s</afType>
636                  <networkRoutes>
637                    <networkRoute>
638                      <networkAddress></networkAddress>
639                      <maskLen></maskLen>
640"""
641CE_GET_BGP_NETWORK_ROUTE_TAIL = """
642                    </networkRoute>
643                  </networkRoutes>
644                </bgpVrfAF>
645              </bgpVrfAFs>
646            </bgpVrf>
647          </bgpVrfs>
648        </bgpcomm>
649      </bgp>
650    </filter>
651"""
652
653# merge bgp network route
654CE_MERGE_BGP_NETWORK_ROUTE_HEADER = """
655    <config>
656      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
657        <bgpcomm>
658          <bgpVrfs>
659            <bgpVrf>
660              <vrfName>%s</vrfName>
661              <bgpVrfAFs>
662                <bgpVrfAF>
663                  <afType>%s</afType>
664                  <networkRoutes>
665                    <networkRoute operation="merge">
666                      <networkAddress>%s</networkAddress>
667                      <maskLen>%s</maskLen>
668"""
669CE_MERGE_BGP_NETWORK_ROUTE_TAIL = """
670                    </networkRoute>
671                  </networkRoutes>
672                </bgpVrfAF>
673              </bgpVrfAFs>
674            </bgpVrf>
675          </bgpVrfs>
676        </bgpcomm>
677      </bgp>
678    </config>
679"""
680
681# create bgp network route
682CE_CREATE_BGP_NETWORK_ROUTE = """
683    <config>
684      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
685        <bgpcomm>
686          <bgpVrfs>
687            <bgpVrf>
688              <vrfName>%s</vrfName>
689              <bgpVrfAFs>
690                <bgpVrfAF>
691                  <afType>%s</afType>
692                  <networkRoutes>
693                    <networkRoute operation="create">
694                      <networkAddress>%s</networkAddress>
695                      <maskLen>%s</maskLen>
696                    </networkRoute>
697                  </networkRoutes>
698                </bgpVrfAF>
699              </bgpVrfAFs>
700            </bgpVrf>
701          </bgpVrfs>
702        </bgpcomm>
703      </bgp>
704    </config>
705"""
706
707# delete bgp network route
708CE_DELETE_BGP_NETWORK_ROUTE = """
709    <config>
710      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
711        <bgpcomm>
712          <bgpVrfs>
713            <bgpVrf>
714              <vrfName>%s</vrfName>
715              <bgpVrfAFs>
716                <bgpVrfAF>
717                  <afType>%s</afType>
718                  <networkRoutes>
719                    <networkRoute operation="delete">
720                      <networkAddress>%s</networkAddress>
721                      <maskLen>%s</maskLen>
722                    </networkRoute>
723                  </networkRoutes>
724                </bgpVrfAF>
725              </bgpVrfAFs>
726            </bgpVrf>
727          </bgpVrfs>
728        </bgpcomm>
729      </bgp>
730    </config>
731"""
732
733# bgp import and network route header
734CE_BGP_IMPORT_NETWORK_ROUTE_HEADER = """
735    <config>
736      <bgp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
737        <bgpcomm>
738          <bgpVrfs>
739            <bgpVrf>
740              <vrfName>%s</vrfName>
741              <bgpVrfAFs>
742                <bgpVrfAF>
743                  <afType>%s</afType>
744"""
745CE_BGP_IMPORT_NETWORK_ROUTE_TAIL = """
746                </bgpVrfAF>
747              </bgpVrfAFs>
748            </bgpVrf>
749          </bgpVrfs>
750        </bgpcomm>
751      </bgp>
752    </config>
753"""
754CE_BGP_MERGE_IMPORT_UNIT = """
755                  <importRoutes>
756                    <importRoute operation="merge">
757                      <importProtocol>%s</importProtocol>
758                      <importProcessId>%s</importProcessId>
759                    </importRoute>
760                  </importRoutes>
761"""
762CE_BGP_CREATE_IMPORT_UNIT = """
763                  <importRoutes>
764                    <importRoute operation="create">
765                      <importProtocol>%s</importProtocol>
766                      <importProcessId>%s</importProcessId>
767                    </importRoute>
768                  </importRoutes>
769"""
770CE_BGP_DELETE_IMPORT_UNIT = """
771                  <importRoutes>
772                    <importRoute operation="delete">
773                      <importProtocol>%s</importProtocol>
774                      <importProcessId>%s</importProcessId>
775                    </importRoute>
776                  </importRoutes>
777"""
778CE_BGP_MERGE_NETWORK_UNIT = """
779                  <networkRoutes>
780                    <networkRoute operation="merge">
781                      <networkAddress>%s</networkAddress>
782                      <maskLen>%s</maskLen>
783                    </networkRoute>
784                  </networkRoutes>
785"""
786CE_BGP_CREATE_NETWORK_UNIT = """
787                  <networkRoutes>
788                    <networkRoute operation="create">
789                      <networkAddress>%s</networkAddress>
790                      <maskLen>%s</maskLen>
791                    </networkRoute>
792                  </networkRoutes>
793"""
794CE_BGP_DELETE_NETWORK_UNIT = """
795                  <networkRoutes>
796                    <networkRoute operation="delete">
797                      <networkAddress>%s</networkAddress>
798                      <maskLen>%s</maskLen>
799                    </networkRoute>
800                  </networkRoutes>
801"""
802
803
804class BgpAf(object):
805    """ Manages BGP Address-family configuration """
806
807    def netconf_get_config(self, **kwargs):
808        """ netconf_get_config """
809
810        module = kwargs["module"]
811        conf_str = kwargs["conf_str"]
812
813        xml_str = get_nc_config(module, conf_str)
814
815        return xml_str
816
817    def netconf_set_config(self, **kwargs):
818        """ netconf_set_config """
819
820        module = kwargs["module"]
821        conf_str = kwargs["conf_str"]
822
823        xml_str = set_nc_config(module, conf_str)
824
825        return xml_str
826
827    def check_bgp_af_args(self, **kwargs):
828        """ check_bgp_af_args """
829
830        module = kwargs["module"]
831        result = dict()
832        need_cfg = False
833
834        vrf_name = module.params['vrf_name']
835        af_type = module.params['af_type']
836        if vrf_name:
837            if len(vrf_name) > 31 or len(vrf_name) == 0:
838                module.fail_json(
839                    msg='Error: The len of vrf_name %s is out of [1 - 31].' % vrf_name)
840        else:
841            module.fail_json(msg='Error: Please input vrf_name.')
842
843        state = module.params['state']
844        af_type = module.params['af_type']
845
846        conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
847            CE_GET_BGP_ADDRESS_FAMILY_TAIL
848        recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
849
850        if state == "present":
851            if "<data/>" in recv_xml:
852                need_cfg = True
853            else:
854                re_find = re.findall(
855                    r'.*<afType>(.*)</afType>.*', recv_xml)
856
857                if re_find:
858                    result["af_type"] = re_find
859                    result["vrf_name"] = vrf_name
860                    if re_find[0] != af_type:
861                        need_cfg = True
862                else:
863                    need_cfg = True
864        else:
865            if "<data/>" in recv_xml:
866                pass
867            else:
868                re_find = re.findall(
869                    r'.*<afType>(.*)</afType>.*', recv_xml)
870
871                if re_find:
872                    result["af_type"] = re_find
873                    result["vrf_name"] = vrf_name
874                    if re_find[0] == af_type:
875                        need_cfg = True
876
877        result["need_cfg"] = need_cfg
878        return result
879
880    def check_bgp_af_other_can_del(self, **kwargs):
881        """ check_bgp_af_other_can_del """
882        module = kwargs["module"]
883        result = dict()
884        need_cfg = False
885
886        state = module.params['state']
887        vrf_name = module.params['vrf_name']
888        af_type = module.params['af_type']
889
890        router_id = module.params['router_id']
891        if router_id:
892            if len(router_id) > 255:
893                module.fail_json(
894                    msg='Error: The len of router_id %s is out of [0 - 255].' % router_id)
895
896            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
897                "<routerId></routerId>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
898            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
899
900            if state == "present":
901                if "<data/>" in recv_xml:
902                    need_cfg = True
903                else:
904                    re_find = re.findall(
905                        r'.*<routerId>(.*)</routerId>.*', recv_xml)
906
907                    if re_find:
908                        if re_find[0] != router_id:
909                            need_cfg = True
910                    else:
911                        need_cfg = True
912            else:
913                if "<data/>" in recv_xml:
914                    pass
915                else:
916                    re_find = re.findall(
917                        r'.*<routerId>(.*)</routerId>.*', recv_xml)
918
919                    if re_find:
920                        if re_find[0] == router_id:
921                            need_cfg = True
922                    else:
923                        pass
924
925        determin_med = module.params['determin_med']
926        if determin_med != 'no_use':
927
928            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
929                "<determinMed></determinMed>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
930            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
931
932            if state == "present":
933                if "<data/>" in recv_xml:
934                    need_cfg = True
935                else:
936                    re_find = re.findall(
937                        r'.*<determinMed>(.*)</determinMed>.*', recv_xml)
938
939                    if re_find:
940                        if re_find[0] != determin_med:
941                            need_cfg = True
942                    else:
943                        need_cfg = True
944            else:
945                if "<data/>" in recv_xml:
946                    pass
947                else:
948                    re_find = re.findall(
949                        r'.*<determinMed>(.*)</determinMed>.*', recv_xml)
950
951                    if re_find:
952                        if re_find[0] == determin_med:
953                            need_cfg = True
954                    else:
955                        pass
956
957        ebgp_if_sensitive = module.params['ebgp_if_sensitive']
958        if ebgp_if_sensitive != 'no_use':
959
960            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
961                "<ebgpIfSensitive></ebgpIfSensitive>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
962            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
963
964            if state == "present":
965                if "<data/>" in recv_xml:
966                    need_cfg = True
967                else:
968                    re_find = re.findall(
969                        r'.*<ebgpIfSensitive>(.*)</ebgpIfSensitive>.*', recv_xml)
970
971                    if re_find:
972                        if re_find[0] != ebgp_if_sensitive:
973                            need_cfg = True
974                    else:
975                        need_cfg = True
976            else:
977                if "<data/>" in recv_xml:
978                    pass
979                else:
980                    re_find = re.findall(
981                        r'.*<ebgpIfSensitive>(.*)</ebgpIfSensitive>.*', recv_xml)
982
983                    if re_find:
984                        if re_find[0] == ebgp_if_sensitive:
985                            need_cfg = True
986                    else:
987                        pass
988
989        relay_delay_enable = module.params['relay_delay_enable']
990        if relay_delay_enable != 'no_use':
991
992            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
993                "<relayDelayEnable></relayDelayEnable>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
994            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
995
996            if state == "present":
997                if "<data/>" in recv_xml:
998                    need_cfg = True
999                else:
1000                    re_find = re.findall(
1001                        r'.*<relayDelayEnable>(.*)</relayDelayEnable>.*', recv_xml)
1002
1003                    if re_find:
1004                        if re_find[0] != relay_delay_enable:
1005                            need_cfg = True
1006                    else:
1007                        need_cfg = True
1008            else:
1009                if "<data/>" in recv_xml:
1010                    pass
1011                else:
1012                    re_find = re.findall(
1013                        r'.*<relayDelayEnable>(.*)</relayDelayEnable>.*', recv_xml)
1014
1015                    if re_find:
1016                        if re_find[0] == relay_delay_enable:
1017                            need_cfg = True
1018                    else:
1019                        pass
1020
1021        result["need_cfg"] = need_cfg
1022        return result
1023
1024    def check_bgp_af_other_args(self, **kwargs):
1025        """ check_bgp_af_other_args """
1026
1027        module = kwargs["module"]
1028        result = dict()
1029        need_cfg = False
1030
1031        vrf_name = module.params['vrf_name']
1032        af_type = module.params['af_type']
1033
1034        max_load_ibgp_num = module.params['max_load_ibgp_num']
1035        if max_load_ibgp_num:
1036            if int(max_load_ibgp_num) > 65535 or int(max_load_ibgp_num) < 1:
1037                module.fail_json(
1038                    msg='Error: The value of max_load_ibgp_num %s is out of [1 - 65535].' % max_load_ibgp_num)
1039
1040            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1041                "<maxLoadIbgpNum></maxLoadIbgpNum>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1042            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1043
1044            if "<data/>" in recv_xml:
1045                need_cfg = True
1046            else:
1047                re_find = re.findall(
1048                    r'.*<maxLoadIbgpNum>(.*)</maxLoadIbgpNum>.*', recv_xml)
1049
1050                if re_find:
1051                    result["max_load_ibgp_num"] = re_find
1052                    result["vrf_name"] = vrf_name
1053                    if re_find[0] != max_load_ibgp_num:
1054                        need_cfg = True
1055                else:
1056                    need_cfg = True
1057
1058        ibgp_ecmp_nexthop_changed = module.params['ibgp_ecmp_nexthop_changed']
1059        if ibgp_ecmp_nexthop_changed != 'no_use':
1060
1061            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1062                "<ibgpEcmpNexthopChanged></ibgpEcmpNexthopChanged>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1063            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1064
1065            if "<data/>" in recv_xml:
1066                need_cfg = True
1067            else:
1068                re_find = re.findall(
1069                    r'.*<ibgpEcmpNexthopChanged>(.*)</ibgpEcmpNexthopChanged>.*', recv_xml)
1070
1071                if re_find:
1072                    result["ibgp_ecmp_nexthop_changed"] = re_find
1073                    result["vrf_name"] = vrf_name
1074                    if re_find[0] != ibgp_ecmp_nexthop_changed:
1075                        need_cfg = True
1076                else:
1077                    need_cfg = True
1078
1079        max_load_ebgp_num = module.params['max_load_ebgp_num']
1080        if max_load_ebgp_num:
1081            if int(max_load_ebgp_num) > 65535 or int(max_load_ebgp_num) < 1:
1082                module.fail_json(
1083                    msg='Error: The value of max_load_ebgp_num %s is out of [1 - 65535].' % max_load_ebgp_num)
1084
1085            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1086                "<maxLoadEbgpNum></maxLoadEbgpNum>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1087            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1088
1089            if "<data/>" in recv_xml:
1090                need_cfg = True
1091            else:
1092                re_find = re.findall(
1093                    r'.*<maxLoadEbgpNum>(.*)</maxLoadEbgpNum>.*', recv_xml)
1094
1095                if re_find:
1096                    result["max_load_ebgp_num"] = re_find
1097                    result["vrf_name"] = vrf_name
1098                    if re_find[0] != max_load_ebgp_num:
1099                        need_cfg = True
1100                else:
1101                    need_cfg = True
1102
1103        ebgp_ecmp_nexthop_changed = module.params['ebgp_ecmp_nexthop_changed']
1104        if ebgp_ecmp_nexthop_changed != 'no_use':
1105
1106            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1107                "<ebgpEcmpNexthopChanged></ebgpEcmpNexthopChanged>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1108            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1109
1110            if "<data/>" in recv_xml:
1111                need_cfg = True
1112            else:
1113                re_find = re.findall(
1114                    r'.*<ebgpEcmpNexthopChanged>(.*)</ebgpEcmpNexthopChanged>.*', recv_xml)
1115
1116                if re_find:
1117                    result["ebgp_ecmp_nexthop_changed"] = re_find
1118                    result["vrf_name"] = vrf_name
1119                    if re_find[0] != ebgp_ecmp_nexthop_changed:
1120                        need_cfg = True
1121                else:
1122                    need_cfg = True
1123
1124        maximum_load_balance = module.params['maximum_load_balance']
1125        if maximum_load_balance:
1126            if int(maximum_load_balance) > 65535 or int(maximum_load_balance) < 1:
1127                module.fail_json(
1128                    msg='Error: The value of maximum_load_balance %s is out of [1 - 65535].' % maximum_load_balance)
1129
1130            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1131                "<maximumLoadBalance></maximumLoadBalance>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1132            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1133
1134            if "<data/>" in recv_xml:
1135                need_cfg = True
1136            else:
1137                re_find = re.findall(
1138                    r'.*<maximumLoadBalance>(.*)</maximumLoadBalance>.*', recv_xml)
1139
1140                if re_find:
1141                    result["maximum_load_balance"] = re_find
1142                    result["vrf_name"] = vrf_name
1143                    if re_find[0] != maximum_load_balance:
1144                        need_cfg = True
1145                else:
1146                    need_cfg = True
1147
1148        ecmp_nexthop_changed = module.params['ecmp_nexthop_changed']
1149        if ecmp_nexthop_changed != 'no_use':
1150
1151            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1152                "<ecmpNexthopChanged></ecmpNexthopChanged>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1153            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1154
1155            if "<data/>" in recv_xml:
1156                need_cfg = True
1157            else:
1158                re_find = re.findall(
1159                    r'.*<ecmpNexthopChanged>(.*)</ecmpNexthopChanged>.*', recv_xml)
1160
1161                if re_find:
1162                    result["ecmp_nexthop_changed"] = re_find
1163                    result["vrf_name"] = vrf_name
1164                    if re_find[0] != ecmp_nexthop_changed:
1165                        need_cfg = True
1166                else:
1167                    need_cfg = True
1168
1169        default_local_pref = module.params['default_local_pref']
1170        if default_local_pref:
1171            if int(default_local_pref) < 0:
1172                module.fail_json(
1173                    msg='Error: The value of default_local_pref %s is out of [0 - 4294967295].' % default_local_pref)
1174
1175            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1176                "<defaultLocalPref></defaultLocalPref>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1177            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1178
1179            if "<data/>" in recv_xml:
1180                need_cfg = True
1181            else:
1182                re_find = re.findall(
1183                    r'.*<defaultLocalPref>(.*)</defaultLocalPref>.*', recv_xml)
1184
1185                if re_find:
1186                    result["default_local_pref"] = re_find
1187                    result["vrf_name"] = vrf_name
1188                    if re_find[0] != default_local_pref:
1189                        need_cfg = True
1190                else:
1191                    need_cfg = True
1192
1193        default_med = module.params['default_med']
1194        if default_med:
1195            if int(default_med) < 0:
1196                module.fail_json(
1197                    msg='Error: The value of default_med %s is out of [0 - 4294967295].' % default_med)
1198
1199            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1200                "<defaultMed></defaultMed>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1201            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1202
1203            if "<data/>" in recv_xml:
1204                need_cfg = True
1205            else:
1206                re_find = re.findall(
1207                    r'.*<defaultMed>(.*)</defaultMed>.*', recv_xml)
1208
1209                if re_find:
1210                    result["default_med"] = re_find
1211                    result["vrf_name"] = vrf_name
1212                    if re_find[0] != default_med:
1213                        need_cfg = True
1214                else:
1215                    need_cfg = True
1216
1217        default_rt_import_enable = module.params['default_rt_import_enable']
1218        if default_rt_import_enable != 'no_use':
1219
1220            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1221                "<defaultRtImportEnable></defaultRtImportEnable>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1222            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1223
1224            if "<data/>" in recv_xml:
1225                need_cfg = True
1226            else:
1227                re_find = re.findall(
1228                    r'.*<defaultRtImportEnable>(.*)</defaultRtImportEnable>.*', recv_xml)
1229
1230                if re_find:
1231                    result["default_rt_import_enable"] = re_find
1232                    result["vrf_name"] = vrf_name
1233                    if re_find[0] != default_rt_import_enable:
1234                        need_cfg = True
1235                else:
1236                    need_cfg = True
1237
1238        router_id = module.params['router_id']
1239        if router_id:
1240            if len(router_id) > 255:
1241                module.fail_json(
1242                    msg='Error: The len of router_id %s is out of [0 - 255].' % router_id)
1243
1244            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1245                "<routerId></routerId>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1246            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1247
1248            if "<data/>" in recv_xml:
1249                need_cfg = True
1250            else:
1251                re_find = re.findall(
1252                    r'.*<routerId>(.*)</routerId>.*', recv_xml)
1253
1254                if re_find:
1255                    result["router_id"] = re_find
1256                    result["vrf_name"] = vrf_name
1257                    if re_find[0] != router_id:
1258                        need_cfg = True
1259                else:
1260                    need_cfg = True
1261
1262        vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
1263        if vrf_rid_auto_sel != 'no_use':
1264
1265            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1266                "<vrfRidAutoSel></vrfRidAutoSel>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1267            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1268
1269            if "<data/>" in recv_xml:
1270                need_cfg = True
1271            else:
1272                re_find = re.findall(
1273                    r'.*<vrfRidAutoSel>(.*)</vrfRidAutoSel>.*', recv_xml)
1274
1275                if re_find:
1276                    result["vrf_rid_auto_sel"] = re_find
1277                    result["vrf_name"] = vrf_name
1278                    if re_find[0] != vrf_rid_auto_sel:
1279                        need_cfg = True
1280                else:
1281                    need_cfg = True
1282
1283        nexthop_third_party = module.params['nexthop_third_party']
1284        if nexthop_third_party != 'no_use':
1285
1286            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1287                "<nexthopThirdParty></nexthopThirdParty>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1288            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1289
1290            if "<data/>" in recv_xml:
1291                need_cfg = True
1292            else:
1293                re_find = re.findall(
1294                    r'.*<nexthopThirdParty>(.*)</nexthopThirdParty>.*', recv_xml)
1295
1296                if re_find:
1297                    result["nexthop_third_party"] = re_find
1298                    result["vrf_name"] = vrf_name
1299                    if re_find[0] != nexthop_third_party:
1300                        need_cfg = True
1301                else:
1302                    need_cfg = True
1303
1304        summary_automatic = module.params['summary_automatic']
1305        if summary_automatic != 'no_use':
1306
1307            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1308                "<summaryAutomatic></summaryAutomatic>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1309            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1310
1311            if "<data/>" in recv_xml:
1312                need_cfg = True
1313            else:
1314                re_find = re.findall(
1315                    r'.*<summaryAutomatic>(.*)</summaryAutomatic>.*', recv_xml)
1316
1317                if re_find:
1318                    result["summary_automatic"] = re_find
1319                    result["vrf_name"] = vrf_name
1320                    if re_find[0] != summary_automatic:
1321                        need_cfg = True
1322                else:
1323                    need_cfg = True
1324
1325        auto_frr_enable = module.params['auto_frr_enable']
1326        if auto_frr_enable != 'no_use':
1327
1328            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1329                "<autoFrrEnable></autoFrrEnable>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1330            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1331
1332            if "<data/>" in recv_xml:
1333                need_cfg = True
1334            else:
1335                re_find = re.findall(
1336                    r'.*<autoFrrEnable>(.*)</autoFrrEnable>.*', recv_xml)
1337
1338                if re_find:
1339                    result["auto_frr_enable"] = re_find
1340                    result["vrf_name"] = vrf_name
1341                    if re_find[0] != auto_frr_enable:
1342                        need_cfg = True
1343                else:
1344                    need_cfg = True
1345
1346        load_balancing_as_path_ignore = module.params['load_balancing_as_path_ignore']
1347        if load_balancing_as_path_ignore != 'no_use':
1348
1349            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1350                "<loadBalancingAsPathIgnore></loadBalancingAsPathIgnore>" + \
1351                CE_GET_BGP_ADDRESS_FAMILY_TAIL
1352            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1353
1354            if "<data/>" in recv_xml:
1355                need_cfg = True
1356            else:
1357                re_find = re.findall(
1358                    r'.*<loadBalancingAsPathIgnore>(.*)</loadBalancingAsPathIgnore>.*', recv_xml)
1359
1360                if re_find:
1361                    result["load_balancing_as_path_ignore"] = re_find
1362                    result["vrf_name"] = vrf_name
1363                    if re_find[0] != load_balancing_as_path_ignore:
1364                        need_cfg = True
1365                else:
1366                    need_cfg = True
1367
1368        rib_only_enable = module.params['rib_only_enable']
1369        if rib_only_enable != 'no_use':
1370
1371            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1372                "<ribOnlyEnable></ribOnlyEnable>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1373            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1374
1375            if "<data/>" in recv_xml:
1376                need_cfg = True
1377            else:
1378                re_find = re.findall(
1379                    r'.*<ribOnlyEnable>(.*)</ribOnlyEnable>.*', recv_xml)
1380
1381                if re_find:
1382                    result["rib_only_enable"] = re_find
1383                    result["vrf_name"] = vrf_name
1384                    if re_find[0] != rib_only_enable:
1385                        need_cfg = True
1386                else:
1387                    need_cfg = True
1388
1389        rib_only_policy_name = module.params['rib_only_policy_name']
1390        if rib_only_policy_name:
1391            if len(rib_only_policy_name) > 40 or len(rib_only_policy_name) < 1:
1392                module.fail_json(
1393                    msg='Error: The len of rib_only_policy_name %s is out of [1 - 40].' % rib_only_policy_name)
1394
1395            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1396                "<ribOnlyPolicyName></ribOnlyPolicyName>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1397            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1398
1399            if "<data/>" in recv_xml:
1400                need_cfg = True
1401            else:
1402                re_find = re.findall(
1403                    r'.*<ribOnlyPolicyName>(.*)</ribOnlyPolicyName>.*', recv_xml)
1404
1405                if re_find:
1406                    result["rib_only_policy_name"] = re_find
1407                    result["vrf_name"] = vrf_name
1408                    if re_find[0] != rib_only_policy_name:
1409                        need_cfg = True
1410                else:
1411                    need_cfg = True
1412
1413        active_route_advertise = module.params['active_route_advertise']
1414        if active_route_advertise != 'no_use':
1415
1416            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1417                "<activeRouteAdvertise></activeRouteAdvertise>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1418            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1419
1420            if "<data/>" in recv_xml:
1421                need_cfg = True
1422            else:
1423                re_find = re.findall(
1424                    r'.*<activeRouteAdvertise>(.*)</activeRouteAdvertise>.*', recv_xml)
1425
1426                if re_find:
1427                    result["active_route_advertise"] = re_find
1428                    result["vrf_name"] = vrf_name
1429                    if re_find[0] != active_route_advertise:
1430                        need_cfg = True
1431                else:
1432                    need_cfg = True
1433
1434        as_path_neglect = module.params['as_path_neglect']
1435        if as_path_neglect != 'no_use':
1436
1437            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1438                "<asPathNeglect></asPathNeglect>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1439            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1440
1441            if "<data/>" in recv_xml:
1442                need_cfg = True
1443            else:
1444                re_find = re.findall(
1445                    r'.*<asPathNeglect>(.*)</asPathNeglect>.*', recv_xml)
1446
1447                if re_find:
1448                    result["as_path_neglect"] = re_find
1449                    result["vrf_name"] = vrf_name
1450                    if re_find[0] != as_path_neglect:
1451                        need_cfg = True
1452                else:
1453                    need_cfg = True
1454
1455        med_none_as_maximum = module.params['med_none_as_maximum']
1456        if med_none_as_maximum != 'no_use':
1457
1458            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1459                "<medNoneAsMaximum></medNoneAsMaximum>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1460            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1461
1462            if "<data/>" in recv_xml:
1463                need_cfg = True
1464            else:
1465                re_find = re.findall(
1466                    r'.*<medNoneAsMaximum>(.*)</medNoneAsMaximum>.*', recv_xml)
1467
1468                if re_find:
1469                    result["med_none_as_maximum"] = re_find
1470                    result["vrf_name"] = vrf_name
1471                    if re_find[0] != med_none_as_maximum:
1472                        need_cfg = True
1473                else:
1474                    need_cfg = True
1475
1476        router_id_neglect = module.params['router_id_neglect']
1477        if router_id_neglect != 'no_use':
1478
1479            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1480                "<routerIdNeglect></routerIdNeglect>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1481            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1482
1483            if "<data/>" in recv_xml:
1484                need_cfg = True
1485            else:
1486                re_find = re.findall(
1487                    r'.*<routerIdNeglect>(.*)</routerIdNeglect>.*', recv_xml)
1488
1489                if re_find:
1490                    result["router_id_neglect"] = re_find
1491                    result["vrf_name"] = vrf_name
1492                    if re_find[0] != router_id_neglect:
1493                        need_cfg = True
1494                else:
1495                    need_cfg = True
1496
1497        igp_metric_ignore = module.params['igp_metric_ignore']
1498        if igp_metric_ignore != 'no_use':
1499
1500            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1501                "<igpMetricIgnore></igpMetricIgnore>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1502            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1503
1504            if "<data/>" in recv_xml:
1505                need_cfg = True
1506            else:
1507                re_find = re.findall(
1508                    r'.*<igpMetricIgnore>(.*)</igpMetricIgnore>.*', recv_xml)
1509
1510                if re_find:
1511                    result["igp_metric_ignore"] = re_find
1512                    result["vrf_name"] = vrf_name
1513                    if re_find[0] != igp_metric_ignore:
1514                        need_cfg = True
1515                else:
1516                    need_cfg = True
1517
1518        always_compare_med = module.params['always_compare_med']
1519        if always_compare_med != 'no_use':
1520
1521            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1522                "<alwaysCompareMed></alwaysCompareMed>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1523            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1524
1525            if "<data/>" in recv_xml:
1526                need_cfg = True
1527            else:
1528                re_find = re.findall(
1529                    r'.*<alwaysCompareMed>(.*)</alwaysCompareMed>.*', recv_xml)
1530
1531                if re_find:
1532                    result["always_compare_med"] = re_find
1533                    result["vrf_name"] = vrf_name
1534                    if re_find[0] != always_compare_med:
1535                        need_cfg = True
1536                else:
1537                    need_cfg = True
1538
1539        determin_med = module.params['determin_med']
1540        if determin_med != 'no_use':
1541
1542            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1543                "<determinMed></determinMed>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1544            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1545
1546            if "<data/>" in recv_xml:
1547                need_cfg = True
1548            else:
1549                re_find = re.findall(
1550                    r'.*<determinMed>(.*)</determinMed>.*', recv_xml)
1551
1552                if re_find:
1553                    result["determin_med"] = re_find
1554                    result["vrf_name"] = vrf_name
1555                    if re_find[0] != determin_med:
1556                        need_cfg = True
1557                else:
1558                    need_cfg = True
1559
1560        preference_external = module.params['preference_external']
1561        if preference_external:
1562            if int(preference_external) > 255 or int(preference_external) < 1:
1563                module.fail_json(
1564                    msg='Error: The value of preference_external %s is out of [1 - 255].' % preference_external)
1565
1566            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1567                "<preferenceExternal></preferenceExternal>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1568            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1569
1570            if "<data/>" in recv_xml:
1571                need_cfg = True
1572            else:
1573                re_find = re.findall(
1574                    r'.*<preferenceExternal>(.*)</preferenceExternal>.*', recv_xml)
1575
1576                if re_find:
1577                    result["preference_external"] = re_find
1578                    result["vrf_name"] = vrf_name
1579                    if re_find[0] != preference_external:
1580                        need_cfg = True
1581                else:
1582                    need_cfg = True
1583
1584        preference_internal = module.params['preference_internal']
1585        if preference_internal:
1586            if int(preference_internal) > 255 or int(preference_internal) < 1:
1587                module.fail_json(
1588                    msg='Error: The value of preference_internal %s is out of [1 - 255].' % preference_internal)
1589
1590            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1591                "<preferenceInternal></preferenceInternal>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1592            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1593
1594            if "<data/>" in recv_xml:
1595                need_cfg = True
1596            else:
1597                re_find = re.findall(
1598                    r'.*<preferenceInternal>(.*)</preferenceInternal>.*', recv_xml)
1599
1600                if re_find:
1601                    result["preference_internal"] = re_find
1602                    result["vrf_name"] = vrf_name
1603                    if re_find[0] != preference_internal:
1604                        need_cfg = True
1605                else:
1606                    need_cfg = True
1607
1608        preference_local = module.params['preference_local']
1609        if preference_local:
1610            if int(preference_local) > 255 or int(preference_local) < 1:
1611                module.fail_json(
1612                    msg='Error: The value of preference_local %s is out of [1 - 255].' % preference_local)
1613
1614            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1615                "<preferenceLocal></preferenceLocal>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1616            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1617
1618            if "<data/>" in recv_xml:
1619                need_cfg = True
1620            else:
1621                re_find = re.findall(
1622                    r'.*<preferenceLocal>(.*)</preferenceLocal>.*', recv_xml)
1623
1624                if re_find:
1625                    result["preference_local"] = re_find
1626                    result["vrf_name"] = vrf_name
1627                    if re_find[0] != preference_local:
1628                        need_cfg = True
1629                else:
1630                    need_cfg = True
1631
1632        prefrence_policy_name = module.params['prefrence_policy_name']
1633        if prefrence_policy_name:
1634            if len(prefrence_policy_name) > 40 or len(prefrence_policy_name) < 1:
1635                module.fail_json(
1636                    msg='Error: The len of prefrence_policy_name %s is out of [1 - 40].' % prefrence_policy_name)
1637
1638            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1639                "<prefrencePolicyName></prefrencePolicyName>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1640            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1641
1642            if "<data/>" in recv_xml:
1643                need_cfg = True
1644            else:
1645                re_find = re.findall(
1646                    r'.*<prefrencePolicyName>(.*)</prefrencePolicyName>.*', recv_xml)
1647
1648                if re_find:
1649                    result["prefrence_policy_name"] = re_find
1650                    result["vrf_name"] = vrf_name
1651                    if re_find[0] != prefrence_policy_name:
1652                        need_cfg = True
1653                else:
1654                    need_cfg = True
1655
1656        reflect_between_client = module.params['reflect_between_client']
1657        if reflect_between_client != 'no_use':
1658
1659            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1660                "<reflectBetweenClient></reflectBetweenClient>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1661            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1662
1663            if "<data/>" in recv_xml:
1664                need_cfg = True
1665            else:
1666                re_find = re.findall(
1667                    r'.*<reflectBetweenClient>(.*)</reflectBetweenClient>.*', recv_xml)
1668
1669                if re_find:
1670                    result["reflect_between_client"] = re_find
1671                    result["vrf_name"] = vrf_name
1672                    if re_find[0] != reflect_between_client:
1673                        need_cfg = True
1674                else:
1675                    need_cfg = True
1676
1677        reflector_cluster_id = module.params['reflector_cluster_id']
1678        if reflector_cluster_id:
1679            if int(reflector_cluster_id) < 0:
1680                module.fail_json(
1681                    msg='Error: The value of reflector_cluster_id %s is out of '
1682                        '[1 - 4294967295].' % reflector_cluster_id)
1683
1684            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1685                "<reflectorClusterId></reflectorClusterId>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1686            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1687
1688            if "<data/>" in recv_xml:
1689                need_cfg = True
1690            else:
1691                re_find = re.findall(
1692                    r'.*<reflectorClusterId>(.*)</reflectorClusterId>.*', recv_xml)
1693
1694                if re_find:
1695                    result["reflector_cluster_id"] = re_find
1696                    result["vrf_name"] = vrf_name
1697                    if re_find[0] != reflector_cluster_id:
1698                        need_cfg = True
1699                else:
1700                    need_cfg = True
1701
1702        reflector_cluster_ipv4 = module.params['reflector_cluster_ipv4']
1703        if reflector_cluster_ipv4:
1704            if len(reflector_cluster_ipv4) > 255:
1705                module.fail_json(
1706                    msg='Error: The len of reflector_cluster_ipv4 %s is out of [0 - 255].' % reflector_cluster_ipv4)
1707
1708            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1709                "<reflectorClusterIpv4></reflectorClusterIpv4>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1710            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1711
1712            if "<data/>" in recv_xml:
1713                need_cfg = True
1714            else:
1715                re_find = re.findall(
1716                    r'.*<reflectorClusterIpv4>(.*)</reflectorClusterIpv4>.*', recv_xml)
1717
1718                if re_find:
1719                    result["reflector_cluster_ipv4"] = re_find
1720                    result["vrf_name"] = vrf_name
1721                    if re_find[0] != reflector_cluster_ipv4:
1722                        need_cfg = True
1723                else:
1724                    need_cfg = True
1725
1726        rr_filter_number = module.params['rr_filter_number']
1727        if rr_filter_number:
1728            if len(rr_filter_number) > 51 or len(rr_filter_number) < 1:
1729                module.fail_json(
1730                    msg='Error: The len of rr_filter_number %s is out of [1 - 51].' % rr_filter_number)
1731
1732            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1733                "<rrFilterNumber></rrFilterNumber>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1734            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1735
1736            if "<data/>" in recv_xml:
1737                need_cfg = True
1738            else:
1739                re_find = re.findall(
1740                    r'.*<rrFilterNumber>(.*)</rrFilterNumber>.*', recv_xml)
1741
1742                if re_find:
1743                    result["rr_filter_number"] = re_find
1744                    result["vrf_name"] = vrf_name
1745                    if re_find[0] != rr_filter_number:
1746                        need_cfg = True
1747                else:
1748                    need_cfg = True
1749
1750        policy_vpn_target = module.params['policy_vpn_target']
1751        if policy_vpn_target != 'no_use':
1752
1753            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1754                "<policyVpnTarget></policyVpnTarget>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1755            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1756
1757            if "<data/>" in recv_xml:
1758                need_cfg = True
1759            else:
1760                re_find = re.findall(
1761                    r'.*<policyVpnTarget>(.*)</policyVpnTarget>.*', recv_xml)
1762
1763                if re_find:
1764                    result["policy_vpn_target"] = re_find
1765                    result["vrf_name"] = vrf_name
1766                    if re_find[0] != policy_vpn_target:
1767                        need_cfg = True
1768                else:
1769                    need_cfg = True
1770
1771        next_hop_sel_depend_type = module.params['next_hop_sel_depend_type']
1772        if next_hop_sel_depend_type:
1773
1774            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1775                "<nextHopSelDependType></nextHopSelDependType>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1776            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1777
1778            if "<data/>" in recv_xml:
1779                need_cfg = True
1780            else:
1781                re_find = re.findall(
1782                    r'.*<nextHopSelDependType>(.*)</nextHopSelDependType>.*', recv_xml)
1783
1784                if re_find:
1785                    result["next_hop_sel_depend_type"] = re_find
1786                    result["vrf_name"] = vrf_name
1787                    if re_find[0] != next_hop_sel_depend_type:
1788                        need_cfg = True
1789                else:
1790                    need_cfg = True
1791
1792        nhp_relay_route_policy_name = module.params[
1793            'nhp_relay_route_policy_name']
1794        if nhp_relay_route_policy_name:
1795            if len(nhp_relay_route_policy_name) > 40 or len(nhp_relay_route_policy_name) < 1:
1796                module.fail_json(
1797                    msg='Error: The len of nhp_relay_route_policy_name %s is '
1798                        'out of [1 - 40].' % nhp_relay_route_policy_name)
1799
1800            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1801                "<nhpRelayRoutePolicyName></nhpRelayRoutePolicyName>" + \
1802                CE_GET_BGP_ADDRESS_FAMILY_TAIL
1803            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1804
1805            if "<data/>" in recv_xml:
1806                need_cfg = True
1807            else:
1808                re_find = re.findall(
1809                    r'.*<nhpRelayRoutePolicyName>(.*)</nhpRelayRoutePolicyName>.*', recv_xml)
1810
1811                if re_find:
1812                    result["nhp_relay_route_policy_name"] = re_find
1813                    result["vrf_name"] = vrf_name
1814                    if re_find[0] != nhp_relay_route_policy_name:
1815                        need_cfg = True
1816                else:
1817                    need_cfg = True
1818
1819        ebgp_if_sensitive = module.params['ebgp_if_sensitive']
1820        if ebgp_if_sensitive != 'no_use':
1821
1822            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1823                "<ebgpIfSensitive></ebgpIfSensitive>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1824            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1825
1826            if "<data/>" in recv_xml:
1827                need_cfg = True
1828            else:
1829                re_find = re.findall(
1830                    r'.*<ebgpIfSensitive>(.*)</ebgpIfSensitive>.*', recv_xml)
1831
1832                if re_find:
1833                    result["ebgp_if_sensitive"] = re_find
1834                    result["vrf_name"] = vrf_name
1835                    if re_find[0] != ebgp_if_sensitive:
1836                        need_cfg = True
1837                else:
1838                    need_cfg = True
1839
1840        reflect_chg_path = module.params['reflect_chg_path']
1841        if reflect_chg_path != 'no_use':
1842
1843            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1844                "<reflectChgPath></reflectChgPath>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1845            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1846
1847            if "<data/>" in recv_xml:
1848                need_cfg = True
1849            else:
1850                re_find = re.findall(
1851                    r'.*<reflectChgPath>(.*)</reflectChgPath>.*', recv_xml)
1852
1853                if re_find:
1854                    result["reflect_chg_path"] = re_find
1855                    result["vrf_name"] = vrf_name
1856                    if re_find[0] != reflect_chg_path:
1857                        need_cfg = True
1858                else:
1859                    need_cfg = True
1860
1861        add_path_sel_num = module.params['add_path_sel_num']
1862        if add_path_sel_num:
1863            if int(add_path_sel_num) > 64 or int(add_path_sel_num) < 2:
1864                module.fail_json(
1865                    msg='Error: The value of add_path_sel_num %s is out of [2 - 64].' % add_path_sel_num)
1866
1867            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1868                "<addPathSelNum></addPathSelNum>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1869            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1870
1871            if "<data/>" in recv_xml:
1872                need_cfg = True
1873            else:
1874                re_find = re.findall(
1875                    r'.*<addPathSelNum>(.*)</addPathSelNum>.*', recv_xml)
1876
1877                if re_find:
1878                    result["add_path_sel_num"] = re_find
1879                    result["vrf_name"] = vrf_name
1880                    if re_find[0] != add_path_sel_num:
1881                        need_cfg = True
1882                else:
1883                    need_cfg = True
1884
1885        route_sel_delay = module.params['route_sel_delay']
1886        if route_sel_delay:
1887            if int(route_sel_delay) > 3600 or int(route_sel_delay) < 0:
1888                module.fail_json(
1889                    msg='Error: The value of route_sel_delay %s is out of [0 - 3600].' % route_sel_delay)
1890
1891            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1892                "<routeSelDelay></routeSelDelay>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1893            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1894
1895            if "<data/>" in recv_xml:
1896                need_cfg = True
1897            else:
1898                re_find = re.findall(
1899                    r'.*<routeSelDelay>(.*)</routeSelDelay>.*', recv_xml)
1900
1901                if re_find:
1902                    result["route_sel_delay"] = re_find
1903                    result["vrf_name"] = vrf_name
1904                    if re_find[0] != route_sel_delay:
1905                        need_cfg = True
1906                else:
1907                    need_cfg = True
1908
1909        allow_invalid_as = module.params['allow_invalid_as']
1910        if allow_invalid_as != 'no_use':
1911
1912            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1913                "<allowInvalidAs></allowInvalidAs>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1914            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1915
1916            if "<data/>" in recv_xml:
1917                need_cfg = True
1918            else:
1919                re_find = re.findall(
1920                    r'.*<allowInvalidAs>(.*)</allowInvalidAs>.*', recv_xml)
1921
1922                if re_find:
1923                    result["allow_invalid_as"] = re_find
1924                    result["vrf_name"] = vrf_name
1925                    if re_find[0] != allow_invalid_as:
1926                        need_cfg = True
1927                else:
1928                    need_cfg = True
1929
1930        policy_ext_comm_enable = module.params['policy_ext_comm_enable']
1931        if policy_ext_comm_enable != 'no_use':
1932
1933            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1934                "<policyExtCommEnable></policyExtCommEnable>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1935            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1936
1937            if "<data/>" in recv_xml:
1938                need_cfg = True
1939            else:
1940                re_find = re.findall(
1941                    r'.*<policyExtCommEnable>(.*)</policyExtCommEnable>.*', recv_xml)
1942
1943                if re_find:
1944                    result["policy_ext_comm_enable"] = re_find
1945                    result["vrf_name"] = vrf_name
1946                    if re_find[0] != policy_ext_comm_enable:
1947                        need_cfg = True
1948                else:
1949                    need_cfg = True
1950
1951        supernet_uni_adv = module.params['supernet_uni_adv']
1952        if supernet_uni_adv != 'no_use':
1953
1954            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1955                "<supernetUniAdv></supernetUniAdv>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1956            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1957
1958            if "<data/>" in recv_xml:
1959                need_cfg = True
1960            else:
1961                re_find = re.findall(
1962                    r'.*<supernetUniAdv>(.*)</supernetUniAdv>.*', recv_xml)
1963
1964                if re_find:
1965                    result["supernet_uni_adv"] = re_find
1966                    result["vrf_name"] = vrf_name
1967                    if re_find[0] != supernet_uni_adv:
1968                        need_cfg = True
1969                else:
1970                    need_cfg = True
1971
1972        supernet_label_adv = module.params['supernet_label_adv']
1973        if supernet_label_adv != 'no_use':
1974
1975            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
1976                "<supernetLabelAdv></supernetLabelAdv>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
1977            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
1978
1979            if "<data/>" in recv_xml:
1980                need_cfg = True
1981            else:
1982                re_find = re.findall(
1983                    r'.*<supernetLabelAdv>(.*)</supernetLabelAdv>.*', recv_xml)
1984
1985                if re_find:
1986                    result["supernet_label_adv"] = re_find
1987                    result["vrf_name"] = vrf_name
1988                    if re_find[0] != supernet_label_adv:
1989                        need_cfg = True
1990                else:
1991                    need_cfg = True
1992
1993        ingress_lsp_policy_name = module.params['ingress_lsp_policy_name']
1994        if ingress_lsp_policy_name:
1995            if len(ingress_lsp_policy_name) > 40 or len(ingress_lsp_policy_name) < 1:
1996                module.fail_json(
1997                    msg='Error: The len of ingress_lsp_policy_name %s is out of [1 - 40].' % ingress_lsp_policy_name)
1998
1999            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
2000                "<ingressLspPolicyName></ingressLspPolicyName>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
2001            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
2002
2003            if "<data/>" in recv_xml:
2004                need_cfg = True
2005            else:
2006                re_find = re.findall(
2007                    r'.*<ingressLspPolicyName>(.*)</ingressLspPolicyName>.*', recv_xml)
2008
2009                if re_find:
2010                    result["ingress_lsp_policy_name"] = re_find
2011                    result["vrf_name"] = vrf_name
2012                    if re_find[0] != ingress_lsp_policy_name:
2013                        need_cfg = True
2014                else:
2015                    need_cfg = True
2016
2017        originator_prior = module.params['originator_prior']
2018        if originator_prior != 'no_use':
2019
2020            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
2021                "<originatorPrior></originatorPrior>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
2022            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
2023
2024            if "<data/>" in recv_xml:
2025                need_cfg = True
2026            else:
2027                re_find = re.findall(
2028                    r'.*<originatorPrior>(.*)</originatorPrior>.*', recv_xml)
2029
2030                if re_find:
2031                    result["originator_prior"] = re_find
2032                    result["vrf_name"] = vrf_name
2033                    if re_find[0] != originator_prior:
2034                        need_cfg = True
2035                else:
2036                    need_cfg = True
2037
2038        lowest_priority = module.params['lowest_priority']
2039        if lowest_priority != 'no_use':
2040
2041            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
2042                "<lowestPriority></lowestPriority>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
2043            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
2044
2045            if "<data/>" in recv_xml:
2046                need_cfg = True
2047            else:
2048                re_find = re.findall(
2049                    r'.*<lowestPriority>(.*)</lowestPriority>.*', recv_xml)
2050
2051                if re_find:
2052                    result["lowest_priority"] = re_find
2053                    result["vrf_name"] = vrf_name
2054                    if re_find[0] != lowest_priority:
2055                        need_cfg = True
2056                else:
2057                    need_cfg = True
2058
2059        relay_delay_enable = module.params['relay_delay_enable']
2060        if relay_delay_enable != 'no_use':
2061
2062            conf_str = CE_GET_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type) + \
2063                "<relayDelayEnable></relayDelayEnable>" + CE_GET_BGP_ADDRESS_FAMILY_TAIL
2064            recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
2065
2066            if "<data/>" in recv_xml:
2067                need_cfg = True
2068            else:
2069                re_find = re.findall(
2070                    r'.*<relayDelayEnable>(.*)</relayDelayEnable>.*', recv_xml)
2071
2072                if re_find:
2073                    result["relay_delay_enable"] = re_find
2074                    result["vrf_name"] = vrf_name
2075                    if re_find[0] != relay_delay_enable:
2076                        need_cfg = True
2077                else:
2078                    need_cfg = True
2079
2080        result["need_cfg"] = need_cfg
2081        return result
2082
2083    def check_bgp_import_network_route(self, **kwargs):
2084        """ check_bgp_import_network_route """
2085
2086        module = kwargs["module"]
2087        result = dict()
2088        import_need_cfg = False
2089        network_need_cfg = False
2090
2091        vrf_name = module.params['vrf_name']
2092
2093        state = module.params['state']
2094        af_type = module.params['af_type']
2095        import_protocol = module.params['import_protocol']
2096        import_process_id = module.params['import_process_id']
2097
2098        if import_protocol and (import_protocol != "direct" and import_protocol != "static"):
2099            if not import_process_id:
2100                module.fail_json(
2101                    msg='Error: Please input import_protocol and import_process_id value at the same time.')
2102            else:
2103                if int(import_process_id) < 0:
2104                    module.fail_json(
2105                        msg='Error: The value of import_process_id %s is out of [0 - 4294967295].' % import_process_id)
2106
2107        if import_process_id:
2108            if not import_protocol:
2109                module.fail_json(
2110                    msg='Error: Please input import_protocol and import_process_id value at the same time.')
2111
2112        network_address = module.params['network_address']
2113        mask_len = module.params['mask_len']
2114
2115        if network_address:
2116            if not mask_len:
2117                module.fail_json(
2118                    msg='Error: Please input network_address and mask_len value at the same time.')
2119        if mask_len:
2120            if not network_address:
2121                module.fail_json(
2122                    msg='Error: Please input network_address and mask_len value at the same time.')
2123
2124        conf_str = CE_GET_BGP_IMPORT_AND_NETWORK_ROUTE % (vrf_name, af_type)
2125        recv_xml = self.netconf_get_config(module=module, conf_str=conf_str)
2126
2127        if import_protocol:
2128
2129            if import_protocol == "direct" or import_protocol == "static":
2130                import_process_id = "0"
2131            else:
2132                if not import_process_id or import_process_id == "0":
2133                    module.fail_json(
2134                        msg='Error: Please input import_process_id not 0 when import_protocol is '
2135                            '[ospf, isis, rip, ospfv3, ripng].')
2136
2137            bgp_import_route_new = (import_protocol, import_process_id)
2138
2139            if state == "present":
2140                if "<data/>" in recv_xml:
2141                    import_need_cfg = True
2142                else:
2143                    re_find = re.findall(
2144                        r'.*<importProtocol>(.*)</importProtocol>.*\s.*<importProcessId>(.*)</importProcessId>.*',
2145                        recv_xml)
2146
2147                    if re_find:
2148                        result["bgp_import_route"] = re_find
2149                        result["vrf_name"] = vrf_name
2150                        if bgp_import_route_new not in re_find:
2151                            import_need_cfg = True
2152                    else:
2153                        import_need_cfg = True
2154            else:
2155                if "<data/>" in recv_xml:
2156                    pass
2157                else:
2158                    re_find = re.findall(
2159                        r'.*<importProtocol>(.*)</importProtocol>.*\s.*<importProcessId>(.*)</importProcessId>.*',
2160                        recv_xml)
2161
2162                    if re_find:
2163                        result["bgp_import_route"] = re_find
2164                        result["vrf_name"] = vrf_name
2165                        if bgp_import_route_new in re_find:
2166                            import_need_cfg = True
2167
2168        if network_address and mask_len:
2169
2170            bgp_network_route_new = (network_address, mask_len)
2171
2172            if not check_ip_addr(ipaddr=network_address):
2173                module.fail_json(
2174                    msg='Error: The network_address %s is invalid.' % network_address)
2175
2176            if len(mask_len) > 128:
2177                module.fail_json(
2178                    msg='Error: The len of mask_len %s is out of [0 - 128].' % mask_len)
2179
2180            if state == "present":
2181                if "<data/>" in recv_xml:
2182                    network_need_cfg = True
2183                else:
2184                    re_find = re.findall(
2185                        r'.*<networkAddress>(.*)</networkAddress>.*\s.*<maskLen>(.*)</maskLen>.*', recv_xml)
2186
2187                    if re_find:
2188                        result["bgp_network_route"] = re_find
2189                        result["vrf_name"] = vrf_name
2190                        if bgp_network_route_new not in re_find:
2191                            network_need_cfg = True
2192                    else:
2193                        network_need_cfg = True
2194            else:
2195                if "<data/>" in recv_xml:
2196                    pass
2197                else:
2198                    re_find = re.findall(
2199                        r'.*<networkAddress>(.*)</networkAddress>.*\s.*<maskLen>(.*)</maskLen>.*', recv_xml)
2200
2201                    if re_find:
2202                        result["bgp_network_route"] = re_find
2203                        result["vrf_name"] = vrf_name
2204                        if bgp_network_route_new in re_find:
2205                            network_need_cfg = True
2206
2207        result["import_need_cfg"] = import_need_cfg
2208        result["network_need_cfg"] = network_need_cfg
2209        return result
2210
2211    def merge_bgp_af(self, **kwargs):
2212        """ merge_bgp_af """
2213
2214        module = kwargs["module"]
2215
2216        vrf_name = module.params['vrf_name']
2217
2218        af_type = module.params['af_type']
2219
2220        conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (
2221            vrf_name, af_type) + CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
2222
2223        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2224
2225        if "<ok/>" not in recv_xml:
2226            module.fail_json(msg='Error: Merge bgp address family failed.')
2227
2228        cmds = []
2229
2230        cmd = "ipv4-family vpn-instance %s" % vrf_name
2231
2232        if af_type == "ipv4multi":
2233            cmd = "ipv4-family multicast"
2234        elif af_type == "ipv4vpn":
2235            cmd = "ipv4-family vpnv4"
2236        elif af_type == "ipv6uni":
2237            cmd = "ipv6-family vpn-instance %s" % vrf_name
2238            if vrf_name == "_public_":
2239                cmd = "ipv6-family unicast"
2240        elif af_type == "ipv6vpn":
2241            cmd = "ipv6-family vpnv6"
2242        elif af_type == "evpn":
2243            cmd = "l2vpn-family evpn"
2244        cmds.append(cmd)
2245
2246        return cmds
2247
2248    def create_bgp_af(self, **kwargs):
2249        """ create_bgp_af """
2250
2251        module = kwargs["module"]
2252
2253        vrf_name = module.params['vrf_name']
2254
2255        af_type = module.params['af_type']
2256
2257        conf_str = CE_CREATE_BGP_ADDRESS_FAMILY_HEADER % (
2258            vrf_name, af_type) + CE_CREATE_BGP_ADDRESS_FAMILY_TAIL
2259
2260        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2261
2262        if "<ok/>" not in recv_xml:
2263            module.fail_json(msg='Error: Create bgp address family failed.')
2264
2265        cmds = []
2266
2267        cmd = "ipv4-family vpn-instance %s" % vrf_name
2268
2269        if af_type == "ipv4multi":
2270            cmd = "ipv4-family multicast"
2271        elif af_type == "ipv4vpn":
2272            cmd = "ipv4-family vpnv4"
2273        elif af_type == "ipv6uni":
2274            cmd = "ipv6-family vpn-instance %s" % vrf_name
2275            if vrf_name == "_public_":
2276                cmd = "ipv6-family unicast"
2277        elif af_type == "ipv6vpn":
2278            cmd = "ipv6-family vpnv6"
2279        elif af_type == "evpn":
2280            cmd = "l2vpn-family evpn"
2281        cmds.append(cmd)
2282
2283        return cmds
2284
2285    def delete_bgp_af(self, **kwargs):
2286        """ delete_bgp_af """
2287
2288        module = kwargs["module"]
2289
2290        vrf_name = module.params['vrf_name']
2291
2292        af_type = module.params['af_type']
2293
2294        conf_str = CE_DELETE_BGP_ADDRESS_FAMILY_HEADER % (
2295            vrf_name, af_type) + CE_DELETE_BGP_ADDRESS_FAMILY_TAIL
2296
2297        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2298
2299        if "<ok/>" not in recv_xml:
2300            module.fail_json(msg='Error: Delete bgp address family failed.')
2301
2302        cmds = []
2303
2304        cmd = "undo ipv4-family vpn-instance %s" % vrf_name
2305
2306        if af_type == "ipv4multi":
2307            cmd = "undo ipv4-family multicast"
2308        elif af_type == "ipv4vpn":
2309            cmd = "undo ipv4-family vpnv4"
2310        elif af_type == "ipv6uni":
2311            cmd = "undo ipv6-family vpn-instance %s" % vrf_name
2312            if vrf_name == "_public_":
2313                cmd = "undo ipv6-family unicast"
2314        elif af_type == "ipv6vpn":
2315            cmd = "undo ipv6-family vpnv6"
2316        elif af_type == "evpn":
2317            cmd = "l2vpn-family evpn"
2318        cmds.append(cmd)
2319
2320        return cmds
2321
2322    def merge_bgp_af_other(self, **kwargs):
2323        """ merge_bgp_af_other """
2324
2325        module = kwargs["module"]
2326        vrf_name = module.params['vrf_name']
2327        af_type = module.params['af_type']
2328
2329        conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type)
2330
2331        cmds = []
2332
2333        max_load_ibgp_num = module.params['max_load_ibgp_num']
2334        if max_load_ibgp_num:
2335            conf_str += "<maxLoadIbgpNum>%s</maxLoadIbgpNum>" % max_load_ibgp_num
2336
2337            cmd = "maximum load-balancing ibgp %s" % max_load_ibgp_num
2338            cmds.append(cmd)
2339
2340        ibgp_ecmp_nexthop_changed = module.params['ibgp_ecmp_nexthop_changed']
2341        if ibgp_ecmp_nexthop_changed != 'no_use':
2342            conf_str += "<ibgpEcmpNexthopChanged>%s</ibgpEcmpNexthopChanged>" % ibgp_ecmp_nexthop_changed
2343
2344            if ibgp_ecmp_nexthop_changed == "true":
2345                cmd = "maximum load-balancing ibgp %s ecmp-nexthop-changed" % max_load_ibgp_num
2346                cmds.append(cmd)
2347            else:
2348                cmd = "undo maximum load-balancing ibgp %s ecmp-nexthop-changed" % max_load_ibgp_num
2349                cmds.append(cmd)
2350        max_load_ebgp_num = module.params['max_load_ebgp_num']
2351        if max_load_ebgp_num:
2352            conf_str += "<maxLoadEbgpNum>%s</maxLoadEbgpNum>" % max_load_ebgp_num
2353
2354            cmd = "maximum load-balancing ebgp %s" % max_load_ebgp_num
2355            cmds.append(cmd)
2356
2357        ebgp_ecmp_nexthop_changed = module.params['ebgp_ecmp_nexthop_changed']
2358        if ebgp_ecmp_nexthop_changed != 'no_use':
2359            conf_str += "<ebgpEcmpNexthopChanged>%s</ebgpEcmpNexthopChanged>" % ebgp_ecmp_nexthop_changed
2360
2361            if ebgp_ecmp_nexthop_changed == "true":
2362                cmd = "maximum load-balancing ebgp %s ecmp-nexthop-changed" % max_load_ebgp_num
2363            else:
2364                cmd = "undo maximum load-balancing ebgp %s ecmp-nexthop-changed" % max_load_ebgp_num
2365            cmds.append(cmd)
2366
2367        maximum_load_balance = module.params['maximum_load_balance']
2368        if maximum_load_balance:
2369            conf_str += "<maximumLoadBalance>%s</maximumLoadBalance>" % maximum_load_balance
2370
2371            cmd = "maximum load-balancing %s" % maximum_load_balance
2372            cmds.append(cmd)
2373
2374        ecmp_nexthop_changed = module.params['ecmp_nexthop_changed']
2375        if ecmp_nexthop_changed != 'no_use':
2376            conf_str += "<ecmpNexthopChanged>%s</ecmpNexthopChanged>" % ecmp_nexthop_changed
2377
2378            if ecmp_nexthop_changed == "true":
2379                cmd = "maximum load-balancing %s ecmp-nexthop-changed" % maximum_load_balance
2380            else:
2381                cmd = "undo maximum load-balancing %s ecmp-nexthop-changed" % maximum_load_balance
2382            cmds.append(cmd)
2383
2384        default_local_pref = module.params['default_local_pref']
2385        if default_local_pref:
2386            conf_str += "<defaultLocalPref>%s</defaultLocalPref>" % default_local_pref
2387
2388            cmd = "default local-preference %s" % default_local_pref
2389            cmds.append(cmd)
2390
2391        default_med = module.params['default_med']
2392        if default_med:
2393            conf_str += "<defaultMed>%s</defaultMed>" % default_med
2394
2395            cmd = "default med %s" % default_med
2396            cmds.append(cmd)
2397
2398        default_rt_import_enable = module.params['default_rt_import_enable']
2399        if default_rt_import_enable != 'no_use':
2400            conf_str += "<defaultRtImportEnable>%s</defaultRtImportEnable>" % default_rt_import_enable
2401
2402            if default_rt_import_enable == "true":
2403                cmd = "default-route imported"
2404            else:
2405                cmd = "undo default-route imported"
2406            cmds.append(cmd)
2407
2408        router_id = module.params['router_id']
2409        if router_id:
2410            conf_str += "<routerId>%s</routerId>" % router_id
2411
2412            cmd = "router-id %s" % router_id
2413            cmds.append(cmd)
2414
2415        vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
2416        if vrf_rid_auto_sel != 'no_use':
2417            conf_str += "<vrfRidAutoSel>%s</vrfRidAutoSel>" % vrf_rid_auto_sel
2418            family = "ipv4-family"
2419            if af_type == "ipv6uni":
2420                family = "ipv6-family"
2421            if vrf_rid_auto_sel == "true":
2422                cmd = "%s vpn-instance %s" % (family, vrf_name)
2423                cmds.append(cmd)
2424                cmd = "router-id auto-select"
2425                cmds.append(cmd)
2426            else:
2427                cmd = "%s vpn-instance %s" % (family, vrf_name)
2428                cmds.append(cmd)
2429                cmd = "undo router-id auto-select"
2430                cmds.append(cmd)
2431
2432        nexthop_third_party = module.params['nexthop_third_party']
2433        if nexthop_third_party != 'no_use':
2434            conf_str += "<nexthopThirdParty>%s</nexthopThirdParty>" % nexthop_third_party
2435
2436            if nexthop_third_party == "true":
2437                cmd = "nexthop third-party"
2438            else:
2439                cmd = "undo nexthop third-party"
2440            cmds.append(cmd)
2441
2442        summary_automatic = module.params['summary_automatic']
2443        if summary_automatic != 'no_use':
2444            conf_str += "<summaryAutomatic>%s</summaryAutomatic>" % summary_automatic
2445
2446            if summary_automatic == "true":
2447                cmd = "summary automatic"
2448            else:
2449                cmd = "undo summary automatic"
2450            cmds.append(cmd)
2451
2452        auto_frr_enable = module.params['auto_frr_enable']
2453        if auto_frr_enable != 'no_use':
2454            conf_str += "<autoFrrEnable>%s</autoFrrEnable>" % auto_frr_enable
2455
2456            if auto_frr_enable == "true":
2457                cmd = "auto-frr"
2458            else:
2459                cmd = "undo auto-frr"
2460            cmds.append(cmd)
2461
2462        load_balancing_as_path_ignore = module.params[
2463            'load_balancing_as_path_ignore']
2464        if load_balancing_as_path_ignore != 'no_use':
2465            conf_str += "<loadBalancingAsPathIgnore>%s</loadBalancingAsPathIgnore>" % load_balancing_as_path_ignore
2466
2467            if load_balancing_as_path_ignore == "true":
2468                cmd = "load-balancing as-path-ignore"
2469            else:
2470                cmd = "undo load-balancing as-path-ignore"
2471            cmds.append(cmd)
2472
2473        rib_only_enable = module.params['rib_only_enable']
2474        if rib_only_enable != 'no_use':
2475            conf_str += "<ribOnlyEnable>%s</ribOnlyEnable>" % rib_only_enable
2476
2477            if rib_only_enable == "true":
2478                cmd = "routing-table rib-only"
2479            else:
2480                cmd = "undo routing-table rib-only"
2481            cmds.append(cmd)
2482
2483        rib_only_policy_name = module.params['rib_only_policy_name']
2484        if rib_only_policy_name and rib_only_enable == "true":
2485            conf_str += "<ribOnlyPolicyName>%s</ribOnlyPolicyName>" % rib_only_policy_name
2486
2487            cmd = "routing-table rib-only route-policy %s" % rib_only_policy_name
2488            cmds.append(cmd)
2489
2490        active_route_advertise = module.params['active_route_advertise']
2491        if active_route_advertise != 'no_use':
2492            conf_str += "<activeRouteAdvertise>%s</activeRouteAdvertise>" % active_route_advertise
2493
2494            if active_route_advertise == "true":
2495                cmd = "active-route-advertise"
2496            else:
2497                cmd = "undo active-route-advertise"
2498            cmds.append(cmd)
2499
2500        as_path_neglect = module.params['as_path_neglect']
2501        if as_path_neglect != 'no_use':
2502            conf_str += "<asPathNeglect>%s</asPathNeglect>" % as_path_neglect
2503
2504            if as_path_neglect == "true":
2505                cmd = "bestroute as-path-ignore"
2506            else:
2507                cmd = "undo bestroute as-path-ignore"
2508            cmds.append(cmd)
2509
2510        med_none_as_maximum = module.params['med_none_as_maximum']
2511        if med_none_as_maximum != 'no_use':
2512            conf_str += "<medNoneAsMaximum>%s</medNoneAsMaximum>" % med_none_as_maximum
2513
2514            if med_none_as_maximum == "true":
2515                cmd = "bestroute med-none-as-maximum"
2516            else:
2517                cmd = "undo bestroute med-none-as-maximum"
2518            cmds.append(cmd)
2519
2520        router_id_neglect = module.params['router_id_neglect']
2521        if router_id_neglect != 'no_use':
2522            conf_str += "<routerIdNeglect>%s</routerIdNeglect>" % router_id_neglect
2523
2524            if router_id_neglect == "true":
2525                cmd = "bestroute router-id-ignore"
2526            else:
2527                cmd = "undo bestroute router-id-ignore"
2528            cmds.append(cmd)
2529
2530        igp_metric_ignore = module.params['igp_metric_ignore']
2531        if igp_metric_ignore != 'no_use':
2532            conf_str += "<igpMetricIgnore>%s</igpMetricIgnore>" % igp_metric_ignore
2533
2534            if igp_metric_ignore == "true":
2535                cmd = "bestroute igp-metric-ignore"
2536                cmds.append(cmd)
2537            else:
2538                cmd = "undo bestroute igp-metric-ignore"
2539                cmds.append(cmd)
2540        always_compare_med = module.params['always_compare_med']
2541        if always_compare_med != 'no_use':
2542            conf_str += "<alwaysCompareMed>%s</alwaysCompareMed>" % always_compare_med
2543
2544            if always_compare_med == "true":
2545                cmd = "compare-different-as-med"
2546                cmds.append(cmd)
2547            else:
2548                cmd = "undo compare-different-as-med"
2549                cmds.append(cmd)
2550        determin_med = module.params['determin_med']
2551        if determin_med != 'no_use':
2552            conf_str += "<determinMed>%s</determinMed>" % determin_med
2553
2554            if determin_med == "true":
2555                cmd = "deterministic-med"
2556                cmds.append(cmd)
2557            else:
2558                cmd = "undo deterministic-med"
2559                cmds.append(cmd)
2560
2561        preference_external = module.params['preference_external']
2562        preference_internal = module.params['preference_internal']
2563        preference_local = module.params['preference_local']
2564        if any([preference_external, preference_internal, preference_local]):
2565            preference_external = preference_external or "255"
2566            preference_internal = preference_internal or "255"
2567            preference_local = preference_local or "255"
2568
2569            conf_str += "<preferenceExternal>%s</preferenceExternal>" % preference_external
2570            conf_str += "<preferenceInternal>%s</preferenceInternal>" % preference_internal
2571            conf_str += "<preferenceLocal>%s</preferenceLocal>" % preference_local
2572
2573            cmd = "preference %s %s %s" % (
2574                preference_external, preference_internal, preference_local)
2575            cmds.append(cmd)
2576
2577        prefrence_policy_name = module.params['prefrence_policy_name']
2578        if prefrence_policy_name:
2579            conf_str += "<prefrencePolicyName>%s</prefrencePolicyName>" % prefrence_policy_name
2580
2581            cmd = "preference route-policy %s" % prefrence_policy_name
2582            cmds.append(cmd)
2583
2584        reflect_between_client = module.params['reflect_between_client']
2585        if reflect_between_client != 'no_use':
2586            conf_str += "<reflectBetweenClient>%s</reflectBetweenClient>" % reflect_between_client
2587
2588            if reflect_between_client == "true":
2589                cmd = "reflect between-clients"
2590            else:
2591                cmd = "undo reflect between-clients"
2592            cmds.append(cmd)
2593
2594        reflector_cluster_id = module.params['reflector_cluster_id']
2595        if reflector_cluster_id:
2596            conf_str += "<reflectorClusterId>%s</reflectorClusterId>" % reflector_cluster_id
2597
2598            cmd = "reflector cluster-id %s" % reflector_cluster_id
2599            cmds.append(cmd)
2600
2601        reflector_cluster_ipv4 = module.params['reflector_cluster_ipv4']
2602        if reflector_cluster_ipv4:
2603            conf_str += "<reflectorClusterIpv4>%s</reflectorClusterIpv4>" % reflector_cluster_ipv4
2604
2605            cmd = "reflector cluster-id %s" % reflector_cluster_ipv4
2606            cmds.append(cmd)
2607
2608        rr_filter_number = module.params['rr_filter_number']
2609        if rr_filter_number:
2610            conf_str += "<rrFilterNumber>%s</rrFilterNumber>" % rr_filter_number
2611            cmd = 'rr-filter %s' % rr_filter_number
2612            cmds.append(cmd)
2613
2614        policy_vpn_target = module.params['policy_vpn_target']
2615        if policy_vpn_target != 'no_use':
2616            conf_str += "<policyVpnTarget>%s</policyVpnTarget>" % policy_vpn_target
2617            if policy_vpn_target == 'true':
2618                cmd = 'policy vpn-target'
2619            else:
2620                cmd = 'undo policy vpn-target'
2621            cmds.append(cmd)
2622
2623        next_hop_sel_depend_type = module.params['next_hop_sel_depend_type']
2624        if next_hop_sel_depend_type:
2625            conf_str += "<nextHopSelDependType>%s</nextHopSelDependType>" % next_hop_sel_depend_type
2626
2627        nhp_relay_route_policy_name = module.params[
2628            'nhp_relay_route_policy_name']
2629        if nhp_relay_route_policy_name:
2630            conf_str += "<nhpRelayRoutePolicyName>%s</nhpRelayRoutePolicyName>" % nhp_relay_route_policy_name
2631
2632            cmd = "nexthop recursive-lookup route-policy %s" % nhp_relay_route_policy_name
2633            cmds.append(cmd)
2634
2635        ebgp_if_sensitive = module.params['ebgp_if_sensitive']
2636        if ebgp_if_sensitive != 'no_use':
2637            conf_str += "<ebgpIfSensitive>%s</ebgpIfSensitive>" % ebgp_if_sensitive
2638
2639            if ebgp_if_sensitive == "true":
2640                cmd = "ebgp-interface-sensitive"
2641            else:
2642                cmd = "undo ebgp-interface-sensitive"
2643            cmds.append(cmd)
2644
2645        reflect_chg_path = module.params['reflect_chg_path']
2646        if reflect_chg_path != 'no_use':
2647            conf_str += "<reflectChgPath>%s</reflectChgPath>" % reflect_chg_path
2648
2649            if reflect_chg_path == "true":
2650                cmd = "reflect change-path-attribute"
2651            else:
2652                cmd = "undo reflect change-path-attribute"
2653            cmds.append(cmd)
2654
2655        add_path_sel_num = module.params['add_path_sel_num']
2656        if add_path_sel_num:
2657            conf_str += "<addPathSelNum>%s</addPathSelNum>" % add_path_sel_num
2658
2659            cmd = "bestroute add-path path-number %s" % add_path_sel_num
2660            cmds.append(cmd)
2661
2662        route_sel_delay = module.params['route_sel_delay']
2663        if route_sel_delay:
2664            conf_str += "<routeSelDelay>%s</routeSelDelay>" % route_sel_delay
2665
2666            cmd = "route-select delay %s" % route_sel_delay
2667            cmds.append(cmd)
2668
2669        allow_invalid_as = module.params['allow_invalid_as']
2670        if allow_invalid_as != 'no_use':
2671            conf_str += "<allowInvalidAs>%s</allowInvalidAs>" % allow_invalid_as
2672
2673        policy_ext_comm_enable = module.params['policy_ext_comm_enable']
2674        if policy_ext_comm_enable != 'no_use':
2675            conf_str += "<policyExtCommEnable>%s</policyExtCommEnable>" % policy_ext_comm_enable
2676
2677            if policy_ext_comm_enable == "true":
2678                cmd = "ext-community-change enable"
2679            else:
2680                cmd = "undo ext-community-change enable"
2681            cmds.append(cmd)
2682
2683        supernet_uni_adv = module.params['supernet_uni_adv']
2684        if supernet_uni_adv != 'no_use':
2685            conf_str += "<supernetUniAdv>%s</supernetUniAdv>" % supernet_uni_adv
2686
2687            if supernet_uni_adv == "true":
2688                cmd = "supernet unicast advertise enable"
2689            else:
2690                cmd = "undo supernet unicast advertise enable"
2691            cmds.append(cmd)
2692
2693        supernet_label_adv = module.params['supernet_label_adv']
2694        if supernet_label_adv != 'no_use':
2695            conf_str += "<supernetLabelAdv>%s</supernetLabelAdv>" % supernet_label_adv
2696
2697            if supernet_label_adv == "true":
2698                cmd = "supernet label-route advertise enable"
2699            else:
2700                cmd = "undo supernet label-route advertise enable"
2701            cmds.append(cmd)
2702
2703        ingress_lsp_policy_name = module.params['ingress_lsp_policy_name']
2704        if ingress_lsp_policy_name:
2705            conf_str += "<ingressLspPolicyName>%s</ingressLspPolicyName>" % ingress_lsp_policy_name
2706            cmd = "ingress-lsp trigger route-policy %s" % ingress_lsp_policy_name
2707            cmds.append(cmd)
2708
2709        originator_prior = module.params['originator_prior']
2710        if originator_prior != 'no_use':
2711            conf_str += "<originatorPrior>%s</originatorPrior>" % originator_prior
2712            if originator_prior == "true":
2713                cmd = "bestroute routerid-prior-clusterlist"
2714            else:
2715                cmd = "undo bestroute routerid-prior-clusterlist"
2716            cmds.append(cmd)
2717
2718        lowest_priority = module.params['lowest_priority']
2719        if lowest_priority != 'no_use':
2720            conf_str += "<lowestPriority>%s</lowestPriority>" % lowest_priority
2721
2722            if lowest_priority == "true":
2723                cmd = "advertise lowest-priority on-startup"
2724            else:
2725                cmd = "undo advertise lowest-priority on-startup"
2726            cmds.append(cmd)
2727
2728        relay_delay_enable = module.params['relay_delay_enable']
2729        if relay_delay_enable != 'no_use':
2730            conf_str += "<relayDelayEnable>%s</relayDelayEnable>" % relay_delay_enable
2731
2732            if relay_delay_enable == "true":
2733                cmd = "nexthop recursive-lookup restrain enable"
2734            else:
2735                cmd = "nexthop recursive-lookup restrain disable"
2736            cmds.append(cmd)
2737        conf_str += CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
2738        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2739
2740        if "<ok/>" not in recv_xml:
2741            module.fail_json(
2742                msg='Error: Merge bgp address family other agrus failed.')
2743
2744        return cmds
2745
2746    def delete_bgp_af_other(self, **kwargs):
2747        """ delete_bgp_af_other """
2748
2749        module = kwargs["module"]
2750        vrf_name = module.params['vrf_name']
2751        af_type = module.params['af_type']
2752
2753        conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (vrf_name, af_type)
2754
2755        cmds = []
2756
2757        router_id = module.params['router_id']
2758        if router_id:
2759            conf_str += "<routerId></routerId>"
2760
2761            cmd = "undo router-id %s" % router_id
2762            cmds.append(cmd)
2763
2764        determin_med = module.params['determin_med']
2765        if determin_med != 'no_use':
2766            conf_str += "<determinMed></determinMed>"
2767
2768            cmd = "undo deterministic-med"
2769            cmds.append(cmd)
2770
2771        ebgp_if_sensitive = module.params['ebgp_if_sensitive']
2772        if ebgp_if_sensitive != 'no_use':
2773            conf_str += "<ebgpIfSensitive></ebgpIfSensitive>"
2774
2775            cmd = "undo ebgp-interface-sensitive"
2776            cmds.append(cmd)
2777
2778        relay_delay_enable = module.params['relay_delay_enable']
2779        if relay_delay_enable != 'no_use':
2780            conf_str += "<relayDelayEnable></relayDelayEnable>"
2781
2782        conf_str += CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
2783        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2784
2785        if "<ok/>" not in recv_xml:
2786            module.fail_json(
2787                msg='Error: Merge bgp address family other agrus failed.')
2788
2789        return cmds
2790
2791    def merge_bgp_import_route(self, **kwargs):
2792        """ merge_bgp_import_route """
2793
2794        module = kwargs["module"]
2795
2796        vrf_name = module.params['vrf_name']
2797
2798        af_type = module.params['af_type']
2799        import_protocol = module.params['import_protocol']
2800        import_process_id = module.params['import_process_id']
2801
2802        if import_protocol == "direct" or import_protocol == "static":
2803            import_process_id = "0"
2804
2805        conf_str = CE_MERGE_BGP_IMPORT_ROUTE_HEADER % (
2806            vrf_name, af_type, import_protocol, import_process_id) + CE_MERGE_BGP_IMPORT_ROUTE_TAIL
2807
2808        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2809
2810        if "<ok/>" not in recv_xml:
2811            module.fail_json(msg='Error: Merge bgp import route failed.')
2812
2813        cmds = []
2814        cmd = "import-route %s %s" % (import_protocol, import_process_id)
2815        if import_protocol == "direct" or import_protocol == "static":
2816            cmd = "import-route %s" % import_protocol
2817        cmds.append(cmd)
2818
2819        return cmds
2820
2821    def create_bgp_import_route(self, **kwargs):
2822        """ create_bgp_import_route """
2823
2824        module = kwargs["module"]
2825
2826        vrf_name = module.params['vrf_name']
2827
2828        af_type = module.params['af_type']
2829        import_protocol = module.params['import_protocol']
2830        import_process_id = module.params['import_process_id']
2831
2832        if import_protocol == "direct" or import_protocol == "static":
2833            import_process_id = "0"
2834
2835        conf_str = CE_CREATE_BGP_IMPORT_ROUTE % (
2836            vrf_name, af_type, import_protocol, import_process_id)
2837
2838        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2839
2840        if "<ok/>" not in recv_xml:
2841            module.fail_json(msg='Error: Create bgp import route failed.')
2842
2843        cmds = []
2844        cmd = "import-route %s %s" % (import_protocol, import_process_id)
2845        if import_protocol == "direct" or import_protocol == "static":
2846            cmd = "import-route %s" % import_protocol
2847        cmds.append(cmd)
2848
2849        return cmds
2850
2851    def delete_bgp_import_route(self, **kwargs):
2852        """ delete_bgp_import_route """
2853
2854        module = kwargs["module"]
2855
2856        vrf_name = module.params['vrf_name']
2857
2858        af_type = module.params['af_type']
2859        import_protocol = module.params['import_protocol']
2860        import_process_id = module.params['import_process_id']
2861
2862        if import_protocol == "direct" or import_protocol == "static":
2863            import_process_id = "0"
2864
2865        conf_str = CE_DELETE_BGP_IMPORT_ROUTE % (
2866            vrf_name, af_type, import_protocol, import_process_id)
2867
2868        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2869
2870        if "<ok/>" not in recv_xml:
2871            module.fail_json(msg='Error: Delete bgp import route failed.')
2872
2873        cmds = []
2874        cmd = "undo import-route %s %s" % (import_protocol, import_process_id)
2875        if import_protocol == "direct" or import_protocol == "static":
2876            cmd = "undo import-route %s" % import_protocol
2877        cmds.append(cmd)
2878
2879        return cmds
2880
2881    def merge_bgp_network_route(self, **kwargs):
2882        """ merge_bgp_network_route """
2883
2884        module = kwargs["module"]
2885
2886        vrf_name = module.params['vrf_name']
2887
2888        af_type = module.params['af_type']
2889        network_address = module.params['network_address']
2890        mask_len = module.params['mask_len']
2891
2892        conf_str = CE_MERGE_BGP_NETWORK_ROUTE_HEADER % (
2893            vrf_name, af_type, network_address, mask_len) + CE_MERGE_BGP_NETWORK_ROUTE_TAIL
2894
2895        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2896
2897        if "<ok/>" not in recv_xml:
2898            module.fail_json(msg='Error: Merge bgp network route failed.')
2899
2900        cmds = []
2901        cmd = "network %s %s" % (network_address, mask_len)
2902        cmds.append(cmd)
2903
2904        return cmds
2905
2906    def create_bgp_network_route(self, **kwargs):
2907        """ create_bgp_network_route """
2908
2909        module = kwargs["module"]
2910
2911        vrf_name = module.params['vrf_name']
2912
2913        af_type = module.params['af_type']
2914        network_address = module.params['network_address']
2915        mask_len = module.params['mask_len']
2916
2917        conf_str = CE_CREATE_BGP_NETWORK_ROUTE % (
2918            vrf_name, af_type, network_address, mask_len)
2919
2920        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2921
2922        if "<ok/>" not in recv_xml:
2923            module.fail_json(msg='Error: Create bgp network route failed.')
2924
2925        cmds = []
2926        cmd = "network %s %s" % (network_address, mask_len)
2927        cmds.append(cmd)
2928
2929        return cmds
2930
2931    def delete_bgp_network_route(self, **kwargs):
2932        """ delete_bgp_network_route """
2933
2934        module = kwargs["module"]
2935
2936        vrf_name = module.params['vrf_name']
2937
2938        af_type = module.params['af_type']
2939        network_address = module.params['network_address']
2940        mask_len = module.params['mask_len']
2941
2942        conf_str = CE_DELETE_BGP_NETWORK_ROUTE % (
2943            vrf_name, af_type, network_address, mask_len)
2944
2945        recv_xml = self.netconf_set_config(module=module, conf_str=conf_str)
2946
2947        if "<ok/>" not in recv_xml:
2948            module.fail_json(msg='Error: Delete bgp network route failed.')
2949
2950        cmds = []
2951        cmd = "undo network %s %s" % (network_address, mask_len)
2952        cmds.append(cmd)
2953
2954        return cmds
2955
2956
2957def main():
2958    """ main """
2959
2960    argument_spec = dict(
2961        state=dict(choices=['present', 'absent'], default='present'),
2962        vrf_name=dict(type='str', required=True),
2963        af_type=dict(choices=['ipv4uni', 'ipv4multi', 'ipv4vpn',
2964                              'ipv6uni', 'ipv6vpn', 'evpn'], required=True),
2965        max_load_ibgp_num=dict(type='str'),
2966        ibgp_ecmp_nexthop_changed=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2967        max_load_ebgp_num=dict(type='str'),
2968        ebgp_ecmp_nexthop_changed=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2969        maximum_load_balance=dict(type='str'),
2970        ecmp_nexthop_changed=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2971        default_local_pref=dict(type='str'),
2972        default_med=dict(type='str'),
2973        default_rt_import_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2974        router_id=dict(type='str'),
2975        vrf_rid_auto_sel=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2976        nexthop_third_party=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2977        summary_automatic=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2978        auto_frr_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2979        load_balancing_as_path_ignore=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2980        rib_only_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2981        rib_only_policy_name=dict(type='str'),
2982        active_route_advertise=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2983        as_path_neglect=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2984        med_none_as_maximum=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2985        router_id_neglect=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2986        igp_metric_ignore=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2987        always_compare_med=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2988        determin_med=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2989        preference_external=dict(type='str'),
2990        preference_internal=dict(type='str'),
2991        preference_local=dict(type='str'),
2992        prefrence_policy_name=dict(type='str'),
2993        reflect_between_client=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2994        reflector_cluster_id=dict(type='str'),
2995        reflector_cluster_ipv4=dict(type='str'),
2996        rr_filter_number=dict(type='str'),
2997        policy_vpn_target=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
2998        next_hop_sel_depend_type=dict(
2999            choices=['default', 'dependTunnel', 'dependIp']),
3000        nhp_relay_route_policy_name=dict(type='str'),
3001        ebgp_if_sensitive=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3002        reflect_chg_path=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3003        add_path_sel_num=dict(type='str'),
3004        route_sel_delay=dict(type='str'),
3005        allow_invalid_as=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3006        policy_ext_comm_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3007        supernet_uni_adv=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3008        supernet_label_adv=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3009        ingress_lsp_policy_name=dict(type='str'),
3010        originator_prior=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3011        lowest_priority=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3012        relay_delay_enable=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
3013        import_protocol=dict(
3014            choices=['direct', 'ospf', 'isis', 'static', 'rip', 'ospfv3', 'ripng']),
3015        import_process_id=dict(type='str'),
3016        network_address=dict(type='str'),
3017        mask_len=dict(type='str'))
3018
3019    argument_spec.update(ce_argument_spec)
3020    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
3021
3022    changed = False
3023    proposed = dict()
3024    existing = dict()
3025    end_state = dict()
3026    updates = []
3027
3028    state = module.params['state']
3029    vrf_name = module.params['vrf_name']
3030    af_type = module.params['af_type']
3031    max_load_ibgp_num = module.params['max_load_ibgp_num']
3032    ibgp_ecmp_nexthop_changed = module.params['ibgp_ecmp_nexthop_changed']
3033    max_load_ebgp_num = module.params['max_load_ebgp_num']
3034    ebgp_ecmp_nexthop_changed = module.params['ebgp_ecmp_nexthop_changed']
3035    maximum_load_balance = module.params['maximum_load_balance']
3036    ecmp_nexthop_changed = module.params['ecmp_nexthop_changed']
3037    default_local_pref = module.params['default_local_pref']
3038    default_med = module.params['default_med']
3039    default_rt_import_enable = module.params['default_rt_import_enable']
3040    router_id = module.params['router_id']
3041    vrf_rid_auto_sel = module.params['vrf_rid_auto_sel']
3042    nexthop_third_party = module.params['nexthop_third_party']
3043    summary_automatic = module.params['summary_automatic']
3044    auto_frr_enable = module.params['auto_frr_enable']
3045    load_balancing_as_path_ignore = module.params[
3046        'load_balancing_as_path_ignore']
3047    rib_only_enable = module.params['rib_only_enable']
3048    rib_only_policy_name = module.params['rib_only_policy_name']
3049    active_route_advertise = module.params['active_route_advertise']
3050    as_path_neglect = module.params['as_path_neglect']
3051    med_none_as_maximum = module.params['med_none_as_maximum']
3052    router_id_neglect = module.params['router_id_neglect']
3053    igp_metric_ignore = module.params['igp_metric_ignore']
3054    always_compare_med = module.params['always_compare_med']
3055    determin_med = module.params['determin_med']
3056    preference_external = module.params['preference_external']
3057    preference_internal = module.params['preference_internal']
3058    preference_local = module.params['preference_local']
3059    prefrence_policy_name = module.params['prefrence_policy_name']
3060    reflect_between_client = module.params['reflect_between_client']
3061    reflector_cluster_id = module.params['reflector_cluster_id']
3062    reflector_cluster_ipv4 = module.params['reflector_cluster_ipv4']
3063    rr_filter_number = module.params['rr_filter_number']
3064    policy_vpn_target = module.params['policy_vpn_target']
3065    next_hop_sel_depend_type = module.params['next_hop_sel_depend_type']
3066    nhp_relay_route_policy_name = module.params['nhp_relay_route_policy_name']
3067    ebgp_if_sensitive = module.params['ebgp_if_sensitive']
3068    reflect_chg_path = module.params['reflect_chg_path']
3069    add_path_sel_num = module.params['add_path_sel_num']
3070    route_sel_delay = module.params['route_sel_delay']
3071    allow_invalid_as = module.params['allow_invalid_as']
3072    policy_ext_comm_enable = module.params['policy_ext_comm_enable']
3073    supernet_uni_adv = module.params['supernet_uni_adv']
3074    supernet_label_adv = module.params['supernet_label_adv']
3075    ingress_lsp_policy_name = module.params['ingress_lsp_policy_name']
3076    originator_prior = module.params['originator_prior']
3077    lowest_priority = module.params['lowest_priority']
3078    relay_delay_enable = module.params['relay_delay_enable']
3079    import_protocol = module.params['import_protocol']
3080    import_process_id = module.params['import_process_id']
3081    network_address = module.params['network_address']
3082    mask_len = module.params['mask_len']
3083
3084    ce_bgp_af_obj = BgpAf()
3085
3086    if not ce_bgp_af_obj:
3087        module.fail_json(msg='Error: Init module failed.')
3088
3089    # get proposed
3090    proposed["state"] = state
3091    if vrf_name:
3092        proposed["vrf_name"] = vrf_name
3093    if af_type:
3094        proposed["af_type"] = af_type
3095    if max_load_ibgp_num:
3096        proposed["max_load_ibgp_num"] = max_load_ibgp_num
3097    if ibgp_ecmp_nexthop_changed != 'no_use':
3098        proposed["ibgp_ecmp_nexthop_changed"] = ibgp_ecmp_nexthop_changed
3099    if max_load_ebgp_num:
3100        proposed["max_load_ebgp_num"] = max_load_ebgp_num
3101    if ebgp_ecmp_nexthop_changed != 'no_use':
3102        proposed["ebgp_ecmp_nexthop_changed"] = ebgp_ecmp_nexthop_changed
3103    if maximum_load_balance:
3104        proposed["maximum_load_balance"] = maximum_load_balance
3105    if ecmp_nexthop_changed != 'no_use':
3106        proposed["ecmp_nexthop_changed"] = ecmp_nexthop_changed
3107    if default_local_pref:
3108        proposed["default_local_pref"] = default_local_pref
3109    if default_med:
3110        proposed["default_med"] = default_med
3111    if default_rt_import_enable != 'no_use':
3112        proposed["default_rt_import_enable"] = default_rt_import_enable
3113    if router_id:
3114        proposed["router_id"] = router_id
3115    if vrf_rid_auto_sel != 'no_use':
3116        proposed["vrf_rid_auto_sel"] = vrf_rid_auto_sel
3117    if nexthop_third_party != 'no_use':
3118        proposed["nexthop_third_party"] = nexthop_third_party
3119    if summary_automatic != 'no_use':
3120        proposed["summary_automatic"] = summary_automatic
3121    if auto_frr_enable != 'no_use':
3122        proposed["auto_frr_enable"] = auto_frr_enable
3123    if load_balancing_as_path_ignore != 'no_use':
3124        proposed["load_balancing_as_path_ignore"] = load_balancing_as_path_ignore
3125    if rib_only_enable != 'no_use':
3126        proposed["rib_only_enable"] = rib_only_enable
3127    if rib_only_policy_name:
3128        proposed["rib_only_policy_name"] = rib_only_policy_name
3129    if active_route_advertise != 'no_use':
3130        proposed["active_route_advertise"] = active_route_advertise
3131    if as_path_neglect != 'no_use':
3132        proposed["as_path_neglect"] = as_path_neglect
3133    if med_none_as_maximum != 'no_use':
3134        proposed["med_none_as_maximum"] = med_none_as_maximum
3135    if router_id_neglect != 'no_use':
3136        proposed["router_id_neglect"] = router_id_neglect
3137    if igp_metric_ignore != 'no_use':
3138        proposed["igp_metric_ignore"] = igp_metric_ignore
3139    if always_compare_med != 'no_use':
3140        proposed["always_compare_med"] = always_compare_med
3141    if determin_med != 'no_use':
3142        proposed["determin_med"] = determin_med
3143    if preference_external:
3144        proposed["preference_external"] = preference_external
3145    if preference_internal:
3146        proposed["preference_internal"] = preference_internal
3147    if preference_local:
3148        proposed["preference_local"] = preference_local
3149    if prefrence_policy_name:
3150        proposed["prefrence_policy_name"] = prefrence_policy_name
3151    if reflect_between_client != 'no_use':
3152        proposed["reflect_between_client"] = reflect_between_client
3153    if reflector_cluster_id:
3154        proposed["reflector_cluster_id"] = reflector_cluster_id
3155    if reflector_cluster_ipv4:
3156        proposed["reflector_cluster_ipv4"] = reflector_cluster_ipv4
3157    if rr_filter_number:
3158        proposed["rr_filter_number"] = rr_filter_number
3159    if policy_vpn_target != 'no_use':
3160        proposed["policy_vpn_target"] = policy_vpn_target
3161    if next_hop_sel_depend_type:
3162        proposed["next_hop_sel_depend_type"] = next_hop_sel_depend_type
3163    if nhp_relay_route_policy_name:
3164        proposed["nhp_relay_route_policy_name"] = nhp_relay_route_policy_name
3165    if ebgp_if_sensitive != 'no_use':
3166        proposed["ebgp_if_sensitive"] = ebgp_if_sensitive
3167    if reflect_chg_path != 'no_use':
3168        proposed["reflect_chg_path"] = reflect_chg_path
3169    if add_path_sel_num:
3170        proposed["add_path_sel_num"] = add_path_sel_num
3171    if route_sel_delay:
3172        proposed["route_sel_delay"] = route_sel_delay
3173    if allow_invalid_as != 'no_use':
3174        proposed["allow_invalid_as"] = allow_invalid_as
3175    if policy_ext_comm_enable != 'no_use':
3176        proposed["policy_ext_comm_enable"] = policy_ext_comm_enable
3177    if supernet_uni_adv != 'no_use':
3178        proposed["supernet_uni_adv"] = supernet_uni_adv
3179    if supernet_label_adv != 'no_use':
3180        proposed["supernet_label_adv"] = supernet_label_adv
3181    if ingress_lsp_policy_name:
3182        proposed["ingress_lsp_policy_name"] = ingress_lsp_policy_name
3183    if originator_prior != 'no_use':
3184        proposed["originator_prior"] = originator_prior
3185    if lowest_priority != 'no_use':
3186        proposed["lowest_priority"] = lowest_priority
3187    if relay_delay_enable != 'no_use':
3188        proposed["relay_delay_enable"] = relay_delay_enable
3189    if import_protocol:
3190        proposed["import_protocol"] = import_protocol
3191    if import_process_id:
3192        proposed["import_process_id"] = import_process_id
3193    if network_address:
3194        proposed["network_address"] = network_address
3195    if mask_len:
3196        proposed["mask_len"] = mask_len
3197
3198    bgp_af_rst = ce_bgp_af_obj.check_bgp_af_args(module=module)
3199    bgp_af_other_rst = ce_bgp_af_obj.check_bgp_af_other_args(module=module)
3200    bgp_af_other_can_del_rst = ce_bgp_af_obj.check_bgp_af_other_can_del(
3201        module=module)
3202    bgp_import_network_route_rst = ce_bgp_af_obj.check_bgp_import_network_route(
3203        module=module)
3204
3205    # state exist bgp address family config
3206    exist_tmp = dict()
3207    for item in bgp_af_rst:
3208        if item != "need_cfg":
3209            exist_tmp[item] = bgp_af_rst[item]
3210
3211    if exist_tmp:
3212        existing["bgp af"] = exist_tmp
3213    # state exist bgp address family other config
3214    exist_tmp = dict()
3215    for item in bgp_af_other_rst:
3216        if item != "need_cfg":
3217            exist_tmp[item] = bgp_af_other_rst[item]
3218    if exist_tmp:
3219        existing["bgp af other"] = exist_tmp
3220    # state exist bgp import route config
3221    exist_tmp = dict()
3222    for item in bgp_import_network_route_rst:
3223        if item != "need_cfg":
3224            exist_tmp[item] = bgp_import_network_route_rst[item]
3225
3226    if exist_tmp:
3227        existing["bgp import & network route"] = exist_tmp
3228
3229    if state == "present":
3230        if bgp_af_rst["need_cfg"] and bgp_import_network_route_rst["import_need_cfg"] and \
3231                bgp_import_network_route_rst["network_need_cfg"]:
3232            changed = True
3233            if "af_type" in bgp_af_rst.keys():
3234                conf_str = CE_MERGE_BGP_ADDRESS_FAMILY_HEADER % (
3235                    vrf_name, af_type)
3236            else:
3237                conf_str = CE_CREATE_BGP_ADDRESS_FAMILY_HEADER % (
3238                    vrf_name, af_type)
3239
3240            if "bgp_import_route" in bgp_import_network_route_rst.keys():
3241                conf_str += CE_BGP_MERGE_IMPORT_UNIT % (
3242                    import_protocol, import_process_id)
3243            else:
3244                conf_str += CE_BGP_CREATE_IMPORT_UNIT % (
3245                    import_protocol, import_process_id)
3246
3247            if "bgp_network_route" in bgp_import_network_route_rst.keys():
3248                conf_str += CE_BGP_MERGE_NETWORK_UNIT % (
3249                    network_address, mask_len)
3250            else:
3251                conf_str += CE_BGP_CREATE_NETWORK_UNIT % (
3252                    network_address, mask_len)
3253
3254            conf_str += CE_MERGE_BGP_ADDRESS_FAMILY_TAIL
3255            recv_xml = ce_bgp_af_obj.netconf_set_config(
3256                module=module, conf_str=conf_str)
3257
3258            if "<ok/>" not in recv_xml:
3259                module.fail_json(
3260                    msg='Error: Present bgp af_type import and network route failed.')
3261
3262            cmd = "import-route %s %s" % (import_protocol, import_process_id)
3263            updates.append(cmd)
3264            cmd = "network %s %s" % (network_address, mask_len)
3265            updates.append(cmd)
3266
3267        elif bgp_import_network_route_rst["import_need_cfg"] and bgp_import_network_route_rst["network_need_cfg"]:
3268            changed = True
3269            conf_str = CE_BGP_IMPORT_NETWORK_ROUTE_HEADER % (vrf_name, af_type)
3270
3271            if "bgp_import_route" in bgp_import_network_route_rst.keys():
3272                conf_str += CE_BGP_MERGE_IMPORT_UNIT % (
3273                    import_protocol, import_process_id)
3274            else:
3275                conf_str += CE_BGP_CREATE_IMPORT_UNIT % (
3276                    import_protocol, import_process_id)
3277
3278            if "bgp_network_route" in bgp_import_network_route_rst.keys():
3279                conf_str += CE_BGP_MERGE_NETWORK_UNIT % (
3280                    network_address, mask_len)
3281            else:
3282                conf_str += CE_BGP_CREATE_NETWORK_UNIT % (
3283                    network_address, mask_len)
3284
3285            conf_str += CE_BGP_IMPORT_NETWORK_ROUTE_TAIL
3286            recv_xml = ce_bgp_af_obj.netconf_set_config(
3287                module=module, conf_str=conf_str)
3288
3289            if "<ok/>" not in recv_xml:
3290                module.fail_json(
3291                    msg='Error: Present bgp import and network route failed.')
3292
3293            cmd = "import-route %s %s" % (import_protocol, import_process_id)
3294            updates.append(cmd)
3295            cmd = "network %s %s" % (network_address, mask_len)
3296            updates.append(cmd)
3297
3298        else:
3299            if bgp_af_rst["need_cfg"]:
3300                if "af_type" in bgp_af_rst.keys():
3301                    cmd = ce_bgp_af_obj.merge_bgp_af(module=module)
3302                    changed = True
3303                    for item in cmd:
3304                        updates.append(item)
3305                else:
3306                    cmd = ce_bgp_af_obj.create_bgp_af(module=module)
3307                    changed = True
3308                    for item in cmd:
3309                        updates.append(item)
3310
3311            if bgp_af_other_rst["need_cfg"]:
3312                cmd = ce_bgp_af_obj.merge_bgp_af_other(module=module)
3313                changed = True
3314                for item in cmd:
3315                    updates.append(item)
3316
3317            if bgp_import_network_route_rst["import_need_cfg"]:
3318                if "bgp_import_route" in bgp_import_network_route_rst.keys():
3319                    cmd = ce_bgp_af_obj.merge_bgp_import_route(module=module)
3320                    changed = True
3321                    for item in cmd:
3322                        updates.append(item)
3323                else:
3324                    cmd = ce_bgp_af_obj.create_bgp_import_route(module=module)
3325                    changed = True
3326                    for item in cmd:
3327                        updates.append(item)
3328
3329            if bgp_import_network_route_rst["network_need_cfg"]:
3330                if "bgp_network_route" in bgp_import_network_route_rst.keys():
3331                    cmd = ce_bgp_af_obj.merge_bgp_network_route(module=module)
3332                    changed = True
3333                    for item in cmd:
3334                        updates.append(item)
3335                else:
3336                    cmd = ce_bgp_af_obj.create_bgp_network_route(module=module)
3337                    changed = True
3338                    for item in cmd:
3339                        updates.append(item)
3340
3341    else:
3342        if bgp_import_network_route_rst["import_need_cfg"] and bgp_import_network_route_rst["network_need_cfg"]:
3343            changed = True
3344            conf_str = CE_BGP_IMPORT_NETWORK_ROUTE_HEADER % (vrf_name, af_type)
3345            conf_str += CE_BGP_DELETE_IMPORT_UNIT % (
3346                import_protocol, import_process_id)
3347            conf_str += CE_BGP_DELETE_NETWORK_UNIT % (
3348                network_address, mask_len)
3349
3350            conf_str += CE_BGP_IMPORT_NETWORK_ROUTE_TAIL
3351            recv_xml = ce_bgp_af_obj.netconf_set_config(
3352                module=module, conf_str=conf_str)
3353
3354            if "<ok/>" not in recv_xml:
3355                module.fail_json(
3356                    msg='Error: Absent bgp import and network route failed.')
3357
3358            cmd = "undo import-route %s %s" % (import_protocol,
3359                                               import_process_id)
3360            updates.append(cmd)
3361            cmd = "undo network %s %s" % (network_address, mask_len)
3362            updates.append(cmd)
3363
3364        else:
3365            if bgp_import_network_route_rst["import_need_cfg"]:
3366                cmd = ce_bgp_af_obj.delete_bgp_import_route(module=module)
3367                changed = True
3368                for item in cmd:
3369                    updates.append(item)
3370
3371            if bgp_import_network_route_rst["network_need_cfg"]:
3372                cmd = ce_bgp_af_obj.delete_bgp_network_route(module=module)
3373                changed = True
3374                for item in cmd:
3375                    updates.append(item)
3376
3377        if bgp_af_other_can_del_rst["need_cfg"]:
3378            cmd = ce_bgp_af_obj.delete_bgp_af_other(module=module)
3379            changed = True
3380            for item in cmd:
3381                updates.append(item)
3382
3383        if bgp_af_rst["need_cfg"] and not bgp_af_other_can_del_rst["need_cfg"]:
3384            cmd = ce_bgp_af_obj.delete_bgp_af(module=module)
3385            changed = True
3386            for item in cmd:
3387                updates.append(item)
3388
3389        if bgp_af_other_rst["need_cfg"]:
3390            pass
3391
3392    # state end bgp address family config
3393    bgp_af_rst = ce_bgp_af_obj.check_bgp_af_args(module=module)
3394    end_tmp = dict()
3395    for item in bgp_af_rst:
3396        if item != "need_cfg":
3397            end_tmp[item] = bgp_af_rst[item]
3398    if end_tmp:
3399        end_state["bgp af"] = end_tmp
3400    # state end bgp address family other config
3401    bgp_af_other_rst = ce_bgp_af_obj.check_bgp_af_other_args(module=module)
3402    end_tmp = dict()
3403    for item in bgp_af_other_rst:
3404        if item != "need_cfg":
3405            end_tmp[item] = bgp_af_other_rst[item]
3406    if end_tmp:
3407        end_state["bgp af other"] = end_tmp
3408    # state end bgp import route config
3409    bgp_import_network_route_rst = ce_bgp_af_obj.check_bgp_import_network_route(
3410        module=module)
3411    end_tmp = dict()
3412    for item in bgp_import_network_route_rst:
3413        if item != "need_cfg":
3414            end_tmp[item] = bgp_import_network_route_rst[item]
3415    if end_tmp:
3416        end_state["bgp import & network route"] = end_tmp
3417    if end_state == existing:
3418        changed = False
3419        updates = list()
3420
3421    results = dict()
3422    results['proposed'] = proposed
3423    results['existing'] = existing
3424    results['changed'] = changed
3425    results['end_state'] = end_state
3426    results['updates'] = updates
3427
3428    module.exit_json(**results)
3429
3430
3431if __name__ == '__main__':
3432    main()
3433