Remove `test/legacy/` directory. (#67786)

* Remove `test/legacy/` directory.

* Remove references to `test/legacy/` directory.

* Update the remaining valid legacy reference.

* Remove outdated legacy references.
pull/67763/head
Matt Clay 4 years ago committed by GitHub
parent a6f24f8aa9
commit b68e55da26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4097,8 +4097,6 @@ files:
test/integration/targets/zabbix_: $team_zabbix
test/integration/targets/ucs_: *ucs
test/integration/targets/vultr: *vultr
test/legacy/:
notified: mattclay
test/lib/:
notified: mattclay
test/lib/ansible_test/_internal/cloud/acme.py: *crypto

@ -68,8 +68,6 @@ The ``ssh_pub_key`` parameter contains your ssh public key as a string. Here is
.. code-block:: yaml
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway_ssh_playbook.yml
- name: Test SSH key lifecycle on a Scaleway account
hosts: localhost
gather_facts: no
@ -120,8 +118,6 @@ Take a look at this short playbook to see a working example using ``scaleway_com
.. code-block:: yaml
# SCW_TOKEN='XXX' ansible-playbook ./test/legacy/scaleway_compute.yml
- name: Test compute instance lifecycle on a Scaleway account
hosts: localhost
gather_facts: no
@ -253,7 +249,7 @@ Scaleway S3 object storage
`Object Storage <https://www.scaleway.com/object-storage>`_ allows you to store any kind of objects (documents, images, videos, etc.).
As the Scaleway API is S3 compatible, Ansible supports it natively through the modules: :ref:`s3_bucket_module`, :ref:`aws_s3_module`.
You can find many examples in ``./test/legacy/roles/scaleway_s3``
You can find many examples in the `scaleway_s3 integration tests <https://github.com/ansible/ansible-legacy-tests/tree/devel/test/legacy/roles/scaleway_s3>`_.
.. code-block:: yaml+jinja

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' SCW_ORG='YYY' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_compute
- include_tasks: state.yml
- include_tasks: ip.yml
- include_tasks: security_group.yml

@ -1,6 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_image_info
- name: Get image informations and register it in a variable
scaleway_image_info:
region: par1

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' SCW_ORG='YYY' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_ip
- name: Create IP (Check)
check_mode: yes
scaleway_ip:

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_ip_info
- name: Get ip informations and register it in a variable
scaleway_ip_info:
region: par1

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' SCW_ORG='YYY' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_lb
- name: Create a load-balancer (Check)
check_mode: yes
scaleway_lb:

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_security_group_info
- name: Get security group informations and register it in a variable
scaleway_security_group_info:
region: par1

@ -1,6 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_security_group_rule
- name: Create a scaleway security_group
scaleway_security_group:
state: present

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_server_info
- name: Get server informations and register it in a variable
scaleway_server_info:
region: par1

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_snapshot_info
- name: Get snapshot informations and register it in a variable
scaleway_snapshot_info:
region: par1

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_ssh
- scaleway_sshkey:
ssh_pub_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf29yyommeGyKSIgSmX0ISVXP+3x6RUY4JDGLoAMFh2efkfDaRVdsvkvnFuUywgP2RewrjTyLE8w0NpCBHVS5Fm1BAn3yvxOUtTMxTbsQcw6HQ8swJ02+1tewJYjHPwc4GrBqiDo3Nmlq354Us0zBOJg/bBzuEnVD5eJ3GO3gKaCSUYTVrYwO0U4eJE0D9OJeUP9J48kl4ULbCub976+mTHdBvlzRw0Tzfl2kxgdDwlks0l2NefY/uiTdz2oMt092bAY3wZHxjto/DXoChxvaf5s2k8Zb+J7CjimUYnzPlH+zA9F6ROjP5AUu6ZWPd0jOIBl1nDWWb2j/qfNLYM43l sieben@sieben-macbook.local"
state: present

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_user_data
- name: Create a server
scaleway_compute:
name: foobar

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' SCW_ORG='YYY' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_volume
- name: Make sure volume is not there before tests
scaleway_volume:
name: ansible-test-volume

@ -1,5 +1,3 @@
# SCW_API_KEY='XXX' ansible-playbook ./test/legacy/scaleway.yml --tags test_scaleway_volume_info
- name: Get volume informations and register it in a variable
scaleway_volume_info:
region: par1

@ -1,147 +0,0 @@
# This Makefile is for legacy integration tests.
# Most new tests should be implemented using ansible-test.
# Existing tests are slowly being migrated to ansible-test.
# See: https://docs.ansible.com/ansible/devel/dev_guide/testing_integration.html
TEST_DIR ?= ~/ansible_testing
INVENTORY ?= inventory
VARS_FILE ?= integration_config.yml
# Create a semi-random string for use when testing cloud-based resources
ifndef CLOUD_RESOURCE_PREFIX
CLOUD_RESOURCE_PREFIX := $(shell python -c "import string,random; print('ansible-testing-' + ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(8)));")
endif
CREDENTIALS_FILE ?= credentials.yml
# If credentials.yml exists, use it
ifneq ("$(wildcard $(CREDENTIALS_FILE))","")
CREDENTIALS_ARG = -e @$(CREDENTIALS_FILE)
else
CREDENTIALS_ARG =
endif
# http://unix.stackexchange.com/questions/30091/fix-or-alternative-for-mktemp-in-os-x
MYTMPDIR = $(shell mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')
VAULT_PASSWORD_FILE = vault-password
CONSUL_RUNNING := $(shell python consul_running.py)
EUID := $(shell id -u -r)
UNAME := $(shell uname | tr '[:upper:]' '[:lower:]')
setup:
rm -rf $(TEST_DIR)
mkdir -p $(TEST_DIR)
cloud: amazon rackspace azure
cloud_cleanup: amazon_cleanup rackspace_cleanup
amazon_cleanup:
python cleanup_ec2.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
azure_cleanup:
python cleanup_azure.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
digital_ocean: $(CREDENTIALS_FILE)
ansible-playbook digital_ocean.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -v $(TEST_FLAGS) ; \
RC=$$? ; \
exit $$RC;
gce_setup:
python setup_gce.py "$(CLOUD_RESOURCE_PREFIX)"
gce_cleanup:
python cleanup_gce.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
rackspace_cleanup:
python cleanup_rax.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
$(CREDENTIALS_FILE):
@echo "No credentials file found. A file named '$(CREDENTIALS_FILE)' is needed to provide credentials needed to run cloud tests. See sample 'credentials.template' file."
@exit 1
amazon: $(CREDENTIALS_FILE)
ANSIBLE_HOST_KEY_CHECKING=False ANSIBLE_PIPELINING=no BOTO_CONFIG=/dev/null ansible-playbook amazon.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make amazon_cleanup ; \
exit $$RC;
azure: $(CREDENTIALS_FILE)
ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook azure.yml -i $(INVENTORY) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make azure_cleanup ; \
exit $$RC;
gce: $(CREDENTIALS_FILE)
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make gce_setup ; \
ansible-playbook gce.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make gce_cleanup ; \
exit $$RC;
rackspace: $(CREDENTIALS_FILE)
ansible-playbook rackspace.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make rackspace_cleanup ; \
exit $$RC;
exoscale:
ansible-playbook exoscale.yml -i $(INVENTORY) -e @$(VARS_FILE) -v $(TEST_FLAGS) ; \
RC=$$? ; \
exit $$RC;
jenkins:
ansible-playbook jenkins.yml -i $(INVENTORY) -e @$(VARS_FILE) -v $(TEST_FLAGS) ; \
RC=$$? ; \
exit $$RC;
cloudflare: $(CREDENTIALS_FILE)
ansible-playbook cloudflare.yml -i $(INVENTORY) -e @$(VARS_FILE) -e @$(CREDENTIALS_FILE) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
exit $$RC;
cloudscale:
ansible-playbook cloudscale.yml -i $(INVENTORY) -e @$(VARS_FILE) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
exit $$RC;
$(CONSUL_RUNNING):
consul:
ifeq ($(CONSUL_RUNNING), True)
ansible-playbook -i $(INVENTORY) consul.yml ; \
ansible-playbook -i ../../contrib/inventory/consul_io.py consul_inventory.yml
else
@echo "Consul agent is not running locally. To run a cluster locally see http://github.com/sgargan/consul-vagrant"
endif
test_galaxy: test_galaxy_spec test_galaxy_yaml test_galaxy_git
test_galaxy_spec: setup
mytmpdir=$(MYTMPDIR) ; \
ansible-galaxy install -r galaxy_rolesfile -p $$mytmpdir/roles -vvvv ; \
cp galaxy_playbook.yml $$mytmpdir ; \
ansible-playbook -i $(INVENTORY) $$mytmpdir/galaxy_playbook.yml -e @$(VARS_FILE) -v $(TEST_FLAGS) ; \
RC=$$? ; \
rm -rf $$mytmpdir ; \
exit $$RC
test_galaxy_yaml: setup
mytmpdir=$(MYTMPDIR) ; \
ansible-galaxy install -r galaxy_roles.yml -p $$mytmpdir/roles -vvvv; \
cp galaxy_playbook.yml $$mytmpdir ; \
ansible-playbook -i $(INVENTORY) $$mytmpdir/galaxy_playbook.yml -e @$(VARS_FILE) -v $(TEST_FLAGS) ; \
RC=$$? ; \
rm -rf $$mytmpdir ; \
exit $$RC
test_galaxy_git: setup
mytmpdir=$(MYTMPDIR) ; \
ansible-galaxy install git+https://bitbucket.org/willthames/git-ansible-galaxy,v1.6 -p $$mytmpdir/roles -vvvv; \
cp galaxy_playbook_git.yml $$mytmpdir ; \
ansible-playbook -i $(INVENTORY) $$mytmpdir/galaxy_playbook_git.yml -v $(TEST_FLAGS) ; \
RC=$$? ; \
rm -rf $$mytmpdir ; \
exit $$RC

@ -1,24 +0,0 @@
---
- name: Services/Subsystems tests for AIX
hosts: localhost
connection: local
tasks:
- name: spooler shutdown
service:
name: spooler
state: started
- name: stopping sendmail
service:
name: sendmail
state: stopped
- name: starting sendmail
service:
name: sendmail
state: started
- name: starting an inexistent subsystem and group subsystem
service:
name: fakeservice
state: stopped

@ -1,35 +0,0 @@
- hosts: amazon
gather_facts: true
roles:
- { role: test_ec2_key, tags: test_ec2_key }
- { role: test_ec2_group, tags: test_ec2_group }
#- { role: test_ec2_vpc, tags: test_ec2_vpc }
#- { role: test_ec2_vol, tags: test_ec2_vol }
#- { role: test_ec2_tag, tags: test_ec2_tag }
#- { role: test_ec2_facts, tags: test_ec2_facts }
- { role: test_ec2_elb_lb, tags: test_ec2_elb_lb }
- { role: test_ec2_eip, tags: test_ec2_eip }
#- { role: test_ec2_ami, tags: test_ec2_ami }
#- { role: test_ec2, tags: test_ec2 }
- { role: test_ec2_asg, tags: test_ec2_asg }
- { role: test_ec2_vpc_nat_gateway, tags: test_ec2_vpc_nat_gateway }
- { role: test_ecs_ecr, tags: test_ecs_ecr }
# complex test for ec2_elb, split up over multiple plays
# since there is a setup component as well as the test which
# runs on a different set of hosts (ec2 instances)
- hosts: amazon
roles:
- { role: ec2_provision_instances, tags: test_ec2_elb, count: 5 }
- hosts: ec2
gather_facts: no
remote_user: ec2-user
become: true
roles:
- { role: ec2_elb_instance_setup, tags: test_ec2_elb }
- hosts: amazon
roles:
- { role: test_ec2_elb, tags: test_ec2_elb }

@ -1,7 +0,0 @@
- hosts: localhost
connection: local
gather_facts: no
tags:
- test_azure
roles:
- { role: test_azure }

@ -1,207 +0,0 @@
'''
Find and delete AWS resources matching the provided --match string. Unless
--yes|-y is provided, the prompt for confirmation prior to deleting resources.
Please use caution, you can easily delete you're *ENTIRE* EC2 infrastructure.
'''
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import boto
import boto.ec2.elb
import optparse
import os
import os.path
import re
import sys
import time
import yaml
from ansible.module_utils.six.moves import input
def delete_aws_resources(get_func, attr, opts):
for item in get_func():
val = getattr(item, attr)
if re.search(opts.match_re, val):
prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
def delete_autoscaling_group(get_func, attr, opts):
assumeyes = opts.assumeyes
group_name = None
for item in get_func():
group_name = getattr(item, attr)
if re.search(opts.match_re, group_name):
if not opts.assumeyes:
assumeyes = input("Delete matching %s? [y/n]: " % (item).lower()) == 'y'
break
if assumeyes and group_name:
groups = asg.get_all_groups(names=[group_name])
if groups:
group = groups[0]
group.max_size = 0
group.min_size = 0
group.desired_capacity = 0
group.update()
instances = True
while instances:
tmp_groups = asg.get_all_groups(names=[group_name])
if tmp_groups:
tmp_group = tmp_groups[0]
if not tmp_group.instances:
instances = False
time.sleep(10)
group.delete()
while len(asg.get_all_groups(names=[group_name])):
time.sleep(5)
print("Terminated ASG: %s" % group_name)
def delete_aws_eips(get_func, attr, opts):
# the file might not be there if the integration test wasn't run
try:
with open(opts.eip_log, 'r') as f:
eip_log = f.read().splitlines()
except IOError:
print('%s not found.' % opts.eip_log)
return
for item in get_func():
val = getattr(item, attr)
if val in eip_log:
prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
def delete_aws_instances(reservation, opts):
for list in reservation:
for item in list.instances:
prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
def prompt_and_delete(item, prompt, assumeyes):
if not assumeyes:
assumeyes = input(prompt).lower() == 'y'
assert hasattr(item, 'delete') or hasattr(item, 'terminate'), "Class <%s> has no delete or terminate attribute" % item.__class__
if assumeyes:
if hasattr(item, 'delete'):
item.delete()
print("Deleted %s" % item)
if hasattr(item, 'terminate'):
item.terminate()
print("Terminated %s" % item)
def parse_args():
# Load details from credentials.yml
default_aws_access_key = os.environ.get('AWS_ACCESS_KEY', None)
default_aws_secret_key = os.environ.get('AWS_SECRET_KEY', None)
if os.path.isfile('credentials.yml'):
credentials = yaml.load(open('credentials.yml', 'r'))
if default_aws_access_key is None:
default_aws_access_key = credentials['ec2_access_key']
if default_aws_secret_key is None:
default_aws_secret_key = credentials['ec2_secret_key']
parser = optparse.OptionParser(
usage="%s [options]" % (sys.argv[0], ),
description=__doc__
)
parser.add_option(
"--access",
action="store", dest="ec2_access_key",
default=default_aws_access_key,
help="Amazon ec2 access id. Can use EC2_ACCESS_KEY environment variable, or a values from credentials.yml."
)
parser.add_option(
"--secret",
action="store", dest="ec2_secret_key",
default=default_aws_secret_key,
help="Amazon ec2 secret key. Can use EC2_SECRET_KEY environment variable, or a values from credentials.yml."
)
parser.add_option(
"--eip-log",
action="store", dest="eip_log",
default=None,
help="Path to log of EIPs created during test."
)
parser.add_option(
"--integration-config",
action="store", dest="int_config",
default="integration_config.yml",
help="path to integration config"
)
parser.add_option(
"--credentials", "-c",
action="store", dest="credential_file",
default="credentials.yml",
help="YAML file to read cloud credentials (default: %default)"
)
parser.add_option(
"--yes", "-y",
action="store_true", dest="assumeyes",
default=False,
help="Don't prompt for confirmation"
)
parser.add_option(
"--match",
action="store", dest="match_re",
default="^ansible-testing-",
help="Regular expression used to find AWS resources (default: %default)"
)
(opts, args) = parser.parse_args()
for required in ['ec2_access_key', 'ec2_secret_key']:
if getattr(opts, required) is None:
parser.error("Missing required parameter: --%s" % required)
return (opts, args)
if __name__ == '__main__':
(opts, args) = parse_args()
int_config = yaml.load(open(opts.int_config).read())
if not opts.eip_log:
output_dir = os.path.expanduser(int_config["output_dir"])
opts.eip_log = output_dir + '/' + opts.match_re.replace('^', '') + '-eip_integration_tests.log'
# Connect to AWS
aws = boto.connect_ec2(aws_access_key_id=opts.ec2_access_key,
aws_secret_access_key=opts.ec2_secret_key)
elb = boto.connect_elb(aws_access_key_id=opts.ec2_access_key,
aws_secret_access_key=opts.ec2_secret_key)
asg = boto.connect_autoscale(aws_access_key_id=opts.ec2_access_key,
aws_secret_access_key=opts.ec2_secret_key)
try:
# Delete matching keys
delete_aws_resources(aws.get_all_key_pairs, 'name', opts)
# Delete matching security groups
delete_aws_resources(aws.get_all_security_groups, 'name', opts)
# Delete matching ASGs
delete_autoscaling_group(asg.get_all_groups, 'name', opts)
# Delete matching launch configs
delete_aws_resources(asg.get_all_launch_configurations, 'name', opts)
# Delete ELBs
delete_aws_resources(elb.get_all_load_balancers, 'name', opts)
# Delete recorded EIPs
delete_aws_eips(aws.get_all_addresses, 'public_ip', opts)
# Delete temporary instances
filters = {"tag:Name": opts.match_re.replace('^', ''), "instance-state-name": ['running', 'pending', 'stopped']}
delete_aws_instances(aws.get_all_instances(filters=filters), opts)
except KeyboardInterrupt as e:
print("\nExiting on user command.")

@ -1,93 +0,0 @@
'''
Find and delete GCE resources matching the provided --match string. Unless
--yes|-y is provided, the prompt for confirmation prior to deleting resources.
Please use caution, you can easily delete your *ENTIRE* GCE infrastructure.
'''
import optparse
import os
import re
import sys
import yaml
try:
from libcloud.common.google import (
GoogleBaseError,
QuotaExceededError,
ResourceExistsError,
ResourceInUseError,
ResourceNotFoundError,
)
from libcloud.compute.providers import get_driver
from libcloud.compute.types import Provider
_ = Provider.GCE
except ImportError:
print("failed=True msg='libcloud with GCE support (0.13.3+) required for this module'")
sys.exit(1)
import gce_credentials
from ansible.module_utils.six.moves import input
def delete_gce_resources(get_func, attr, opts):
for item in get_func():
val = getattr(item, attr)
if re.search(opts.match_re, val, re.IGNORECASE):
prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
def prompt_and_delete(item, prompt, assumeyes):
if not assumeyes:
assumeyes = input(prompt).lower() == 'y'
assert hasattr(item, 'destroy'), "Class <%s> has no delete attribute" % item.__class__
if assumeyes:
item.destroy()
print("Deleted %s" % item)
def parse_args():
parser = optparse.OptionParser(
usage="%s [options]" % sys.argv[0],
description=__doc__
)
gce_credentials.add_credentials_options(parser)
parser.add_option(
"--yes", "-y",
action="store_true", dest="assumeyes",
default=False,
help="Don't prompt for confirmation"
)
parser.add_option(
"--match",
action="store", dest="match_re",
default="^ansible-testing-",
help="Regular expression used to find GCE resources (default: %default)"
)
(opts, args) = parser.parse_args()
gce_credentials.check_required(opts, parser)
return (opts, args)
if __name__ == '__main__':
(opts, args) = parse_args()
# Connect to GCE
gce = gce_credentials.get_gce_driver(opts)
try:
# Delete matching instances
delete_gce_resources(gce.list_nodes, 'name', opts)
# Delete matching snapshots
def get_snapshots():
for volume in gce.list_volumes():
for snapshot in gce.list_volume_snapshots(volume):
yield snapshot
delete_gce_resources(get_snapshots, 'name', opts)
# Delete matching disks
delete_gce_resources(gce.list_volumes, 'name', opts)
except KeyboardInterrupt as e:
print("\nExiting on user command.")

@ -1,182 +0,0 @@
#!/usr/bin/env python
import os
import re
import yaml
import argparse
try:
import pyrax
HAS_PYRAX = True
except ImportError:
HAS_PYRAX = False
from ansible.module_utils.six.moves import input
def rax_list_iterator(svc, *args, **kwargs):
method = kwargs.pop('method', 'list')
items = getattr(svc, method)(*args, **kwargs)
while items:
retrieved = getattr(svc, method)(*args, marker=items[-1].id, **kwargs)
if items and retrieved and items[-1].id == retrieved[0].id:
del items[-1]
items.extend(retrieved)
if len(retrieved) < 2:
break
return items
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('-y', '--yes', action='store_true', dest='assumeyes',
default=False, help="Don't prompt for confirmation")
parser.add_argument('--match', dest='match_re',
default='^ansible-testing',
help='Regular expression used to find resources '
'(default: %(default)s)')
return parser.parse_args()
def authenticate():
try:
with open(os.path.realpath('./credentials.yml')) as f:
credentials = yaml.load(f)
except Exception as e:
raise SystemExit(e)
try:
pyrax.set_credentials(credentials.get('rackspace_username'),
credentials.get('rackspace_api_key'))
except Exception as e:
raise SystemExit(e)
def prompt_and_delete(item, prompt, assumeyes):
if not assumeyes:
assumeyes = input(prompt).lower() == 'y'
assert hasattr(item, 'delete') or hasattr(item, 'terminate'), \
"Class <%s> has no delete or terminate attribute" % item.__class__
if assumeyes:
if hasattr(item, 'delete'):
item.delete()
print("Deleted %s" % item)
if hasattr(item, 'terminate'):
item.terminate()
print("Terminated %s" % item)
def delete_rax(args):
"""Function for deleting CloudServers"""
print("--- Cleaning CloudServers matching '%s'" % args.match_re)
search_opts = dict(name='^%s' % args.match_re)
for region in pyrax.identity.services.compute.regions:
cs = pyrax.connect_to_cloudservers(region=region)
servers = rax_list_iterator(cs.servers, search_opts=search_opts)
for server in servers:
prompt_and_delete(server,
'Delete matching %s? [y/n]: ' % server,
args.assumeyes)
def delete_rax_clb(args):
"""Function for deleting Cloud Load Balancers"""
print("--- Cleaning Cloud Load Balancers matching '%s'" % args.match_re)
for region in pyrax.identity.services.load_balancer.regions:
clb = pyrax.connect_to_cloud_loadbalancers(region=region)
for lb in rax_list_iterator(clb):
if re.search(args.match_re, lb.name):
prompt_and_delete(lb,
'Delete matching %s? [y/n]: ' % lb,
args.assumeyes)
def delete_rax_keypair(args):
"""Function for deleting Rackspace Key pairs"""
print("--- Cleaning Key Pairs matching '%s'" % args.match_re)
for region in pyrax.identity.services.compute.regions:
cs = pyrax.connect_to_cloudservers(region=region)
for keypair in cs.keypairs.list():
if re.search(args.match_re, keypair.name):
prompt_and_delete(keypair,
'Delete matching %s? [y/n]: ' % keypair,
args.assumeyes)
def delete_rax_network(args):
"""Function for deleting Cloud Networks"""
print("--- Cleaning Cloud Networks matching '%s'" % args.match_re)
for region in pyrax.identity.services.network.regions:
cnw = pyrax.connect_to_cloud_networks(region=region)
for network in cnw.list():
if re.search(args.match_re, network.name):
prompt_and_delete(network,
'Delete matching %s? [y/n]: ' % network,
args.assumeyes)
def delete_rax_cbs(args):
"""Function for deleting Cloud Networks"""
print("--- Cleaning Cloud Block Storage matching '%s'" % args.match_re)
for region in pyrax.identity.services.network.regions:
cbs = pyrax.connect_to_cloud_blockstorage(region=region)
for volume in cbs.list():
if re.search(args.match_re, volume.name):
prompt_and_delete(volume,
'Delete matching %s? [y/n]: ' % volume,
args.assumeyes)
def delete_rax_cdb(args):
"""Function for deleting Cloud Databases"""
print("--- Cleaning Cloud Databases matching '%s'" % args.match_re)
for region in pyrax.identity.services.database.regions:
cdb = pyrax.connect_to_cloud_databases(region=region)
for db in rax_list_iterator(cdb):
if re.search(args.match_re, db.name):
prompt_and_delete(db,
'Delete matching %s? [y/n]: ' % db,
args.assumeyes)
def _force_delete_rax_scaling_group(manager):
def wrapped(uri):
manager.api.method_delete('%s?force=true' % uri)
return wrapped
def delete_rax_scaling_group(args):
"""Function for deleting Autoscale Groups"""
print("--- Cleaning Autoscale Groups matching '%s'" % args.match_re)
for region in pyrax.identity.services.autoscale.regions:
asg = pyrax.connect_to_autoscale(region=region)
for group in rax_list_iterator(asg):
if re.search(args.match_re, group.name):
group.manager._delete = \
_force_delete_rax_scaling_group(group.manager)
prompt_and_delete(group,
'Delete matching %s? [y/n]: ' % group,
args.assumeyes)
def main():
if not HAS_PYRAX:
raise SystemExit('The pyrax python module is required for this script')
args = parse_args()
authenticate()
funcs = [f for n, f in globals().items() if n.startswith('delete_rax')]
for func in sorted(funcs, key=lambda f: f.__name__):
try:
func(args)
except Exception as e:
print("---- %s failed (%s)" % (func.__name__, e.message))
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\nExiting...')

@ -1,8 +0,0 @@
---
- hosts: localhost
connection: local
gather_facts: no
tags:
- cloudflare
roles:
- { role: test_cloudflare_dns, tags: test_cloudflare_dns }

@ -1,24 +0,0 @@
- hosts: cnos
gather_facts: no
connection: local
vars:
limit_to: "*"
debug: false
roles:
- { role: cnos_facts, when: "limit_to in ['*', 'cnos_facts']" }
- { role: cnos_vlan, when: "limit_to in ['*', 'cnos_vlan']" }
- { role: cnos_ethernet, when: "limit_to in ['*', 'cnos_ethernet']" }
- { role: cnos_image, when: "limit_to in ['*', 'cnos_image']" }
- { role: cnos_portchannel, when: "limit_to in ['*', 'cnos_portchannel']" }
- { role: cnos_rollback, when: "limit_to in ['*', 'cnos_rollback']" }
- { role: cnos_save, when: "limit_to in ['*', 'cnos_save']" }
- { role: cnos_template, when: "limit_to in ['*', 'cnos_template']" }
- { role: cnos_conditional_template, when: "limit_to in ['*', 'cnos_conditional_template']" }
- { role: cnos_conditional_command, when: "limit_to in ['*', 'cnos_conditional_command']" }
- { role: cnos_vlag, when: "limit_to in ['*', 'cnos_vlag']" }
- { role: cnos_command, when: "limit_to in ['*', 'cnos_command']" }
- { role: cnos_bgp, when: "limit_to in ['*', 'cnos_bgp']" }
- { role: cnos_backup, when: "limit_to in ['*', 'cnos_backup']" }
- { role: cnos_showrun, when: "limit_to in ['*', 'cnos_showrun']" }

@ -1,5 +0,0 @@
- hosts: buildah-container
connection: buildah
gather_facts: no
roles:
- { role: connection_buildah }

@ -1,78 +0,0 @@
- hosts: localhost
connection: local
gather_facts: false
vars:
# these are the defaults from the consul-vagrant cluster setup
- mgmt_token: '4791402A-D875-4C18-8316-E652DBA53B18'
- acl_host: '11.0.0.2'
- metadata_json: '{"clearance": "top_secret"}'
pre_tasks:
# this works except for the KV_lookusp
- name: check that the consul agent is running locally
local_action: wait_for port=8500 timeout=5
ignore_errors: true
register: consul_running
roles:
- {role: test_consul_service,
when: not consul_running.failed is defined}
- {role: test_consul_kv,
when: not consul_running.failed is defined}
- {role: test_consul_acl,
when: not consul_running.failed is defined}
- {role: test_consul_session,
when: not consul_running.failed is defined}
tasks:
- name: setup services with passing check for consul inventory test
consul:
service_name: nginx
service_port: 80
script: "sh -c true"
interval: 5
token: '4791402A-D875-4C18-8316-E652DBA53B18'
tags:
- dev
- master
- name: setup failing service for inventory test
consul:
service_name: nginx
service_port: 443
script: "sh -c false"
interval: 5
tags:
- qa
- slave
- name: setup ssh service for inventory test
consul:
service_name: ssh
service_port: 2222
script: "sh -c true"
interval: 5
token: '4791402A-D875-4C18-8316-E652DBA53B18'
- name: update the Anonymous token to allow anon access to kv store
consul_acl:
mgmt_token: '{{mgmt_token}}'
host: '{{acl_host}}'
token: 'anonymous'
rules:
- key: ''
policy: write
- name: add metadata for the node through kv_store
consul_kv: "key=ansible/metadata/dc1/consul-1 value='{{metadata_json}}'"
- name: add metadata for the node through kv_store
consul_kv: key=ansible/groups/dc1/consul-1 value='a_group, another_group'
- name: warn that tests are ignored if consul agent is not running
debug: msg="A consul agent needs to be running inorder to run the tests. To setup a vagrant cluster for use in testing see http://github.com/sgargan/consul-vagrant"
when: consul_running.failed is defined

@ -1,19 +0,0 @@
- hosts: all;!localhost
gather_facts: false
pre_tasks:
- name: check that the consul agent is running locally
local_action: wait_for port=8500 timeout=5
ignore_errors: true
register: consul_running
roles:
- {role: test_consul_inventory,
when: not consul_running.failed is defined}
tasks:
- name: warn that tests are ignored if consul agent is not running
debug: msg="A consul agent needs to be running inorder to run the tests. To setup a vagrant cluster for use in testing see http://github.com/sgargan/consul-vagrant"
when: consul_running.failed is defined

@ -1,11 +0,0 @@
''' Checks that the consul agent is running locally. '''
if __name__ == '__main__':
try:
import consul
consul = consul.Consul(host='0.0.0.0', port=8500)
consul.catalog.nodes()
print("True")
except Exception:
pass

@ -1,26 +0,0 @@
---
# Rackspace Credentials
rackspace_username:
rackspace_api_key:
rackspace_region:
# AWS Credentials
ec2_access_key:
ec2_secret_key:
security_token:
# GCE Credentials
gce_service_account_email:
gce_pem_file:
gce_project_id:
# Azure Credentials
azure_subscription_id: "{{ lookup('env', 'AZURE_SUBSCRIPTION_ID') }}"
azure_cert_path: "{{ lookup('env', 'AZURE_CERT_PATH') }}"
# Cloudflare Credentials
cloudflare_api_token:
cloudflare_email:
cloudflare_zone:
digitalocean_oauth_token: "{{ lookup('env', 'DO_API_TOKEN') }}"

@ -1,9 +0,0 @@
- hosts: localhost
connection: local
gather_facts: no
tags:
- test_digital_ocean
vars:
dummy_ssh_pub_key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCzTSH4WVqnK2kUgtbs2VryNUXBaox7SoXPmV4yMP4INPAndrtPTS3BRzBPrJwQSwjsT7y3kBLNIHGppxLFMoQTEL03WlMDfM1TthMT7Y5B65wOUMxdwbSn9zlblAqbbRg7XU/UgNZb+B2kBPepPRJlh1ap4CPTNrbzdKlmwqS4X3+hX/WM3Gt3S09eNxUKDBK18Fbf/yKvhXP4bGtD0cxYNKL4qoGjEZTkjiYQyC4TvfuZaUtOFpiMLPAt0V7ao2S2bKr8hAgxl9MtrJpa2q1FueAjljMSBWUhOjFgmO0SpWDcBu157vMtscmtUC2cMpQwAY2HQyMJAYs0HOa59dpUKtxBR3LwjXyZvL+RbjEbzZjp4JQSer/bB/jekrxHAIABCwdFmx6qBGNVqDdfT7o+OcEJaAvk4gKEFI24OU8k6WF4ss97VfxlvIT6Bq2p04oUsxN0qh9aSjRVfqJmhkSocf+1iGWGfa4DMFpeQAXCzUkhJS5ecYXSDmyMHGtl7OfhLnncUDHVRjhsmrCFb5kkHHVfNd601ixixydInlssUhQRRzhnJ+ciTh/x7ARDfwMendHTTHCj5sO1IvnOJdCcX4FTMKp1GLo6eaK738o9w4rWL0bs3kWJfxWg91QegwZW0r8xSJBtga7HyQafxivhwEN8knN8HuD47iBuAL+VTw==
roles:
- { role: test_digital_ocean, tags: test_digital_ocean }

@ -1,5 +0,0 @@
---
- hosts: localhost
gather_facts: no
roles:
- { role: test_exoscale_dns, tags: test_exoscale_dns }

@ -1,7 +0,0 @@
- hosts: localhost
connection: local
roles:
- "git-ansible-galaxy"
- "http-role"
- "hg-ansible-galaxy"

@ -1,5 +0,0 @@
- hosts: localhost
connection: local
roles:
- "git-ansible-galaxy"

@ -1,16 +0,0 @@
# change these to some ansible owned test roles
- src: briancoca.oracle_java7
name: oracle_java7
- src: git+http://bitbucket.org/willthames/git-ansible-galaxy
version: pr-10620
- src: http://bitbucket.org/willthames/hg-ansible-galaxy
scm: hg
- src: https://bitbucket.org/willthames/http-ansible-galaxy/get/master.tar.gz
name: http-role
- src: git@github.com:geerlingguy/ansible-role-php.git
scm: git
name: php

@ -1,8 +0,0 @@
# deliberate non-empty whitespace line to follow
git+https://bitbucket.org/willthames/git-ansible-galaxy,pr-10620
hg+https://bitbucket.org/willthames/hg-ansible-galaxy
https://bitbucket.org/willthames/http-ansible-galaxy/get/master.tar.gz,,http-role
# comment
git+git@github.com:geerlingguy/ansible-role-php.git

@ -1,14 +0,0 @@
- hosts: testhost
gather_facts: true
roles:
- { role: test_gce, tags: test_gce }
- { role: test_gce_pd, tags: test_gce_pd }
- { role: test_gce_mig, tags: test_gce_mig }
- { role: test_gcdns, tags: test_gcdns }
- { role: test_gce_tag, tags: test_gce_tag }
- { role: test_gce_net, tags: test_gce_net }
- { role: test_gcp_url_map, tags: test_gcp_url_map }
- { role: test_gcp_glb, tags: test_gcp_glb }
- { role: test_gcp_healthcheck, tags: test_gcp_healthcheck }
- { role: test_gce_labels, tags: test_gce_labels }
# TODO: tests for gce_lb, gc_storage

@ -1,52 +0,0 @@
import collections
import os
import sys
import yaml
try:
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
_ = Provider.GCE
except ImportError:
print("failed=True msg='libcloud with GCE support (0.13.3+) required for this module'")
sys.exit(1)
def add_credentials_options(parser):
default_service_account_email = None
default_pem_file = None
default_project_id = None
# Load details from credentials.yml
if os.path.isfile('credentials.yml'):
credentials = yaml.load(open('credentials.yml', 'r'))
default_service_account_email = credentials[
'gce_service_account_email']
default_pem_file = credentials['gce_pem_file']
default_project_id = credentials['gce_project_id']
parser.add_option(
"--service_account_email", action="store",
dest="service_account_email", default=default_service_account_email,
help="GCE service account email. Default is loaded from credentials.yml.")
parser.add_option(
"--pem_file", action="store", dest="pem_file",
default=default_pem_file,
help="GCE client key. Default is loaded from credentials.yml.")
parser.add_option(
"--project_id", action="store", dest="project_id",
default=default_project_id,
help="Google Cloud project ID. Default is loaded from credentials.yml.")
def check_required(opts, parser):
for required in ['service_account_email', 'pem_file', 'project_id']:
if getattr(opts, required) is None:
parser.error("Missing required parameter: --%s" % required)
def get_gce_driver(opts):
# Connect to GCE
gce_cls = get_driver(Provider.GCE)
return gce_cls(opts.service_account_email, opts.pem_file,
project=opts.project_id)

@ -1,17 +0,0 @@
a: 999
b: 998
c: 997
d: 996
uno: 1
dos: 2
tres: 3
etest: 'from group_vars'
inventory_beats_default: 'narf'
# variables used for hash merging behavior testing
test_hash:
group_vars_all: "this is in group_vars/all"
# variables used for conditional testing
test_bare: true
test_bare_var: 123
test_bare_nested_good: "test_bare_var == 123"
test_bare_nested_bad: "{{test_bare_var}} == 321"

@ -1,3 +0,0 @@
---
ec2_url: ec2.amazonaws.com
ec2_region: us-east-1

@ -1,3 +0,0 @@
tres: 'three'
hash_test:
group_vars_local: "this is in group_vars/local"

@ -1,5 +0,0 @@
---
cli:
host: "{{ ansible_ssh_host }}"
# username: "{{ vyos_cli_user | default('ansible-admin') }}"
# password: "{{ vyos_cli_pass | default('adminpw') }}"

@ -1,10 +0,0 @@
a: 1
b: 2
c: 3
d: 4
role_var_beats_inventory: 'should_not_see_this'
test_hash:
host_vars_testhost: "this is in host_vars/testhost"
# Var precedence testing
defaults_file_var_role3: "overridden from inventory"

@ -1,5 +0,0 @@
---
win_output_dir: 'C:\ansible_testing'
output_dir: ~/ansible_testing
non_root_test_user: ansible
pip_test_package: isort

@ -1,55 +0,0 @@
[local]
testhost ansible_ssh_host=127.0.0.1 ansible_connection=local
testhost2 ansible_ssh_host=127.0.0.1 ansible_connection=local
# For testing delegate_to
testhost3 ansible_ssh_host=127.0.0.3
testhost4 ansible_ssh_host=127.0.0.4
# For testing fact gathering
facthost[0:20] ansible_host=127.0.0.1 ansible_connection=local
[binary_modules]
testhost_binary_modules ansible_host=127.0.0.1 ansible_connection=local
[local_group]
kube-pippin.knf.local
# the following inline declarations are accompanied
# by (preferred) group_vars/ and host_vars/ variables
# and are used in testing of variable precedence
[inven_overridehosts]
invenoverride ansible_ssh_host=127.0.0.1 ansible_connection=local
[all:vars]
extra_var_override=FROM_INVENTORY
inven_var=inventory_var
unicode_host_var=CaféEñyei
[inven_overridehosts:vars]
foo=foo
var_dir=vars
[arbitrary_parent:children]
local
[local:vars]
parent_var=6000
groups_tree_var=5000
[arbitrary_parent:vars]
groups_tree_var=4000
overridden_in_parent=1000
[arbitrary_grandparent:children]
arbitrary_parent
[arbitrary_grandparent:vars]
groups_tree_var=3000
grandparent_var=2000
overridden_in_parent=2000
[amazon]
localhost ansible_ssh_host=127.0.0.1 ansible_connection=local
[azure]
localhost ansible_ssh_host=127.0.0.1 ansible_connection=local

@ -1,62 +0,0 @@
all:
children:
local:
hosts:
testhost:
ansible_host: 127.0.0.1
ansible_connection: local
testhost2:
ansible_host: 127.0.0.1
ansible_connection: local
# For testing delegate_to
testhost3:
ansible_ssh_host: 127.0.0.3
testhost4:
ansible_ssh_host: 127.0.0.4
# For testing fact gathering
'facthost[0:20]':
ansible_host: 1270.0.0.1
ansible_connection: local
vars:
parent_var: 6000
groups_tree_var: 5000
binary_modules:
hosts:
testhost_binary_modules:
ansible_host: 127.0.0.1
ansible_connection: local
inven_overridehosts:
desc: |
the following inline declarations are accompanied# by (preferred) group_vars/ and host_vars/ variables and
are used in testing of variable precedence
hosts:
invenoverride:
ansible_ssh_host: 127.0.0.1
ansible_connection: local
vars:
foo: foo
var_dir: vars
arbitrary_grandparent:
children:
arbitrary_parent:
children:
local:
vars:
groups_tree_var: 4000
overridden_in_parent: 1000
vars:
groups_tree_var: 3000
grandparent_var: 2000
overridden_in_parent: 2000
amazon:
hosts:
localhost:
ansible_ssh_host: 127.0.0.1
ansible_connection: local
vars:
extra_var_override: FROM_INVENTORY
inven_var: inventory_var
unicode_host_var: CaféEñyei

@ -1,8 +0,0 @@
---
- hosts: localhost
connection: local
gather_facts: no
tags:
- jenkins
roles:
- test_jenkins_job

@ -1,25 +0,0 @@
---
- hosts: netscaler
gather_facts: no
connection: local
vars:
limit_to: "*"
debug: false
roles:
- { role: netscaler_cs_action, when: "limit_to in ['*', 'netscaler_cs_action']" }
- { role: netscaler_cs_policy, when: "limit_to in ['*', 'netscaler_cs_policy']" }
- { role: netscaler_cs_vserver, when: "limit_to in ['*', 'netscaler_cs_vserver']" }
- { role: netscaler_server, when: "limit_to in ['*', 'netscaler_server']" }
- { role: netscaler_lb_vserver, when: "limit_to in ['*', 'netscaler_lb_vserver']" }
- { role: netscaler_lb_monitor, when: "limit_to in ['*', 'netscaler_lb_monitor']" }
- { role: netscaler_save_config, when: "limit_to in ['*', 'netscaler_save_config']" }
- { role: netscaler_service, when: "limit_to in ['*', 'netscaler_service']" }
- { role: netscaler_servicegroup, when: "limit_to in ['*', 'netscaler_servicegroup']" }
- { role: netscaler_gslb_service, when: "limit_to in ['*', 'netscaler_gslb_service']" }
- { role: netscaler_gslb_site, when: "limit_to in ['*', 'netscaler_gslb_site']" }
- { role: netscaler_gslb_vserver, when: "limit_to in ['*', 'netscaler_gslb_vserver']" }
- { role: netscaler_ssl_certkey, when: "limit_to in ['*', 'netscaler_ssl_certkey']" }

@ -1,11 +0,0 @@
---
- hosts: nuage
gather_facts: no
connection: local
vars:
limit_to: "*"
debug: false
roles:
- { role: nuage_vspk, when: "limit_to in ['*', 'nuage_vspk']" }

@ -1,8 +0,0 @@
---
- hosts: localhost
gather_facts: no
connection: local
roles:
- { role: online_server_info, tags: test_online_server_info }
- { role: online_user_info, tags: test_online_user_info }

@ -1,7 +0,0 @@
---
- hosts: localhost
roles:
- { role: one_vm, tags: test_one_vm }
- { role: one_image, tags: test_one_image }
- { role: one_image_info, tags: test_one_image_info }
- { role: one_service, tags: test_one_service }

@ -1,36 +0,0 @@
---
- hosts: ovs
gather_facts: no
remote_user: ubuntu
become: yes
vars:
limit_to: "*"
debug: false
# Run the tests within blocks allows the next module to be tested if the previous one fails.
# This is done to allow https://github.com/ansible/dci-partner-ansible/ to run the full set of tests.
tasks:
- set_fact:
test_failed: false
failed_modules: []
- block:
- include_role:
name: openvswitch_db
when: "limit_to in ['*', 'openvswitch_db']"
rescue:
- set_fact:
failed_modules: "{{ failed_modules + [ 'openvswitch_db' ]}}"
test_failed: true
###########
- debug: var=failed_modules
when: test_failed
- name: Has any previous test failed?
fail:
msg: "One or more tests failed, check log for details"
when: test_failed

@ -1,45 +0,0 @@
---
- hosts: localhost
connection: local
gather_facts: false
tags:
- rackspace
roles:
- role: test_rax
tags: test_rax
- role: test_rax_facts
tags: test_rax_facts
- role: test_rax_meta
tags: test_rax_meta
- role: test_rax_keypair
tags: test_rax_keypair
- role: test_rax_clb
tags: test_rax_clb
- role: test_rax_clb_nodes
tags: test_rax_clb_nodes
- role: test_rax_network
tags: test_rax_network
- role: test_rax_cbs
tags: test_rax_cbs
- role: test_rax_cbs_attachments
tags: test_rax_cbs_attachments
- role: test_rax_identity
tags: test_rax_identity
- role: test_rax_cdb
tags: test_rax_cdb
- role: test_rax_cdb_database
tags: test_rax_cdb_database
- role: test_rax_scaling_group
tags: test_rax_scaling_group

@ -1,339 +0,0 @@
- name: Create virtual network
azure_rm_virtualnetwork:
name: vnet001
resource_group: "{{ resource_group }}"
address_prefixes_cidr: "10.10.0.0/16"
register: output
- name: Create subnet
azure_rm_subnet:
name: subnet001
resource_group: "{{ resource_group }}"
virtual_network_name: vnet001
address_prefix_cidr: "10.10.0.0/24"
register: output
- name: Create second virtual network
azure_rm_virtualnetwork:
name: vnet002
resource_group: "{{ resource_group }}"
address_prefixes_cidr: "10.20.0.0/16"
register: output
- name: Create second subnet
azure_rm_subnet:
name: subnet002
resource_group: "{{ resource_group }}"
virtual_network_name: vnet002
address_prefix_cidr: "10.20.0.0/24"
register: output
- name: Create security group
azure_rm_securitygroup:
name: secgroup001
resource_group: "{{ resource_group }}"
register: output
- name: Create second security group
azure_rm_securitygroup:
name: secgroup002
resource_group: "{{ resource_group }}"
register: output
- name: Create a public ip
azure_rm_publicipaddress:
name: publicip001
resource_group: "{{ resource_group }}"
allocation_method: "Static"
register: output
- name: Create second public ip
azure_rm_publicipaddress:
name: publicip002
resource_group: "{{ resource_group }}"
allocation_method: "Static"
register: output
- name: Delete network interface, if it exists
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
state: absent
register: output
- name: Should require subnet when creating nic
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
virtual_network_name: vnet001
security_group_name: secgroup001
public_ip_address_name: publicip001
register: output
ignore_errors: yes
- assert:
that:
- output.failed
- "'subnet' in output.msg"
- name: Should require virtual network when creating nic
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
security_group_name: secgroup001
public_ip_address_name: publicip001
subnet: subnet001
register: output
ignore_errors: yes
- assert:
that:
- output.failed
- "'virtual_network_name' in output.msg"
- name: Create nic
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
virtual_network_name: vnet001
subnet: subnet001
security_group_name: secgroup001
public_ip_address_name: publicip001
register: output
- name: Should be idempotent
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
virtual_network_name: vnet001
subnet: subnet001
security_group_name: secgroup001
public_ip_address_name: publicip001
register: output
- assert:
that: not output.changed
- name: Should change private IP address
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
private_ip_address: 10.10.0.10
private_ip_allocation_method: Static
virtual_network_name: vnet001
subnet: subnet001
security_group_name: secgroup001
public_ip_address_name: publicip001
register: output
- assert:
that:
- output.changed
- output.state.ip_configuration.private_ip_address == '10.10.0.10'
- output.state.ip_configuration.private_ip_allocation_method == 'Static'
- name: Should change virtual network and subnet
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
private_ip_allocation_method: Dynamic
virtual_network_name: vnet002
subnet: subnet002
security_group_name: secgroup002
public_ip_address_name: publicip002
register: output
- assert:
that:
- output.changed
- "'10.20' in output.state.ip_configuration.private_ip_address"
- output.state.ip_configuration.private_ip_allocation_method == 'Dynamic'
- output.state.ip_configuration.subnet.name == 'subnet002'
- output.state.ip_configuration.public_ip_address.name == 'publicip002'
- name: Add tags
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
tags:
testing: testing
foo: bar
register: output
- assert:
that:
- output.state.tags | length == 2
- output.state.tags.testing == 'testing'
- name: Gather facts for tags
azure_rm_networkinterface_info:
tags: testing
register: output
- assert:
that:
- azure_networkinterfaces | length >= 1
- name: Gather facts for resource group and tags
azure_rm_networkinterface_info:
resource_group: "{{ resource_group }}"
tags: testing
register: output
- assert:
that:
- azure_networkinterfaces| length == 1
- name: Gather facts for name and tags
azure_rm_networkinterface_info:
resource_group: "{{ resource_group }}"
name: nic003
tags: testing
register: output
- assert:
that:
- azure_networkinterfaces | length == 1
- name: Purge one tag
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
tags:
testing: testing
register: output
- assert:
that:
- output.changed
- output.state.tags | length == 1
- name: Purge all tags
azure_rm_networkinterface:
name: nic003
resource_group: "{{ resource_group }}"
tags: {}
register: output
- assert:
that:
- output.changed
- output.state.tags | length == 0
- name: Remove network interface, if it exists
azure_rm_networkinterface:
name: "{{ item }}"
resource_group: "{{ resource_group }}"
state: absent
register: output
with_items:
- nic004
- nic005
- name: Remove publicip, if it exists
azure_rm_publicipaddress:
name: "{{ item }}"
resource_group: "{{ resource_group }}"
state: absent
with_items:
- nic00401
- nic00501
- name: Remove security group, if it exists
azure_rm_securitygroup:
name: "{{ item }}"
resource_group: "{{ resource_group }}"
state: absent
with_items:
- nic00401
- nic00501
- name: Should create default security group and default public ip for linux host
azure_rm_networkinterface:
name: nic004
resource_group: "{{ resource_group }}"
virtual_network_name: vnet001
subnet: subnet001
register: output
- assert:
that:
- output.state.ip_configuration.public_ip_address.name == 'nic00401'
- output.state.network_security_group.name == 'nic00401'
- name: Gather facts for security group nic00401
azure_rm_securitygroup_info:
resource_group: "{{ resource_group }}"
name: nic00401
register: output
- assert:
that:
- azure_securitygroups[0].properties.securityRules[0].properties.destinationPortRange == '22'
- name: Should create default security group and default public ip for windows host
azure_rm_networkinterface:
name: nic005
resource_group: "{{ resource_group }}"
virtual_network_name: vnet001
subnet: subnet001
os_type: Windows
open_ports:
- 9000
- '9005-9010'
register: output
- assert:
that:
- output.state.ip_configuration.public_ip_address.name == 'nic00501'
- output.state.network_security_group.name == 'nic00501'
- name: Gather facts for security group nic00501
azure_rm_securitygroup_info:
resource_group: "{{ resource_group }}"
name: nic00501
register: output
- name: Security group should allow RDP access on custom port
assert:
that:
- azure_securitygroups[0].properties.securityRules[0].properties.destinationPortRange == '9000'
- azure_securitygroups[0].properties.securityRules[1].properties.destinationPortRange == '9005-9010'
- name: Gather facts for one nic
azure_rm_networkinterface_info:
resource_group: "{{ resource_group }}"
name: nic003
register: output
- assert:
that:
- azure_networkinterfaces | length == 1
- name: Gather facts for all nics in resource groups
azure_rm_networkinterface_info:
resource_group: "{{ resource_group }}"
register: output
- assert:
that:
- azure_networkinterfaces | length >= 3
- name: Gather facts for all nics
azure_rm_networkinterface_info:
register: output
- assert:
that:
- azure_networkinterfaces | length >= 3
- name: Delete nic
azure_rm_networkinterface:
name: "{{ item }}"
resource_group: "{{ resource_group }}"
state: absent
register: output
with_items:
- nic003
- nic004
- nic005

@ -1,142 +0,0 @@
- name: Get resource group
azure_rm_resourcegroup_info:
name: "{{ resource_group }}"
- name: Create resource group
azure_rm_resourcegroup:
name: "{{ resource_prefix }}"
location: "{{ azure_resourcegroups[0].location }}"
tags:
testing: testing
delete: never
register: output
- assert:
that:
- output.state.tags.testing == 'testing'
- output.state.tags.delete == 'never'
- output.state.location == '{{ location }}'
- name: Should be idempotent
azure_rm_resourcegroup:
name: "{{ resource_prefix }}"
tags:
testing: testing
delete: never
register: output
- assert:
that: not output.changed
- name: Change resource group tags
azure_rm_resourcegroup:
name: "{{ resource_prefix }}"
tags:
testing: 'no'
delete: 'on-exit'
foo: 'bar'
register: output
- assert:
that:
- output.state.tags | length == 3
- output.state.tags.testing == 'no'
- output.state.tags.delete == 'on-exit'
- output.state.tags.foo == 'bar'
- name: Gather facts by tags
azure_rm_resourcegroup_info:
tags:
- testing
- foo:bar
register: output
- assert:
that: azure_resourcegroups | length == 1
- name: Purge one tag
azure_rm_resourcegroup:
name: "{{ resource_prefix }}"
tags:
testing: 'no'
delete: 'on-exit'
debug: yes
register: output
- assert:
that:
- output.state.tags | length == 2
- output.state.tags.testing == 'no'
- output.state.tags.delete == 'on-exit'
- name: Purge no tags
azure_rm_resourcegroup:
name: "{{ resource_prefix }}"
register: output
- assert:
that:
- output.state.tags | length == 2
- name: Purge all tags
azure_rm_resourcegroup:
name: "{{ resource_prefix }}"
tags: {}
register: output
- assert:
that:
- output.state.tags | length == 0
- name: Add a resource
azure_rm_virtualnetwork:
resource_group: "{{ resource_prefix }}"
name: "virtualnet01"
address_prefixes_cidr: '10.1.0.0/16'
register: output
- name: Remove resource group should fail
azure_rm_resourcegroup:
name: "{{ resource_prefix }}"
state: absent
register: output
ignore_errors: yes
- assert:
that:
- output.failed
- "'Resources exist' in output.msg"
- name: Create a second resource group
azure_rm_resourcegroup:
name: Testing2
location: "{{ location }}"
register: output
- name: Gather facts for a resource group
azure_rm_resourcegroup_info:
name: "{{ resource_group }}"
register: output
- assert:
that: azure_resourcegroups | length == 1
- name: Gather facts for all resource groups
azure_rm_resourcegroup_info:
register: output
- assert:
that: azure_resourcegroups | length > 1
- name: Force remove resource group
azure_rm_resourcegroup:
name: "{{ resource_group }}"
state: absent
force: yes
register: output
- name: Remove second resource group
azure_rm_resourcegroup:
name: Testing2
state: absent
register: output

@ -1,113 +0,0 @@
# Ansible Role: cnos_backup_sample - Saving the switch configuration to a remote server
---
<add role description below>
This role is an example of using the *cnos_backup.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with switch configurations. It provides a way to back up the running or startup configurations of a switch to a remote server. This is achieved by periodically saving a copy of the startup or running configuration of the network device to a remote server using FTP, SFTP, TFTP, or SCP.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_backup](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_backup.html&cp=0_3_1_0_4_4).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`configType` | Specifies the type of configuration to be backed up to the remote server (**running-config** - running configuration, **startup-config** - startup configuration)
`protocol` | Specifies the protocol used by the network device to interact with the remote server to where to upload the backup configuration (**ftp** - FTP, **sftp** - SFTP, **tftp** - TFTP, **scp** - SCP)
`serverip` | Specifies the IP Address of the remote server to where the configuration will be backed up
`rcpath` | Specifies the full file path where the configuration file will be copied on the remote server (when backing up the switch configuration through TFTP, an empty directory needs to be created, otherwise the operation will fail)
`serverusername` | Configures the username for the server relating to the protocol used
`serverpassword` | Configures the password for the server relating to the protocol used
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_backup.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_backup_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_backup_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_backup_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to back up configuration
hosts: cnos_backup_sample
gather_facts: no
connection: local
roles:
- cnos_backup_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,18 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_backup_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_backup_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos rcpath=/root/cnos_config/G8272-running-config.txt
#Use this in case its TFTP as tftpboot folder is the starting point for tftp
#10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos rcpath=/anil/G8272-running-config.txt

@ -1,24 +0,0 @@
# This contain sample config back up tasks
---
- name: Test Running Config Backup
cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}} serverusername='{{item.serverusername}}' serverpassword='{{item.serverpassword}}'
with_items: "{{test_config_data1}}"
- name: Test Startup Config Backup
cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}} serverusername='{{item.serverusername}}' serverpassword='{{item.serverpassword}}'
with_items: "{{test_config_data2}}"
#Root folder will be different for SFTP/SCP and TFTP
#The following task is commented.
#Before trying this, please change in /etc/ansible/hosts file
#and backup the config file with reference to your tftp-root folder
#- name: Test Running Config Backup -TFTP
# cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}}
# with_items: "{{test_config_data3}}"
#- name: Test Startup Config Backup - TFTP
# cnos_backup: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_backup_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}}
# with_items: "{{test_config_data4}}"
# Completed file

