-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial commit of aoscx-ansible-role
- Loading branch information
0 parents
commit f538c7b
Showing
21 changed files
with
3,569 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
|
||
aoscx | ||
========= | ||
|
||
This Ansible Network role provides a set of platform dependent configuration | ||
management modules specifically designed for the AOS-CX network device. | ||
|
||
Requirements | ||
------------ | ||
|
||
* Python 2.7 or 3.5+ | ||
* Ansible 2.8.1 or later | ||
* Minimum supported AOS-CX firmware version 10.03 | ||
* Enable REST on your AOS-CX device with the following commands: | ||
``` | ||
switch(config)# https-server rest access-mode read-write | ||
switch(config)# https-server vrf mgmt | ||
``` | ||
Installation | ||
------------ | ||
Through Github, use the following command. Use option `-f` to overwrite current role version: | ||
``` | ||
ansible-galaxy install git+https://github.com/aruba/aoscx-ansible-role.git | ||
``` | ||
Through Galaxy: | ||
``` | ||
ansible-galaxy install arubanetworks.aoscx | ||
``` | ||
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 | ||
* `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 | ||
Sample `inventory.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 | ||
``` | ||
|
||
Example Playbook | ||
---------------- | ||
|
||
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 | ||
tasks: | ||
- name: Create L3 Interface 1/1/3 | ||
aoscx_l3_interface: | ||
interface: 1/1/3 | ||
description: Uplink_Interface | ||
ipv4: ['10.20.1.3/24'] | ||
ipv6: ['2000:db8::1234/32'] | ||
``` | ||
If role installed through [Galaxy]() | ||
set role to `aoscx`: | ||
|
||
```yaml | ||
--- | ||
- hosts: all | ||
roles: | ||
- role: aoscx | ||
tasks: | ||
- name: Create L3 Interface 1/1/3 | ||
aoscx_l3_interface: | ||
interface: 1/1/3 | ||
description: Uplink_Interface | ||
ipv4: ['10.20.1.3/24'] | ||
ipv6: ['2000:db8::1234/32'] | ||
``` | ||
|
||
Contribution | ||
------- | ||
At Aruba Networks we're dedicated to ensuring the quality of our products, 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! | ||
|
||
|
||
License | ||
------- | ||
|
||
Apache 2.0 | ||
|
||
Author Information | ||
------------------ | ||
Madhusudan Pranav Venugopal (madhusudan-pranav-venugopal) | ||
Yang Liu (yliu-aruba) | ||
Tiffany Chiapuzio-Wong (tchiapuziowong) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
# | ||
# (C) Copyright 2019 Hewlett Packard Enterprise Development LP. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, | ||
# software distributed under the License is distributed on an | ||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
# KIND, either express or implied. See the License for the | ||
# specific language governing permissions and limitations | ||
# under the License. | ||
|
||
DOCUMENTATION = """ | ||
--- | ||
author: Aruba Networks | ||
httpapi: aoscx | ||
short_description: Use REST to push configs to CX devices | ||
description: | ||
- This ArubaOSCX module provides REST interactions with ArubaOS-CX devices | ||
version_added: "2.8" | ||
options: | ||
acx_no_proxy: | ||
type: bool | ||
default: True | ||
description: | ||
- Specifies whether to set no_proxy for devices | ||
env: | ||
- name: ANSIBLE_ACX_NO_PROXY | ||
vars: | ||
- name: ansible_acx_no_proxy | ||
version_added: '2.8' | ||
""" | ||
|
||
import json | ||
import os | ||
from ansible.module_utils._text import to_text | ||
from ansible.module_utils.connection import ConnectionError | ||
from ansible.module_utils.parsing.convert_bool import boolean | ||
from ansible.module_utils.six.moves.urllib.error import HTTPError | ||
from ansible.plugins.httpapi import HttpApiBase | ||
|
||
|
||
try: | ||
from __main__ import display | ||
except ImportError: | ||
from ansible.utils.display import Display | ||
display = Display() | ||
|
||
|
||
class HttpApi(HttpApiBase): | ||
|
||
def set_no_proxy(self): | ||
try: | ||
no_proxy = boolean(self.get_option("acx_no_proxy")) | ||
except NameError: | ||
no_proxy = False | ||
if no_proxy: | ||
os.environ['no_proxy'] = "*" | ||
display.vvvv("no_proxy set to True") | ||
|
||
def login(self, username, password): | ||
self.set_no_proxy() | ||
path = '/rest/v1/login?username='+username+'&password='+password | ||
method = 'POST' | ||
headers = {} | ||
|
||
_ = self.send_request(data=None, path=path, method=method, | ||
headers=headers) | ||
|
||
def logout(self): | ||
path = '/rest/v1/logout' | ||
data = None | ||
method = 'POST' | ||
self.send_request(data, path=path, method=method) | ||
|
||
def send_request(self, data, **message_kwargs): | ||
headers = {} | ||
if self.connection._auth: | ||
headers.update(self.connection._auth) | ||
response, response_data = self.connection.send( | ||
data=data, headers=headers, path=message_kwargs['path'], | ||
method=message_kwargs['method']) | ||
return self.handle_response(response, response_data) | ||
|
||
def handle_response(self, response, response_data): | ||
response_data_json = '' | ||
try: | ||
response_data_json = json.loads(to_text(response_data.getvalue())) | ||
except ValueError: | ||
|
||
response_data = response_data.read() | ||
if isinstance(response, HTTPError): | ||
if response_data: | ||
if 'errors' in response_data: | ||
errors = response_data['errors']['error'] | ||
error_text = '\n'.join((error['error-message'] for error in errors)) # NOQA | ||
else: | ||
error_text = response_data | ||
|
||
raise ConnectionError(error_text, code=response.code) | ||
raise ConnectionError(to_text(response), code=response.code) | ||
|
||
auth = self.update_auth(response, response_data) | ||
if auth: | ||
self.connection._auth = auth | ||
return response_data_json | ||
|
||
def get_running_config(self): | ||
if self.connection._connected: | ||
path = '/rest/v1/fullconfigs/running-config' | ||
method = 'GET' | ||
data = None | ||
response_data = self.send_request(data=data, method=method, | ||
path=path) | ||
display.vvvv(json.dumps(response_data)) | ||
return response_data | ||
|
||
def put_running_config(self, updated_config): | ||
if self.connection._connected: | ||
path = '/rest/v1/fullconfigs/running-config' | ||
method = 'PUT' | ||
data = json.dumps(updated_config) | ||
self.send_request(data=data, method=method, path=path) |
Oops, something went wrong.