1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3# Copyright 2019 Red Hat 4# GNU General Public License v3.0+ 5# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6# 7 8from __future__ import (absolute_import, division, print_function) 9__metaclass__ = type 10 11DOCUMENTATION = ''' 12--- 13module: ce_is_is_interface 14version_added: '0.2.0' 15author: xuxiaowei0512 (@CloudEngine-Ansible) 16short_description: Manages isis interface configuration on HUAWEI CloudEngine devices. 17description: 18 - Manages isis process id, creates a isis instance id or deletes a process id on HUAWEI CloudEngine devices. 19notes: 20 - Interface must already be a L3 port when using this module. 21 - This module requires the netconf system service be enabled on the remote device being managed. 22 - This module works with connection C(netconf). 23options: 24 instance_id: 25 description: 26 - Specifies the id of a isis process. 27 The value is a number of 1 to 4294967295. 28 required: true 29 type: int 30 ifname: 31 description: 32 - A L3 interface. 33 required: true 34 type: str 35 leveltype: 36 description: 37 - level type for three types. 38 type: str 39 choices: ['level_1', 'level_2', 'level_1_2'] 40 level1dispriority: 41 description: 42 - the dispriority of the level1. 43 The value is a number of 1 to 127. 44 type: int 45 level2dispriority: 46 description: 47 - the dispriority of the level1. 48 The value is a number of 1 to 127. 49 type: int 50 silentenable: 51 description: 52 - enable the interface can send isis message. 53 The value is a bool type. 54 type: bool 55 silentcost: 56 description: 57 - Specifies whether the routing cost of the silent interface is 0. 58 The value is a bool type. 59 type: bool 60 typep2penable: 61 description: 62 - Simulate the network type of the interface as P2P. 63 The value is a bool type. 64 type: bool 65 snpacheck: 66 description: 67 - Enable SNPA check for LSPs and SNPs. 68 The value is a bool type. 69 type: bool 70 p2pnegotiationmode: 71 description: 72 - Set the P2P neighbor negotiation type. 73 type: str 74 choices: ['2_way', '3_way', '3_wayonly'] 75 p2ppeeripignore: 76 description: 77 - When the P2P hello packet is received, no IP address check is performed. 78 The value is a bool type. 79 type: bool 80 ppposicpcheckenable: 81 description: 82 - Interface for setting PPP link protocol to check OSICP negotiation status. 83 The value is a bool type. 84 type: bool 85 level1cost: 86 description: 87 - Specifies the link cost of the interface when performing Level-1 SPF calculation. 88 The value is a number of 0 to 16777215. 89 type: int 90 level2cost: 91 description: 92 - Specifies the link cost of the interface when performing Level-2 SPF calculation. 93 The value is a number of 0 to 16777215. 94 type: int 95 bfdstaticen: 96 description: 97 - Configure static BFD on a specific interface enabled with ISIS. 98 The value is a bool type. 99 type: bool 100 bfdblocken: 101 description: 102 - Blocking interfaces to dynamically create BFD features. 103 The value is a bool type. 104 type: bool 105 state: 106 description: 107 - Determines whether the config should be present or not on the device. 108 type: str 109 default: 'present' 110 choices: ['present', 'absent'] 111''' 112 113EXAMPLES = ''' 114 - name: "create vlan and config vlanif" 115 ce_config: 116 lines: 'vlan {{ test_vlan_id }},quit,interface {{test_intf_vlanif}},ip address {{test_vlanif_ip}} 24' 117 match: none 118 119 - name: "create eth-trunk and config eth-trunk" 120 ce_config: 121 lines: 'interface {{test_intf_trunk}},undo portswitch,ip address {{test_trunk_ip}} 24' 122 match: none 123 124 - name: "create vpn instance" 125 ce_config: 126 lines: 'ip vpn-instance {{test_vpn}},ipv4-family' 127 match: none 128 129 - name: Set isis circuit-level 130 community.network.ce_is_is_interface: 131 instance_id: 3 132 ifname: Eth-Trunk10 133 leveltype: level_1_2 134 state: present 135 136 - name: Set isis level1dispriority 137 community.network.ce_is_is_interface: 138 instance_id: 3 139 ifname: Eth-Trunk10 140 level1dispriority: 0 141 state: present 142 143 - name: Set isis level2dispriority 144 community.network.ce_is_is_interface: 145 instance_id: 3 146 ifname: Eth-Trunk10 147 level2dispriority: 0 148 state: present 149 150 - name: Set isis silentenable 151 community.network.ce_is_is_interface: 152 instance_id: 3 153 ifname: Eth-Trunk10 154 silentenable: true 155 state: present 156 157 - name: Set vpn name 158 ce_is_is_instance: 159 instance_id: 22 160 vpn_name: vpn1 161 state: present 162''' 163 164RETURN = ''' 165proposed: 166 description: k/v pairs of parameters passed into module 167 returned: always 168 type: dict 169 sample: { 170 "addr_type": null, 171 "create_type": null, 172 "dest_addr": null, 173 "out_if_name": "10GE1/0/1", 174 "session_name": "bfd_l2link", 175 "src_addr": null, 176 "state": "present", 177 "use_default_ip": true, 178 "vrf_name": null 179 } 180existing: 181 description: k/v pairs of existing configuration 182 returned: always 183 type: dict 184 sample: { 185 "session": {} 186 } 187end_state: 188 description: k/v pairs of configuration after module execution 189 returned: always 190 type: dict 191 sample: { 192 "session": { 193 "addrType": "IPV4", 194 "createType": "SESS_STATIC", 195 "destAddr": null, 196 "outIfName": "10GE1/0/1", 197 "sessName": "bfd_l2link", 198 "srcAddr": null, 199 "useDefaultIp": "true", 200 "vrfName": null 201 } 202 } 203updates: 204 description: commands sent to the device 205 returned: always 206 type: list 207 sample: [ 208 "bfd bfd_l2link bind peer-ip default-ip interface 10ge1/0/1" 209 ] 210changed: 211 description: check to see if a change was made on the device 212 returned: always 213 type: bool 214 sample: true 215''' 216 217import sys 218import socket 219from xml.etree import ElementTree 220from ansible.module_utils.basic import AnsibleModule 221from ansible_collections.community.network.plugins.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config 222 223CE_NC_GET_ISIS = """ 224 <filter type="subtree"> 225 <isiscomm xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0"> 226 %s 227 </isiscomm> 228 </filter> 229""" 230 231CE_NC_GET_ISIS_INTERFACE = """ 232 <isSites> 233 <isSite> 234 <instanceId>%s</instanceId> 235 <isCircuits> 236 <isCircuit> 237 <ifName></ifName> 238 <circuitLevelType></circuitLevelType> 239 <level1DisPriority></level1DisPriority> 240 <level2DisPriority></level2DisPriority> 241 <silentEnable></silentEnable> 242 <silentCost></silentCost> 243 <typeP2pEnable></typeP2pEnable> 244 <snpaCheck></snpaCheck> 245 <p2pNegotiationMode></p2pNegotiationMode> 246 <p2pPeerIPIgnore></p2pPeerIPIgnore> 247 <pPPOsicpCheckEnable></pPPOsicpCheckEnable> 248 <level1Cost></level1Cost> 249 <level2Cost></level2Cost> 250 </isCircuit> 251 </isCircuits> 252 </isSite> 253 </isSites> 254""" 255 256CE_NC_MERGE_ISIS_INTERFACE = """ 257 <isSites> 258 <isSite> 259 <instanceId>%s</instanceId> 260 <isCircuits> 261 <isCircuit operation="merge"> 262 %s 263 </isCircuit> 264 </isCircuits> 265 </isSite> 266 </isSites> 267""" 268 269CE_NC_DELETE_ISIS_INTERFACE = """ 270 <isSites> 271 <isSite> 272 <instanceId>%s</instanceId> 273 <isCircuits> 274 <isCircuit operation="delete"> 275 %s 276 </isCircuit> 277 </isCircuits> 278 </isSite> 279 </isSites> 280""" 281 282CE_NC_GET_ISIS_BFDINTERFACE = """ 283 <isSites> 284 <isSite> 285 <instanceId>%s</instanceId> 286 <isSiteMTs> 287 <isSiteMT> 288 <addressFamily>afIpv4</addressFamily> 289 <mtId>0</mtId> 290 <isCircMts> 291 <isCircMt> 292 <bfdStaticEn></bfdStaticEn> 293 <bfdBlockEn></bfdBlockEn> 294 </isCircMt> 295 </isCircMts> 296 </isSiteMT> 297 </isSiteMTs> 298 </isSite> 299 </isSites> 300""" 301 302CE_NC_MERGE_ISIS_BFDINTERFACE = """ 303 <isSites> 304 <isSite> 305 <instanceId>%s</instanceId> 306 <isSiteMTs> 307 <isSiteMT> 308 <addressFamily>afIpv4</addressFamily> 309 <mtId>0</mtId> 310 <isCircMts> 311 <isCircMt operation="merge"> 312 %s 313 </isCircMt> 314 </isCircMts> 315 </isSiteMT> 316 </isSiteMTs> 317 </isSite> 318 </isSites> 319""" 320 321CE_NC_DELETE_ISIS_BFDINTERFACE = """ 322 <isSites> 323 <isSite> 324 <instanceId>%s</instanceId> 325 <isSiteMTs> 326 <isSiteMT> 327 <addressFamily>afIpv4</addressFamily> 328 <mtId>0</mtId> 329 <isCircMts> 330 <isCircMt operation="delete"> 331 %s 332 </isCircMt> 333 </isCircMts> 334 </isSiteMT> 335 </isSiteMTs> 336 </isSite> 337 </isSites> 338""" 339 340 341def is_valid_ip_vpn(vpname): 342 """check ip vpn""" 343 344 if not vpname: 345 return False 346 347 if vpname == "_public_": 348 return False 349 350 if len(vpname) < 1 or len(vpname) > 31: 351 return False 352 353 return True 354 355 356def check_ip_addr(ipaddr): 357 """check ip address, Supports IPv4 and IPv6""" 358 359 if not ipaddr or '\x00' in ipaddr: 360 return False 361 362 try: 363 res = socket.getaddrinfo(ipaddr, 0, socket.AF_UNSPEC, 364 socket.SOCK_STREAM, 365 0, socket.AI_NUMERICHOST) 366 return bool(res) 367 except socket.gaierror: 368 err = sys.exc_info()[1] 369 if err.args[0] == socket.EAI_NONAME: 370 return False 371 raise 372 373 return True 374 375 376def check_default_ip(ipaddr): 377 """check the default multicast IP address""" 378 379 # The value ranges from 224.0.0.107 to 224.0.0.250 380 if not check_ip_addr(ipaddr): 381 return False 382 383 if ipaddr.count(".") != 3: 384 return False 385 386 ips = ipaddr.split(".") 387 if ips[0] != "224" or ips[1] != "0" or ips[2] != "0": 388 return False 389 390 if not ips[3].isdigit() or int(ips[3]) < 107 or int(ips[3]) > 250: 391 return False 392 393 return True 394 395 396def get_interface_type(interface): 397 """get the type of interface, such as 10GE, ETH-TRUNK, VLANIF...""" 398 399 if interface.upper().startswith('GE'): 400 return 'ge' 401 elif interface.upper().startswith('10GE'): 402 return '10ge' 403 elif interface.upper().startswith('25GE'): 404 return '25ge' 405 elif interface.upper().startswith('4X10GE'): 406 return '4x10ge' 407 elif interface.upper().startswith('40GE'): 408 return '40ge' 409 elif interface.upper().startswith('100GE'): 410 return '100ge' 411 elif interface.upper().startswith('VLANIF'): 412 return 'vlanif' 413 elif interface.upper().startswith('LOOPBACK'): 414 return 'loopback' 415 elif interface.upper().startswith('METH'): 416 return 'meth' 417 elif interface.upper().startswith('ETH-TRUNK'): 418 return 'eth-trunk' 419 elif interface.upper().startswith('VBDIF'): 420 return 'vbdif' 421 elif interface.upper().startswith('NVE'): 422 return 'nve' 423 elif interface.upper().startswith('TUNNEL'): 424 return 'tunnel' 425 elif interface.upper().startswith('ETHERNET'): 426 return 'ethernet' 427 elif interface.upper().startswith('FCOE-PORT'): 428 return 'fcoe-port' 429 elif interface.upper().startswith('FABRIC-PORT'): 430 return 'fabric-port' 431 elif interface.upper().startswith('STACK-PORT'): 432 return 'stack-port' 433 elif interface.upper().startswith('NULL'): 434 return 'null' 435 else: 436 return None 437 438 439class ISIS_Instance(object): 440 """Manages ISIS Instance""" 441 442 def __init__(self, argument_spec): 443 self.spec = argument_spec 444 self.module = None 445 self.__init_module__() 446 447 # module input info 448 self.instance_id = self.module.params['instance_id'] 449 self.ifname = self.module.params['ifname'] 450 self.leveltype = self.module.params['leveltype'] 451 self.level1dispriority = self.module.params['level1dispriority'] 452 self.level2dispriority = self.module.params['level2dispriority'] 453 self.silentenable = self.module.params['silentenable'] 454 self.silentcost = self.module.params['silentcost'] 455 self.typep2penable = self.module.params['typep2penable'] 456 self.snpacheck = self.module.params['snpacheck'] 457 self.p2pnegotiationmode = self.module.params['p2pnegotiationmode'] 458 self.p2ppeeripignore = self.module.params['p2ppeeripignore'] 459 self.ppposicpcheckenable = self.module.params['ppposicpcheckenable'] 460 self.level1cost = self.module.params['level1cost'] 461 self.level2cost = self.module.params['level2cost'] 462 self.bfdstaticen = self.module.params['bfdstaticen'] 463 self.bfdblocken = self.module.params['bfdblocken'] 464 self.state = self.module.params['state'] 465 466 # state 467 self.changed = False 468 self.isis_dict = dict() 469 self.updates_cmd = list() 470 self.commands = list() 471 self.results = dict() 472 self.proposed = dict() 473 self.existing = dict() 474 self.end_state = dict() 475 476 def __init_module__(self): 477 """init module""" 478 mutually_exclusive = [["level1dispriority", "level2dispriority"], 479 ["level1cost", "level2cost"]] 480 self.module = AnsibleModule( 481 argument_spec=self.spec, 482 mutually_exclusive=mutually_exclusive, 483 supports_check_mode=True) 484 485 def get_isis_dict(self): 486 """bfd config dict""" 487 488 isis_dict = dict() 489 isis_dict["instance"] = dict() 490 conf_str = CE_NC_GET_ISIS % ( 491 (CE_NC_GET_ISIS_INTERFACE % self.instance_id)) 492 if self.bfdstaticen or self.bfdblocken: 493 conf_str = CE_NC_GET_ISIS % ( 494 (CE_NC_GET_ISIS_BFDINTERFACE % self.instance_id)) 495 496 xml_str = get_nc_config(self.module, conf_str) 497 if "<data/>" in xml_str: 498 return isis_dict 499 500 xml_str = xml_str.replace('\r', '').replace('\n', '').\ 501 replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\ 502 replace('xmlns="http://www.huawei.com/netconf/vrp"', "") 503 root = ElementTree.fromstring(xml_str) 504 505 # 506 glb = root.find("isiscomm/isSites/isSite/isCircuits/isCircuit") 507 if self.bfdstaticen or self.bfdblocken: 508 glb = root.find("isiscomm/isSites/isSite/isSiteMTs/isSiteMT/isCircMts/isCircMt") 509 if glb: 510 for attr in glb: 511 isis_dict["instance"][attr.tag] = attr.text 512 513 return isis_dict 514 515 def config_session(self): 516 """configures bfd session""" 517 518 xml_str = "" 519 instance = self.isis_dict["instance"] 520 if not self.instance_id: 521 return xml_str 522 if self.ifname: 523 xml_str = "<ifName>%s</ifName>" % self.ifname 524 self.updates_cmd.append("interface %s" % self.ifname) 525 if self.state == "present": 526 self.updates_cmd.append("isis enable %s" % self.instance_id) 527 528 if self.leveltype: 529 if self.leveltype == "level_1": 530 xml_str += "<circuitLevelType>level_1</circuitLevelType>" 531 self.updates_cmd.append("isis circuit-level level-1") 532 elif self.leveltype == "level_2": 533 xml_str += "<circuitLevelType>level_2</circuitLevelType>" 534 self.updates_cmd.append("isis circuit-level level-2") 535 elif self.leveltype == "level_1_2": 536 xml_str += "<circuitLevelType>level_1_2</circuitLevelType>" 537 self.updates_cmd.append("isis circuit-level level-1-2") 538 if self.level1dispriority is not None: 539 xml_str += "<level1DisPriority>%s</level1DisPriority>" % self.level1dispriority 540 self.updates_cmd.append("isis dis-priority %s level-1" % self.level1dispriority) 541 if self.level2dispriority is not None: 542 xml_str += "<level2DisPriority>%s</level2DisPriority>" % self.level2dispriority 543 self.updates_cmd.append("isis dis-priority %s level-2" % self.level2dispriority) 544 if self.p2pnegotiationmode: 545 if self.p2pnegotiationmode == "2_way": 546 xml_str += "<p2pNegotiationMode>2_way</p2pNegotiationMode>" 547 self.updates_cmd.append("isis ppp-negotiation 2-way") 548 elif self.p2pnegotiationmode == "3_way": 549 xml_str += "<p2pNegotiationMode>3_way</p2pNegotiationMode>" 550 self.updates_cmd.append("isis ppp-negotiation 3-way") 551 elif self.p2pnegotiationmode == "3_wayonly": 552 xml_str += "<p2pNegotiationMode>3_wayonly</p2pNegotiationMode>" 553 self.updates_cmd.append("isis ppp-negotiation only") 554 if self.level1cost is not None: 555 xml_str += "<level1Cost>%s</level1Cost>" % self.level1cost 556 self.updates_cmd.append("isis cost %s level-1" % self.level1cost) 557 if self.level2cost is not None: 558 xml_str += "<level2Cost>%s</level2Cost>" % self.level2cost 559 self.updates_cmd.append("isis cost %s level-2" % self.level2cost) 560 561 else: 562 # absent 563 self.updates_cmd.append("undo isis enable") 564 if self.leveltype and self.leveltype == instance.get("circuitLevelType"): 565 xml_str += "<circuitLevelType>level_1_2</circuitLevelType>" 566 self.updates_cmd.append("undo isis circuit-level") 567 if self.level1dispriority is not None and self.level1dispriority == instance.get("level1DisPriority"): 568 xml_str += "<level1DisPriority>64</level1DisPriority>" 569 self.updates_cmd.append("undo isis dis-priority %s level-1" % self.level1dispriority) 570 if self.level2dispriority is not None and self.level2dispriority == instance.get("level2dispriority"): 571 xml_str += "<level2dispriority>64</level2dispriority>" 572 self.updates_cmd.append("undo isis dis-priority %s level-2" % self.level2dispriority) 573 if self.p2pnegotiationmode and self.p2pnegotiationmode == instance.get("p2pNegotiationMode"): 574 xml_str += "<p2pNegotiationMode/>" 575 self.updates_cmd.append("undo isis ppp-negotiation") 576 if self.level1cost is not None and self.level1cost == instance.get("level1Cost"): 577 xml_str += "<level1Cost/>" 578 self.updates_cmd.append("undo isis cost %s level-1" % self.level1cost) 579 if self.level2cost is not None and self.level2cost == instance.get("level2Cost"): 580 xml_str += "<level2Cost/>" 581 self.updates_cmd.append("undo isis cost %s level-2" % self.level2cost) 582 583 if self.silentenable and instance.get("silentEnable", "false") == "false": 584 xml_str += "<silentEnable>true</silentEnable>" 585 self.updates_cmd.append("isis silent") 586 elif not self.silentenable and instance.get("silentEnable", "false") == "true": 587 xml_str += "<silentEnable>false</silentEnable>" 588 self.updates_cmd.append("undo isis silent") 589 590 if self.silentcost and instance.get("silentCost", "false") == "false": 591 xml_str += "<silentCost>true</silentCost>" 592 self.updates_cmd.append("isis silent advertise-zero-cost") 593 elif not self.silentcost and instance.get("silentCost", "false") == "true": 594 xml_str += "<silentCost>false</silentCost>" 595 596 if self.typep2penable and instance.get("typeP2pEnable", "false") == "false": 597 xml_str += "<typeP2pEnable>true</typeP2pEnable>" 598 self.updates_cmd.append("isis circuit-type p2p") 599 elif not self.typep2penable and instance.get("typeP2pEnable", "false") == "true": 600 xml_str += "<typeP2pEnable>false</typeP2pEnable>" 601 self.updates_cmd.append("undo isis circuit-type") 602 603 if self.snpacheck and instance.get("snpaCheck", "false") == "false": 604 xml_str += "<snpaCheck>true</snpaCheck>" 605 self.updates_cmd.append("isis circuit-type p2p strict-snpa-check") 606 elif not self.snpacheck and instance.get("snpaCheck", "false") == "true": 607 xml_str += "<snpaCheck>false</snpaCheck>" 608 609 if self.p2ppeeripignore and instance.get("p2pPeerIPIgnore", "false") == "false": 610 xml_str += "<p2pPeerIPIgnore>true</p2pPeerIPIgnore>" 611 self.updates_cmd.append("isis peer-ip-ignore") 612 elif not self.p2ppeeripignore and instance.get("p2pPeerIPIgnore", "false") == "true": 613 xml_str += "<p2pPeerIPIgnore>false</p2pPeerIPIgnore>" 614 self.updates_cmd.append("undo isis peer-ip-ignore") 615 616 if self.ppposicpcheckenable and instance.get("pPPOsicpCheckEnable", "false") == "false": 617 xml_str += "<pPPOsicpCheckEnable>true</pPPOsicpCheckEnable>" 618 self.updates_cmd.append("isis ppp-osicp-check") 619 elif not self.ppposicpcheckenable and instance.get("pPPOsicpCheckEnable", "false") == "true": 620 xml_str += "<pPPOsicpCheckEnable>false</pPPOsicpCheckEnable>" 621 self.updates_cmd.append("undo isis ppp-osicp-check") 622 if self.bfdstaticen and instance.get("bfdStaticEn", "false") == "false": 623 xml_str += "<bfdStaticEn>true</bfdStaticEn>" 624 self.updates_cmd.append("isis bfd static") 625 elif not self.bfdstaticen and instance.get("bfdStaticEn", "false") == "true": 626 xml_str += "<bfdStaticEn>false</bfdStaticEn>" 627 self.updates_cmd.append("undo isis bfd static") 628 if self.bfdblocken and instance.get("bfdBlockEn", "false") == "false": 629 xml_str += "<bfdBlockEn>true</bfdBlockEn>" 630 self.updates_cmd.append("isis bfd block") 631 elif not self.bfdblocken and instance.get("bfdBlockEn", "false") == "true": 632 xml_str += "<bfdBlockEn>false</bfdBlockEn>" 633 self.updates_cmd.append("undo isis bfd block") 634 635 if self.state == "present": 636 if self.bfdstaticen is not None or self.bfdblocken is not None: 637 return CE_NC_MERGE_ISIS_BFDINTERFACE % (self.instance_id, xml_str) 638 return CE_NC_MERGE_ISIS_INTERFACE % (self.instance_id, xml_str) 639 else: 640 if self.bfdstaticen is not None or self.bfdblocken is not None: 641 return CE_NC_DELETE_ISIS_BFDINTERFACE % (self.instance_id, xml_str) 642 return CE_NC_DELETE_ISIS_INTERFACE % (self.instance_id, xml_str) 643 644 def netconf_load_config(self, xml_str): 645 """load bfd config by netconf""" 646 647 if not xml_str: 648 return 649 650 xml_cfg = """ 651 <config> 652 <isiscomm xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0"> 653 %s 654 </isiscomm> 655 </config>""" % xml_str 656 set_nc_config(self.module, xml_cfg) 657 self.changed = True 658 659 def check_params(self): 660 """Check all input params""" 661 662 # check instance id 663 if not self.instance_id: 664 self.module.fail_json(msg="Error: Missing required arguments: instance_id.") 665 666 if self.instance_id: 667 if self.instance_id < 1 or self.instance_id > 4294967295: 668 self.module.fail_json(msg="Error: Instance id is not ranges from 1 to 4294967295.") 669 670 # check level1dispriority 671 if self.level1dispriority is not None: 672 if self.level1dispriority < 0 or self.level1dispriority > 127: 673 self.module.fail_json(msg="Error: level1dispriority is not ranges from 0 to 127.") 674 675 if self.level2dispriority is not None: 676 if self.level2dispriority < 0 or self.level2dispriority > 127: 677 self.module.fail_json(msg="Error: level2dispriority is not ranges from 0 to 127.") 678 679 if self.level1cost is not None: 680 if self.level1cost < 0 or self.level1cost > 16777215: 681 self.module.fail_json(msg="Error: level1cost is not ranges from 0 to 16777215.") 682 683 if self.level2cost is not None: 684 if self.level2cost < 0 or self.level2cost > 16777215: 685 self.module.fail_json(msg="Error: level2cost is not ranges from 0 to 16777215.") 686 687 def get_proposed(self): 688 """get proposed info""" 689 self.proposed["instance_id"] = self.instance_id 690 self.proposed["ifname"] = self.ifname 691 self.proposed["leveltype"] = self.leveltype 692 self.proposed["level1dispriority"] = self.level1dispriority 693 self.proposed["level2dispriority"] = self.level2dispriority 694 self.proposed["silentenable"] = self.silentenable 695 self.proposed["silentcost"] = self.silentcost 696 self.proposed["typep2penable"] = self.typep2penable 697 self.proposed["snpacheck"] = self.snpacheck 698 self.proposed["p2pnegotiationmode"] = self.p2pnegotiationmode 699 self.proposed["p2ppeeripignore"] = self.p2ppeeripignore 700 self.proposed["ppposicpcheckenable"] = self.ppposicpcheckenable 701 self.proposed["level1cost"] = self.level1cost 702 self.proposed["level2cost"] = self.level2cost 703 self.proposed["bfdstaticen"] = self.bfdstaticen 704 self.proposed["bfdblocken"] = self.bfdblocken 705 self.proposed["state"] = self.state 706 707 def get_existing(self): 708 """get existing info""" 709 710 if not self.isis_dict: 711 self.existing["instance"] = None 712 else: 713 self.existing["instance"] = self.isis_dict.get("instance") 714 715 def get_end_state(self): 716 """get end state info""" 717 718 isis_dict = self.get_isis_dict() 719 if not isis_dict: 720 self.end_state["instance"] = None 721 else: 722 self.end_state["instance"] = isis_dict.get("instance") 723 if self.existing == self.end_state: 724 self.changed = False 725 726 def work(self): 727 """worker""" 728 729 self.check_params() 730 self.isis_dict = self.get_isis_dict() 731 self.get_existing() 732 self.get_proposed() 733 734 # deal present or absent 735 xml_str = '' 736 if self.instance_id: 737 xml_str += self.config_session() 738 739 # update to device 740 if xml_str: 741 self.netconf_load_config(xml_str) 742 self.changed = True 743 744 self.get_end_state() 745 self.results['changed'] = self.changed 746 self.results['proposed'] = self.proposed 747 self.results['existing'] = self.existing 748 self.results['end_state'] = self.end_state 749 if self.changed: 750 self.results['updates'] = self.updates_cmd 751 else: 752 self.results['updates'] = list() 753 754 self.module.exit_json(**self.results) 755 756 757def main(): 758 """Module main""" 759 760 argument_spec = dict( 761 instance_id=dict(required=True, type='int'), 762 ifname=dict(required=True, type='str'), 763 leveltype=dict(required=False, type='str', choices=['level_1', 'level_2', 'level_1_2']), 764 level1dispriority=dict(required=False, type='int'), 765 level2dispriority=dict(required=False, type='int'), 766 silentenable=dict(required=False, type='bool'), 767 silentcost=dict(required=False, type='bool'), 768 typep2penable=dict(required=False, type='bool'), 769 snpacheck=dict(required=False, type='bool'), 770 p2pnegotiationmode=dict(required=False, type='str', choices=['2_way', '3_way', '3_wayonly']), 771 p2ppeeripignore=dict(required=False, type='bool'), 772 ppposicpcheckenable=dict(required=False, type='bool'), 773 level1cost=dict(required=False, type='int'), 774 level2cost=dict(required=False, type='int'), 775 bfdstaticen=dict(required=False, type='bool'), 776 bfdblocken=dict(required=False, type='bool'), 777 state=dict(required=False, default='present', choices=['present', 'absent']) 778 ) 779 780 module = ISIS_Instance(argument_spec) 781 module.work() 782 783 784if __name__ == '__main__': 785 main() 786