@ -1,12 +0,0 @@
---
test_config_data1:
- {configType: running-config, protocol: "sftp", serverip: "10.241.106.118", serverusername: "root", serverpassword: "root123"}
test_config_data2:
- {configType: startup-config, protocol: "sftp", serverip: "10.241.106.118", serverusername: "root", serverpassword: "root123"}
test_config_data3:
- {configType: running-config, protocol: "tftp", serverip: "10.241.106.118"}
test_config_data4:
- {configType: startup-config, protocol: "tftp", serverip: "10.241.106.118"}

@ -1,118 +0,0 @@
# Ansible Role: cnos_bgp_sample - CNOS Switch BGP Configuration
---
<add role description below>
This role is an example of using the *cnos_bgp.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with Border Gateway Protocol (BGP) related configurations. The operators used are overloaded to ensure control over switch BGP configurations. This module is invoked using method with *asNumber* as one of its arguments.
The first level of the BGP configuration allows to set up an AS number, with the following attributes going into various configuration operations under the context of BGP. After passing this level, there are eight BGP arguments that will perform further configurations. They are *bgpArg1*, *bgpArg2*, *bgpArg3*, *bgpArg4*, *bgpArg5*, *bgpArg6*, *bgpArg7*, and *bgpArg8*.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_bgp](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_bgp.html&cp=0_3_1_0_4_16).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`asNum` | Specifies the AS number
`bgpArg1` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **address-family**, **bestpath**, **bgp**, **cluster-id**, **confederation**, **enforce-first-as**, **fast-external-failover**, **graceful-restart**, **graceful-restart-helper**, **log-neighbor-changes**, **maxas-limit**, **neighbor**, **router-id**, **shutdown**, **synchronization**, **timers**, **vrf**.
`bgpArg2` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **ipv4**, **ipv6**, **always-compare-med**, **compare-confed-aspath**, **compare-routerid**, **dont-compare-originator-id**, **tie-break-on-age**, **as-path**, **med**, number of times to prepend the local AS, Route Reflector Cluster ID as a 32 bit quantity or in IP address format, **identifier**, **peers**, delay value, number of autonomous systems in the AS-path attribute, neighbor address, neighbor prefix, manually configured router identifier, keepalive interval.
`bgpArg3` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **aggregate-address**, **client-to-client**, **dampening**, **distance**, **maximum-paths**, **network**, **nexthop**, **redistribute**, **save**, **synchronization**, **ignore**, **multipath-relax**, **confed**, **missing-as-worst**, **non-deterministic**, **remove-recv-med**, **remove-send-med**, set routing domain confederation AS, AS number.
`bgpArg4` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: IP address/prefix length, **route-map**, time after which a penalty is decreased by half, administrative distance to routes outside the AS, **ebgp**, **ibgp**, **synchronization**, IP address, delay value, **direct**, **ospf**, **static**, **memory**.
`bgpArg5` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **as-set**, **summary-only**, name of the route map that controls where BGP route dampening is enabled, value to start reusing a route, administrative distance to routes inside the AS, value for maximum path numbers, **backdoor**, **mask**, **route-map**.
`bgpArg6` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **summary-only**, **as-set**, value to start suppressing a route, administrative distance for local routes, IP subnet address mask, name of the route map.
`bgpArg7` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: maximum duration to suppress a stable route, **route-map**, **backdoor**.
`bgpArg8` | This is an overloaded BGP variable. Please refer to the [cnos_bgp module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_bgp.html?cp=0_3_1_0_2_13) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: time after which an unreachable route's penalty is decreased by half, **backdoor**.
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_bgp.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_bgp_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_bgp_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_bgp_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do BGP configuration
hosts: cnos_bgp_sample
gather_facts: no
connection: local
roles:
- cnos_bgp_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_bgp_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_bgp_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos

