Пример #1
0
def create_virtual_server(
        ns_client, client_ctx_traf, client_ctx_comm,
        ns_server, server_ctx_traf, server_ctx_comm
) -> subprocess.Popen:
    """
    Create a server process in separate network namespace,
    connect it by virtual links and start it.
    Returns the process of the created server.
    """
    server_ctx_comm_ = ContextLocal(server_ctx_traf.iface + "_comm",
                                    inet=server_ctx_comm.inet,
                                    mask=server_ctx_comm.mask)
    client_ctx_comm_ = ContextLocal(client_ctx_traf.iface + "_comm",
                                    inet=client_ctx_comm.inet,
                                    mask=client_ctx_comm.mask)

    create_virtual_link(ns_client, client_ctx_traf,
                        ns_server, server_ctx_traf)
    create_virtual_link(ns_client, client_ctx_comm_,
                        ns_server, server_ctx_comm_)

    to_run = [
        "python3", "-m", "xdp_test_harness.server",
        pickle.dumps(ContextServer(
            server_ctx_traf, server_ctx_comm,
        ), 0).decode()
    ]

    if hasattr(ns_server, "netns"):
        server_process = pyroute2.NSPopen(ns_server.netns, to_run)
    else:
        server_process = subprocess.Popen(to_run)

    return server_process
Пример #2
0
def clean_traffic(iface: str,
                  netns: pyroute2.NetNS = None,
                  restore_on_exit: bool = True):
    sysctl_state = []
    MILLISECONDS_IN_HOUR = 1000 * 60 * 60

    for (folder, setting, value) in [
        ("conf", "autoconf", 0),
        ("conf", "accept_ra", 0),
        ("conf", "accept_dad", 0),
        ("conf", "mldv1_unsolicited_report_interval", MILLISECONDS_IN_HOUR),
        ("conf", "mldv2_unsolicited_report_interval", MILLISECONDS_IN_HOUR),
        ("neigh", "mcast_solicit", 0),
    ]:
        if netns:
            # No need to remember previous setting of network namespace,
            # since it is going to be destroyed anyway.
            pyroute2.NSPopen(netns.netns, [
                "sysctl", "-w", "net.ipv6." + folder + "." + iface + "." +
                setting + "=" + str(value)
            ],
                             stdout=subprocess.DEVNULL,
                             stderr=subprocess.DEVNULL).wait()
        else:
            try:
                previous = subprocess.check_output([
                    "sysctl",
                    "net.ipv6." + folder + "." + iface + "." + setting
                ])
                sysctl_state.append(previous)
            except:
                pass

            subprocess.run([
                "sysctl", "-w", "net.ipv6." + folder + "." + iface + "." +
                setting + "=" + str(value)
            ],
                           capture_output=True)

    atexit.register(restore_traffic, sysctl_state)
Пример #3
0
    def plug_vip(self, vip, subnet_cidr, gateway,
                 mac_address, mtu=None, vrrp_ip=None, host_routes=None):
        # Validate vip and subnet_cidr, calculate broadcast address and netmask
        try:
            render_host_routes = []
            ip = ipaddress.ip_address(
                vip if isinstance(vip, six.text_type) else six.u(vip))
            network = ipaddress.ip_network(
                subnet_cidr if isinstance(subnet_cidr, six.text_type)
                else six.u(subnet_cidr))
            vip = ip.exploded
            broadcast = network.broadcast_address.exploded
            netmask = (network.prefixlen if ip.version == 6
                       else network.netmask.exploded)
            vrrp_version = None
            if vrrp_ip:
                vrrp_ip_obj = ipaddress.ip_address(
                    vrrp_ip if isinstance(vrrp_ip, six.text_type)
                    else six.u(vrrp_ip)
                )
                vrrp_version = vrrp_ip_obj.version
            if host_routes:
                for hr in host_routes:
                    network = ipaddress.ip_network(
                        hr['destination'] if isinstance(
                            hr['destination'], six.text_type) else
                        six.u(hr['destination']))
                    render_host_routes.append({'network': network,
                                               'gw': hr['nexthop']})
        except ValueError:
            return webob.Response(json=dict(message="Invalid VIP"),
                                  status=400)

        # Check if the interface is already in the network namespace
        # Do not attempt to re-plug the VIP if it is already in the
        # network namespace
        if self._netns_interface_exists(mac_address):
            return webob.Response(
                json=dict(message="Interface already exists"), status=409)

        # Check that the interface has been fully plugged
        self._interface_by_mac(mac_address)

        # Always put the VIP interface as eth1
        primary_interface = consts.NETNS_PRIMARY_INTERFACE
        secondary_interface = "{interface}:0".format(
            interface=primary_interface)

        interface_file_path = self._osutils.get_network_interface_file(
            primary_interface)

        self._osutils.create_netns_dir()

        self._osutils.write_interfaces_file()
        self._osutils.write_vip_interface_file(
            interface_file_path=interface_file_path,
            primary_interface=primary_interface,
            vip=vip,
            ip=ip,
            broadcast=broadcast,
            netmask=netmask,
            gateway=gateway,
            mtu=mtu,
            vrrp_ip=vrrp_ip,
            vrrp_version=vrrp_version,
            render_host_routes=render_host_routes)

        # Update the list of interfaces to add to the namespace
        # This is used in the amphora reboot case to re-establish the namespace
        self._update_plugged_interfaces_file(primary_interface, mac_address)

        # Create the namespace
        netns = pyroute2.NetNS(consts.AMPHORA_NAMESPACE, flags=os.O_CREAT)
        netns.close()

        # Load sysctl in new namespace
        sysctl = pyroute2.NSPopen(consts.AMPHORA_NAMESPACE,
                                  [consts.SYSCTL_CMD, '--system'],
                                  stdout=subprocess.PIPE)

        sysctl.communicate()
        sysctl.wait()
        sysctl.release()

        cmd_list = [['modprobe', 'ip_vs'],
                    [consts.SYSCTL_CMD, '-w', 'net.ipv4.vs.conntrack=1']]
        if ip.version == 4:
            # For lvs function, enable ip_vs kernel module, enable ip_forward
            # conntrack in amphora network namespace.
            cmd_list.append([consts.SYSCTL_CMD, '-w', 'net.ipv4.ip_forward=1'])
        elif ip.version == 6:
            cmd_list.append([consts.SYSCTL_CMD, '-w',
                             'net.ipv6.conf.all.forwarding=1'])
        for cmd in cmd_list:
            ns_exec = pyroute2.NSPopen(consts.AMPHORA_NAMESPACE, cmd,
                                       stdout=subprocess.PIPE)
            ns_exec.wait()
            ns_exec.release()

        with pyroute2.IPRoute() as ipr:
            # Move the interfaces into the namespace
            idx = ipr.link_lookup(address=mac_address)[0]
            ipr.link('set', index=idx, net_ns_fd=consts.AMPHORA_NAMESPACE,
                     IFLA_IFNAME=primary_interface)

        # In an ha amphora, keepalived should bring the VIP interface up
        if (CONF.controller_worker.loadbalancer_topology ==
                consts.TOPOLOGY_ACTIVE_STANDBY):
            secondary_interface = None
        # bring interfaces up
        self._osutils.bring_interfaces_up(
            ip, primary_interface, secondary_interface)

        return webob.Response(json=dict(
            message="OK",
            details="VIP {vip} plugged on interface {interface}".format(
                vip=vip, interface=primary_interface)), status=202)
