diff --git a/mars/config.py b/mars/config.py index bb7f08578..9a4fc6f66 100755 --- a/mars/config.py +++ b/mars/config.py @@ -22,7 +22,7 @@ if socket.gethostname() == 'AutoTestMars': INI_FILE = "auto-test.ini" elif socket.gethostname() == 'Mars-charles': - INI_FILE = "mars-charles.ini" + INI_FILE = "mars-charles-58.ini" elif socket.gethostname() == 'ubuntu-mars': INI_FILE = "mars-mini-pc.ini" @@ -52,6 +52,8 @@ def create_device(conf, device_name): 'mgmtPort': conf.get(device_name, 'mgmtPort'), 'front_port_A': int(conf.get(device_name, 'front_port_A')), 'front_port_B': int(conf.get(device_name, 'front_port_B')), + 'front_port_C': int(conf.get(device_name, 'front_port_C')), + 'front_port_D': int(conf.get(device_name, 'front_port_D')), } return device @@ -88,25 +90,41 @@ def create_remote_power(conf, rp_name): host0 = { 'id': 'host0', 'mac': '00:00:01:00:00:01', - 'ip': '' + 'ip': '', + 'mgmt_ip': '192.168.40.117', + 'username': 'mars', + 'password': 'accton', + 'nic_name': 'enp1s0' } host1 = { 'id': 'host1', 'mac': '00:00:01:00:00:02', - 'ip': '' + 'ip': '', + 'mgmt_ip': '192.168.40.118', + 'username': 'mars', + 'password': 'accton', + 'nic_name': 'enp1s0' } host2 = { 'id': 'host2', 'mac': '00:00:01:00:00:03', - 'ip': '' + 'ip': '', + 'mgmt_ip': '192.168.40.63', + 'username': 'mars', + 'password': 'accton', + 'nic_name': 'enp1s0' } host3 = { 'id': 'host3', 'mac': '00:00:01:00:00:04', - 'ip': '' + 'ip': '', + 'mgmt_ip': '192.168.40.113', + 'username': 'mars', + 'password': 'accton', + 'nic_name': 'enp6s16' } external_router0 = { diff --git a/mars/ini/mars-charles-58.ini b/mars/ini/mars-charles-58.ini index 2093ac81c..d555d1359 100755 --- a/mars/ini/mars-charles-58.ini +++ b/mars/ini/mars-charles-58.ini @@ -13,6 +13,8 @@ remotePowerIp = 192.168.40.171 remotePowerPlugId = A front_port_A = 0 front_port_B = 0 +front_port_C = 0 +front_port_D = 0 [spine1] id = rest:192.168.40.170:80 name = spine1 @@ -28,6 +30,8 @@ remotePowerIp = 192.168.40.171 remotePowerPlugId = B front_port_A = 0 front_port_B = 0 +front_port_C = 0 +front_port_D = 0 [leaf0] id = rest:192.168.40.168:80 name = leaf0 @@ -43,6 +47,8 @@ remotePowerIp = 192.168.40.171 remotePowerPlugId = C front_port_A = 46 front_port_B = 48 +front_port_C = 45 +front_port_D = 47 [leaf1] id = rest:192.168.40.166:80 name = leaf1 @@ -58,3 +64,5 @@ remotePowerIp = 192.168.40.171 remotePowerPlugId = D front_port_A = 46 front_port_B = 48 +front_port_C = 45 +front_port_D = 47 \ No newline at end of file diff --git a/mars/test_vrf.py b/mars/test_vrf.py new file mode 100644 index 000000000..800d0bb4a --- /dev/null +++ b/mars/test_vrf.py @@ -0,0 +1,131 @@ +""" +ref: http://docs.python-requests.org/zh_CN/latest/user/quickstart.html + +Test TenantLogicalRouter RestAPI. + +Test environment + + +--------+ +--------+ + | spine0 | | spine1 | + +--------+ +--------+ + 49 | | 50 49 | | 50 + | +------------+ | + 49 | | 50 49 | | 50 + +--------+ +--------+ + | leaf0 | | leaf1 | + +--------+ +--------+ + | | | | + p0 p1 p2 p3 + | | | | + host0 host1 host2 host3 + +p0: port A of leaf0 +p1: port B of leaf0 +p2: port A of leaf1 +p3: port B of leaf1 + +""" + + +import oftest.base_tests as base_tests +import config as cfg +import requests +import time +import utils +import paramiko +from oftest import config +from oftest.testutils import * +from utils import * + +URL = cfg.API_BASE_URL +LOGIN = cfg.LOGIN +AUTH_TOKEN = 'BASIC ' + LOGIN +GET_HEADER = {'Authorization': AUTH_TOKEN} +POST_HEADER = {'Authorization': AUTH_TOKEN, 'Content-Type': 'application/json'} + + +class VRF(base_tests.SimpleDataPlane): + def setUp(self): + base_tests.SimpleDataPlane.setUp(self) + + setup_configuration() + port_configuration() + + def tearDown(self): + base_tests.SimpleDataPlane.tearDown(self) + + +class MultipleTenant(VRF): + """ + Test multiple tenant with VRF feature + """ + + def runTest(self): + ports = sorted(config["port_map"].keys()) + + s1_ip = '192.168.10.1' + s2_ip = '192.168.20.1' + ports = sorted(config["port_map"].keys()) + + t1 = ( + Tenant('t1') + .segment('s1', 'vlan', [s1_ip], 100) + .segment_member(SegmentMember('s1', cfg.leaf0['id']).ports([cfg.leaf0['portC'].name])) + .segment('s2', 'vlan', [s2_ip], 200) + .segment_member(SegmentMember('s2', cfg.leaf1['id']).ports([cfg.leaf1['portC'].name])) + .build() + ) + + t2 = ( + Tenant('t2') + .segment('s1', 'vlan', [s1_ip], 101) + .segment_member(SegmentMember('s1', cfg.leaf0['id']).ports([cfg.leaf0['portD'].name])) + .segment('s2', 'vlan', [s2_ip], 201) + .segment_member(SegmentMember('s2', cfg.leaf1['id']).ports([cfg.leaf1['portD'].name])) + .build() + ) + + wait_for_system_stable() + + lrouter_r1 = ( + LogicalRouter('r1', 't1') + .interfaces(['s1', 's2']) + .build() + ) + + wait_for_system_stable() + + lrouter_r2 = ( + LogicalRouter('r2', 't2') + .interfaces(['s1', 's2']) + .build() + ) + + wait_for_system_stable() + + cfg.host0['ip'] = '192.168.10.10' + cfg.host1['ip'] = '192.168.20.10' + cfg.host2['ip'] = '192.168.10.20' + cfg.host3['ip'] = '192.168.20.20' + + testhost_configuration() + + route_add(cfg.host0, '192.168.20.0', s1_ip) + route_add(cfg.host1, '192.168.10.0', s2_ip) + route_add(cfg.host2, '192.168.20.0', s1_ip) + route_add(cfg.host3, '192.168.10.0', s2_ip) + + ping_result = ping_test(cfg.host0, cfg.host1['ip']) + + assert(ping_verify('64 bytes from ' + + cfg.host1['ip'], ping_result)) + + ping_result1 = ping_test(cfg.host2, cfg.host3['ip']) + + assert(ping_verify('64 bytes from ' + + cfg.host3['ip'], ping_result1)) + + lrouter_r1.destroy() + lrouter_r2.destroy() + t1.destroy() + t2.destroy() diff --git a/mars/utils.py b/mars/utils.py index 1e381641f..d8e054115 100755 --- a/mars/utils.py +++ b/mars/utils.py @@ -7,6 +7,8 @@ import requests import config as cfg import oftest +import paramiko +import re from oftest.testutils import * from telnetlib import Telnet from scapy.layers.l2 import * @@ -36,6 +38,42 @@ def wait_for_seconds(sec): time.sleep(sec) +def route_add(host, subnet, gateway): + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(host['mgmt_ip'], 22, username=host['username'], + password=host['password'], timeout=5) + stdin, stdout, stderr = client.exec_command( + 'sudo route add -net {}/24 gw {}'.format(subnet, gateway)) + client.close() + + +def ping_test(host, target_ip, debug=False): + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(host['mgmt_ip'], 22, username=host['username'], + password=host['password'], timeout=30) + stdin, stdout, stderr = client.exec_command( + 'ping -c 20 ' + target_ip) + ping_result = stdout.read() + client.close() + + if debug == True: + print(ping_result) + + return ping_result + + +def ping_verify(expected_str, content, debug=False): + if debug == True: + print(content) + + if re.search(expected_str, content): + return True + else: + return False + + def get_master_spine(dataplane, sender, target_ip, port, debug=False, count=5): arp_request = simple_arp_packet( pktlen=42, @@ -163,6 +201,16 @@ def port_configuration(): .tagged(False) .nos(cfg.leaf0['nos']) ) + cfg.leaf0['portC'] = ( + Port(cfg.leaf0['front_port_C']) + .tagged(False) + .nos(cfg.leaf0['nos']) + ) + cfg.leaf0['portD'] = ( + Port(cfg.leaf0['front_port_D']) + .tagged(False) + .nos(cfg.leaf0['nos']) + ) cfg.leaf1['portA'] = ( Port(cfg.leaf1['front_port_A']) .tagged(False) @@ -173,6 +221,28 @@ def port_configuration(): .tagged(False) .nos(cfg.leaf1['nos']) ) + cfg.leaf1['portC'] = ( + Port(cfg.leaf1['front_port_C']) + .tagged(False) + .nos(cfg.leaf1['nos']) + ) + cfg.leaf1['portD'] = ( + Port(cfg.leaf1['front_port_D']) + .tagged(False) + .nos(cfg.leaf1['nos']) + ) + + +def testhost_configuration(): + for host in [cfg.host0, cfg.host1, cfg.host2, cfg.host3]: + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(host['mgmt_ip'], 22, username=host['username'], + password=host['password'], timeout=10) + stdin, stdout, stderr = client.exec_command( + 'sh reset_route.sh ' + host['nic_name'] + ' ' + host['ip']) + # print(stdout.read()) + client.close() def config_exists(device):