@ -1,78 +0,0 @@
## This contain sample BGP execution tasks
---
- name: Test BGP - neighbor
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}' bgpArg5='{{item.bgpArg5}}' bgpArg6='{{item.bgpArg6}}'
with_items: "{{test_bgp_data13}}"
- name: Test BGP - BFD
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}'
with_items: "{{test_bgp_data19}}"
- name: Test BGP - address-family - dampening
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}' bgpArg5='{{item.bgpArg5}}' bgpArg6='{{item.bgpArg6}}' bgpArg7='{{item.bgpArg7}}' bgpArg8='{{item.bgpArg8}}'
with_items: "{{test_bgp_data1}}"
- name: Test BGP - address-family - network
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}' bgpArg4='{{item.bgpArg4}}' bgpArg5='{{item.bgpArg5}}'
with_items: "{{test_bgp_data18}}"
- name: Test BGP - bestpath - always-compare-med
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data2}}"
- name: Test BGP - bestpath-compare-confed-aspat
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data3}}"
- name: Test BGP - bgp
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data4}}"
- name: Test BGP - cluster-id
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data5}}"
- name: Test BGP - confederation-identifier
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}'
with_items: "{{test_bgp_data6}}"
- name: Test BGP - enforce-first-as
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data7}}"
- name: Test BGP - fast-external-failover
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data8}}"
- name: Test BGP - graceful-restart
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data9}}"
- name: Test BGP - graceful-restart-helper
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data10}}"
- name: Test BGP - maxas-limit
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data11}}"
#- name: Test BGP - neighbor
# cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}'
# with_items: "{{test_bgp_data13}}"
- name: Test BGP - router-id
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}'
with_items: "{{test_bgp_data14}}"
- name: Test BGP - synchronization
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data15}}"
- name: Test BGP - timers
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}' bgpArg2='{{item.bgpArg2}}' bgpArg3='{{item.bgpArg3}}'
with_items: "{{test_bgp_data16}}"
- name: Test BGP - vrf
cnos_bgp: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_bgp_{{ inventory_hostname }}_output.txt asNum='{{item.asNum}}' bgpArg1='{{item.bgpArg1}}'
with_items: "{{test_bgp_data17}}"
# Completed file