Пример #4
0
    def plug_vip(self,
                 vip,
                 subnet_cidr,
                 gateway,
                 mac_address,
                 mtu=None,
                 vrrp_ip=None,
                 host_routes=None):
        # Validate vip and subnet_cidr, calculate broadcast address and netmask
        try:
            render_host_routes = []
            ip = ipaddress.ip_address(
                vip if isinstance(vip, six.text_type) else six.u(vip))
            network = ipaddress.ip_network(subnet_cidr if isinstance(
                subnet_cidr, six.text_type) else six.u(subnet_cidr))
            vip = ip.exploded
            broadcast = network.broadcast_address.exploded
            netmask = (network.prefixlen
                       if ip.version is 6 else network.netmask.exploded)
            vrrp_version = None
            if vrrp_ip:
                vrrp_ip_obj = ipaddress.ip_address(vrrp_ip if isinstance(
                    vrrp_ip, six.text_type) else six.u(vrrp_ip))
                vrrp_version = vrrp_ip_obj.version
            if host_routes:
                for hr in host_routes:
                    network = ipaddress.ip_network(
                        hr['destination'] if isinstance(
                            hr['destination'], six.text_type
                        ) else six.u(hr['destination']))
                    render_host_routes.append({
                        'network': network,
                        'gw': hr['nexthop']
                    })
        except ValueError:
            return webob.Response(json=dict(message="Invalid VIP"), status=400)

        # Check if the interface is already in the network namespace
        # Do not attempt to re-plug the VIP if it is already in the
        # network namespace
        if self._netns_interface_exists(mac_address):
            return webob.Response(
                json=dict(message="Interface already exists"), status=409)

        # This is the interface prior to moving into the netns
        default_netns_interface = self._interface_by_mac(mac_address)

        # Always put the VIP interface as eth1
        primary_interface = consts.NETNS_PRIMARY_INTERFACE
        secondary_interface = "{interface}:0".format(
            interface=primary_interface)

        interface_file_path = self._osutils.get_network_interface_file(
            primary_interface)

        self._osutils.create_netns_dir()

        self._osutils.write_interfaces_file()
        self._osutils.write_vip_interface_file(
            interface_file_path=interface_file_path,
            primary_interface=primary_interface,
            vip=vip,
            ip=ip,
            broadcast=broadcast,
            netmask=netmask,
            gateway=gateway,
            mtu=mtu,
            vrrp_ip=vrrp_ip,
            vrrp_version=vrrp_version,
            render_host_routes=render_host_routes)

        # Update the list of interfaces to add to the namespace
        # This is used in the amphora reboot case to re-establish the namespace
        self._update_plugged_interfaces_file(primary_interface, mac_address)

        # Create the namespace
        netns = pyroute2.NetNS(consts.AMPHORA_NAMESPACE, flags=os.O_CREAT)
        netns.close()

        # Load sysctl in new namespace
        sysctl = pyroute2.NSPopen(consts.AMPHORA_NAMESPACE,
                                  [consts.SYSCTL_CMD, '--system'],
                                  stdout=subprocess.PIPE)
        sysctl.communicate()
        sysctl.wait()
        sysctl.release()

        with pyroute2.IPRoute() as ipr:
            # Move the interfaces into the namespace
            idx = ipr.link_lookup(ifname=default_netns_interface)[0]
            ipr.link('set',
                     index=idx,
                     net_ns_fd=consts.AMPHORA_NAMESPACE,
                     IFLA_IFNAME=primary_interface)

        # bring interfaces up
        self._osutils.bring_interfaces_up(ip, primary_interface,
                                          secondary_interface)

        return webob.Response(json=dict(
            message="OK",
            details="VIP {vip} plugged on interface {interface}".format(
                vip=vip, interface=primary_interface)),
                              status=202)