def check_uplink(vm, vm_host, fip, dst_port): quagga_cont = service.get_container_by_hostname('quagga0') vm_cont = service.get_container_by_hostname(vm_host) # First check Quagga to VM. vm_listen_cmd =\ 'ip netns exec %s nc -l %d' % (vm.get_vm_ns(), dst_port) quagga_send_cmd =\ "/bin/sh -c 'echo test | nc -w 5 %s %d'" % (fip, dst_port) result, exec_id = vm_cont.exec_command(vm_listen_cmd, stream=True) quagga_cont.exec_command(quagga_send_cmd) # nc -l has no timeout mechanism, so make sure the process completed # before we try to read the result stream. vm_cont.check_exit_status(exec_id, timeout=5) assert_that(result.next(), equal_to('test\n')) # Now check VM to quagga. quagga_listen_cmd = 'nc -l %d' % dst_port vm_send_cmd =\ "ip netns exec %s /bin/sh -c 'echo test | nc -w 5 1.1.1.1 %d'" \ % (vm.get_vm_ns(), dst_port) result, exec_id = quagga_cont.exec_command(quagga_listen_cmd, stream=True) vm_cont.exec_command(vm_send_cmd) quagga_cont.check_exit_status(exec_id, timeout=5) assert_that(result.next(), equal_to('test\n'))
def check_uplink(vm, vm_host, fip, dst_port): quagga_cont = service.get_container_by_hostname('quagga0') vm_cont = service.get_container_by_hostname(vm_host) # First check Quagga to VM. vm_listen_cmd =\ 'ip netns exec %s nc -l %d' % (vm.get_vm_ns(), dst_port) quagga_send_cmd =\ "/bin/sh -c 'echo test | nc -w 5 %s %d'" % (fip, dst_port) result, exec_id = vm_cont.exec_command(vm_listen_cmd, stream=True) quagga_cont.exec_command(quagga_send_cmd) # nc -l has no timeout mechanism, so make sure the process completed # before we try to read the result stream. vm_cont.check_exit_status(exec_id, timeout=5) assert_that(result.next(), equal_to('test\n')) # Now check VM to quagga. quagga_listen_cmd = 'nc -l %d' % dst_port vm_send_cmd =\ "ip netns exec %s /bin/sh -c 'echo test | nc -w 5 1.1.1.1 %d'" \ % (vm.get_vm_ns(), dst_port) result, exec_id = quagga_cont.exec_command(quagga_listen_cmd, stream=True) vm_cont.exec_command(vm_send_cmd) quagga_cont.check_exit_status(exec_id, timeout=5) assert_that(result.next(), equal_to('test\n'))
def build(self, data=None): # Building physical topology with two vms on midolman 1 and one vm on # midolman2 host1 = service.get_container_by_hostname('midolman1') host2 = service.get_container_by_hostname('midolman2') self.add_host_to_tunnel_zone('midolman1', 'tztest2') self.add_host_to_tunnel_zone('midolman2', 'tztest2') vm1data = { 'hw_addr': 'aa:bb:cc:00:00:11', 'ipv4_addr': ['172.16.1.2/24'], 'ipv4_gw': '172.16.1.1' } vm2data = { 'hw_addr': 'aa:bb:cc:00:00:22', 'ipv4_addr': ['172.16.1.3/24'], 'ipv4_gw': '172.16.1.1' } vm1 = host1.create_vmguest(**vm1data) vm2 = host1.create_vmguest(**vm2data) vm3 = host2.create_vmguest(**vm2data) self.addCleanup(host1.destroy_vmguest, vm1) self.addCleanup(host1.destroy_vmguest, vm2) self.addCleanup(host2.destroy_vmguest, vm3) self.set_resource('vm1_host1', vm1) self.set_resource('vm2_host1', vm2) self.set_resource('vm2_host2', vm3)
def start_midolman_agents(): agents = [service.get_container_by_hostname('midolman1'), service.get_container_by_hostname('midolman2')] for agent in agents: agent.start() for agent in agents: agent.wait_for_status("up")
def build(self, binding_data=None, ptm=None): super(QosTopology, self).build(binding_data) ptm.add_host_to_tunnel_zone('midolman1', 'tztest1') ptm.add_host_to_tunnel_zone('midolman2', 'tztest1') self.add_bridge({'name': 'main1'}) self.main_bridge = self.get_bridge('main1') self.main_bridge.add_dhcp_subnet( {'id': 1, 'ipv4_gw': '172.16.1.254', 'network': '172.16.1.0/24'}) self.main_bridge.add_port({'id': 1, 'type': 'exterior'}) self.main_bridge.add_port({'id': 2, 'type': 'exterior'}) self.vm1_port = self.main_bridge.get_port(1) self.vm2_port = self.main_bridge.get_port(2) host1 = service.get_container_by_hostname('midolman1') host2 = service.get_container_by_hostname('midolman2') vm1data = {'hw_addr': 'aa:bb:cc:00:00:11', 'ipv4_addr': ['172.16.1.2/24'], 'ipv4_gw': '172.16.1.1'} vm2data = {'hw_addr': 'aa:bb:cc:00:00:22', 'ipv4_addr': ['172.16.1.3/24'], 'ipv4_gw': '172.16.1.1'} self.vm1 = host1.create_vmguest(**vm1data) self.vm2 = host2.create_vmguest(**vm2data) ptm.addCleanup(host1.destroy_vmguest, self.vm1) ptm.addCleanup(host2.destroy_vmguest, self.vm2) port1_real_id = self.vm1_port.get_real_id() port2_real_id = self.vm2_port.get_real_id() host1.bind_port(self.vm1, port1_real_id) host2.bind_port(self.vm2, port2_real_id) utils.await_port_active(port1_real_id, active=True) utils.await_port_active(port2_real_id, active=True) self.qos_pol1 = self.add_qos_policy( {'name': 'pol1', 'description': 'Description', 'shared': True}) self.qos_pol2 = self.add_qos_policy( {'name': 'pol2', 'description': 'Description Two', 'shared': True}) assert_that(self.qos_pol1) assert_that(self.qos_pol2)
def build(self, binding_data=None, ptm=None): super(QosTopology, self).build(binding_data) ptm.add_host_to_tunnel_zone('midolman1', 'tztest1') ptm.add_host_to_tunnel_zone('midolman2', 'tztest1') self.add_bridge({'name': 'main1'}) self.main_bridge = self.get_bridge('main1') self.main_bridge.add_dhcp_subnet( {'id': 1, 'ipv4_gw': '172.16.1.254', 'network': '172.16.1.0/24'}) self.main_bridge.add_port({'id': 1, 'type': 'exterior'}) self.main_bridge.add_port({'id': 2, 'type': 'exterior'}) self.vm1_port = self.main_bridge.get_port(1) self.vm2_port = self.main_bridge.get_port(2) host1 = service.get_container_by_hostname('midolman1') host2 = service.get_container_by_hostname('midolman2') vm1data = {'hw_addr': 'aa:bb:cc:00:00:11', 'ipv4_addr': ['172.16.1.2/24'], 'ipv4_gw': '172.16.1.1'} vm2data = {'hw_addr': 'aa:bb:cc:00:00:22', 'ipv4_addr': ['172.16.1.3/24'], 'ipv4_gw': '172.16.1.1'} self.vm1 = host1.create_vmguest(**vm1data) self.vm2 = host2.create_vmguest(**vm2data) ptm.addCleanup(host1.destroy_vmguest, self.vm1) ptm.addCleanup(host2.destroy_vmguest, self.vm2) port1_real_id = self.vm1_port.get_real_id() port2_real_id = self.vm2_port.get_real_id() host1.bind_port(self.vm1, port1_real_id) host2.bind_port(self.vm2, port2_real_id) utils.await_port_active(port1_real_id, active=True) utils.await_port_active(port2_real_id, active=True) self.qos_pol1 = self.add_qos_policy( {'name': 'pol1', 'description': 'Description', 'shared': True}) self.qos_pol2 = self.add_qos_policy( {'name': 'pol2', 'description': 'Description Two', 'shared': True}) assert_that(self.qos_pol1) assert_that(self.qos_pol2)
def cleanup(): agent = service.get_container_by_hostname('midolman1') # We wait just to make sure that it's been unregistered agent.stop(wait=True) # Wipe out the container sandbox.remove_container(agent) # Restart sandbox, the --no-recreate flag will spawn only missing containers sandbox.restart_sandbox('default_neutron+kilo+compat', conf.sandbox_name(), 'sandbox/override_compat') # Reset cached containers and reload them (await for the new agent to be up) service.loaded_containers = None agent = service.get_container_by_hostname('midolman1') agent.wait_for_status('up')
def cleanup(): agent = service.get_container_by_hostname('midolman1') # We wait just to make sure that it's been unregistered agent.stop(wait=True) # Wipe out the container sandbox.remove_container(agent) # Restart sandbox, the --no-recreate flag will spawn only missing containers sandbox.restart_sandbox('default_v2_neutron+kilo+compat', 'sandbox/override_v2_compat') # Reset cached containers and reload them (await for the new agent to be up) service.loaded_containers = None agent = service.get_container_by_hostname('midolman1') agent.wait_for_status('up')
def test_simple_port_migration(): """ Title: Tests that flow state changes are backwards compatible The topology is set up in such a way that both conntrack and NAT flow state is generated. Send nonfip-to-fip udp packets between two agents and return packets Unbind the public port and bind it to a different vm Verify that previous flows still work in both directions """ binding_type = BM.get_binding_data()['binding_type'] agent2 = service.get_container_by_hostname('midolman2') agent3 = service.get_container_by_hostname('midolman3') # vm on midolman1 private_interface_vm = BM.get_interface_on_vport('private_port') # vm on midolman2 public_interface_vm = BM.get_interface_on_vport('public_port') # port to be migrated public_port = VTM.get_resource('public_port')['port'] # new free vm on midolman3 free_interface_vm_data = { 'hw_addr': public_port['mac_address'], 'ipv4_addr': [public_port['fixed_ips'][0]['ip_address'] + '/24'], 'ipv4_gw': '10.0.1.1' } free_interface_vm = agent3.create_vmguest(**free_interface_vm_data) VTM.addCleanup(agent3.destroy_vmguest, free_interface_vm) fip = VTM.get_resource( 'public_port_fip')['floatingip']['floating_ip_address'] # Generate flow state snat = check_forward_flow(private_interface_vm, public_interface_vm, fip, 50000, 80) check_return_flow(public_interface_vm, private_interface_vm, snat['ip'], snat['port'], 50000, 80) # Unbind/bind port to a different host if binding_type == BindingType.API: agent2.unbind_port(public_interface_vm, type=binding_type) agent3.bind_port(free_interface_vm, public_port['id'], type=binding_type) await_port_active(public_port['id'], active=True) check_return_flow(free_interface_vm, private_interface_vm, snat['ip'], snat['port'], 50000, 80)
def bind(self): # Schedule deletion of virtual and physical topologies self.addCleanup(self._ptm.destroy) self._ptm.build(self._data) self.addCleanup(self._vtm.destroy) self._add_hosts_to_tunnel_zone() self._vtm.build(self._data) for binding in self._data['bindings']: vport = self._vtm.get_resource(binding['vport']) bind_iface = binding['interface'] if isinstance(bind_iface, dict): # We are specifying the vms inside the binding iface_def = self._update_addresses(bind_iface['definition'], vport) iface_type = bind_iface['type'] hostname = bind_iface['hostname'] host = service.get_container_by_hostname(hostname) iface = getattr(host, "create_%s" % iface_type)(**iface_def) self.addCleanup(getattr(host, "destroy_%s" % iface_type), iface) else: # It's a vm already created and saved as a resource iface = self._ptm.get_resource(binding['interface']) vport_id = self._get_port_id(vport) # Do the actual binding binding = iface.compute_host.bind_port(iface, vport_id) self.addCleanup(iface.compute_host.unbind_port, iface) self._mappings[vport_id] = iface await_port_active(vport_id) # create and bind a "router", which is actually just a namespace # residing on the host with multiple interfaces that can be bound # to a port in midonet. # Example definition: # # 'routers': [ # {'bindings': [ # {'vport': 'uplink_left', # 'iface': 'l_tun', # 'addr': '100.0.0.10/24'}, # {'vport': 'uplink_right', # 'iface': 'r_tun', # 'addr': '200.0.0.10/24'}], # 'name': 'UPL', # 'host': 'midolman1'}], for router_def in self._data.get('routers') or []: hostname = router_def['host'] host = service.get_container_by_hostname(hostname) host.create_netns_router(router_def['name'], router_def['bindings']) self.addCleanup(host.destroy_router, router_def['name'])
def test_simple_port_migration(): """ Title: Tests that flow state changes are backwards compatible The topology is set up in such a way that both conntrack and NAT flow state is generated. Send nonfip-to-fip udp packets between two agents and return packets Unbind the public port and bind it to a different vm Verify that previous flows still work in both directions """ binding_type = BM.get_binding_data()['binding_type'] agent2 = service.get_container_by_hostname('midolman2') agent3 = service.get_container_by_hostname('midolman3') # vm on midolman1 private_interface_vm = BM.get_interface_on_vport('private_port') # vm on midolman2 public_interface_vm = BM.get_interface_on_vport('public_port') # port to be migrated public_port = VTM.get_resource('public_port')['port'] # new free vm on midolman3 free_interface_vm_data = { 'hw_addr': public_port['mac_address'], 'ipv4_addr': [public_port['fixed_ips'][0]['ip_address'] + '/24'], 'ipv4_gw': '10.0.1.1'} free_interface_vm = agent3.create_vmguest(**free_interface_vm_data) VTM.addCleanup(agent3.destroy_vmguest, free_interface_vm) fip = VTM.get_resource('public_port_fip')['floatingip']['floating_ip_address'] # Generate flow state snat = check_forward_flow( private_interface_vm, public_interface_vm, fip, 50000, 80) check_return_flow( public_interface_vm, private_interface_vm, snat['ip'], snat['port'], 50000, 80) # Unbind/bind port to a different host if binding_type == BindingType.API: agent2.unbind_port(public_interface_vm, type=binding_type) agent3.bind_port(free_interface_vm, public_port['id'], type=binding_type) await_port_active(public_port['id'], active=True) check_return_flow( free_interface_vm, private_interface_vm, snat['ip'], snat['port'], 50000, 80)
def test_mmctl_unbinding_without_mm_running(): """ Title: Unbinding a port using mmctl when midolman is not running """ mm1 = service.get_container_by_hostname('midolman1') port1 = VTM.port1 iface_port2 = BM.get_interface_on_vport('port2') iface = mm1.create_vmguest(hw_addr=port1['mac_address']) VTM.addCleanup(iface.destroy) mm1.bind_port(iface, port1['id'], BindingType.MMCTL) VTM.addCleanup(mm1.unbind_port, iface, BindingType.MMCTL) iface.dhclient() iface.try_command_blocking("ping -c 5 %s" % (iface_port2.get_ip())) mm1.stop() mm1.unbind_port(iface, BindingType.MMCTL) mm1.start() ret = iface.exec_command_blocking("ping -c 5 %s" % (iface_port2.get_ip())) # Ping returns 0 if the ping succeeds, 1 or 2 on error conditions. assert_that(ret, is_not(equal_to(0)), "Ping should have failed, but did not.")
def stop_server(container): cont_services = service.get_container_by_hostname(container) namespace = cont_services.exec_command('ip netns') pid = cont_services.exec_command( '/bin/sh -c "ip netns exec %s netstat -ntlp | grep ncat | awk \'{print $7}\' | cut -d/ -f1"' % namespace) cont_services.try_command_blocking("kill %s" % pid)
def bind(self): # Schedule deletion of virtual and physical topologies self.addCleanup(self._ptm.destroy) self._ptm.build(self._data) self.addCleanup(self._vtm.destroy) self._vtm.build(self._data) self._add_hosts_to_tunnel_zone() for binding in self._data['bindings']: vport = self._vtm.get_resource(binding['vport']) bind_iface = binding['interface'] if isinstance(bind_iface, dict): # We are specifying the vms inside the binding iface_def = self._update_addresses(bind_iface['definition'], vport) iface_type = bind_iface['type'] hostname = bind_iface['hostname'] host = service.get_container_by_hostname(hostname) iface = getattr(host, "create_%s" % iface_type)(**iface_def) self.addCleanup(getattr(host, "destroy_%s" % iface_type), iface) else: # It's a vm already created and saved as a resource iface = self._ptm.get_resource(binding['interface']) vport_id = self._get_port_id(vport) # Do the actual binding binding = iface.compute_host.bind_port(iface, vport_id) self.addCleanup(iface.compute_host.unbind_port, iface) self._mappings[vport_id] = iface await_port_active(vport_id)
def test_new_interface_becomes_visible(): """ mdts.tests.functional_tests.test_midolman_and_interfaces.test_new_interface_becomes_visible Scenario: When: On start up, a Midolman sees no interface, Then: adds a new interface, And: Midolman detects a new interface. """ # FIXME: pick the midonet-agent from binding manager (when parallel) midonet_api = get_midonet_api() agent = service.get_container_by_hostname('midolman1') iface_name = 'interface%d' % random.randint(1, 100) new_interface = get_interface(midonet_api, agent.get_midonet_host_id(), iface_name) # Test that no interface with name 'interface_01' exists. assert_that(new_interface, none(), iface_name) # Create a new interface 'interface_01'. iface = agent.create_vmguest(ifname=iface_name) time.sleep(5) new_interface = get_interface(midonet_api, agent.get_midonet_host_id(), iface_name) # Test that the created interface is visible. assert_that(new_interface, not_none(), iface_name) agent.destroy_vmguest(iface)
def ping_from_inet(container, ipv6 = '2001::1', count=4, namespace=None): count = max(1, count) cmd = "%s ping6 %s -c %d" % ( "ip netns exec %s" % namespace if namespace else "", ipv6, count) cont_services = service.get_container_by_hostname(container) cont_services.try_command_blocking(cmd)
def setup_remote_host(self, container, interface, gw_address, local_address, local_router): self.addCleanup(self.cleanup_remote_host, container, interface, gw_address) cont = service.get_container_by_hostname(container) cont.try_command_blocking('ip r add 100.0.0.0/8 via 10.1.0.1') cont.try_command_blocking('ip a add %s/64 dev %s' % (gw_address, interface)) cont.try_command_blocking('ip -6 r add cccc:bbbb::/32 via 2001::1') cont.try_command_blocking('ip -6 r add cccc:cccc::/32 via 2001::1') # enable ip6 forwarding cont.try_command_blocking('sysctl net.ipv6.conf.all.forwarding=1') # setup ip6 namespace cont.try_command_blocking('ip netns add ip6') cont.try_command_blocking( 'ip l add name ip6dp type veth peer name ip6ns') cont.try_command_blocking('ip l set netns ip6 dev ip6ns') cont.try_command_blocking('ip l set up dev ip6dp') cont.try_command_blocking('ip netns exec ip6 ip link set up dev lo') cont.try_command_blocking('ip netns exec ip6 ip link set up dev ip6ns') cont.try_command_blocking( 'ip a add %s/48 dev ip6dp' % local_router) cont.try_command_blocking( 'ip netns exec ip6 ip a add %s/48 dev ip6ns' % local_address) cont.try_command_blocking( 'ip netns exec ip6 ip -6 r add default via %s' % local_router)
def add_host_to_tunnel_zone(self, hostname, tz_name, add_clean_up=True): """ :param hostname: string :param tz_name: string :param add_clean_up: boolean :rtype: None """ def get_or_create_tz(tz_name): tzones = self._midonet_api.get_tunnel_zones() for tz in tzones: if tz_name in tz.get_name(): return tz tz = self._midonet_api.add_vxlan_tunnel_zone() tz.name('%s-%s' % (tz_name, str(uuid.uuid4())[:4])) tz.create() self.addCleanup(tz.delete) return tz tz = get_or_create_tz(tz_name) host = service.get_container_by_hostname(hostname) hostid = host.get_midonet_host_id() tz_hostids = [tz_host.get_host_id() for tz_host in tz.get_hosts()] # Make sure not to add an existing host in the tz if hostid not in tz_hostids: tz_host = tz.add_tunnel_zone_host() tz_host.ip_address(host.get_ip_address()) tz_host.host_id(host.get_midonet_host_id()) tz_host.create() if add_clean_up: self.addCleanup(tz_host.delete)
def add_host_to_tunnel_zone(self, hostname, tz_name, add_clean_up=True): """ :param hostname: string :param tz_name: string :param add_clean_up: boolean :rtype: None """ def get_or_create_tz(tz_name): tzones = self._midonet_api.get_tunnel_zones() for tz in tzones: if tz_name in tz.get_name(): return tz tz = self._midonet_api.add_vxlan_tunnel_zone() tz.name('%s-%s' % (tz_name, str(uuid.uuid4())[:4])) tz.create() self.addCleanup(tz.delete) return tz tz = get_or_create_tz(tz_name) host = service.get_container_by_hostname(hostname) hostid = host.get_midonet_host_id() tz_hostids = [tz_host.get_host_id() for tz_host in tz.get_hosts()] # Make sure not to add an existing host in the tz if hostid not in tz_hostids: tz_host = tz.add_tunnel_zone_host() tz_host.ip_address(host.get_ip_address()) tz_host.host_id(host.get_midonet_host_id()) tz_host.create() if add_clean_up: self.addCleanup(tz_host.delete)
def del_route_from_vpp(self, container, prefix, via, port, vrf): cont = service.get_container_by_hostname(container) try: cont.vppctl('ip route del %s table %s' % (prefix, vrf)) except Exception: LOG.error("Erroring deleting route %s from vpp in table %s" % (prefix, vrf))
def bind(self): # Schedule deletion of virtual and physical topologies self.addCleanup(self._ptm.destroy) self._ptm.build(self._data) self.addCleanup(self._vtm.destroy) self._vtm.build(self._data) self._add_hosts_to_tunnel_zone() for binding in self._data['bindings']: vport = self._vtm.get_resource(binding['vport']) bind_iface = binding['interface'] if isinstance(bind_iface, dict): # We are specifying the vms inside the binding iface_def = self._update_addresses(bind_iface['definition'], vport) iface_type = bind_iface['type'] hostname = bind_iface['hostname'] host = service.get_container_by_hostname(hostname) iface = getattr(host, "create_%s" % iface_type)(**iface_def) self.addCleanup(getattr(host, "destroy_%s" % iface_type), iface) else: # It's a vm already created and saved as a resource iface = self._ptm.get_resource(binding['interface']) vport_id = self._get_port_id(vport) # Do the actual binding binding = iface.compute_host.bind_port(iface, vport_id) self.addCleanup(iface.compute_host.unbind_port, iface) self._mappings[vport_id] = iface await_port_active(vport_id)
def _write_per_test_debug_info(self, test, result): test_id = test.id() #test_id = "%s.%s" % (test_case.get('classname'), # test_case.get('name')) dump_dir = "%s/%s" % (self.log_dir, test_id) if not os.path.exists(dump_dir): os.makedirs(dump_dir) # Any midolman works for us in here. # FIXME: should be zk maybe? whatever works but still midolman = service.get_container_by_hostname('midolman1') zkdump_output = midolman.exec_command( 'zkdump -z zookeeper1:2181 -d -p') with open("%s/zkdump_output.log" % dump_dir, 'w') as f: f.write(zkdump_output) midolmans = service.get_all_containers('midolman') for midolman in midolmans: mmdpctl_show = midolman.exec_command( 'mm-dpctl --timeout 10 datapath --show midonet') mmdpctl_dump = midolman.exec_command( 'mm-dpctl --timeout 10 datapath --dump midonet') service_dir = "%s/%s" % (dump_dir, midolman.get_hostname()) if not os.path.exists(service_dir): os.makedirs(service_dir) with open("%s/mmdpctl_output.log" % service_dir, 'w') as f: f.write("------------------------------------------------\n") f.write("mm-dpctl --timeout 10 datapath --show midonet \n") f.write("------------------------------------------------\n") f.write(mmdpctl_show) f.write("------------------------------------------------\n\n") f.write("------------------------------------------------\n") f.write("mm-dpctl --timeout 10 datapath --dump midonet \n") f.write("------------------------------------------------\n") f.write(mmdpctl_dump)
def test_new_interface_becomes_visible(): """ mdts.tests.functional_tests.test_midolman_and_interfaces.test_new_interface_becomes_visible Scenario: When: On start up, a Midolman sees no interface, Then: adds a new interface, And: Midolman detects a new interface. """ # FIXME: pick the midonet-agent from binding manager (when parallel) midonet_api = get_midonet_api() agent = service.get_container_by_hostname('midolman1') iface_name = 'interface%d' % random.randint(1, 100) new_interface = get_interface( midonet_api, agent.get_midonet_host_id(), iface_name) # Test that no interface with name 'interface_01' exists. assert_that(new_interface, none(), iface_name) # Create a new interface 'interface_01'. iface = agent.create_vmguest(ifname=iface_name) time.sleep(5) new_interface = get_interface( midonet_api, agent.get_midonet_host_id(), iface_name) # Test that the created interface is visible. assert_that(new_interface, not_none(), iface_name) agent.destroy_vmguest(iface)
def cleanup_remote_host(self, container, interface): cont = service.get_container_by_hostname(container) cont.exec_command('ip r del 100.0.0.0/8') cont.exec_command('ip a del 2001::2/64 dev %s' % interface) cont.exec_command('ip -6 r del cccc:bbbb::/32') cont.exec_command('ip netns delete ip6')
def test_mmctl_unbinding_without_mm_running(): """ Title: Unbinding a port using mmctl when midolman is not running """ mm1 = service.get_container_by_hostname('midolman1') port1 = VTM.port1 iface_port2 = BM.get_interface_on_vport('port2') iface = mm1.create_vmguest(hw_addr=port1['mac_address']) VTM.addCleanup(iface.destroy) mm1.bind_port(iface, port1['id'], BindingType.MMCTL) VTM.addCleanup(mm1.unbind_port, iface, BindingType.MMCTL) iface.dhclient() iface.try_command_blocking("ping -c 5 %s" % (iface_port2.get_ip())) mm1.stop() mm1.unbind_port(iface, BindingType.MMCTL) mm1.start() ret = iface.exec_command_blocking("ping -c 5 %s" % (iface_port2.get_ip())) # Ping returns 0 if the ping succeeds, 1 or 2 on error conditions. assert_that(ret, is_not(equal_to(0)), "Ping should have failed, but did not.")
def setup_package(): """ Setup method at the tests module level (init) :return: """ # Read configuration conf_file = os.getenv('MDTS_CONF_FILE', 'mdts.conf') config = SafeConfigParser() config.read(conf_file) # Check all services (including midolman) are online api_host = service.get_container_by_hostname('cluster1') api_host.wait_for_status('up') for type, hosts in service.get_all_containers().items(): for host in hosts: LOG.debug("Checking liveness of %s" % host.get_hostname()) host.wait_for_status('up', timeout=240) # Wait until bindings do not fail, at that point, mdts is ready for test max_attempts = 10 for current_attempts in xrange(max_attempts): topology = build_simple_topology() try: destroy_simple_topology(topology) LOG.debug("MDTS ready to run tests.") return except: destroy_simple_topology(topology) current_attempts += 1 LOG.debug("MDTS failed to bind port... check again. Attempt: %d" % current_attempts) raise RuntimeError("MDTS was unable to bind a single port... Exiting.")
def setup_package(): """ Setup method at the tests module level (init) :return: """ # Check all services (including midolman) are online api_host = service.get_container_by_hostname('cluster1') api_host.wait_for_status('up') for type, hosts in service.get_all_containers().items(): for host in hosts: LOG.debug("Checking liveness of %s" % host.get_hostname()) host.wait_for_status('up', timeout=conf.service_status_timeout()) # Wait until bindings do not fail, at that point, mdts is ready for test max_attempts = 10 for current_attempts in xrange(max_attempts): topology = build_simple_topology() try: destroy_simple_topology(topology) LOG.debug("MDTS ready to run tests.") return except: destroy_simple_topology(topology) current_attempts += 1 LOG.debug("MDTS failed to bind port... check again. Attempt: %d" % current_attempts) raise RuntimeError("MDTS was unable to bind a single port... Exiting.")
def __init__(self, container, gateway, address, prefix, server, port): ns = 'client%d' % self.__class__.instance_id self.ns = ns self.container = container self.__class__.instance_id += 1 cont = service.get_container_by_hostname(container) cont.exec_command('ip netns add %s' % ns) cont.try_command_blocking( 'ip l add name %sdp type veth peer name %sns' % (ns, ns)) cont.try_command_blocking('ip l set netns %s dev %sns' % (ns, ns)) cont.try_command_blocking('ip l set up dev %sdp' % ns) cont.try_command_blocking('ip a add %s/%d dev %sdp' % (gateway, prefix, ns)) cont.try_command_blocking('ip netns exec %s ip link set up dev lo' % ns) cont.try_command_blocking('ip netns exec %s ip link set up dev %sns' % (ns, ns)) cont.try_command_blocking('ip netns exec %s ip a add %s/%d dev %sns' % (ns, address, prefix, ns)) cont.try_command_blocking( 'ip netns exec %s ip -6 r add default via %s' % (ns, gateway)) cmd = 'ip netns exec %s /bin/nc %s %d' % (ns, server, port) self.counter = 0 self.io = None self.cmd = cmd.split()
def ping_from_inet(container, ipv6='2001::1', count=4, namespace=None): count = max(1, count) cmd = "%s ping6 %s -c %d" % ( "ip netns exec %s" % namespace if namespace else "", ipv6, count) cont_services = service.get_container_by_hostname(container) cont_services.try_command_blocking(cmd)
def setup_remote_host(self, container, interface, gw_address, local_address, local_router): self.addCleanup(self.cleanup_remote_host, container, interface, gw_address) cont = service.get_container_by_hostname(container) cont.try_command_blocking('ip r add 100.0.0.0/8 via 10.1.0.1') cont.try_command_blocking('ip a add %s/64 dev %s' % (gw_address, interface)) cont.try_command_blocking('ip -6 r add cccc:bbbb::/32 via 2001::1') cont.try_command_blocking('ip -6 r add cccc:cccc::/32 via 2001::1') # enable ip6 forwarding cont.try_command_blocking('sysctl net.ipv6.conf.all.forwarding=1') # setup ip6 namespace cont.try_command_blocking('ip netns add ip6') cont.try_command_blocking( 'ip l add name ip6dp type veth peer name ip6ns') cont.try_command_blocking('ip l set netns ip6 dev ip6ns') cont.try_command_blocking('ip l set up dev ip6dp') cont.try_command_blocking('ip netns exec ip6 ip link set up dev lo') cont.try_command_blocking('ip netns exec ip6 ip link set up dev ip6ns') cont.try_command_blocking( 'ip a add %s/48 dev ip6dp' % local_router) cont.try_command_blocking( 'ip netns exec ip6 ip a add %s/48 dev ip6ns' % local_address) cont.try_command_blocking( 'ip netns exec ip6 ip -6 r add default via %s' % local_router)
def cleanup_ipv6_flows(self, container, from_port, to_port): cont = service.get_container_by_hostname(container) cont.exec_command( 'mm-dpctl flows --delete -d midonet -e 86dd -i %s -o %s' % (from_port, to_port)) cont.exec_command( 'mm-dpctl flows --delete -d midonet -e 86dd -i %s -o %s' % (to_port, from_port))
def cleanup_remote_host(self, container, interface, address): cont = service.get_container_by_hostname(container) cont.exec_command('ip r del 100.0.0.0/8') cont.exec_command('ip a del %s/64 dev %s' % (address, interface)) cont.exec_command('ip -6 r del cccc:bbbb::/32') cont.exec_command('ip -6 r del cccc:cccc::/32') cont.exec_command('ip netns delete ip6')
def client_prepare(container, namespace): cont_services = service.get_container_by_hostname(container) # optional: install ethtool # cont_services.try_command_blocking("sh -c 'apt-get update && apt-get -y install ethtool'") # disable TCP checksums cont_services.try_command_blocking("ip netns exec ip6 ethtool -K ip6ns tx off rx off")
def add_port_to_vpp(self, container, port, mac, address, vrf=0): cont = service.get_container_by_hostname(container) self.addCleanup(self.del_port_from_vpp, container, port) cont.vppctl('create host-interface name %s hw-addr %s' % (port, mac)) cont.vppctl('set int state host-%s up' % port) if vrf != 0: cont.vppctl('set int ip table host-%s %d' % (port, vrf)) self.add_vpp_ip_address(cont, port, address)
def cleanup_ipv6_flows(self, container, from_port, to_port): cont = service.get_container_by_hostname(container) cont.exec_command( 'mm-dpctl flows --delete -d midonet -e 86dd -i %s -o %s' % (from_port, to_port)) cont.exec_command( 'mm-dpctl flows --delete -d midonet -e 86dd -i %s -o %s' % (to_port, from_port))
def add_port_to_vpp(self, container, port, mac, address, vrf=0): cont = service.get_container_by_hostname(container) self.addCleanup(self.del_port_from_vpp, container, port) cont.vppctl('create host-interface name %s hw-addr %s' % (port, mac)) cont.vppctl('set int state host-%s up' % port) if vrf != 0: cont.vppctl('set int ip table host-%s %d' % (port, vrf)) cont.vppctl('set int ip address host-%s %s' % (port, address))
def test_qos_dscp_mark_on_network(): """ 1) Test that setting a DSCP rule on a network will transform all default packets that ingress the cloud on the network to set the IP DS headers to the given DSCP mark, or reset the IP DS headers to the given DSCP mark, if already set. 2) Test that clearing a DSCP rule on a network will no longer set the IP DS header on default, and will no longer change the IP DS header on packets with DS header already set. 3) Test that setting and clearing the DSCP rule on a network will also affect any traffic on any new ports created on that network. """ try: PTM.build() VTM.build(ptm=PTM) VTM.qos_pol1.add_dscp_rule({'dscp_mark': 11}) VTM.main_bridge.set_qos_policy(VTM.qos_pol1) VTM.vm1.verify_packet_field( target_iface=VTM.vm2, field='tos', value=11) VTM.main_bridge.add_port({'id': 3, 'type': 'exterior'}) vm3_port = VTM.main_bridge.get_port(3) host1 = service.get_container_by_hostname('midolman1') vm3data = {'hw_addr': 'aa:bb:cc:00:00:11', 'ipv4_addr': ['172.16.1.4/24'], 'ipv4_gw': '172.16.1.1'} vm3 = host1.create_vmguest(**vm3data) port3_real_id = vm3_port.get_real_id() host1.bind_port(vm3, port3_real_id) utils.await_port_active(port3_real_id, active=True) vm3.verify_packet_field( target_iface=VTM.vm2, field='tos', value=11) VTM.main_bridge.clear_qos_policy() VTM.vm1.verify_packet_field( target_iface=VTM.vm2, field='tos', value=None) vm3.verify_packet_field( target_iface=VTM.vm2, field='tos', value=None) VTM.qos_pol2.clear_dscp_rules() VTM.qos_pol1.clear_dscp_rules() host1.destroy_vmguest(vm3) finally: VTM.destroy() PTM.destroy()
def test_qos_dscp_mark_on_network(): """ 1) Test that setting a DSCP rule on a network will transform all default packets that ingress the cloud on the network to set the IP DS headers to the given DSCP mark, or reset the IP DS headers to the given DSCP mark, if already set. 2) Test that clearing a DSCP rule on a network will no longer set the IP DS header on default, and will no longer change the IP DS header on packets with DS header already set. 3) Test that setting and clearing the DSCP rule on a network will also affect any traffic on any new ports created on that network. """ try: PTM.build() VTM.build(ptm=PTM) VTM.qos_pol1.add_dscp_rule({'dscp_mark': 11}) VTM.main_bridge.set_qos_policy(VTM.qos_pol1) VTM.vm1.verify_packet_field( target_iface=VTM.vm2, field='tos', value=11) VTM.main_bridge.add_port({'id': 3, 'type': 'exterior'}) vm3_port = VTM.main_bridge.get_port(3) host1 = service.get_container_by_hostname('midolman1') vm3data = {'hw_addr': 'aa:bb:cc:00:00:11', 'ipv4_addr': ['172.16.1.4/24'], 'ipv4_gw': '172.16.1.1'} vm3 = host1.create_vmguest(**vm3data) port3_real_id = vm3_port.get_real_id() host1.bind_port(vm3, port3_real_id) utils.await_port_active(port3_real_id, active=True) vm3.verify_packet_field( target_iface=VTM.vm2, field='tos', value=11) VTM.main_bridge.clear_qos_policy() VTM.vm1.verify_packet_field( target_iface=VTM.vm2, field='tos', value=None) vm3.verify_packet_field( target_iface=VTM.vm2, field='tos', value=None) VTM.qos_pol2.clear_dscp_rules() VTM.qos_pol1.clear_dscp_rules() host1.destroy_vmguest(vm3) finally: VTM.destroy() PTM.destroy()
def stop_jfr(hostname, filename): agent = service.get_container_by_hostname(hostname) pid = agent.exec_command("pgrep -f Midolman") output, exec_id = agent.exec_command( "jcmd %s JFR.stop name=%s" % (pid, filename), stream=True) exit_code = agent.check_exit_status(exec_id, output, timeout=60) if exit_code != 0: raise RuntimeError("Failed to stop Java Flight Recorder for " "'%s'" % (hostname))
def stop_jfr(hostname, filename): agent = service.get_container_by_hostname(hostname) pid = agent.exec_command("pgrep -f Midolman") output, exec_id = agent.exec_command( "jcmd %s JFR.stop name=%s" % (pid, filename), stream=True) exit_code = agent.check_exit_status(exec_id, output, timeout=60) if exit_code != 0: raise RuntimeError("Failed to stop Java Flight Recorder for " "'%s'" % (hostname))
def execute_mn_conf(switch_flag, switch_id, config): host = service.get_container_by_hostname("midolman1") conf_file = tempfile.NamedTemporaryFile() for k, v in config.items(): conf_file.write("%s=%s\n" % (k, v)) conf_file.flush() cmd = "mn-conf set %s %s < %s" % (switch_flag, switch_id, conf_file.name) host.exec_command(cmd, stream=False) conf_file.close()
def execute_mn_conf(switch_flag, switch_id, config): host = service.get_container_by_hostname("midolman1") conf_file = tempfile.NamedTemporaryFile() for k, v in config.items(): conf_file.write("%s=%s\n" % (k, v)) conf_file.flush() cmd = "mn-conf set %s %s < %s" % (switch_flag, switch_id, conf_file.name) host.exec_command(cmd, stream=False) conf_file.close()
def __init__(self, container, command): cont = service.get_container_by_hostname(container) container = cont.get_name() cmdline = ['docker', 'exec', '-i', container] + command LOG.debug('DockerIOExecutor. command=%s' % cmdline) self.subprocess = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def close(self): cont = service.get_container_by_hostname(self.container) cont.try_command_blocking('ip link del %sdp' % self.ns) cont.try_command_blocking('ip netns del %s' % self.ns) try: cont.try_command_blocking('pkill -f nc') except Exception: pass self.io.close()
def create_ipv6_flows(self, container, from_port, to_port): cont = service.get_container_by_hostname(container) self.addCleanup(self.cleanup_ipv6_flows, container, from_port, to_port) cont.try_command_blocking( 'mm-dpctl flows -d midonet -e 86dd -i %s -o %s' % (from_port, to_port)) cont.try_command_blocking( 'mm-dpctl flows -d midonet -e 86dd -i %s -o %s' % (to_port, from_port))
def __init__(self, container, command): cont = service.get_container_by_hostname(container) container = cont.get_name() cmdline = ['docker', 'exec', '-i', container] + command LOG.debug('DockerIOExecutor. command=%s' % cmdline) self.subprocess = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def add_member(host_name, tzone_name): host_container = service.get_container_by_hostname(host_name) tz_host = _tunnel_zones[tzone_name].add_tunnel_zone_host() tz_host.host_id(host_container.get_midonet_host_id()) tz_host.ip_address(host_container.get_ip_address()) tz_host.create() LOG.debug("Added VTEP tunnel zone member: {0} <- {1} @ {2}" .format(tzone_name, host_container.get_midonet_host_id(), host_container.get_ip_address()))
def install_packages(container_name, *packages): container = service.get_container_by_hostname(container_name) output, exec_id = container.exec_command( "sh -c 'env DEBIAN_FRONTEND=noninteractive apt-get install " + \ "-qy --force-yes -o Dpkg::Options::=\"--force-confnew\" " + \ "%s'" % (" ".join(packages)), stream=True) exit_code = container.check_exit_status(exec_id, output, timeout=60) if exit_code != 0: raise RuntimeError("Failed to update packages (%s)." % (packages))
def add_member(host_name, tzone_name): host_container = service.get_container_by_hostname(host_name) tz_host = _tunnel_zones[tzone_name].add_tunnel_zone_host() tz_host.host_id(host_container.get_midonet_host_id()) tz_host.ip_address(host_container.get_ip_address()) tz_host.create() LOG.debug("Added VTEP tunnel zone member: {0} <- {1} @ {2}" .format(tzone_name, host_container.get_midonet_host_id(), host_container.get_ip_address()))
def close(self): cont = service.get_container_by_hostname(self.container) cont.try_command_blocking('ip link del %sdp' % self.ns) cont.try_command_blocking('ip netns del %s' % self.ns) try: cont.try_command_blocking('pkill -f nc') except Exception: pass self.io.close()
def create_ipv6_flows(self, container, from_port, to_port): cont = service.get_container_by_hostname(container) self.addCleanup(self.cleanup_ipv6_flows, container, from_port, to_port) cont.try_command_blocking( 'mm-dpctl flows -d midonet -e 86dd -i %s -o %s' % (from_port, to_port)) cont.try_command_blocking( 'mm-dpctl flows -d midonet -e 86dd -i %s -o %s' % (to_port, from_port))
def __init__(self, filename=None, data=None, midonet_api=None): super(TopologyManager, self).__init__() # deprecate self._data = self._get_data(filename, data) self._midonet_api_host = service.get_container_by_hostname('cluster1') # New model self._midonet_api = utils.get_midonet_api() self._cleanups = callmany.CallMany() self._resources = {}
def install(): # Install new package so the new version is updated immediately after reboot agent = service.get_container_by_hostname('midolman1') output, exec_id = agent.exec_command( "apt-get install -qy --force-yes " "-o Dpkg::Options::=\"--force-confnew\" " "midolman/local midonet-tools/local", stream=True) exit_code = agent.check_exit_status(exec_id, output, timeout=60) if exit_code != 0: raise RuntimeError("Failed to update package.")
def ping_from_inet(container, ip='2001::1', count=4, namespace=None): count = max(1, count) if ':' in ip: ping_cmd = "ping6" else: ping_cmd = "ping" cmd = "%s %s %s -c %d" % ( "ip netns exec %s" % namespace if namespace else "", ping_cmd, ip, count) cont_services = service.get_container_by_hostname(container) cont_services.try_command_blocking(cmd)
def create_veth_pair(self, container, ep1name, ep2name, ep1mac=None, ep2mac=None): cont = service.get_container_by_hostname(container) cmd = 'ip l add name %s %s type veth peer name %s %s' % ( ep1name, 'address %s' % ep1mac if ep1mac else '', ep2name, 'address %s' % ep2mac if ep2mac else '') # cleaning up one end will clean up both self.addCleanup(self.cleanup_veth, container, ep1name) cont.try_command_blocking(cmd) cont.try_command_blocking('ip l set up dev %s' % (ep1name)) cont.try_command_blocking('ip l set up dev %s' % (ep2name))
def client_wait_for_termination(container, server_port): cont_services = service.get_container_by_hostname(container) tries = 12 delay_seconds = 10 for i in range(tries): time.sleep(delay_seconds) if (len(cont_services.exec_command("pidof nc")) < 2): break else: raise Exception('TCP client at %s did not terminate within %d seconds' % (container, tries * delay_seconds))
def start_jfr(hostname, filename): agent = service.get_container_by_hostname(hostname) pid = agent.exec_command("pgrep -f Midolman") output, exec_id = agent.exec_command( "jcmd %s JFR.start duration=0s " "filename=/tmp/jfr/%s.%s.jfr dumponexit=true " "name=%s" % (pid, hostname, filename, filename), stream=True) exit_code = agent.check_exit_status(exec_id, output, timeout=60) if exit_code != 0: raise RuntimeError("Failed to start Java Flight Recorder for " "'%s'" % (hostname))