@ -1,37 +0,0 @@
---
test_bgp_data1:
- {asNum: 33, bgpArg1: "address-family", bgpArg2: "ipv4", bgpArg3: "dampening", bgpArg4: 13, bgpArg5: 233, bgpArg6: 333, bgpArg7: 15, bgpArg8: 33 }
test_bgp_data2:
- {asNum: 33, bgpArg1: "bestpath", bgpArg2: "always-compare-med"}
test_bgp_data3:
- {asNum: 33, bgpArg1: "bestpath", bgpArg2: "compare-confed-aspath"}
test_bgp_data4:
- {asNum: 33, bgpArg1: "bgp", bgpArg2: 33}
test_bgp_data5:
- {asNum: 33, bgpArg1: "cluster-id", bgpArg2: "1.2.3.4"}
test_bgp_data6:
- {asNum: 33, bgpArg1: "confederation", bgpArg2: "identifier", bgpArg3: 333}
test_bgp_data7:
- {asNum: 33, bgpArg1: "enforce-first-as"}
test_bgp_data8:
- {asNum: 33, bgpArg1: "fast-external-failover"}
test_bgp_data9:
- {asNum: 33, bgpArg1: "graceful-restart", bgpArg2: 333}
test_bgp_data10:
- {asNum: 33, bgpArg1: "graceful-restart-helper"}
test_bgp_data11:
- {asNum: 33, bgpArg1: "maxas-limit", bgpArg2: 333}
test_bgp_data13:
- {asNum: 33, bgpArg1: "neighbor", bgpArg2: "10.241.107.40", bgpArg3: 13, bgpArg4: "address-family", bgpArg5: "ipv4", bgpArg6: "next-hop-self" }
test_bgp_data14:
- {asNum: 33, bgpArg1: "router-id", bgpArg2: "1.2.3.4"}
test_bgp_data15:
- {asNum: 33, bgpArg1: "synchronization"}
test_bgp_data16:
- {asNum: 33, bgpArg1: "timers", bgpArg2: 333, bgpArg3: 3333}
test_bgp_data17:
- {asNum: 33, bgpArg1: "vrf"}
test_bgp_data18:
- {asNum: 33, bgpArg1: "address-family", bgpArg2: "ipv4", bgpArg3: "network", bgpArg4: "1.2.3.4/5", bgpArg5: "backdoor"}
test_bgp_data19:
- {asNum: 33, bgpArg1: "neighbor", bgpArg2: "10.241.107.40", bgpArg3: 13, bgpArg4: "bfd"}

