WIP: Aruba switches #103
12 changed files with 498 additions and 0 deletions
83
action_plugins/aruba_cfg_restore.py
Normal file
83
action_plugins/aruba_cfg_restore.py
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import base64
|
||||||
|
import time
|
||||||
|
import functools
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from ansible.errors import AnsibleActionFail
|
||||||
|
from ansible.plugins.action import ActionBase
|
||||||
|
|
||||||
|
|
||||||
|
class Aruba:
|
||||||
|
def __init__(self, base_url):
|
||||||
|
self._session = requests.session()
|
||||||
|
self._base_url = base_url
|
||||||
|
|
||||||
|
def _url(self, url):
|
||||||
|
return urllib.parse.urljoin(self._base_url, url)
|
||||||
|
|
||||||
|
def login(self, username, password):
|
||||||
|
response = self._session.post(
|
||||||
|
self._url("/rest/v4/login-sessions"),
|
||||||
|
json={"userName": username, "password": password},
|
||||||
|
)
|
||||||
|
if response.status_code != requests.codes.created:
|
||||||
|
raise AnsibleActionFail("Login failed")
|
||||||
|
|
||||||
|
def logout(self):
|
||||||
|
response = self._session.delete(self._url("/rest/v4/login-sessions"))
|
||||||
|
if response.status_code != requests.codes.no_content:
|
||||||
|
raise AnsibleActionFail("Logout failed")
|
||||||
|
|
||||||
|
def restore(self, config):
|
||||||
|
response = self._session.post(
|
||||||
|
self._url(
|
||||||
|
"/rest/v4/system/config/cfg_restore/payload"
|
||||||
|
),
|
||||||
|
json={
|
||||||
|
"config_base64_encoded": base64.b64encode(config.encode()),
|
||||||
|
"is_forced_reboot_enabled": True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if response.status_code != requests.codes.accepted:
|
||||||
|
raise AnsibleActionFail("Restore failed")
|
||||||
|
|
||||||
|
response = self._session.get(
|
||||||
|
self._url(
|
||||||
|
"/rest/v4/system/config/cfg_restore/payload/status"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(response.text)
|
||||||
|
|
||||||
|
|
||||||
|
class ActionModule(ActionBase):
|
||||||
|
|
||||||
|
_VALID_ARGS = frozenset(("username", "password", "config", "url"))
|
||||||
|
|
||||||
|
def _require_arg(self, name):
|
||||||
|
try:
|
||||||
|
return self._task.args[name]
|
||||||
|
except KeyError:
|
||||||
|
raise AnsibleActionFail("Missing argument: {}".format(name))
|
||||||
|
|
||||||
|
def run(self, tmp=None, task_vars=None):
|
||||||
|
task_vars = task_vars or {}
|
||||||
|
result = super().run(tmp, task_vars)
|
||||||
|
|
||||||
|
base_url = self._task.args.get("url")
|
||||||
|
username = self._require_arg("username")
|
||||||
|
password = self._require_arg("password")
|
||||||
|
config = self._require_arg("config")
|
||||||
|
|
||||||
|
aruba = Aruba(base_url)
|
||||||
|
aruba.login(username, password)
|
||||||
|
|
||||||
|
try:
|
||||||
|
aruba.restore(config)
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
aruba.logout()
|
||||||
|
|
||||||
|
return result
|
|
@ -4,6 +4,7 @@ roles_path = ./roles
|
||||||
retry_files_enabled = False
|
retry_files_enabled = False
|
||||||
inventory = ./hosts
|
inventory = ./hosts
|
||||||
filter_plugins = ./filter_plugins
|
filter_plugins = ./filter_plugins
|
||||||
|
action_plugins = ./action_plugins
|
||||||
ansible_managed = Ansible managed, modified on %Y-%m-%d %H:%M:%S
|
ansible_managed = Ansible managed, modified on %Y-%m-%d %H:%M:%S
|
||||||
nocows = 1
|
nocows = 1
|
||||||
forks = 15
|
forks = 15
|
||||||
|
|
17
filter_plugins/aruba.py
Normal file
17
filter_plugins/aruba.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
class FilterModule:
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
"aruba_ints": aruba_ints,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def aruba_ints(seq, sep=",", hyphen="-"):
|
||||||
|
ranges = []
|
||||||
|
for value in sorted(seq):
|
||||||
|
if not ranges or ranges[-1][1] + 1 != value:
|
||||||
|
ranges.append((value, value))
|
||||||
|
else:
|
||||||
|
ranges[-1] = (ranges[-1][0], value)
|
||||||
|
return sep.join(
|
||||||
|
(f"{a}" if a == b else f"{a}{hyphen}{b}" for a, b in ranges)
|
||||||
|
)
|
16
filter_plugins/enquote.py
Normal file
16
filter_plugins/enquote.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
class FilterModule:
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
"enquote": enquote,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def enquote(string, delimiter='"', escape="\\"):
|
||||||
|
translation = str.maketrans(
|
||||||
|
{
|
||||||
|
delimiter: f"{escape}{delimiter}",
|
||||||
|
escape: f"{escape}{escape}",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
escaped = string.translate(translation)
|
||||||
|
return f"{delimiter}{escaped}{delimiter}"
|
9
filter_plugins/list_utils.py
Normal file
9
filter_plugins/list_utils.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
class FilterModule:
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
"contains": contains,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def contains(a, b):
|
||||||
|
return b in a
|
|
@ -8,6 +8,7 @@ class FilterModule:
|
||||||
def filters(self):
|
def filters(self):
|
||||||
return {
|
return {
|
||||||
"remove_domain_suffix": remove_domain_suffix,
|
"remove_domain_suffix": remove_domain_suffix,
|
||||||
|
"hostname": hostname,
|
||||||
"ipaddr_sort": ipaddr_sort,
|
"ipaddr_sort": ipaddr_sort,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +18,11 @@ def remove_domain_suffix(name):
|
||||||
return parent.to_text()
|
return parent.to_text()
|
||||||
|
|
||||||
|
|
||||||
|
def hostname(fqdn):
|
||||||
|
name = dns.name.from_text(fqdn)
|
||||||
|
return name.relativize(name.parent()).to_text()
|
||||||
|
|
||||||
|
|
||||||
def ipaddr_sort(addrs, types, unknown_after=True):
|
def ipaddr_sort(addrs, types, unknown_after=True):
|
||||||
check_types = {
|
check_types = {
|
||||||
"global": attrgetter("is_global"),
|
"global": attrgetter("is_global"),
|
||||||
|
|
11
filter_plugins/validators.py
Normal file
11
filter_plugins/validators.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class FilterModule:
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
"choices": choices,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def choices(value, choices):
|
||||||
|
if value not in choices:
|
||||||
|
raise ValueError(f"{value} not in {choices}")
|
||||||
|
return value
|
1
hosts
1
hosts
|
@ -96,6 +96,7 @@ radius-fleming.adm.auro.re
|
||||||
dns-1.int.infra.auro.re
|
dns-1.int.infra.auro.re
|
||||||
isp-1.rtr.infra.auro.re
|
isp-1.rtr.infra.auro.re
|
||||||
isp-2.rtr.infra.auro.re
|
isp-2.rtr.infra.auro.re
|
||||||
|
test-1.switch.infra.auro.re
|
||||||
dhcp-1.isp.auro.re
|
dhcp-1.isp.auro.re
|
||||||
dhcp-2.isp.auro.re
|
dhcp-2.isp.auro.re
|
||||||
radius-fleming-backup.adm.auro.re
|
radius-fleming-backup.adm.auro.re
|
||||||
|
|
84
playbooks/aruba.yml
Executable file
84
playbooks/aruba.yml
Executable file
|
@ -0,0 +1,84 @@
|
||||||
|
#!/usr/bin/env ansible-playbook
|
||||||
|
---
|
||||||
|
- hosts:
|
||||||
|
- test-1.switch.infra.auro.re
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
aruba__api_url: "http://{{ inventory_hostname }}"
|
||||||
|
aruba__api_username: "manager"
|
||||||
|
aruba__api_password: "manager"
|
||||||
|
aruba__model: J9773A
|
||||||
|
aruba__release: YA.16.11.002
|
||||||
|
aruba__hostname: "{{ inventory_hostname | hostname }}"
|
||||||
|
aruba__rest_enabled: true
|
||||||
|
aruba__ssh_enabled: true
|
||||||
|
aruba__ntp_servers:
|
||||||
|
- 10.128.0.1
|
||||||
|
- 2a09:6840:128:0:1::1
|
||||||
|
aruba__timezone: Europe/Paris
|
||||||
|
aruba__dns_servers:
|
||||||
|
- 10.128.0.1
|
||||||
|
- 2a09:6840:128:0:1::1
|
||||||
|
aruba__dns_domain_names:
|
||||||
|
- switch.infra.auro.re
|
||||||
|
- infra.auro.re
|
||||||
|
- toto.auro.re
|
||||||
|
aruba__manager_password: "manager"
|
||||||
|
aruba__operator_password: "operator"
|
||||||
|
aruba__default_gateways:
|
||||||
|
- 10.131.0.1
|
||||||
|
- 2a09:6840:131:0:1::1
|
||||||
|
aruba__vlans:
|
||||||
|
1:
|
||||||
|
name: Default
|
||||||
|
131:
|
||||||
|
name: Switchs
|
||||||
|
addresses:
|
||||||
|
- 10.131.1.1/16
|
||||||
|
- 2a09:6840:131:1:1::1/56
|
||||||
|
1000:
|
||||||
|
name: "Client 0"
|
||||||
|
1001:
|
||||||
|
name: "Client 1"
|
||||||
|
1002:
|
||||||
|
name: "Client 2"
|
||||||
|
1003:
|
||||||
|
name: "Client 3"
|
||||||
|
1004:
|
||||||
|
name: "Client 4"
|
||||||
|
aruba__interfaces:
|
||||||
|
1:
|
||||||
|
name: Uplink
|
||||||
|
untagged: 131
|
||||||
|
tagged:
|
||||||
|
- 1000
|
||||||
|
- 1001
|
||||||
|
- 1002
|
||||||
|
- 1003
|
||||||
|
- 1004
|
||||||
|
loop_protect: true
|
||||||
|
lldp: true
|
||||||
|
2:
|
||||||
|
name: "Client 0"
|
||||||
|
untagged: 1000
|
||||||
|
loop_protect: true
|
||||||
|
3:
|
||||||
|
name: "Client 1"
|
||||||
|
untagged: 1001
|
||||||
|
loop_protect: true
|
||||||
|
4:
|
||||||
|
name: "Client 2"
|
||||||
|
untagged: 1002
|
||||||
|
speed_duplex: 100-full
|
||||||
|
loop_protect: true
|
||||||
|
5:
|
||||||
|
name: "Client 3"
|
||||||
|
untagged: 1003
|
||||||
|
loop_protect: true
|
||||||
|
6:
|
||||||
|
name: "Client 4"
|
||||||
|
untagged: 1004
|
||||||
|
loop_protect: true
|
||||||
|
roles:
|
||||||
|
- aruba
|
||||||
|
...
|
11
roles/aruba/defaults/main.yml
Normal file
11
roles/aruba/defaults/main.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
aruba__ntp_servers: []
|
||||||
|
aruba__vlans: {}
|
||||||
|
aruba__interfaces: {}
|
||||||
|
aruba__default_gateways: []
|
||||||
|
aruba__ssh_enabled: False
|
||||||
|
aruba__rest_enabled: True
|
||||||
|
aruba__dns_domain_names: []
|
||||||
|
aruba__loop_protect_disable_timer: 30
|
||||||
|
aruba__loop_protect_tx_interval: 3
|
||||||
|
...
|
97
roles/aruba/tasks/main.yml
Normal file
97
roles/aruba/tasks/main.yml
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
---
|
||||||
|
- name: Generate configuration
|
||||||
|
set_fact:
|
||||||
|
aruba__config: "{{ lookup('template', './config.j2') }}"
|
||||||
|
when: "aruba__config is not defined"
|
||||||
|
|
||||||
|
- name: Restore configuration
|
||||||
|
aruba_cfg_restore:
|
||||||
|
url: "http://{{ inventory_hostname }}/"
|
||||||
|
username: "{{ aruba__api_username }}"
|
||||||
|
password: "{{ aruba__api_password }}"
|
||||||
|
config: "{{ aruba__config }}"
|
||||||
|
|
||||||
|
#- name: Login to switch
|
||||||
|
# delegate_to: localhost
|
||||||
|
# uri:
|
||||||
|
# url: "{{ aruba__api_base_url }}/rest/v4/login-sessions"
|
||||||
|
# method: POST
|
||||||
|
# status_code: 201
|
||||||
|
# body_format: json
|
||||||
|
# body:
|
||||||
|
# userName: "{{ aruba__api_username }}"
|
||||||
|
# password: "{{ aruba__api_password }}"
|
||||||
|
# register: login
|
||||||
|
|
||||||
|
#- name: Get diff
|
||||||
|
# delegate_to: localhost
|
||||||
|
# uri:
|
||||||
|
# url: "{{ aruba__api_base_url }}/rest/v4/system/config/cfg_restore/payload/latest_diff"
|
||||||
|
# method: POST
|
||||||
|
# body_format: json
|
||||||
|
# status_code: 202
|
||||||
|
# body:
|
||||||
|
# config_base64_encoded: "{{ aruba__config | b64encode }}"
|
||||||
|
# headers:
|
||||||
|
# Cookie: "{{ login.json.cookie }}"
|
||||||
|
# register: diff
|
||||||
|
|
||||||
|
#- name: Diff
|
||||||
|
# debug:
|
||||||
|
# msg: "{{ diff }}"
|
||||||
|
|
||||||
|
#- name: Get diff
|
||||||
|
# delegate_to: localhost
|
||||||
|
# uri:
|
||||||
|
# url: "{{ aruba__api_base_url }}/rest/v4/system/config/cfg_restore/payload/latest_diff/status"
|
||||||
|
# method: GET
|
||||||
|
# status_code: 200
|
||||||
|
# headers:
|
||||||
|
# Cookie: "{{ login.json.cookie }}"
|
||||||
|
# register: diff
|
||||||
|
|
||||||
|
#- name: Diff
|
||||||
|
# debug:
|
||||||
|
# msg: "{{ diff }}"
|
||||||
|
|
||||||
|
#- name: Restore configuration
|
||||||
|
# delegate_to: localhost
|
||||||
|
# uri:
|
||||||
|
# url: "{{ aruba__api_base_url }}/rest/v4/system/config/cfg_restore/payload"
|
||||||
|
# method: POST
|
||||||
|
# body_format: json
|
||||||
|
# status_code: 202
|
||||||
|
# body:
|
||||||
|
# config_base64_encoded: "{{ aruba__config | b64encode }}"
|
||||||
|
# is_forced_reboot_enabled: true
|
||||||
|
# headers:
|
||||||
|
# Cookie: "{{ login.json.cookie }}"
|
||||||
|
# register: status
|
||||||
|
#
|
||||||
|
#- name: XX
|
||||||
|
# debug:
|
||||||
|
# msg: "{{ status }}"
|
||||||
|
#
|
||||||
|
#- name: Get diff
|
||||||
|
# delegate_to: localhost
|
||||||
|
# uri:
|
||||||
|
# url: "{{ aruba__api_base_url }}/rest/v4/system/config/cfg_restore/payload/status"
|
||||||
|
# method: GET
|
||||||
|
# status_code: 200
|
||||||
|
# headers:
|
||||||
|
# Cookie: "{{ login.json.cookie }}"
|
||||||
|
# register: diff
|
||||||
|
|
||||||
|
#- name: Diff
|
||||||
|
# debug:
|
||||||
|
# msg: "{{ diff }}"
|
||||||
|
|
||||||
|
#- name: Logout
|
||||||
|
# delegate_to: localhost
|
||||||
|
# uri:
|
||||||
|
# url: "{{ aruba__api_base_url }}/rest/v4/login-sessions"
|
||||||
|
# method: DELETE
|
||||||
|
# status_code: 204
|
||||||
|
# headers:
|
||||||
|
# Cookie: "{{ login.json.cookie }}"
|
||||||
|
...
|
162
roles/aruba/templates/config.j2
Normal file
162
roles/aruba/templates/config.j2
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
; {{ aruba__model }} Configuration Editor; Created on release #{{ aruba__release }}
|
||||||
|
|
||||||
|
hostname {{ aruba__hostname | hostname | truncate(32) | enquote }}
|
||||||
|
|
||||||
|
include-credentials
|
||||||
|
|
||||||
|
{% if aruba__ntp_servers %}
|
||||||
|
timesync ntp
|
||||||
|
ntp unicast
|
||||||
|
{% for addr in aruba__ntp_servers %}
|
||||||
|
ntp server {{ addr | ipaddr }} iburst
|
||||||
|
{% endfor %}
|
||||||
|
{% if aruba__timezone == "Europe/Paris" %}
|
||||||
|
time daylight-time-rule western-europe
|
||||||
|
time timezone 60
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for addr in aruba__dns_servers[:2] %}
|
||||||
|
ip dns server-address priority {{ loop.index }} {{ addr | ipaddr }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for domain in aruba__dns_domain_names[:5] %}
|
||||||
|
ip dns domain-name {{ domain | enquote }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
activate provision disable
|
||||||
|
activate software-update disable
|
||||||
|
|
||||||
|
{% if False %}
|
||||||
|
snmpv3 enable
|
||||||
|
snmpv3 only
|
||||||
|
snmpv3 user "re2o"
|
||||||
|
snmpv3 group ManagerPriv user "re2o" sec-model ver3
|
||||||
|
snmp-server community "public" Operator
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
no cdp run
|
||||||
|
lldp run
|
||||||
|
|
||||||
|
{%
|
||||||
|
set lldp_disabled =
|
||||||
|
aruba__interfaces.keys()
|
||||||
|
| difference(aruba__interfaces
|
||||||
|
| dict2items
|
||||||
|
| selectattr("value.lldp", "defined")
|
||||||
|
| selectattr("value.lldp", "==", True)
|
||||||
|
| map(attribute="key"))
|
||||||
|
| list
|
||||||
|
%}
|
||||||
|
{% if lldp_disabled %}
|
||||||
|
lldp admin-status {{ lldp_disabled | aruba_ints }} disable
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
password manager sha1 {{ aruba__manager_password | hash("sha1") }}
|
||||||
|
{% if aruba__operator_password is defined %}
|
||||||
|
password operator sha1 {{ aruba__operator_password | hash("sha1") }}
|
||||||
|
{% endif %}
|
||||||
|
#}
|
||||||
|
|
||||||
|
{% if aruba__ssh_enabled %}
|
||||||
|
ip ssh
|
||||||
|
{# ip ssh cipher aes256–ctr #}
|
||||||
|
{# ip ssh kex ecdh-sha2-nistp521 #}
|
||||||
|
{# ip ssh mac hmac-sha2-256 #}
|
||||||
|
ip ssh filetransfer
|
||||||
|
{% else %}
|
||||||
|
no ip ssh
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
no telnet-server
|
||||||
|
no tftp
|
||||||
|
|
||||||
|
{% if aruba__rest_enabled %}
|
||||||
|
{# FIXME: ssl #}
|
||||||
|
web-management plaintext
|
||||||
|
rest-interface
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{%
|
||||||
|
set loop_protect =
|
||||||
|
aruba__interfaces
|
||||||
|
| dict2items
|
||||||
|
| selectattr("value.loop_protect", "defined")
|
||||||
|
| selectattr("value.loop_protect")
|
||||||
|
| map(attribute="key")
|
||||||
|
| list
|
||||||
|
%}
|
||||||
|
{% if loop_protect %}
|
||||||
|
loop-protect disable-timer {{ aruba__loop_protect_disable_timer | int }}
|
||||||
|
loop-protect transmit-interval {{ aruba__loop_protect_tx_interval | int }}
|
||||||
|
loop-protect {{ loop_protect | aruba_ints }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if aruba__default_gateways | ipv4 %}
|
||||||
|
ip default-gateway {{ aruba__default_gateways | ipv4 | first }}
|
||||||
|
{% endif %}
|
||||||
|
{% if aruba__default_gateways | ipv6 %}
|
||||||
|
{# ipv6 default-gateway {{ aruba__default_gateways | ipv6 | first }} #}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for id, vlan in aruba__vlans.items() %}
|
||||||
|
vlan {{ id | int }}
|
||||||
|
{% if vlan.name is defined %}
|
||||||
|
name {{ vlan.name | truncate(32) | enquote }}
|
||||||
|
{% endif %}
|
||||||
|
{%
|
||||||
|
set untagged =
|
||||||
|
aruba__interfaces
|
||||||
|
| dict2items
|
||||||
|
| selectattr("value.untagged", "defined")
|
||||||
|
| selectattr("value.untagged", "==", id)
|
||||||
|
| map(attribute="key")
|
||||||
|
| list
|
||||||
|
%}
|
||||||
|
{% if untagged %}
|
||||||
|
untagged {{ untagged | aruba_ints }}
|
||||||
|
{% endif %}
|
||||||
|
{%
|
||||||
|
set tagged =
|
||||||
|
aruba__interfaces
|
||||||
|
| dict2items
|
||||||
|
| selectattr("value.tagged", "defined")
|
||||||
|
| selectattr("value.tagged", "contains", id)
|
||||||
|
| map(attribute="key")
|
||||||
|
| list
|
||||||
|
%}
|
||||||
|
{% if tagged %}
|
||||||
|
tagged {{ tagged | aruba_ints }}
|
||||||
|
{% endif %}
|
||||||
|
{% if vlan.addresses | default([]) %}
|
||||||
|
{% for addr in vlan.addresses | ipv4 %}
|
||||||
|
ip address {{ addr | ipaddr("host") }}
|
||||||
|
{% endfor %}
|
||||||
|
{% for addr in vlan.addresses | ipv6 %}
|
||||||
|
ipv6 address {{ addr | ipaddr("host") }}
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
no ip address
|
||||||
|
{% endif %}
|
||||||
|
exit
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for id, iface in aruba__interfaces.items() %}
|
||||||
|
interface {{ id | int }}
|
||||||
|
{% if iface.name is defined %}
|
||||||
|
name {{ iface.name | truncate(32) | enquote }}
|
||||||
|
{% endif %}
|
||||||
|
{% if iface.enabled | default(True) %}
|
||||||
|
enable
|
||||||
|
{% else %}
|
||||||
|
no enable
|
||||||
|
{% endif %}
|
||||||
|
{# TODO: split and check speed/duplex #}
|
||||||
|
{% if iface.speed_duplex is defined %}
|
||||||
|
speed-duplex {{ iface.speed_duplex }}
|
||||||
|
{% endif %}
|
||||||
|
no flow-control
|
||||||
|
exit
|
||||||
|
|
||||||
|
{% endfor %}
|
Loading…
Reference in a new issue