1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
import ansible_runner
from network_runner import exceptions
from network_runner.models.playbook import Playbook
from network_runner.models.inventory import Inventory
from network_runner.models.inventory import Host
ALL = 'all'
IMPORT_ROLE = 'import_role'
NETWORK_RUNNER = 'network-runner'
CREATE_VLAN = 'create_vlan'
DELETE_VLAN = 'delete_vlan'
LIST_VLANS = 'list_vlans'
CONF_ACCESS_PORT = 'conf_access_port'
CONF_TRUNK_PORT = 'conf_trunk_port'
ADD_TRUNK_VLAN = 'add_trunk_vlan'
DELETE_TRUNK_VLAN = 'delete_trunk_vlan'
DELETE_PORT = 'delete_port'
class NetworkRunner(object):
"""Object to invoke ansible_runner to call Ansible Networking
Hold inventory and provide an interface for calling
roles in Ansible Networking to manipulate switch configuration
"""
def __init__(self, inventory=None):
if inventory is not None:
assert isinstance(inventory, Inventory)
self.inventory = inventory or Inventory()
def has_host(self, host):
"""Check if given host is in the inventory
:param host: Name or ansible host of ```Host```
:type host: String
:returns: Boolean
"""
for n, h in self.inventory.hosts.items():
if h.ansible_host == host or n == host:
return True
return False
def add_host(self, host):
"""Add host to inventory
Adds a new ```Host``` instance to the current inventory
object. The value must be a value ```Host``` instance.
:param host: A valid instance of ```Host```
:type host: network_runner.models.inventory.hosts.Host
:returns: None
"""
assert isinstance(host, Host)
self.inventory.hosts.add(host)
def run(self, playbook):
assert isinstance(playbook, Playbook)
# invoke ansible networking via ansible runner
result = ansible_runner.run(playbook=playbook.serialize(),
inventory=self.inventory.serialize(),
settings={'pexpect_use_poll': False})
# check for failure
if result.status == 'failed' or \
(result.stats and result.stats.get('failures', [])):
raise exceptions.NetworkRunnerException(' '.join(result.stdout))
return result
def play(self, tasks_from, hosts=None, variables=None):
"""Play a set of tasks from the role
:param tasks_from: the task to play
:type tasks_from: str
:param hosts: the hosts to execute against
:type hosts: str
:param variables: values to be passed into the play
:type variables: dict
:returns: the results of the playbook run
:rtype: AnsibleRunner
"""
pb = Playbook()
play = pb.new(hosts=(hosts or ALL), gather_facts=False)
task = play.tasks.new(action=IMPORT_ROLE)
task.args = {'name': NETWORK_RUNNER, 'tasks_from': tasks_from}
if variables:
task.vars = variables
return self.run(pb)
def create_vlan(self, hostname, vlan_id, vlan_name=None, **kwargs):
"""Create VLAN.
:param hostname: The name of the host in Ansible inventory.
:param vlan_id: The VLAN's ID to create.
:param vlan_name: The VLAN's name/description.
"""
variables = {'vlan_id': vlan_id, 'vlan_name': vlan_name}
variables.update(kwargs)
return self.play(CREATE_VLAN, hostname, variables)
def list_vlans(self, hostname, **kwargs):
"""List VLANs.
:param hostname: The name of the host in Ansible inventory.
"""
variables = kwargs
return self.play(LIST_VLANS, hostname, variables)
def delete_vlan(self, hostname, vlan_id, **kwargs):
"""Delete VLAN.
:param hostname: The name of the host in Ansible inventory.
:param vlan_id: The VLAN's ID to delete.
"""
variables = {'vlan_id': vlan_id}
variables.update(kwargs)
return self.play(DELETE_VLAN, hostname, variables)
def conf_access_port(self, hostname, port, vlan_id, **kwargs):
"""Configure access port on a vlan.
:param hostname: The name of the host in Ansible inventory.
:param port: The port to configure.
:param vlan_id: The vlan_id to assign to the port.
An empty or None value will default to the
target device's default VLAN assignment. This
default is assigned in the ansible role.
:param kwargs: used to pass platform specific parameters into
the ansible roles. For example immediate STP
fwding state is named different things on different
platforms.
"""
variables = {'vlan_id': vlan_id, 'port_name': port,
'port_description': port}
variables.update(kwargs)
return self.play(CONF_ACCESS_PORT, hostname, variables)
def conf_trunk_port(self, hostname, port, vlan_id,
trunked_vlans, **kwargs):
"""Configure trunk port w/ default vlan and optional additional vlans
:param hostname: The name of the host in Ansible inventory.
:param port: The port to configure.
:param vlan_id: the default VLAN ID to assign to the port
An empty or None value will default to the
target device's default VLAN assignment. This
default is assigned in the ansible role.
:param trunked_vlans: A list of VLAN IDs to add to the port in
addition to the default VLAN.
:param kwargs: used to pass platform specific parameters into
the ansible roles. For example immediate STP
fwding state is named different things on different
platforms.
"""
variables = {'vlan_id': vlan_id, 'port_name': port,
'port_description': port, 'trunked_vlans': trunked_vlans}
variables.update(kwargs)
return self.play(CONF_TRUNK_PORT, hostname, variables)
def add_trunk_vlan(self, hostname, port, vlan_id, **kwargs):
"""Add VLAN to trunk port.
:param hostname: The name of the host in Ansible inventory.
:param port: The port to configure.
:param vlan_id: The VLAN's ID to delete.
"""
variables = {'vlan_id': vlan_id, 'port_name': port}
variables.update(kwargs)
return self.play(ADD_TRUNK_VLAN, hostname, variables)
def delete_trunk_vlan(self, hostname, port, vlan_id, **kwargs):
"""Delete VLAN.
:param hostname: The name of the host in Ansible inventory.
:param port: The port to configure.
:param vlan_id: The VLAN's ID to delete.
"""
variables = {'vlan_id': vlan_id, 'port_name': port}
variables.update(kwargs)
return self.play(DELETE_TRUNK_VLAN, hostname, variables)
def delete_port(self, hostname, port, **kwargs):
"""Delete port configuration.
:param hostname: The name of the host in Ansible inventory.
:param port: The port to configure.
"""
variables = {'port_name': port}
variables.update(kwargs)
return self.play(DELETE_PORT, hostname, variables)
|