@ -1,110 +0,0 @@
# Ansible Role: cnos_command_sample - Executing a single CNOS command
---
<add role description below>
This role is an example of using the *cnos_command.py* Lenovo module in the context of CNOS switch configuration. This module allows you to modify the switch running configuration. It provides a way to execute a single CNOS command on a switch by evaluating the current running configuration and executing the command only if the specific setting has not been already configured.
The CNOS command is passed as an argument of the method.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_command](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_command.html&cp=0_3_1_0_4_8).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`clicommand` | Specifies the CLI command as an attribute to this method
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_command.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_command_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_command_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_command_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do some CLI Command configurations
hosts: cnos_command_sample
gather_facts: no
connection: local
roles:
- cnos_command_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_command_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_command_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos

@ -1,7 +0,0 @@
# This contain sample template execution tasks
---
- name: Test Command
cnos_command: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} clicommand='{{item.clicommand}}' outputfile=./results/cnos_command_{{ inventory_hostname }}_output.txt
with_items: "{{test_runcommand_data1}}"
# Completed file

@ -1,3 +0,0 @@
---
test_runcommand_data1:
- {clicommand: "display users"}

@ -1,118 +0,0 @@
# Ansible Role: cnos_conditional_command_sample - Executing a single CNOS command with respect to conditions specified in the inventory
---
<add role description below>
This role is an example of using the *cnos_conditional_command.py* Lenovo module in the context of CNOS switch configuration. This module allows you to modify the running configuration of a switch. It provides a way to execute a single CNOS command on a network device by evaluating the current running configuration and executing the command only if the specific settings have not been already configured.
The CNOS command is passed as an argument of the method.
This module functions the same as the *cnos_command.py* module. The only exception is that the following inventory variable can be specified: condition = <flag string>
When this inventory variable is specified as the variable of a task, the command is executed for the network element that matches the flag string.
Usually, commands are executed across a group of network devices. When there is a requirement to skip the execution of the command on one or more devices, it is recommended to use this module.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_conditional_command](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_conditional_command.html&cp=0_3_1_0_4_9).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
`condition` | If `condition=false` is specified in the inventory file against any device, the command execution is skipped for that device (**true**, **false**)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`flag` | If a task needs to be executed, the flag needs to be set the same as it is specified in the inventory for that device
`clicommand` | Specifies the CLI command as an attribute to this method
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_conditional_command.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_conditional_command_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_conditional_command_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos condition=pass
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_conditional_command_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do some configurations
hosts: cnos_conditional_command_sample
gather_facts: no
connection: local
roles:
- cnos_conditional_command_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_conditional_command_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_conditional_command_sample]
10.241.107.39 username=<username> password=<password> condition=pass deviceType=g8272_cnos

