Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions ansible/library/conn_graph_facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
DOCUMENTATION='''
module: conn_graph_facts.py
version_added: 2.0
short_description: Retrive lab fanout switches physical and vlan connections
short_description: Retrive lab fanout switches physical and vlan connections
Description:
Retrive lab fanout switches physical and vlan connections
add to Ansible facts
Expand All @@ -23,7 +23,7 @@
Ansible_facts:
device_info: The device(host) type and hwsku
device_conn: each physical connection of the device(host)
device_vlan_range: all configured vlan range for the device(host)
device_vlan_range: all configured vlan range for the device(host)
device_port_vlans: detailed vlanids for each physical port and switchport mode
server_links: each server port vlan ids

Expand All @@ -34,35 +34,35 @@

return:
"device_info": {
"ManagementIp": "10.251.0.76/24",
"HwSku": "Arista-7260QX-64",
"ManagementIp": "10.251.0.76/24",
"HwSku": "Arista-7260QX-64",
"Type": "FanoutLeaf"
},
"device_conn": [
{
"StartPort": "Ethernet0",
"EndPort": "Ethernet33",
"StartDevice": "str-s6000-on-1",
"VlanID": "233",
"BandWidth": "40000",
"VlanMode": "Access",
"StartPort": "Ethernet0",
"EndPort": "Ethernet33",
"StartDevice": "str-s6000-on-1",
"VlanID": "233",
"BandWidth": "40000",
"VlanMode": "Access",
"EndDevice": "str-7260-01"
},
{...}
],
"device_vlan_range": {
"VlanRange": "201-980,1041-1100"
},
},
"device_vlan_port:=: {
...
"Ethernet44": {
"vlanids": "801-860",
"vlanids": "801-860",
"mode": "Trunk"
},
},
"Ethernet42": {
"vlanids": "861-920",
"vlanids": "861-920",
"mode": "Trunk"
},......
},......
}


Expand Down Expand Up @@ -240,7 +240,11 @@ def main():
m_args = module.params
hostname = m_args['host']
try:
lab_graph = Parse_Lab_Graph(LAB_GRAPHFILE_PATH+LAB_CONNECTION_GRAPH_FILE)
if m_args['filename']:
filename = m_args['filename']
else:
filename = LAB_GRAPHFILE_PATH + LAB_CONNECTION_GRAPH_FILE
lab_graph = Parse_Lab_Graph(filename)
lab_graph.parse_graph()
dev = lab_graph.get_host_device_info(hostname)
if dev is None:
Expand Down
31 changes: 31 additions & 0 deletions tests/ansible_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
""" This module provides few pytest-ansible fixtures overridden """

import pytest

# Here we override ansible_adhoc fixture from pytest-ansible plugin to overcome
# scope limitation issue; since we want to be able to use ansible_adhoc in module/class scope
# fixtures we have to override the scope here in global conftest.py
# Let's have it with module scope for now, so if something really breaks next test module run will have
# this fixture reevaluated
@pytest.fixture(scope='module')
def ansible_adhoc(request):
"""Return an inventory initialization method."""
plugin = request.config.pluginmanager.getplugin("ansible")

def init_host_mgr(**kwargs):
return plugin.initialize(request.config, request, **kwargs)
return init_host_mgr


# Same as for ansible_adhoc, let's have localhost fixture with session scope
# as it feels that during session run the localhost object should persist unchanged.
# Also, we have autouse=True here to force pytest to evaluate localhost fixture to overcome
# some hidden dependency between localhost and ansible_adhoc (even with default scope) (FIXME)
@pytest.fixture(scope='session', autouse=True)
def localhost(request):
"""Return a host manager representing localhost."""
# NOTE: Do not use ansible_adhoc as a dependent fixture since that will assert specific command-line parameters have
# been supplied. In the case of localhost, the parameters are provided as kwargs below.
plugin = request.config.pluginmanager.getplugin("ansible")
return plugin.initialize(request.config, request, inventory='localhost,', connection='local',
host_pattern='localhost').localhost
43 changes: 43 additions & 0 deletions tests/ansible_host.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from ansible.plugins import callback_loader
from ansible.errors import AnsibleError

def dump_ansible_results(results, stdout_callback='yaml'):
cb = callback_loader.get(stdout_callback)
return cb._dump_results(results) if cb else results

class AnsibleModuleException(AnsibleError):

"""Sub-class AnsibleError when module exceptions occur."""

def __init__(self, msg, results=None):
super(AnsibleModuleException, self).__init__(msg)
self.results = results

def __str__(self):
return "{}\nAnsible Results => {}".format(self.message, dump_ansible_results(self.results))

class AnsibleHost(object):
""" wrapper for ansible host object """

def __init__(self, ansible_adhoc, hostname, is_local=False):
if is_local:
self.host = ansible_adhoc(inventory='localhost', connection='local')[hostname]
else:
self.host = ansible_adhoc(become=True)[hostname]
self.hostname = hostname

def __getattr__(self, item):
self.module_name = item
self.module = getattr(self.host, item)

return self._run

def _run(self, *module_args, **complex_args):

module_ignore_errors = complex_args.pop('module_ignore_errors', False)

res = self.module(*module_args, **complex_args)[self.hostname]
if res.is_failed and not module_ignore_errors:
raise AnsibleModuleException("run module {} failed".format(self.module_name), res)

return res
24 changes: 24 additions & 0 deletions tests/bgp_speaker/announce_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python

import cPickle
import os
import time
import sys

with open(sys.argv[1]) as f:
routes = f.readlines()

routes=[x.strip() for x in routes]
ports = set()

for route in routes:
[command, port] = route.split(";")
port = port.strip()
ports.add(port)
os.system('curl -s --form "command=%s" http://localhost:%s/' % (command, port))

for n in range(0, 20):
time.sleep(10)
for port in ports:
os.system('curl -s --form "command=flush route" http://localhost:%s/' % port)

3 changes: 3 additions & 0 deletions tests/bgp_speaker/bgp_speaker_route.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
0.0.0.0/0 {% for portchannel, v in minigraph_portchannels.iteritems() %}[{% for member in v.members %}{{ '%d' % minigraph_port_indices[member]}}{% if not loop.last %} {% endif %}{% endfor %}]{% if not loop.last %} {% endif %}{% endfor %}

{{announce_prefix}} {% for vlan, v in minigraph_vlans.iteritems() %}{% for member in v.members %}[{{ '%d' % minigraph_port_indices[member]}}]{% if not loop.last %} {% endif %}{% endfor %}{% if not loop.last %} {% endif %}{% endfor %}
24 changes: 24 additions & 0 deletions tests/bgp_speaker/config.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
group exabgp {
process dump {
encoder json;
receive {
parsed;
update;
}
run /usr/bin/python {{ helper_dir }}/dump.py;
}

process http-api {
run /usr/bin/python {{ helper_dir }}/http_api.py {{ port_num[cidx] }};
}

neighbor {{ lo_addr }} {
router-id {{ speaker_ip }};
local-address {{ speaker_ip }};
peer-as {{ peer_asn }};
local-as {{ my_asn }};
auto-flush false;
group-updates true;
}

}
16 changes: 16 additions & 0 deletions tests/bgp_speaker/dump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env python

from sys import stdin
import json
import os
import sys

while True:
try:
line = stdin.readline()
obj = json.loads(line)
f = open("/root/exabgp/" + obj["neighbor"]["ip"], "a")
print >> f, line,
f.close()
except:
continue
16 changes: 16 additions & 0 deletions tests/bgp_speaker/http_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from flask import Flask, request
import sys

app = Flask(__name__)

# Setup a command route to listen for prefix advertisements
@app.route('/', methods=['POST'])
def run_command():
command = request.form['command']
sys.stdout.write('%s\n' % command)
sys.stdout.flush()
return 'OK\n'

if __name__ == '__main__':
app.run(port=sys.argv[1])

3 changes: 3 additions & 0 deletions tests/bgp_speaker/routes.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
neighbor {{ lo_addr }} announce route {{ announce_prefix }} next-hop {{ vlan_ips[1].split('/')[0] }};{{ port_num[0] }}
neighbor {{ lo_addr }} announce route {{ announce_prefix }} next-hop {{ vlan_ips[2].split('/')[0] }};{{ port_num[1] }}
neighbor {{ lo_addr }} announce route {{ peer_range }} next-hop {{ vlan_ips[0].split('/')[0] }};{{ port_num[2] }}
20 changes: 20 additions & 0 deletions tests/bgp_speaker/start.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash -ex

ifconfig eth{{ '%d' % (vlan_ports[0]) }} {{ vlan_ips[0] }}
ifconfig eth{{ '%d' % (vlan_ports[0]) }}:0 {{ speaker_ips[0] }}
ifconfig eth{{ '%d' % (vlan_ports[0]) }}:1 {{ speaker_ips[1] }}

{% set intf = 'eth%d' % (vlan_ports[1]) %}
ifconfig {{intf}} {{ vlan_ips[1] }}
# i=0; until [ $i -eq 10 ] || ping {{ vlan_addr }} -I {{intf}} -c 1 >/dev/null 2>&1; do i=`expr $i + 1`; done &

{% set intf = 'eth%d' % (vlan_ports[2]) %}
ifconfig {{intf}} {{ vlan_ips[2] }}
# i=0; until [ $i -eq 10 ] || ping {{ vlan_addr }} -I {{intf}} -c 1 >/dev/null 2>&1; do i=`expr $i + 1`; done &

ip route flush {{ lo_addr }}/{{ lo_addr_prefixlen }}
ip route add {{ lo_addr }}/{{ lo_addr_prefixlen }} via {{ vlan_addr }}

env exabgp.daemon.user=root nohup exabgp {{ exabgp_dir }}/{{ cfnames[0] }} >/dev/null 2>&1 &
env exabgp.daemon.user=root nohup exabgp {{ exabgp_dir }}/{{ cfnames[1] }} >/dev/null 2>&1 &
env exabgp.daemon.user=root nohup exabgp {{ exabgp_dir }}/{{ cfnames[2] }} >/dev/null 2>&1 &
Empty file added tests/common/__init__.py
Empty file.
Loading