├── ansible.cfg ├── collections └── requirements.yml ├── templates └── vlan_template.j2 ├── inventory.yml ├── configure_vlans.yml ├── configure_using_cli_snmp.yml ├── vsf_auto_stack.yml ├── configure_using_cli_template.yml ├── configure_l3_interfaces.yml ├── get_facts_example.yml ├── configure_l2_interfaces.yml ├── upload_firmware_boot.yml ├── vsf_conductor_config.yml ├── copy_config_using_cli_prompt.yml ├── configure_acl.yml ├── README.md ├── check_firmware_then_upgrade.yml ├── CONTRIBUTING.md └── License.md /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | host_key_checking=False 3 | -------------------------------------------------------------------------------- /collections/requirements.yml: -------------------------------------------------------------------------------- 1 | collections: 2 | - arubanetworks.aoscx 3 | -------------------------------------------------------------------------------- /templates/vlan_template.j2: -------------------------------------------------------------------------------- 1 | {% for vlan in num_vlans %} 2 | {% set vlan_id = vlan + starting_vlan %} 3 | vlan {{vlan_id}} 4 | {% endfor %} 5 | -------------------------------------------------------------------------------- /inventory.yml: -------------------------------------------------------------------------------- 1 | all: 2 | hosts: 3 | aoscx_1: 4 | ansible_host: 10.0.0.1 5 | ansible_user: admin 6 | ansible_password: password 7 | ansible_network_os: arubanetworks.aoscx.aoscx 8 | ansible_connection: arubanetworks.aoscx.aoscx # REST API via pyaoscx connection method 9 | ansible_aoscx_validate_certs: False 10 | ansible_aoscx_use_proxy: False 11 | ansible_acx_no_proxy: True -------------------------------------------------------------------------------- /configure_vlans.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | collections: 3 | - arubanetworks.aoscx 4 | gather_facts: False 5 | tasks: 6 | - name: Create VLAN 300 with description and name 7 | aoscx_vlan: 8 | vlan_id: 300 9 | name: UPLINK_VLAN 10 | description: This is VLAN 300 11 | 12 | - name: Create VLAN 200 with description and name 13 | aoscx_vlan: 14 | vlan_id: 200 15 | name: UPLINK_VLAN 16 | description: This is VLAN 200 17 | -------------------------------------------------------------------------------- /configure_using_cli_snmp.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | collections: 3 | - arubanetworks.aoscx 4 | vars: 5 | ansible_python_interpreter: /usr/bin/python3 #ensure this value matches your env python3 - this changes when venv 6 | ansible_connection: network_cli 7 | tasks: 8 | - name: Configure SNMP through SSH/CLI 9 | aoscx_config: 10 | lines: 11 | - snmp-server vrf default 12 | - snmp-server community Sacramento 13 | - snmp-server community Roseville 14 | match: line 15 | -------------------------------------------------------------------------------- /vsf_auto_stack.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | gather_facts: False 4 | collections: 5 | - arubanetworks.aoscx 6 | vars: 7 | ansible_connection: network_cli 8 | tasks: 9 | - name: Enable auto-confirm and begin auto stacking process 10 | aoscx_command: 11 | commands: 12 | - auto-confirm 13 | - conf 14 | - vsf start-auto-stacking 15 | 16 | - name: Pause for 25 seconds to allow for switch to reboot 17 | pause: 18 | seconds: 25 19 | 20 | - name: Wait for Standby to join stack by entering Show vsf 21 | aoscx_command: 22 | commands: 23 | - 'show vsf' 24 | wait_for: 25 | - result[0] contains "Standby" 26 | #- result[0] contains "Member" 27 | match: all 28 | retries: 20 29 | interval: 5 -------------------------------------------------------------------------------- /configure_using_cli_template.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | collections: 3 | - arubanetworks.aoscx 4 | vars: 5 | ansible_python_interpreter: /usr/bin/python3 #ensure this value matches your env python3 - this changes when venv 6 | ansible_connection: network_cli 7 | tasks: 8 | - name: generate vlans based on template 9 | template: 10 | src: vlan_template.j2 11 | dest: ./generated_vlans.txt 12 | vars: 13 | starting_vlan: 10 14 | num_vlans: [1, 2, 3] 15 | 16 | - name: configure vlans using template 17 | aoscx_config: 18 | src: ./generated_vlans.txt 19 | 20 | - name: configure vlans through lines 21 | aoscx_config: 22 | lines: 23 | - vlan99 24 | - vlan89 25 | 26 | - name: Execute show vlan on the switch 27 | aoscx_command: 28 | commands: ['show vlan'] 29 | register: show_vlan_output 30 | 31 | - debug: 32 | var: show_vlan_output 33 | -------------------------------------------------------------------------------- /configure_l3_interfaces.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | collections: 3 | - arubanetworks.aoscx 4 | vars: 5 | ansible_python_interpreter: /usr/bin/python3 6 | gather_facts: False 7 | tasks: 8 | - name: Configure L3 interface 1/1/3 with IPv4 and IPv6 address 9 | aoscx_l3_interface: 10 | interface: 1/1/3 11 | description: Uplink Interface 12 | ipv4: ['10.20.1.3/24'] 13 | ipv6: ['2000:db8::1234/64'] 14 | 15 | - name: Configure IP Helper Address on Interface 1/1/3 16 | aoscx_l3_interface: 17 | interface: 1/1/3 18 | ip_helper_address: ['172.1.2.32'] 19 | 20 | - name: Configure L3 interface 1/1/4 with IPv4 21 | aoscx_l3_interface: 22 | interface: 1/1/4 23 | description: Downlink Interface 24 | ipv4: ['172.138.23.3/24'] 25 | 26 | - name: Administratively enable interfaces 1/1/3-1/1/4 27 | aoscx_interface: 28 | name: "{{item}}" 29 | enabled: true 30 | loop: ['1/1/3', '1/1/4'] -------------------------------------------------------------------------------- /get_facts_example.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | collections: 3 | - arubanetworks.aoscx 4 | vars: 5 | ansible_aoscx_rest_version: 10.09 # Necessary for physical interfaces 6 | tasks: 7 | - name: > 8 | Retrieve all information from the device and save into a variable 9 | "facts_output". 10 | aoscx_facts: 11 | register: facts_output 12 | 13 | - set_fact: 14 | current_version_primary: "{{facts_output['ansible_facts']['ansible_net_software_images'].primary_image_version}}" 15 | 16 | - set_fact: 17 | current_version_secondary: "{{facts_output['ansible_facts']['ansible_net_software_images'].secondary_image_version}}" 18 | 19 | - set_fact: 20 | switch_hostname: "{{facts_output['ansible_facts']['ansible_net_platform_name']}}" 21 | 22 | - set_fact: 23 | system_mac: "{{facts_output['ansible_facts']['ansible_net_product_info']['chassis,1'].base_mac_address}}" 24 | 25 | - debug: 26 | var: current_version_primary 27 | - debug: 28 | var: current_version_secondary 29 | - debug: 30 | var: switch_hostname 31 | - debug: 32 | var: system_mac 33 | 34 | -------------------------------------------------------------------------------- /configure_l2_interfaces.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | collections: 3 | - arubanetworks.aoscx 4 | vars: 5 | ansible_python_interpreter: /usr/bin/python3 6 | gather_facts: False 7 | tasks: 8 | - name: Create VLAN 300 9 | aoscx_vlan: 10 | vlan_id: 300 11 | name: Building-3 12 | 13 | - name: Create VLAN 400 14 | aoscx_vlan: 15 | vlan_id: 400 16 | description: Building-4 17 | 18 | - name: Configure Interface 1/1/3 - vlan trunk allowed 300,400 , vlan trunk native 300 19 | aoscx_l2_interface: 20 | interface: 1/1/3 21 | vlan_mode: trunk 22 | vlan_trunks: ['400','300'] 23 | native_vlan_id: '300' 24 | 25 | - name: Configure Interface 1/1/4 - vlan access 300 26 | aoscx_l2_interface: 27 | interface: 1/1/4 28 | vlan_mode: access 29 | vlan_access: '300' 30 | 31 | - name: Configure Interface 1/1/5 - vlan trunk allowed all, vlan trunk native 400 tag 32 | aoscx_l2_interface: 33 | interface: 1/1/5 34 | vlan_mode: trunk 35 | trunk_allowed_all: True 36 | native_vlan_id: '400' 37 | native_vlan_tag: True 38 | 39 | - name: Disable Interface 1/1/6 40 | aoscx_interface: 41 | name: 1/1/6 42 | enabled: true -------------------------------------------------------------------------------- /upload_firmware_boot.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | collections: 3 | - arubanetworks.aoscx 4 | gather_facts: False 5 | tasks: 6 | - name: Upload firmware through local file 7 | throttle: 1 8 | aoscx_upload_firmware: 9 | partition_name: 'primary' 10 | firmware_file_path: '/var/lib/tftpboot/GL_10_08_1010.swi' 11 | tags: ['test'] 12 | 13 | - name: Boot the switch with the new image uploaded to primary partition. 14 | aoscx_boot_firmware: 15 | partition_name: 'primary' 16 | 17 | - name: Pause for 10 seconds to allow for boot command 18 | pause: 19 | seconds: 10 20 | 21 | - name: Wait for the switch to come online after FW upgrade and reboot. 22 | wait_for: 23 | host: "{{ ansible_host }}" 24 | port: 22 25 | sleep: 10 26 | timeout: 900 27 | 28 | # Check each line card and verify if it's ready 29 | - name: Wait for Line Cards to be Ready - max 5 min wait 30 | aoscx_facts: 31 | gather_subset: ['physical_interfaces'] 32 | register: facts_output 33 | until: facts_output['ansible_facts']['ansible_net_interfaces']['line_card,1/1']['1/1/1']['physical_interface_state'] is match("ready") 34 | retries: 40 35 | delay: 10 36 | 37 | - name: Adding or Updating Banner 38 | aoscx_banner: 39 | banner_type: banner 40 | banner: "Aruba Rocks!" -------------------------------------------------------------------------------- /vsf_conductor_config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | gather_facts: False 4 | collections: 5 | - arubanetworks.aoscx 6 | vars: 7 | ansible_connection: network_cli 8 | tasks: 9 | - name: Configure VSF secondary member on Conductor 10 | aoscx_config: 11 | lines: 12 | - do auto-confirm 13 | - vsf secondary-member {{vsf_secondary | default('2')}} 14 | when: vsf_role | default('conductor') == 'conductor' 15 | 16 | - name: Configure VSF Link 1 on Conductor 17 | aoscx_config: 18 | lines: 19 | - link 1 {{vsf_link1 | default('1/1/26')}} 20 | before: 21 | - vsf member 1 22 | when: vsf_role | default('conductor') == 'conductor' 23 | 24 | - name: Configure VSF Link 2 on Conductor 25 | aoscx_config: 26 | lines: 27 | - link 2 {{vsf_link2}} 28 | before: 29 | - vsf member 1 30 | when: vsf_role | default('conductor') == 'conductor' and vsf_link2 is defined 31 | 32 | - name: Pause for 25 seconds to allow for switch to reboot 33 | pause: 34 | seconds: 25 35 | 36 | - name: Wait for Standby to join stack by entering Show vsf 37 | aoscx_command: 38 | commands: 39 | - 'show vsf' 40 | wait_for: 41 | - result[0] contains "Standby" 42 | #- result[0] contains "Member" 43 | match: all 44 | retries: 20 45 | interval: 5 46 | -------------------------------------------------------------------------------- /copy_config_using_cli_prompt.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | gather_facts: False 4 | collections: 5 | - arubanetworks.aoscx 6 | vars: 7 | ansible_connection: network_cli 8 | tasks: 9 | - name: Upload via TFTP 10 | aoscx_command: 11 | commands: 12 | - command: 'copy tftp://10.0.9.87/TL_10_08_0001CN.swi secondary vrf mgmt' 13 | prompt: 14 | - '.*Continue.*' 15 | answer: 16 | - y 17 | 18 | - name: Show images 19 | aoscx_command: 20 | commands: ["show image"] 21 | 22 | - hosts: all 23 | gather_facts: False 24 | collections: 25 | - arubanetworks.aoscx 26 | vars: 27 | ansible_connection: network_cli 28 | tasks: 29 | - name: Upload via SFTP 30 | aoscx_command: 31 | commands: 32 | - command: "copy sftp://chiapuzi@10.0.9.87/TL_10_07_0030O.swi primary vrf mgmt" 33 | check_all: True 34 | prompt: 35 | - '.*\(y\/n\)\?.*' 36 | - '.*password:.*' 37 | answer: 38 | - 'y' 39 | - 'password' 40 | 41 | - name: Show images 42 | aoscx_command: 43 | commands: ["show image"] 44 | 45 | - hosts: all 46 | collections: 47 | - arubanetworks.aoscx 48 | gather_facts: False 49 | vars: 50 | ansible_connection: network_cli 51 | tasks: 52 | - name: Optional - Accept authenticity Upload via SCP 53 | aoscx_command: 54 | commands: 55 | - command: "copy scp://administrator@10.80.2.153/config.txt running-config vrf mgmt" 56 | check_all: True 57 | prompt: 58 | - '.*\(yes\/no.*\)\?.*' 59 | answer: 60 | - 'yes' 61 | ignore_errors: True 62 | # If fingerprint prompt does not come up then this will fail which is okay 63 | 64 | - name: Copy config via SCP 65 | aoscx_command: 66 | commands: 67 | - command: "copy scp://administrator@10.80.2.153/config.txt running-config vrf mgmt" 68 | prompt: 69 | - '.*password:.*' 70 | answer: 71 | - 'password' 72 | -------------------------------------------------------------------------------- /configure_acl.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | gather_facts: False 4 | collections: 5 | - arubanetworks.aoscx 6 | vars: 7 | ansible_python_interpreter: /usr/bin/python3 8 | tasks: 9 | - name: Configure ALLOW_HOSTS ACL 10 | aoscx_acl: 11 | name: ALLOW_HOSTS 12 | type: ipv4 13 | acl_entries: 14 | 10: 15 | action: permit 16 | src_ip: 172.38.49.127/255.255.255.255 17 | protocol: any 18 | 20: 19 | action: permit 20 | src_ip: 172.38.49.127/255.255.255.255 21 | protocol: any 22 | 30: 23 | action: permit 24 | src_ip: 172.38.49.126/255.255.255.255 25 | protocol: any 26 | 40: 27 | action: permit 28 | src_ip: 172.38.49.125/255.255.255.255 29 | protocol: any 30 | 31 | - name: Configure ALLOW_FTP ACL 32 | aoscx_acl: 33 | name: ALLOW_FTP 34 | type: ipv4 35 | acl_entries: 36 | 10: 37 | comment: "---FTP---" 38 | action: permit 39 | protocol: tcp 40 | src_l4_port_max: 21 41 | src_l4_port_min: 21 42 | 20: 43 | action: permit 44 | protocol: tcp 45 | dst_l4_port_max: 21 46 | dst_l4_port_min: 21 47 | 30: 48 | action: permit 49 | protocol: tcp 50 | dst_l4_port_max: 20 51 | dst_l4_port_min: 20 52 | 40: 53 | action: permit 54 | protocol: tcp 55 | src_l4_port_max: 20 56 | src_l4_port_min: 20 57 | 58 | - name: Configure L3 interface 1/1/4 59 | aoscx_l3_interface: 60 | interface: 1/1/4 61 | description: Downlink Interface 62 | ipv4: ['172.138.23.3/24'] 63 | admin_state: down 64 | 65 | - name: Configure L3 interface 1/1/5 66 | aoscx_l3_interface: 67 | interface: 1/1/5 68 | description: Downlink Interface 69 | ipv4: ['172.139.29.3/24'] 70 | admin_state: down 71 | 72 | - name: Apply ALLOW_HOSTS ACL to interface 1/1/4 73 | aoscx_acl_interface: 74 | acl_name: ALLOW_HOSTS 75 | acl_type: ipv4 76 | acl_interface_list: ["1/1/4"] 77 | 78 | - name: Apply ALLOW_FTP ACL to interface 1/1/5 79 | aoscx_acl_interface: 80 | acl_name: ALLOW_FTP 81 | acl_type: ipv4 82 | acl_interface_list: ["1/1/5"] 83 | acl_direction: out -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aoscx-ansible-workflows 2 | This repository contains ready-to-use workflows using the [AOS-CX Ansible Collection](https://galaxy.ansible.com/arubanetworks/aoscx). For detailed guides on using Ansible with AOS-CX visit us on our [HPE Aruba Networking Developer Hub](https://developer.arubanetworks.com/aruba-aoscx/docs/ansible-getting-started). 3 | 4 | 5 | Requirements 6 | ------------ 7 | 8 | * Python 3 or later 9 | * Ansible 2.9.0 or later 10 | * Refer to [Ansible's documentation](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) for installation steps 11 | * Ansible 2.10+ requires `ansible.netcommon` collection along with the `arubanetworks.aoscx` collection to be installed 12 | `ansible-galaxy collection install ansible.netcommon -f` 13 | `ansible-galaxy collection install arubanetworks.aoscx -f` 14 | * Minimum supported AOS-CX firmware version 10.04 15 | * Enable REST on your AOS-CX device with the following commands: 16 | ``` 17 | switch(config)# https-server rest access-mode read-write 18 | switch(config)# https-server vrf mgmt 19 | ``` 20 | * Enable SSH on your AOS-CX device with the following command: 21 | ``` 22 | switch(config)# ssh server vrf mgmt 23 | ``` 24 | 25 | 26 | Executing Workflows 27 | ------------ 28 | 1. Ensure you've completed all the requirements stated above. 29 | 2. Clone this repository onto your Ansible Control Machine: 30 | ``` 31 | git clone https://github.com/aruba/aoscx-ansible-workflows.git 32 | ``` 33 | 3. Modify the `inventory.yml` file to match the IP address and login credentials of your AOS-CX switch: 34 | * `ansible_host`: IP address of switch in `A.B.C.D` format. For IPv6 hosts use a string and enclose in square brackets E.G. `'[2001::1]'`. 35 | * `ansible_user`: Username for switch in `plaintext` format 36 | * `ansible_password`: Password for switch in `plaintext` format 37 | 4. Run the desired workflow using the `ansible-playbook` command and providing the `inventory.yml` file: 38 | ``` 39 | ansible-playbook configure_vlans.yml -i inventory.yml 40 | ``` 41 | 42 | Contribution 43 | ------- 44 | At HPE Aruba Networking we're dedicated to ensuring the quality of our products, so if you find any 45 | issues at all please open an issue on our [Github](https://github.com/aruba/aoscx-ansible-workflows) and we'll be sure to respond promptly! 46 | 47 | For more contribution opportunities follow our guidelines outlined in our [CONTRIBUTING.md](https://github.com/aruba/aoscx-ansible-workflows/blob/master/CONTRIBUTING.md) 48 | 49 | License 50 | ------- 51 | 52 | Apache 2.0 53 | -------------------------------------------------------------------------------- /check_firmware_then_upgrade.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # First play just captures FW version & hostname of the switch. 3 | 4 | - name: Get the switch version and hostname. 5 | hosts: all 6 | collections: 7 | - arubanetworks.aoscx 8 | 9 | gather_facts: False 10 | vars: 11 | ansible_connection: network_cli 12 | 13 | tasks: 14 | - name: Run the command to get output with the current Firmware version on the switch. 15 | aoscx_command: 16 | commands: ['show version'] 17 | register: vers 18 | 19 | - name: Parse the output from the switch and save the exact FW version to the variable. 20 | set_fact: 21 | vers: "{{ vers.stdout | join('') | regex_search('Version.*:.*GL.([0-9]{2}.){2}.[0-9]+') | replace('Version : ','') }}" 22 | 23 | - debug: 24 | msg: "{{ vers }}" 25 | 26 | - name: Run the command to get output with the Switch Hostname. 27 | aoscx_command: 28 | commands: ['show hostname'] 29 | register: hostname 30 | 31 | - name: Parse the output from the switch and save the exact Switch Hostname. 32 | set_fact: 33 | hostname: "{{ hostname.stdout | join('') }}" 34 | 35 | - debug: 36 | msg: "{{ hostname }}" 37 | 38 | 39 | # Second play is executed only if a FW upgrade is required. 40 | # If FW upgrade is required, it will take a backup of the running-config, upload FW to primary partition then boot the switch from primary partition with new FW. 41 | 42 | - name: Take a backup of running-config, upload FW to primary partition, then boot from new FW on primary partition, if an upgrade is required. 43 | hosts: all 44 | collections: 45 | - arubanetworks.aoscx 46 | gather_facts: False 47 | vars: 48 | target_version: 'GL.10.07.0021' 49 | tasks: 50 | - name: Take a backup of running-config, upload FW to primary partition, then boot from new FW on primary partition, if an upgrade is required 51 | block: 52 | - name: Copy Running Config to local (Ansible control node) as JSON file. 53 | aoscx_backup_config: 54 | config_name: 'running-config' 55 | output_file: '/tmp/test-HK/glx/running-config_{{ hostname }}.json' 56 | 57 | - name: Upload FW to primary partition through local. 58 | aoscx_upload_firmware: 59 | partition_name: 'primary' 60 | firmware_file_path: '/tmp/test-HK/glx/ArubaOS-CX_8325_10_07_0021.swi' 61 | 62 | - name: Boot the switch with the new image uploaded to primary partition. 63 | aoscx_boot_firmware: 64 | partition_name: 'primary' 65 | 66 | - name: Wait for the switch to come online after FW upgrade and reboot. 67 | wait_for: 68 | host: "{{ ansible_host }}" 69 | port: 22 70 | sleep: 10 71 | timeout: 900 72 | when: vers.find(target_version) == -1 73 | ... 74 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | If you're reading this, you're probably thinking about contributing to this repository. We really appreciate that--thank you! 4 | 5 | This document provides guidelines on contributing to this repository. Please follow these guidelines when creating issues, making commits, and submitting pull requests. The repository maintainers review all pull requests and verify that they conform to these guidelines before approving and merging. 6 | 7 | #### Table Of Contents 8 | [How Can I Contribute?](#how-can-i-contribute) 9 | * [Contribution Ideas](#contribution-ideas) 10 | * [What should I know before I get started?](#what-should-i-know-before-i-get-started) 11 | 12 | [Licensing](#licensing) 13 | * [Developer's Certificate of Origin](#developers-certificate-of-origin) 14 | * [Sign Your Work](#sign-your-work) 15 | 16 | [Coding Conventions](#coding-conventions) 17 | 18 | [Additional Notes](#additional-notes) 19 | * [Resources](#resources) 20 | 21 | ## How Can I Contribute? 22 | 23 | ### Contribution Ideas 24 | 25 | 1. Raise issues for bugs, features, and enhancements. 26 | 1. Submit updates and improvements to the documentation. 27 | 1. Submit articles and guides, which are also part of the documentation. 28 | 1. Help out repo maintainers by answering questions in [Airheads Developer Community][airheads-link]. 29 | 1. Share feedback and let us know about interesting use cases in [Airheads Developer Community][airheads-link]. 30 | 31 | ### What should I know before I get started? 32 | 33 | The best way to directly collaborate with the project contributors is through GitHub. 34 | 35 | * If you want to raise an issue such as a defect, an enhancement request, feature request, or a general issue, please open a GitHub issue. 36 | * If you want to contribute to our code by either fixing a problem, enhancing some code, or creating a new feature, please open a GitHub pull request against the development branch. 37 | > **Note:** All pull requests require an associated issue number, must be made against the **development** branch, and require acknowledgement of the DCO. See the [Licensing](#licensing) section below. 38 | 39 | Before you start to code, we recommend discussing your plans through a GitHub issue, especially for more ambitious contributions. This gives other contributors a chance to point you in the right direction, give you feedback on your design, and help you find out if someone else is working on the same thing. 40 | 41 | It is your responsibility to test and verify, prior to submitting a pull request, that your updated code doesn't introduce any bugs. Please write a clear commit message for each commit. Brief messages are fine for small changes, but bigger changes warrant a little more detail (at least a few sentences). 42 | Note that all patches from all contributors get reviewed. 43 | After a pull request is made, other contributors will offer feedback. If the patch passes review, a maintainer will accept it with a comment. 44 | When a pull request fails review, the author is expected to update the pull request to address the issue until it passes review and the pull request merges successfully. 45 | 46 | At least one review from a maintainer is required for all patches. 47 | 48 | ## Licensing 49 | 50 | All contributions must include acceptance of the DCO: 51 | 52 | ### Developer’s Certificate of Origin 53 | 54 | > Developer Certificate of Origin Version 1.1 55 | > 56 | > Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 660 57 | > York Street, Suite 102, San Francisco, CA 94110 USA 58 | > 59 | > Everyone is permitted to copy and distribute verbatim copies of this 60 | > license document, but changing it is not allowed. 61 | > 62 | > Developer's Certificate of Origin 1.1 63 | > 64 | > By making a contribution to this project, I certify that: 65 | > 66 | > \(a) The contribution was created in whole or in part by me and I have 67 | > the right to submit it under the open source license indicated in the 68 | > file; or 69 | > 70 | > \(b) The contribution is based upon previous work that, to the best of my 71 | > knowledge, is covered under an appropriate open source license and I 72 | > have the right under that license to submit that work with 73 | > modifications, whether created in whole or in part by me, under the same 74 | > open source license (unless I am permitted to submit under a different 75 | > license), as indicated in the file; or 76 | > 77 | > \(c) The contribution was provided directly to me by some other person 78 | > who certified (a), (b) or (c) and I have not modified it. 79 | > 80 | > \(d) I understand and agree that this project and the contribution are 81 | > public and that a record of the contribution (including all personal 82 | > information I submit with it, including my sign-off) is maintained 83 | > indefinitely and may be redistributed consistent with this project or 84 | > the open source license(s) involved. 85 | 86 | ### Sign Your Work 87 | 88 | To accept the DCO, simply add this line to each commit message with your 89 | name and email address (`git commit -s` will do this for you): 90 | 91 | Signed-off-by: Jane Example 92 | 93 | For legal reasons, no anonymous or pseudonymous contributions are 94 | accepted. 95 | 96 | ## Coding Conventions 97 | 98 | 1. Python code should conform to PEP-8. PyCharm editor has a built-in PEP-8 checker. 99 | 1. Since this is a collaborative project, document your code with comments that will help other contributors understand the code you write. 100 | 1. When in doubt, follow conventions you see used in the source already. 101 | 102 | ## Additional Notes 103 | 104 | > **Note:** Please don't file an issue to ask a question. Please reach out to us via email or disucssion forums. 105 | 106 | ### Resources 107 | 108 | | Resource | Description | 109 | | --- | --- | 110 | | [Aruba Developer Hub][devhub-link] | Aruba Developer Hub that showcases all automated solutions for Aruba products. | 111 | | [Airheads Developer Community][airheads-link] | Aruba Airheads forum to discuss all things network automation. | 112 | | [Aruba Bots Automate Videos][aruba-bots-playlist-link]| YouTube playlist containing instructional videos for Ansible and Python automation repositories. | 113 | | [aruba-automation@hpe.com][email-link] | Distribution list email to contact the Aruba Automation Technical Marketing Engineering team. | 114 | 115 | 116 | [devhub-link]: https://developer.arubanetworks.com/ 117 | [airheads-link]: https://community.arubanetworks.com/t5/Developer-Community/bd-p/DeveloperCommunity 118 | [aruba-bots-playlist-link]: https://www.youtube.com/playlist?list=PLsYGHuNuBZcY02FUh95ZpOB5VFkPurVaX 119 | [email-link]: mailto:aruba-automation@hpe.com 120 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------