@ -1,7 +0,0 @@
# This contain sample command execution tasks
---
- name: Run a command
cnos_conditional_command: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} condition={{ hostvars[inventory_hostname]['condition'] }} flag='{{item.flag}}' clicommand='{{item.clicommand}}' outputfile=./results/cnos_conditional_command_{{ inventory_hostname }}_output.txt
with_items: "{{conditional_command_data1}}"
# Completed file

@ -1,3 +0,0 @@
---
conditional_command_data1:
- {flag: "pass", clicommand: "display users"}

@ -1,118 +0,0 @@
# Ansible Role: cnos_conditional_template_sample - Manages switch configuration using templates with respect to conditions specified in the inventory
---
<add role description below>
This role is an example of using the *cnos_conditional_template.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with the running configuration of a switch. It provides a way to execute a set of CNOS commands on a switch by evaluating the current running configuration and executing the commands only if the specific settings have not been already configured.
The configuration source can be a set of commands or a template written in the Jinja2 templating language.
This module functions the same as the *cnos_template.py* module. The only exception is that the following inventory variable can be specified: condition = <flag string>
When this inventory variable is specified as the variable of a task, the template is executed for the network element that matches the flag string.
Usually, templates are used when commands are the same across a group of network devices. When there is a requirement to skip the execution of the template on one or more devices, it is recommended to use this module.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_conditional_template](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_conditional_template.html&cp=0_3_1_0_4_11).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
`condition` | If `condition=<flag string>` is specified in the inventory file against any device, the template execution is done for that device in case it matches the flag setting for that task
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`flag` | If a task needs to be executed, you have to set the flag the same as it is specified in the inventory for that device
`commandfile` | Specifies the path to the CNOS command file which needs to be applied
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_conditional_template.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_conditional_template_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_conditional_template_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos condition=pass
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_conditional_template_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do some template configurations
hosts: cnos_conditional_template_sample
gather_facts: no
connection: local
roles:
- cnos_conditional_template_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_conditional_template_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_conditional_template_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos condition=pass

@ -1,11 +0,0 @@
# This contain sample conditional template execution tasks
---
- name: Replace Config CLI command template with values
template: src=demo_template.j2 dest=./commands/cnos_conditional_template_{{ inventory_hostname }}_command.txt
with_items: "{{conditional_template_data1}}"
- name: Applying CLI commands on Switches
cnos_conditional_template: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}}
condition={{ hostvars[inventory_hostname]['condition'] }} flag='{{item.flag}}' commandfile=./commands/cnos_conditional_template_{{ inventory_hostname }}_command.txt outputfile=./results/cnos_conditional_template_{{ inventory_hostname }}_output.txt
with_items: "{{conditional_template_data1}}"
# Completed file

@ -1,14 +0,0 @@
#Demo Template
vlan {{item.vlanid1}}
exit
config d
interface ethernet {{item.slot_chassis_number1}}
aggregation-group {{item.portchannel_interface_number1}} mode {{item.portchannel_mode1}}
exit
config d
interface port-aggregation {{item.portchannel_interface_number1}}
shut
lacp suspend-individual
no shut
exit

@ -1,3 +0,0 @@
---
conditional_template_data1:
- {flag: "pass", vlanid1: 13, slot_chassis_number1: "1/2", portchannel_interface_number1: 100, portchannel_mode1: "active"}

@ -1,118 +0,0 @@
# Ansible Role: cnos_ethernet_sample - Performs switch ethernet port configuration and state management
---
<add role description below>
This role is an example of using the *cnos_interface.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with interface related configurations. The operators used are overloaded to ensure control over switch interface configurations, such as ethernet ports, loopback interfaces, VLANs, and the management interface.
Apart from the regular device connection related attributes, there are seven interface arguments that will perform further configurations. They are *interfaceArg1*, *interfaceArg2*, *interfaceArg3*, *interfaceArg4*, *interfaceArg5*, *interfaceArg6*, and *interfaceArg7*.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_interface](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_interface.html&cp=0_3_1_0_4_12).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`interfaceOption` | Specifies the type of the interface that will be configured (**ethernet** - ethernet port, **loopback** - loopback interface, **vlan** - VLAN, **mgmt** - management interface, **port-aggregation** - Link Aggregation Group)
`interfaceRange` | Specifies the interface range that will be configured
`interfaceArg1` | This is an overloaded BGP variable. Please refer to the [cnos_interface module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_interface.html?cp=0_3_1_0_2_12) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **aggregation-group**, **bfd**, **bridge-port**, **description**, **duplex**, **flowcontrol**, **ip**, **ipv6**, **lacp**, **lldp**, **load-interval**, **mac**, **mac-address**, **mac-learn**, **microburst-detection**, **mtu**, **service**, **service-policy**, **shutdown**, **snmp**, **spanning-tree**, **speed**, **storm-control**, **vlan**, **vrrp**, **port-aggregation**.
`interfaceArg2` | This is an overloaded BGP variable. Please refer to the [cnos_interface module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_interface.html?cp=0_3_1_0_2_12) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: specify a LAG number, **authentication**, **echo**, **ipv4**, **ipv6**, **interval**, **neighbor**, **access**, **mode**, **trunk**, interface description, **auto**, **full**, **half**, **receive**, **send**, **access-group**, **arp**, **dhcp**, **port**, **port-unreachable**, **redirects**, **router**, **unreachables**, **address**, **link-local**, **port-priority**, **suspend-individual**, **timeout**, **transmit**, **trap-notification**, **tlv-select**, load interval delay, **counter**, name for the MAC access group, MAC address in XXXX.XXXX.XXXX format, threshold value, MTU in bytes, instance ID to map to the EVC, **input**, **output**, **copp-system-policy**, **type**, **bpdufilter**, **bpduguard**, **cost**, **enable**, **disable**, **guard**, **link-type**, **mst**, **port**, **port-priority**, **vlan**, **auto**, 1000, 10000, 40000, **broadcast**, **unicast**, **multicast**, **egress-only**, **destination-ip**, **destination-mac**, **destination-port**, **source-dest-ip**, **source-dest-mac**, **source-dest-port**, **source-interface**, **source-ip**, **source-mac**, **source-port**.
`interfaceArg3` | This is an overloaded BGP variable. Please refer to the [cnos_interface module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_interface.html?cp=0_3_1_0_2_12) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **active**, **passive**, **on**, **keyed-md5**, **keyed-sha1**, **meticulous-keyed-md5**, **meticulous-keyed-sha1**, **simple**, **authentication**, **echo**, **interval**, interval value, source IP address, **off**, ACL name, IP address of the ARP entry, **timeout**, **client**, **relay**, **area**, **multi-area**, **dhcp**, IPv6 address, IPv6 address of the DHCP Relay, Neighbor IPv6 address, LACP port priority, **long**, **short**, **link-aggregation**, **mac-phy-status**, **management-address**, **max-frame-size**, **port-description**, **port-protocol-vlan**, **port-vlan**, **power-mdi**, **protocol-identity**, **system-capabilities**, **system-description**, **system-name**, **vid-management**, **vlan-name**, counter for the load interval, name of the policy to attach, **all**, COPP class name to attach, **qos**, **queuing**, **enable**, **disable**, **auto**, port path cost, **loop**, **root**, **auto**, **point-to-point**, **shared**, MSTP instance range, port priority value, specify VLAN, allowed traffic level, **ipv6**, **source-interface**.
`interfaceArg4` | This is an overloaded BGP variable. Please refer to the [cnos_interface module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_interface.html?cp=0_3_1_0_2_12) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **key-chain**, **key-id**, **keyed-md5**, **keyed-sha1**, **meticulous-keyed-md5**, **meticulous-keyed-sha1**, **simple**, interval value, BFD minimum receive interval, destination IP address, **in**, **out**, MAC address in XXXX.XXXX.XXXX format, timeout value, **class-id**, **request**, IPv4 address of the DHCP Relay, OSPF area ID, **anycast**, **secondary**, **ethernet**, **vlan**, load interval delay, name of the QoS policy to attach, **input**, **output**, **cost**, **port-priority**.
`interfaceArg5` | This is an overloaded BGP variable. Please refer to the [cnos_interface module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_interface.html?cp=0_3_1_0_2_12) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: name of the key chain, key ID, **key-chain**, **key-id**, BFD minimum receive interval, Hello multiplier value, **admin-down**, **multihop**, **non-persistent**, vendor class ID name, **bootfile-name**, **host-name**, **log-server**, **ntp-server**, **tftp-server-name**, specify ethernet port, specify VLAN, name of the QoS policy to attach, **auto**, port path cost, port priority value.
`interfaceArg6` | This is an overloaded BGP variable. Please refer to the [cnos_interface module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_interface.html?cp=0_3_1_0_2_12) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: authentication key string, name of the key chain, key ID, Hello multiplier value, **admin-down**, **non-persistent**.
`interfaceArg7` | This is an overloaded BGP variable. Please refer to the [cnos_interface module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_interface.html?cp=0_3_1_0_2_12) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: authentication key string, **admin-down**.
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_interface.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_interface_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_ethernet_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_interface_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do Interface Ethernet configurations
hosts: cnos_ethernet_sample
gather_facts: no
connection: local
roles:
- cnos_ethernet_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_ethernet_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_ethernet_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos

@ -1,98 +0,0 @@
### This contain sample execution tasks
---
- name: Test Interface Ethernet - aggregation-group
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data1}}"
#- name: Test Interface Ethernet - aggregation-group - Interface Range
# cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
# with_items: "{{test_ethernet_data24}}"
- name: Test Interface Ethernet - bridge-port
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data2}}"
- name: Test Interface Ethernet - bridgeport mode
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data3}}"
- name: Test Interface Ethernet - Description
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_ethernet_data4}}"
- name: Test Interface Ethernet - Duplex
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_ethernet_data5}}"
- name: Test Interface Ethernet - flowcontrol
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data6}}"
- name: Test Interface Ethernet - lacp
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data7}}"
- name: Test Interface Ethernet - lldp
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data8}}"
- name: Test Interface Ethernet - load-interval
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}'
with_items: "{{test_ethernet_data9}}"
#- name: Test Interface Ethernet - mac
# cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
# with_items: "{{test_ethernet_data10}}"
- name: Test Interface Ethernet - microburst-detection
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_ethernet_data11}}"
- name: Test Interface Ethernet - mtu
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_ethernet_data12}}"
- name: Test Interface Ethernet - service-policy
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data13}}"
- name: Test Interface Ethernet - speed
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_ethernet_data14}}"
- name: Test Interface Ethernet - storm
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data15}}"
#- name: Test Interface Ethernet - vlan
# cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
# with_items: "{{test_ethernet_data16}}"
- name: Test Interface Ethernet - vrrp
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_ethernet_data17}}"
- name: Test Interface Ethernet - spanning tree1
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data18}}"
- name: Test Interface Ethernet - spanning tree 2
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}' interfaceArg5='{{item.interfaceArg5}}'
with_items: "{{test_ethernet_data19}}"
- name: Test Interface Ethernet - ip1
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}'
with_items: "{{test_ethernet_data20}}"
- name: Test Interface Ethernet - ip2
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_ethernet_data21}}"
- name: Test Interface Ethernet - bfd
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}' interfaceArg5='{{item.interfaceArg5}}'
with_items: "{{test_ethernet_data22}}"
- name: Test Interface Ethernet - bfd
cnos_interface: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_ethernet_{{ inventory_hostname }}_output.txt interfaceOption='{{item.interfaceOption}}' interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}' interfaceArg5='{{item.interfaceArg5}}' interfaceArg6='{{item.interfaceArg6}}'
with_items: "{{test_ethernet_data23}}"
# Completed file

