Skip to content

Commit

Permalink
New modules and bug fixes
Browse files Browse the repository at this point in the history
- This release includes new modules that allow for SSH/CLI commands and configuration.
- New Modules
- aoscx_command - This module connects to the CX device via SSH and allows CLI commands to be executed.
- aoscx_config - This module connects to the CX device via SSH and allows CLI configuration commands to be executed.
- aoscx_facts - This module used REST API to retrieve a subset of information from the CX device.
- Known Issues
- To use the aoscx_facts module, the device must be running firmware version 10.4 or higher.
  • Loading branch information
tchiapuziowong committed Mar 20, 2020
1 parent ab3712e commit da0d435
Show file tree
Hide file tree
Showing 19 changed files with 2,382 additions and 55 deletions.
142 changes: 124 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
aoscx
=========

This Ansible Network role provides a set of platform dependent configuration
This Ansible network role provides a set of platform-dependent configuration
management modules specifically designed for the AOS-CX network device.

Requirements
Expand All @@ -16,6 +16,26 @@ Requirements
switch(config)# https-server rest access-mode read-write
switch(config)# https-server vrf mgmt
```
SSH/CLI Modules
---------------
* To use the SSH/CLI modules `aoscx_config` and `aoscx_command`, SSH access must
be enabled on your AOS-CX device. It is enabled by default.
* If necessary, re-enable SSH access on the device with the following command:
```
switch(config)# ssh server vrf mgmt
```
* The control machine's `known_hosts` file must contain the target device's public key.
* Alternatively, host key checking by the control machine may be disabled, although this is not recommended.
* To disable host key checking modify the ansible.cfg file (default /etc/ansible/ansible.cfg) to include:
`host_key_checking = false`
#### Limitations and Notes
* The default command timeout is 30 seconds. If a command takes more than 30
seconds to execute, the task will time out.
* If you regularly encounter the `command timeout triggered, timeout value
is 30 secs` error, consider setting the environment variable
`ANSIBLE_PERSISTENT_COMMAND_TIMEOUT` to a greater value. See Ansible documentation [here](https://docs.ansible.com/ansible/latest/network/user_guide/network_debug_troubleshooting.html).
Installation
------------
Expand All @@ -33,28 +53,32 @@ ansible-galaxy install arubanetworks.aoscx_role
```
Inventory Variables
--------------
-------------------
The variables that should be defined in your inventory for your AOS-CX host are:
* `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]'`.
* `ansible_user`: Username for switch in `plaintext` format
* `ansible_password`: Password for switch in `plaintext` format
* `ansible_connection`: Must always be set to `httpapi`
* `ansible_network_os`: Must always be set to `aoscx`
* `ansible_httpapi_use_ssl`: Must always be `True` as AOS-CX uses port 443 for REST
* `ansible_httpapi_validate_certs`: Set `True` or `False` depending on if Ansible should attempt to validate certificates
* `ansible_acx_no_proxy`: Set `True` or `False` depending if Ansible should bypass environment proxies to connect to AOS-CX
* `ansible_password`: Password for switch in `plaintext` format
* `ansible_network_os`: Must always be set to `aoscx`
* `ansible_connection`: Set to `httpapi` to use REST API modules, and to `network_cli` to use SSH/CLI modules
* See [below](#using-both-rest-api-and-sshcli-modules-on-a-host) for info on using both REST API modules and SSH/CLI modules on a host
* `ansible_httpapi_use_ssl`: (Only required for REST API modules) Must always be `True` as AOS-CX uses port 443 for REST
* `ansible_httpapi_validate_certs`: (Only required for REST API modules) Set `True` or `False` depending on if Ansible should attempt to validate certificates
* `ansible_acx_no_proxy`: Set to `True` or `False` depending if Ansible should bypass environment proxies to connect to AOS-CX
### Sample Inventories:
### Sample Inventory:
#### REST API Modules Only:
#### INI
##### INI
```INI
aoscx_1 ansible_host=10.0.0.1 ansible_user=admin ansible_password=password ansible_connection=httpapi ansible_network_os=aoscx ansible_httpapi_validate_certs=False ansible_httpapi_use_ssl=True ansible_acx_no_proxy=True
aoscx_1 ansible_host=10.0.0.1 ansible_user=admin ansible_password=password ansible_network_os=aoscx ansible_connection=httpapi ansible_httpapi_validate_certs=False ansible_httpapi_use_ssl=True ansible_acx_no_proxy=True
```

#### YAML
##### YAML


```yaml
all:
Expand All @@ -63,21 +87,43 @@ all:
ansible_host: 10.0.0.1
ansible_user: admin
ansible_password: password
ansible_connection: httpapi # Do not change
ansible_network_os: aoscx
ansible_connection: httpapi # REST API connection method
ansible_httpapi_validate_certs: False
ansible_httpapi_use_ssl: True
ansible_acx_no_proxy: True
```
Example Playbook
----------------
#### SSH/CLI Modules Only:
##### INI
```INI
aoscx_1 ansible_host=10.0.0.1 ansible_user=admin ansible_password=password ansible_network_os=aoscx ansible_connection=network_cli
```

##### YAML

```yaml
all:
hosts:
aoscx_1:
ansible_host: 10.0.0.1
ansible_user: admin
ansible_password: password
ansible_network_os: aoscx
ansible_connection: network_cli # SSH connection method
```
Example Playbooks
-----------------
### Including the Role
If role installed through [Github](https://github.com/aruba/aoscx-ansible-role)
set role to `aoscx-ansible-role`:

```yaml
---
- hosts: all
roles:
- role: aoscx-ansible-role
Expand All @@ -94,7 +140,6 @@ If role installed through [Galaxy](https://galaxy.ansible.com/arubanetworks/aosc
set role to `arubanetworks.aoscx_role`:

```yaml
---
- hosts: all
roles:
- role: arubanetworks.aoscx_role
Expand All @@ -107,9 +152,69 @@ set role to `arubanetworks.aoscx_role`:
ipv6: ['2001:db8::1234/64']
```

Using Both REST API and SSH/CLI Modules on a Host
-------------------------------------------------

To use both REST API and SSH/CLI modules on the same host,
you must create separate plays such
that each play uses either only REST API modules or only SSH/CLI modules.
A play cannot mix and match REST API and SSH/CLI module calls.
In each play, `ansible_connection` must possess the appropriate value
according to the modules used.
If the play uses REST API modules, the value should be `httpapi`.
If the play uses SSH/CLI modules, the value should be `network_cli`.

A recommended approach to successfully using both types of modules for a host
is as follows:
1. Set the host variables such that Ansible will connect to the host using REST API,
like seen [above](#rest-api-modules-only).
2. In the playbook, in each play wherein the SSH/CLI
modules are used, set the `ansible_connection` to `network_cli`.

The inventory should look something like this:

```yaml
all:
hosts:
aoscx_1:
ansible_host: 10.0.0.1
ansible_user: admin
ansible_password: password
ansible_network_os: aoscx
ansible_connection: httpapi # REST API connection method
ansible_httpapi_validate_certs: False
ansible_httpapi_use_ssl: True
ansible_acx_no_proxy: True
```

and the playbook like this (note how the second play, which uses the SSH/CLI module `aoscx_command`,
sets the `ansible_connection` value accordingly):

```yaml
- hosts: all
roles:
- role: arubanetworks.aoscx_role
tasks:
- name: Adding or Updating Banner
aoscx_banner:
banner_type: banner
banner: "Hi!"
- hosts: all
roles:
- role: arubanetworks.aoscx_role
vars:
ansible_connection: network_cli
tasks:
- name: Execute show run on the switch
aoscx_command:
commands: ['show run']
```


Contribution
-------
At Aruba Networks we're dedicated to ensuring the quality of our products, if you find any
At Aruba Networks we're dedicated to ensuring the quality of our products, so if you find any
issues at all please open an issue on our [Github](https://github.com/aruba/aoscx-ansible-role) and we'll be sure to respond promptly!


Expand All @@ -123,4 +228,5 @@ Author Information
- Madhusudan Pranav Venugopal (@madhusudan-pranav-venugopal)
- Yang Liu (@yliu-aruba)
- Tiffany Chiapuzio-Wong (@tchiapuziowong)
- Derek Wang (@derekwangHPEAruba)

18 changes: 16 additions & 2 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# 2.1.0

## Notable Changes
* New Modules and Bug fixes
* This release includes new modules that allow for SSH/CLI commands and configuration. Refer to module documentation found in [docs/](https://github.com/aruba/aoscx-ansible-role/tree/master/docs).

## New Modules
* aoscx_command - This module connects to the CX device via SSH and allows CLI commands to be executed.
* aoscx_config - This module connects to the CX device via SSH and allows CLI configuration commands to be executed.
* aoscx_facts - This module used REST API to retrieve a subset of information from the CX device.

## Known Issues
* To use the aoscx_facts module, the device must be running firmware version 10.4 or higher.

# 2.0.0

## Notable Changes
Expand All @@ -13,8 +27,8 @@

## Known Issues
* There is a known issue with the following modules on all platforms and 10.4 firmware version. Please only use these modules with 10.3 at this time:
* aoscx_l3_interface
* aoscx_vlan_interface
** aoscx_l3_interface
** aoscx_vlan_interface
* To upload firmware using HTTP server with the module aoscx_upload_firmware, the device must be running firmware version 10.4 or higher.

# 1.0.5
Expand Down
138 changes: 138 additions & 0 deletions cliconf_plugins/aoscx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP.
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)


DOCUMENTATION = """
---
author: Aruba Networks (@ArubaNetworks)
network_cli: aoscx
short_description: Use CLI to run commands to CX devices
description:
- This ArubaOSCX plugin provides CLI operations with ArubaOS-CX Devices
version_added: "2.9"
"""

import json
import re
from itertools import chain

from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils._text import to_text
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase, enable_mode


class Cliconf(CliconfBase):
'''
Cliconf class for AOS-CX
'''

def __init__(self, *args, **kwargs):
'''
init function
'''
super(Cliconf, self).__init__(*args, **kwargs)

@enable_mode
def get_config(self, source='running', format='text', flags=None):
'''
Get the switch config
'''
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from {} is not"
" supported".format(source))
if source == 'running':
cmd = 'show running-config all'
else:
cmd = 'show configuration'
return self.send_command(cmd)

@enable_mode
def edit_config(self, command):
'''
Edit the switch config
'''
for cmd in chain(['configure terminal'], to_list(command), ['end']):
self.send_command(cmd)

def get(self, command, prompt=None, answer=None, sendonly=False,
newline=True, check_all=False):
'''
Get command output from switch
'''
return self.send_command(command=command, prompt=prompt, answer=answer,
sendonly=sendonly, newline=newline,
check_all=check_all)

def get_device_info(self):
'''
Get device info
'''
device_info = {}

device_info['network_os'] = 'aruba'
reply = self.get('show version')
data = to_text(reply, errors='surrogate_or_strict').strip()

match = re.search(r'Version (\S+)', data)
if match:
device_info['network_os_version'] = match.group(1)

match = re.search(r'^MODEL: (\S+)\),', data, re.M)
if match:
device_info['network_os_model'] = match.group(1)

reply = self.get('show hostname')
data = to_text(reply, errors='surrogate_or_strict').strip()

match = re.search(r'^Hostname is (.+)', data, re.M)
if match:
device_info['network_os_hostname'] = match.group(1)

return device_info

def get_capabilities(self):
'''
Get capabilities
'''
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)

def run_commands(self, commands=None, check_rc=False):
'''
Run commands on the switch
'''
if commands is None:
raise ValueError("'commands' value is required")
responses = list()
for cmd in to_list(commands):

if not isinstance(cmd, Mapping):
cmd = {'command': cmd}

try:
out = self.send_command(**cmd)
except AnsibleConnectionFailure as exception:

if check_rc:
raise
out = getattr(exception, 'err', exception)

out = to_text(out, errors='surrogate_or_strict')

responses.append(out)

return responses

def set_cli_prompt_context(self):
"""
Make sure we are in the operational cli mode
:return: None
"""
if self._connection.connected:
self._update_cli_prompt_context(config_context=')#')
Loading

0 comments on commit da0d435

Please sign in to comment.