@ -1,49 +0,0 @@
---
test_ethernet_data1:
- {interfaceOption: 'ethernet', interfaceRange: 1, interfaceArg1: "aggregation-group", interfaceArg2: 33, interfaceArg3: "on"}
test_ethernet_data2:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "bridge-port", interfaceArg2: "access", interfaceArg3: 33}
test_ethernet_data3:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "bridge-port", interfaceArg2: "mode", interfaceArg3: "access"}
test_ethernet_data4:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "description", interfaceArg2: "Hentammoo "}
test_ethernet_data5:
- {interfaceOption: 'ethernet', interfaceRange: 1, interfaceArg1: "duplex", interfaceArg2: "auto"}
test_ethernet_data6:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "flowcontrol", interfaceArg2: "send", interfaceArg3: "off"}
test_ethernet_data7:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "lacp", interfaceArg2: "port-priority", interfaceArg3: 33}
test_ethernet_data8:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "lldp", interfaceArg2: "tlv-select", interfaceArg3: "max-frame-size"}
test_ethernet_data9:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "load-interval", interfaceArg2: "counter", interfaceArg3: 2, interfaceArg4: 33}
test_ethernet_data10:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "mac", interfaceArg2: "copp-system-acl-vlag-hc"}
test_ethernet_data11:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "microburst-detection", interfaceArg2: 25}
test_ethernet_data12:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "mtu", interfaceArg2: 66}
test_ethernet_data13:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "service-policy", interfaceArg2: "input", interfaceArg3: "Anil"}
test_ethernet_data14:
- {interfaceOption: 'ethernet', interfaceRange: 1, interfaceArg1: "speed", interfaceArg2: "auto"}
test_ethernet_data15:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "storm-control", interfaceArg2: "broadcast", interfaceArg3: 12.5 }
test_ethernet_data16:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "vlan", interfaceArg2: "disable"}
test_ethernet_data17:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "vrrp", interfaceArg2: 33}
test_ethernet_data18:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "spanning-tree", interfaceArg2: "bpduguard", interfaceArg3: "enable"}
test_ethernet_data19:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "spanning-tree", interfaceArg2: "mst", interfaceArg3: "33-35", interfaceArg4: "cost", interfaceArg5: 33}
test_ethernet_data20:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "ip", interfaceArg2: "access-group", interfaceArg3: "anil", interfaceArg4: "in"}
test_ethernet_data21:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "ip", interfaceArg2: "port", interfaceArg3: "anil" }
test_ethernet_data22:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "bfd", interfaceArg2: "interval", interfaceArg3: 55, interfaceArg4: 55, interfaceArg5: 33}
test_ethernet_data23:
- {interfaceOption: 'ethernet', interfaceRange: 33, interfaceArg1: "bfd", interfaceArg2: "ipv4", interfaceArg3: "authentication", interfaceArg4: "meticulous-keyed-md5", interfaceArg5: "key-chain", interfaceArg6: "mychain"}
test_ethernet_data24:
- {interfaceOption: 'ethernet', interfaceRange: "1/1-2", interfaceArg1: "aggregation-group", interfaceArg2: 33, interfaceArg3: "on"}

@ -1,94 +0,0 @@
# Ansible Role: cnos_facts_sample - Displays switch information
---
<add role description below>
This role is an example of using the *cnos_facts.py* Lenovo module in the context of CNOS switch configuration. This module allows you to view the switch information. It executes the **display sys-info** CLI command on a switch and returns a file containing all the system information of the target network device.
The results of the operation can be viewed in results directory.
For more details, see [Lenovo modules for Ansible: cnos_facts](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_facts.html&cp=0_3_1_0_4_0).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_facts.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_facts_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_facts_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_facts_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do Show Sys Info
hosts: cnos_facts_sample
gather_facts: no
connection: local
roles:
- cnos_facts_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_facts_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_facts_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos

@ -1,7 +0,0 @@
# This contain sample show sys info tasks
---
- name: Test Sys Info
cnos_facts: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} enablePassword='{{item.enablePassword}}' outputfile=./results/cnos_facts_{{ inventory_hostname }}_output.txt
with_items: "{{test_showsysinfo_data}}"
# Completed file

@ -1,3 +0,0 @@
---
test_showsysinfo_data:
- {enablePassword: "anil"}

@ -1,117 +0,0 @@
# Ansible Role: cnos_image_sample - Switch firmware download from a remote server
---
<add role description below>
This role is an example of using the *cnos_image.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with switch firmware images. It provides a way to download a firmware image to a network device from a remote server using FTP, SFTP, TFTP, or SCP.
The first step is to create a directory from where the remote server can be reached. The next step is to provide the full file path of the image's location. Authentication details required by the remote server must be provided as well.
By default, this method makes the newly downloaded firmware image the active image, which will be used by the switch during the next restart.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_image](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_image.html&cp=0_3_1_0_4_2).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`imgType` | Specifies the firmware image type to be downloaded (**all** - both Uboot and OS images, **boot** - only the Uboot image, **os** - only the OS image, **onie** - ONIE image)
`protocol` | Specifies the protocol used by the network device to interact with the remote server from where to download the firmware image (**ftp** - FTP, **sftp** - SFTP, **tftp** - TFTP, **scp** - SCP)
`serverip` | Specifies the IP Address of the remote server from where the software image will be downloaded
`imgpath` | Specifies the full file path of the image located on the remote server (in case the relative path is used as the variable value, the root folder for the user of the server needs to be specified)
`serverusername` | Configures the username for the server relating to the protocol used
`serverpassword` | Configures the password for the server relating to the protocol used
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_image.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_image_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_image_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_image_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do image download
hosts: cnos_image_sample
gather_facts: no
connection: local
roles:
- cnos_image_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,17 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_image_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_image_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos imgpath=/root/cnos_images/G8272-10.1.0.112.img
#Use this in case its TFTP as tftpboot is the starting point for tftp
#10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos imgpath="/anil/G8272-10.2.0.34.img

@ -1,16 +0,0 @@
# This contain sample Image download tasks
---
- name: Test Image transfer
cnos_image: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_image_{{ inventory_hostname }}_output.txt protocol='{{item.protocol}}' serverip='{{item.serverip}}' imgpath={{ hostvars[inventory_hostname]['imgpath']}} imgtype='{{item.imgtype}}' serverusername='{{item.serverusername}}' serverpassword='{{item.serverpassword}}'
with_items: "{{test_image_data1}}"
#Root folder will be different for SFTP/SCP and TFTP
#The following task is commented.
#Before trying this, please change in /etc/ansible/hosts file
#and place an image with reference to your tftp-root folder
#- name: Test Image tftp
# cnos_image: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_image_{{ inventory_hostname }}_output.txt protocol='{{item.protocol}}' serverip='{{item.serverip}}' imgpath={{ hostvars[inventory_hostname]['imgpath']}} imgtype='{{item.imgtype}}'
# with_items: "{{test_image_data2}}"
# Completed file

@ -1,6 +0,0 @@
---
test_image_data1:
- {protocol: "sftp", serverip: "10.241.106.118", imgtype: "os", serverusername: "root", serverpassword: "root123"}
test_image_data2:
- {protocol: "tftp", serverip: "10.241.106.118", imgtype: "os"}

@ -1,115 +0,0 @@
# Ansible Role: cnos_portchannel_sample - Switch Link Aggregation Group (LAG) configuration
---
<add role description below>
This role is an example of using the *cnos_portchannel.py* Lenovo module in the context of CNOS switch configuration. This module allows you to work with port aggregation related configurations. The operators used are overloaded to ensure control over switch port aggregation configurations.
Apart from the regular device connection related attributes, there are five vLAG arguments which are overloaded variables that will perform further configurations. They are portChArg1, portChArg2, portChArg3, portChArg4, and portChArg5.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_portchannel](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_portchannel.html&cp=0_3_1_0_4_13).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`interfaceRange` | Specifies the interface range that will be part of the LAG
`portChArg1` | This is an overloaded BGP variable. Please refer to the [cnos_portchannel module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_portchannel.html?cp=0_3_1_0_2_14) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **aggregation-group**, **bridge-port**, **description**, **duplex**, **flowcontrol**, **lacp**, **lldp**, **load-interval**, **mac**, **mac-address**, **mac-learn**, **microburst-detection**, **mtu**, **service**, **service-policy**, **shutdown**, **snmp**, **speed**, **storm-control**, **vlan**, **vrrp**, **port-aggregation**.
`portChArg2` | This is an overloaded BGP variable. Please refer to the [cnos_portchannel module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_portchannel.html?cp=0_3_1_0_2_14) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: specify a LAG number, **access**, **mode**, **trunk**, LAG description, **auto**, **full**, **half**, **receive**, **send**, **port-priority**, **suspend-individual**, **timeout**, **transmit**, **trap-notification**, **tlv-select**, load interval delay, **counter**, name for the MAC access group, MAC address in XXXX.XXXX.XXXX format, threshold value, MTU in bytes, instance ID to map to the EVC, **input**, **output**, **copp-system-policy**, **type**, **auto**, 1000, 10000, 40000, **broadcast**, **unicast**, **multicast**, **disable**, **enable**, **egress-only**, virtual router ID, **destination-ip**, **destination-mac**, **destination-port**, **source-dest-ip**, **source-dest-mac**, **source-dest-port**, **source-interface**, **source-ip**, **source-mac**, **source-port**.
`portChArg3` | This is an overloaded BGP variable. Please refer to the [cnos_portchannel module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_portchannel.html?cp=0_3_1_0_2_14) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: **active**, **passive**, **on**, **off**, LACP port priority, **long**, **short**, **link-aggregation**, **mac-phy-status**, **management-address**, **max-frame-size**, **port-description**, **port-protocol-vlan**, **port-vlan**, **power-mdi**, **protocol-identity**, **system-capabilities**, **system-description**, **system-name**, **vid-management**, **vlan-name**, counter for the load interval, the name of the policy to attach, **all**, COPP class name to attach, **qos**, **queuing**, allowed traffic level, **ipv6**, **source-interface**.
`portChArg4` | This is an overloaded BGP variable. Please refer to the [cnos_portchannel module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_portchannel.html?cp=0_3_1_0_2_14) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: load interval delay, name of the QoS policy to attach, **input**, **output**
`portChArg5` | This is an overloaded BGP variable. Please refer to the [cnos_portchannel module documentation](http://ralfss28.labs.lenovo.com:5555/help/topic/com.lenovo.switchmgt.ansible.doc/cnos_portchannel.html?cp=0_3_1_0_2_14) for detailed information on usage. The values of these variables depend on the configuration context and the choices are the following: name of the QoS policy to attach
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_portchannel.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_portchannel_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_portchannel_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_portchannel_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do Port Channel configurations
hosts: cnos_portchannel_sample
gather_facts: no
connection: local
roles:
- cnos_portchannel_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_portchannel_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_portchannel_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos

@ -1,98 +0,0 @@
# This contain sample template execution tasks
---
- name: Test Port Channel - aggregation-group
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data1}}"
- name: Test Port Channel - aggregation-group - Interface Range
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data24}}"
- name: Test Port Channel - bridge-port
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data2}}"
- name: Test Port Channel - bridgeport mode
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data3}}"
- name: Test Port Channel - Description
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_portchannel_data4}}"
- name: Test Port Channel - Duplex
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_portchannel_data5}}"
- name: Test Port Channel - flowcontrol
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data6}}"
- name: Test Port Channel - lacp
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data7}}"
- name: Test Port Channel - lldp
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data8}}"
- name: Test Port Channel - load-interval
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}'
with_items: "{{test_portchannel_data9}}"
#- name: Test Port Channel - mac
# cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
# with_items: "{{test_portchannel_data10}}"
- name: Test Port Channel - microburst-detection
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_portchannel_data11}}"
- name: Test Port Channel - mtu
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_portchannel_data12}}"
- name: Test Port Channel - service-policy
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data13}}"
- name: Test Port Channel - speed
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_portchannel_data14}}"
- name: Test Port Channel - storm
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data15}}"
#- name: Test Port Channel - vlan
# cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
# with_items: "{{test_portchannel_data16}}"
- name: Test Port Channel - vrrp
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}'
with_items: "{{test_portchannel_data17}}"
- name: Test Port Channel - spanning tree1
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data18}}"
- name: Test Port Channel - spanning tree 2
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}' interfaceArg5='{{item.interfaceArg5}}'
with_items: "{{test_portchannel_data19}}"
- name: Test Port Channel - ip1
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}'
with_items: "{{test_portchannel_data20}}"
- name: Test Port Channel - ip2
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}'
with_items: "{{test_portchannel_data21}}"
- name: Test Port Channel - bfd
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}' interfaceArg5='{{item.interfaceArg5}}'
with_items: "{{test_portchannel_data22}}"
- name: Test Port Channel - bfd
cnos_portchannel: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_portchannel_{{ inventory_hostname }}_output.txt interfaceRange='{{item.interfaceRange}}' interfaceArg1='{{item.interfaceArg1}}' interfaceArg2='{{item.interfaceArg2}}' interfaceArg3='{{item.interfaceArg3}}' interfaceArg4='{{item.interfaceArg4}}' interfaceArg5='{{item.interfaceArg5}}' interfaceArg6='{{item.interfaceArg6}}'
with_items: "{{test_portchannel_data23}}"
## Completed file

@ -1,49 +0,0 @@
---
test_portchannel_data1:
- {interfaceRange: 33, interfaceArg1: "aggregation-group", interfaceArg2: 33, interfaceArg3: "on"}
test_portchannel_data2:
- {interfaceRange: 33, interfaceArg1: "bridge-port", interfaceArg2: "access", interfaceArg3: 33}
test_portchannel_data3:
- {interfaceRange: 33, interfaceArg1: "bridge-port", interfaceArg2: "mode", interfaceArg3: "access"}
test_portchannel_data4:
- {interfaceRange: 33, interfaceArg1: "description", interfaceArg2: "Hentammoo "}
test_portchannel_data5:
- {interfaceRange: 2, interfaceArg1: "duplex", interfaceArg2: "auto"}
test_portchannel_data6:
- {interfaceRange: 33, interfaceArg1: "flowcontrol", interfaceArg2: "send", interfaceArg3: "off"}
test_portchannel_data7:
- {interfaceRange: 33, interfaceArg1: "lacp", interfaceArg2: "port-priority", interfaceArg3: 33}
test_portchannel_data8:
- {interfaceRange: 33, interfaceArg1: "lldp", interfaceArg2: "tlv-select", interfaceArg3: "max-frame-size"}
test_portchannel_data9:
- {interfaceRange: 33, interfaceArg1: "load-interval", interfaceArg2: "counter", interfaceArg3: 2, interfaceArg4: 33 }
test_portchannel_data10:
- {interfaceRange: 33, interfaceArg1: "mac", interfaceArg2: "copp-system-acl-vlag-hc"}
test_portchannel_data11:
- {interfaceRange: 33, interfaceArg1: "microburst-detection", interfaceArg2: 25}
test_portchannel_data12:
- {interfaceRange: 33, interfaceArg1: "mtu", interfaceArg2: 66}
test_portchannel_data13:
- {interfaceRange: 33, interfaceArg1: "service-policy", interfaceArg2: "input", interfaceArg3: "Anil"}
test_portchannel_data14:
- {interfaceRange: 13, interfaceArg1: "speed", interfaceArg2: "auto"}
test_portchannel_data15:
- {interfaceRange: 33, interfaceArg1: "storm-control", interfaceArg2: "broadcast", interfaceArg3: 12.5 }
test_portchannel_data16:
- {interfaceRange: 33, interfaceArg1: "vlan", interfaceArg2: "disable"}
test_portchannel_data17:
- {interfaceRange: 33, interfaceArg1: "vrrp", interfaceArg2: 33}
test_portchannel_data18:
- {interfaceRange: 33, interfaceArg1: "spanning-tree", interfaceArg2: "bpduguard", interfaceArg3: "enable"}
test_portchannel_data19:
- {interfaceRange: 33, interfaceArg1: "spanning-tree", interfaceArg2: "mst", interfaceArg3: "33-35", interfaceArg4: "cost", interfaceArg5: 33}
test_portchannel_data20:
- {interfaceRange: 33, interfaceArg1: "ip", interfaceArg2: "access-group", interfaceArg3: "anil", interfaceArg4: "in"}
test_portchannel_data21:
- {interfaceRange: 33, interfaceArg1: "ip", interfaceArg2: "port", interfaceArg3: "anil" }
test_portchannel_data22:
- {interfaceRange: 33, interfaceArg1: "bfd", interfaceArg2: "interval", interfaceArg3: 55, interfaceArg4: 55, interfaceArg5: 33}
test_portchannel_data23:
- {interfaceRange: 33, interfaceArg1: "bfd", interfaceArg2: "ipv4", interfaceArg3: "authentication", interfaceArg4: "meticulous-keyed-md5", interfaceArg5: "key-chain", interfaceArg6: "mychain"}
test_portchannel_data24:
- {interfaceRange: "1/1-2", interfaceArg1: "aggregation-group", interfaceArg2: 33, interfaceArg3: "on"}

@ -1,117 +0,0 @@
# Ansible Role: cnos_rollback_sample - Rolls back the configuration of a switch from a remote server
---
<add role description below>
This role is an example of using the *cnos_rollback.py* Lenovo module in the context of CNOS switch configuration.This module allows you to work with switch configurations. It provides a way to roll back configurations of a switch from a remote server. This is achieved by using startup or running configurations of the target device that were previously backed up to a remote server using FTP, SFTP, TFTP, or SCP.
The first step is to create a directory from where the remote server can be reached. The next step is to provide the full file path of the backup configuration's location. Authentication details required by the remote server must be provided as well.
By default, this method overwrites the switch's configuration file with the newly downloaded file.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_rollback](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_rollback.html&cp=0_3_1_0_4_5).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
The values of the variables used need to be modified to fit the specific scenario in which you are deploying the solution. To change the values of the variables, you need to visits the *vars* directory of each role and edit the *main.yml* file located there. The values stored in this file will be used by Ansible when the template is executed.
The syntax of *main.yml* file for variables is the following:
```
<template variable>:<value>
```
You will need to replace the `<value>` field with the value that suits your topology. The `<template variable>` fields are taken from the template and it is recommended that you leave them unchanged.
Variable | Description
--- | ---
`configType` | Specifies the type of configuration which will be used for the rolling back process (**running-config** - running configuration, **startup-config** - startup configuration)
`protocol` | Specifies the protocol used by the network device to interact with the remote server from where to download the backup configuration (**ftp** - FTP, **sftp** - SFTP, **tftp** - TFTP, **scp** - SCP)
`serverip` | Specifies the IP Address of the remote server from where the backup configuration will be downloaded
`rcpath` | Specifies the full file path where the configuration file located on the remote server (in case the relative path is used as the variable value, the root folder for the user of the server needs to be specified)
`serverusername` | Configures the username for the server relating to the protocol used
`serverpassword` | Configures the password for the server relating to the protocol used
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_rollback.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_rollback_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_rollback_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_rollback_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do rollback of configurations
hosts: cnos_rollback_sample
gather_facts: no
connection: local
roles:
- cnos_rollback_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,18 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_rollback_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_rollback_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos rcpath=/root/cnos_config/G8272-running-config.txt
#Use this in case its TFTP as tftpboot folder is the starting point for tftp
#10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos rcpath=/anil/G8272-running-config.txt

@ -1,25 +0,0 @@
# This contain sample config Roll Back execution tasks
---
- name: Test Rollback of config - Running config
cnos_rollback: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_rollback_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}} serverusername='{{item.serverusername}}' serverpassword='{{item.serverpassword}}'
with_items: "{{test_rollback_data1}}"
- name: Test Rollback of config - Startup config
cnos_rollback: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_rollback_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}} serverusername='{{item.serverusername}}' serverpassword='{{item.serverpassword}}'
with_items: "{{test_rollback_data2}}"
#Root folder will be different for SFTP/SCP and TFTP
#The following task is commented.
#Before trying this, please change in /etc/ansible/hosts file
#and place an config file with reference to your tftp-root folder
#- name: Test Rollback of config - Running config - TFTP
# cnos_rollback: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_rollback_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}}
# with_items: "{{test_rollback_data3}}"
#- name: Test Rollback of config - Startup config - TFTP
# cnos_rollback: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_rollback_{{ inventory_hostname }}_output.txt configType='{{item.configType}}' protocol='{{item.protocol}}' serverip='{{item.serverip}}' rcpath={{ hostvars[inventory_hostname]['rcpath']}}
# with_items: "{{test_rollback_data4}}"
# Completed file

@ -1,12 +0,0 @@
---
test_rollback_data1:
- {configType: running-config, protocol: "sftp", serverip: "10.241.106.118", serverusername: "root", serverpassword: "root123"}
test_rollback_data2:
- {configType: startup-config, protocol: "sftp", serverip: "10.241.106.118", serverusername: "root", serverpassword: "root123"}
test_rollback_data3:
- {configType: running-config, protocol: "tftp", serverip: "10.241.106.118"}
test_rollback_data4:
- {configType: startup-config, protocol: "tftp", serverip: "10.241.106.118"}

@ -1,94 +0,0 @@
# Ansible Role: cnos_save_sample - Saving the switch running configuration
---
<add role description below>
This role is an example of using the *cnos_save.py* Lenovo module in the context of CNOS switch configuration. This module allows you to copy the running configuration of a switch over its startup configuration. It is recommended to use this module shortly after any major configuration changes so they persist after a switch restart.
The results of the operation can be viewed in *results* directory.
For more details, see [Lenovo modules for Ansible: cnos_save](http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_save.html&cp=0_3_1_0_4_3).
## Requirements
---
<add role requirements information below>
- Ansible version 2.2 or later ([Ansible installation documentation](https://docs.ansible.com/ansible/intro_installation.html))
- Lenovo switches running CNOS version 10.2.1.0 or later
- an SSH connection to the Lenovo switch (SSH must be enabled on the network device)
## Role Variables
---
<add role variables information below>
Available variables are listed below, along with description.
The following are mandatory inventory variables:
Variable | Description
--- | ---
`username` | Specifies the username used to log into the switch
`password` | Specifies the password used to log into the switch
`enablePassword` | Configures the password used to enter Global Configuration command mode on the switch (this is an optional parameter)
`hostname` | Searches the hosts file at */etc/ansible/hosts* and identifies the IP address of the switch on which the role is going to be applied
`deviceType` | Specifies the type of device from where the configuration will be backed up (**g8272_cnos** - G8272, **g8296_cnos** - G8296)
## Dependencies
---
<add dependencies information below>
- username.iptables - Configures the firewall and blocks all ports except those needed for web server and SSH access.
- username.common - Performs common server configuration.
- cnos_save.py - This modules needs to be present in the *library* directory of the role.
- cnos.py - This module needs to be present in the PYTHONPATH environment variable set in the Ansible system.
- /etc/ansible/hosts - You must edit the */etc/ansible/hosts* file with the device information of the switches designated as leaf switches. You may refer to *cnos_save_sample_hosts* for a sample configuration.
Ansible keeps track of all network elements that it manages through a hosts file. Before the execution of a playbook, the hosts file must be set up.
Open the */etc/ansible/hosts* file with root privileges. Most of the file is commented out by using **#**. You can also comment out the entries you will be adding by using **#**. You need to copy the content of the hosts file for the role into the */etc/ansible/hosts* file. The sample hosts file for the role is located in the main directory.
```
[cnos_save_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos
10.241.107.40 username=<username> password=<password> deviceType=g8272_cnos
```
**Note:** You need to change the IP addresses to fit your specific topology. You also need to change the `<username>` and `<password>` to the appropriate values used to log into the specific Lenovo network devices.
## Example Playbook
---
<add playbook samples below>
To execute an Ansible playbook, use the following command:
```
ansible-playbook cnos_save_sample.yml -vvv
```
`-vvv` is an optional verbose command that helps identify what is happening during playbook execution. The playbook for each role is located in the main directory of the solution.
```
- name: Module to do save configurations
hosts: cnos_save_sample
gather_facts: no
connection: local
roles:
- cnos_save_sample
```
## License
---
<add license information below>
Copyright (C) 2017 Lenovo, Inc.
This file is part of Ansible
Ansible is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Ansible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Ansible. If not, see <http://www.gnu.org/licenses/>.

@ -1,15 +0,0 @@
# You have to paste this dummy information in /etc/ansible/hosts
# Notes:
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
#
# In the /etc/ansible/hosts file u have to enter [cnos_save_sample] tag
# Following you should specify IP Addresses details
# Please change <username> and <password> with appropriate value for your switch.
[cnos_save_sample]
10.241.107.39 username=<username> password=<password> deviceType=g8272_cnos

@ -1,18 +0,0 @@
# This contain sample template execution tasks
---
- name: Test Save
cnos_save: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_save_{{ inventory_hostname }}_output.txt
with_items: "{{cnos_save_data1}}"
- name: Test Reset to factory
cnos_factory: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_save_{{ inventory_hostname }}_output.txt
with_items: "{{cnos_save_data2}}"
- name: Test Again save
cnos_save: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_save_{{ inventory_hostname }}_output.txt
with_items: "{{cnos_save_data3}}"
- name: Test Reload
cnos_reload: host={{ inventory_hostname }} username={{ hostvars[inventory_hostname]['username']}} password={{ hostvars[inventory_hostname]['password']}} deviceType={{ hostvars[inventory_hostname]['deviceType']}} outputfile=./results/cnos_save_{{ inventory_hostname }}_output.txt
with_items: "{{cnos_save_data4}}"
# Completed file

@ -1,9 +0,0 @@
---
cnos_save_data1:
- {}
cnos_save_data2:
- {}
cnos_save_data3:
- {}
cnos_save_data4:
- {}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save