Ejemplo n.º 1
0
 def test_dummy0_unloaded(object):
     require_user('root')
     # firstly unload the dummy module
     with open(os.devnull, 'w') as fnull:
         subprocess.call(['modprobe', '-r', 'dummy'],
                         stdout=fnull,
                         stderr=fnull)
     ip = None
     try:
         # now create the dummy0 -- it will cause the
         # module autoload
         ip = IPDB()
         # that must succeed
         ip.create(ifname='dummy0', kind='dummy').commit()
         # just in case: the second attempt must fail on the
         # create() stage, even w/o any commit()
         try:
             ip.create(ifname='dummy0', kind='dummy')
         except CreateException:
             pass
     except Exception:
         raise
     finally:
         if ip is not None:
             ip.release()
Ejemplo n.º 2
0
    def test_commit_barrier(self):
        require_user("root")

        ifname = uifname()

        # barrier 0
        try:
            ip = IPDB()
            config.commit_barrier = 0
            ts1 = time.time()
            ip.create(ifname=ifname, kind="dummy").commit()
            ts2 = time.time()
            assert 0 < (ts2 - ts1) < 1
        except:
            raise
        finally:
            config.commit_barrier = 0.2
            ip.interfaces[ifname].remove().commit()
            ip.release()

        # barrier 5
        try:
            ip = IPDB()
            config.commit_barrier = 5
            ts1 = time.time()
            ip.create(ifname=ifname, kind="dummy").commit()
            ts2 = time.time()
            assert 5 < (ts2 - ts1) < 6
        except:
            raise
        finally:
            config.commit_barrier = 0.2
            ip.interfaces[ifname].remove().commit()
            ip.release()
Ejemplo n.º 3
0
    def test_move_ns_pid(self):
        foo = str(uuid4())
        bar = str(uuid4())
        ifA = uifname()
        netnsmod.create(foo)
        netnsmod.create(bar)

        ns_foo = IPDB(nl=NetNS(foo))
        ns_bar = IPDB(nl=NetNS(bar))

        try:
            ns_foo.create(ifname=ifA, kind='dummy').commit()
            with ns_foo.interfaces[ifA] as iface:
                iface.net_ns_pid = ns_bar.nl.server.pid

            assert ifA in ns_bar.interfaces.keys()
            assert ifA not in ns_foo.interfaces.keys()

            with ns_bar.interfaces[ifA] as iface:
                iface.net_ns_pid = ns_foo.nl.server.pid

            assert ifA not in ns_bar.interfaces.keys()
            assert ifA in ns_foo.interfaces.keys()

        finally:
            ns_foo.release()
            ns_bar.release()
            netnsmod.remove(foo)
            netnsmod.remove(bar)
Ejemplo n.º 4
0
class TestDirect(object):

    def setup(self):
        self.ifname = uifname()
        self.ip = IPDB(mode='direct')
        try:
            self.ip.create(ifname=self.ifname, kind='dummy')
        except:
            pass

    def teardown(self):
        try:
            self.ip.interfaces[self.ifname].remove()
        except KeyError:
            pass
        self.ip.release()

    def test_context_fail(self):
        require_user('root')
        try:
            with self.ip.interfaces[self.ifname] as i:
                i.down()
        except TypeError:
            pass

    def test_create(self):
        require_user('root')
        ifname = uifname()
        assert ifname not in self.ip.interfaces
        self.ip.create(ifname=ifname, kind='dummy')
        assert ifname in self.ip.interfaces
        self.ip.interfaces[ifname].remove()
        assert ifname not in self.ip.interfaces

    def test_updown(self):
        require_user('root')

        assert not (self.ip.interfaces[self.ifname].flags & 1)
        self.ip.interfaces[self.ifname].up()

        assert self.ip.interfaces[self.ifname].flags & 1
        self.ip.interfaces[self.ifname].down()

        assert not (self.ip.interfaces[self.ifname].flags & 1)

    def test_exceptions_last(self):
        try:
            self.ip.interfaces.lo.last()
        except TypeError:
            pass

    def test_exception_review(self):
        try:
            self.ip.interfaces.lo.review()
        except TypeError:
            pass
Ejemplo n.º 5
0
class _TestDhcpClient(object):

    def setup(self):
        require_user('root')
        require_executable('busybox')
        self.ip = IPDB()
        # create internal network
        self.if1 = uifname()
        self.if2 = uifname()
        self.ip.create(kind='veth', ifname=self.if1, peer=self.if2).commit()
        # set interfaces up
        with self.ip.interfaces[self.if1] as i:
            i.add_ip('172.16.101.1/24')
            i.up()

        with self.ip.interfaces[self.if2] as i:
            i.up()
        # prepare configuration for udhcpd
        with open('udhcpd.conf.in', 'r') as conf_in:
            with open('udhcpd.conf', 'w') as conf_out:
                conf_out.write('interface %s\n' % self.if1)
                conf_out.write(conf_in.read())
        # run busybox dhcp server on $if1
        with open(os.devnull, 'w') as fnull:
            subprocess.check_call(['busybox', 'udhcpd', 'udhcpd.conf'],
                                  stdout=fnull,
                                  stderr=fnull)

    def teardown(self):
        # read pid from file and kill the server
        with open('udhcpd.pid', 'r') as pid_file:
            pid = int(pid_file.read())
            os.kill(pid, 15)
        # teardown interfaces (enough to remove only master)
        self.ip.interfaces[self.if1].remove().commit()
        # release IPDB
        self.ip.release()
        # remove configuration file
        os.unlink('udhcpd.conf')
        # collect garbage
        gc.collect()

    def test_defaults(self):
        msg = dhclient.action(self.if2)
        assert msg['yiaddr'].startswith('172.16.101.')
        assert msg['op'] == BOOTREPLY
        assert msg['options']['message_type'] == DHCPACK
        assert msg['options']['router'] == ['172.16.101.1']
        assert msg['options']['server_id'] == '172.16.101.1'
        assert msg['options']['subnet_mask'] == '255.255.255.0'
        assert set(msg['options']['name_server']) ==\
            set(('172.16.101.1', '172.16.101.2'))
Ejemplo n.º 6
0
	def createInterface(self):
		ipdb = IPDB()
		ipdb.create(ifname=self.veth0, kind='veth', peer=self.veth1).commit()

		with ipdb.interfaces[self.veth0] as i:
			i.up()

		with ipdb.interfaces[self.veth1] as i:
			i.up()
			i.net_ns_fd = self.nsname

		with ipdb.interfaces[self.bridge_iface] as i:
			i.add_port(ipdb.interfaces[self.veth0])

		ipdb.release()
Ejemplo n.º 7
0
def createService(name, terminalName, svcId):
    subprocess.call(["ovs-vsctl", "add-br", "vs-" + name])
    if_svc_name = name
    if_terminal_name = name + '_' + terminalName
    ip_host = IPDB()
    ip_host.create(ifname=if_svc_name, kind='veth', peer=if_terminal_name).commit()
    with ip_host.interfaces[if_svc_name] as veth:
        veth.up()
    with ip_host.interfaces[if_terminal_name] as veth:
        veth.up()
    ip_host.release()
    subprocess.call(["ovs-vsctl", "add-port", "vs-" + name, if_svc_name])
    subprocess.call(["ovs-vsctl", "add-port", "br0", if_terminal_name])
    subprocess.call(["ovs-vsctl", "set", "port", if_terminal_name, "tag=" + str(svcId)])
    return json.dumps({ 'status' : 'created service'})
Ejemplo n.º 8
0
    def test_create(self):
        require_user('root')

        nsid = str(uuid4())
        ipdb_main = IPDB()
        ipdb_test = IPDB(nl=NetNS(nsid))
        if1 = uifname()
        if2 = uifname()

        # create VETH pair
        ipdb_main.create(ifname=if1, kind='veth', peer=if2).commit()

        # move the peer to netns
        with ipdb_main.interfaces[if2] as veth:
            veth.net_ns_fd = nsid

        # assign addresses
        with ipdb_main.interfaces[if1] as veth:
            veth.add_ip('172.16.200.1/24')
            veth.up()

        with ipdb_test.interfaces[if2] as veth:
            veth.add_ip('172.16.200.2/24')
            veth.up()

        # ping peer
        try:
            with open('/dev/null', 'w') as fnull:
                subprocess.check_call(['ping', '-c', '1', '172.16.200.2'],
                                      stdout=fnull, stderr=fnull)
            ret_ping = True
        except Exception:
            ret_ping = False

        # check ARP
        time.sleep(0.5)
        ret_arp = '172.16.200.1' in list(ipdb_test.interfaces[if2].neighbours)
        # ret_arp = list(ipdb_test.interfaces.v0p1.neighbours)

        # cleanup
        ipdb_main.interfaces[if1].remove().commit()
        ipdb_main.release()
        ipdb_test.release()
        netnsmod.remove(nsid)

        assert ret_ping
        assert ret_arp
        assert nsid not in netnsmod.listnetns()
Ejemplo n.º 9
0
def createEndpoint(name, svcName, endpointtype):
    if endpointtype == 'ns':
        ip_host = IPDB()
        ip_host.create(ifname=name, kind='veth', peer=name + '_' + svcName).commit()
        ip_ns = IPDB(nl=NetNS(name))
        with ip_host.interfaces[name] as veth:
            veth.net_ns_fd = name
            veth.up()
        with ip_host.interfaces[name + '_' + svcName] as veth:
            veth.up()
        subprocess.call(["ovs-vsctl", "add-port", "vs-" + svcName, name + '_' + svcName])
        ip_host.release()
        ip_ns.release()
        nsp = NSPopen(name, ['dhclient', '-lf', '/tmp/' + name + '.lease', name], stdout=subprocess.PIPE)
        nsp.wait()
        nsp.release()
    if endpointtype == 'lxc':
        subprocess.call(['/usr/bin/lxc-clone','template',name])
        lxcUpOvsScript = '#!/bin/bash\n'
        lxcUpOvsScript += 'BRIDGE="vs-'+ svcName + '"\n'
        lxcUpOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n'
        lxcUpOvsScript += 'ovs-vsctl add-port $BRIDGE $5\n'
        f = open('/var/lib/lxc/' + name + '/ovsup.sh','w+')
        f.write(lxcUpOvsScript)
        f.close()
        lxcDownOvsScript = '#!/bin/bash\n'
        lxcDownOvsScript += 'BRIDGE="vs-'+ svcName + '"\n'
        lxcDownOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n'
        f = open('/var/lib/lxc/' + name + '/ovsdown.sh','w+')
        f.write(lxcDownOvsScript)
        f.close()
        os.chmod('/var/lib/lxc/' + name + '/ovsup.sh',stat.S_IRWXU)
        os.chmod('/var/lib/lxc/' + name + '/ovsdown.sh',stat.S_IRWXU)
        lxcConfig = 'lxc.include = /usr/share/lxc/config/ubuntu.common.conf\n'
        lxcConfig += 'lxc.arch = x86_64\n' 
        lxcConfig += 'lxc.rootfs = /var/lib/lxc/' + name + '/rootfs\n'
        lxcConfig += 'lxc.utsname = ' + name + '\n'
        lxcConfig += 'lxc.network.type = veth\n'
        lxcConfig += 'lxc.network.veth.pair = ' + name + '\n'
        lxcConfig += 'lxc.network.script.up = /var/lib/lxc/' + name + '/ovsup.sh\n'
        lxcConfig += 'lxc.network.script.down = /var/lib/lxc/' + name + '/ovsdown.sh\n'
        lxcConfig += 'lxc.network.flags = up\n'
        f = open('/var/lib/lxc/' + name + '/config','w+')
        f.write(lxcConfig)
        f.close()
        subprocess.call(['/usr/bin/lxc-start','-d','-n',name])
        pass
    return json.dumps({ 'status' : 'created endpoint'})
Ejemplo n.º 10
0
 def test_dummy0_loaded(object):
     require_user("root")
     # assert the module is loaded
     ifA = uifname()
     ip = IPDB()
     ip.create(ifname=ifA, kind="dummy").commit()
     try:
         # try to create and fail in create()
         ip.create(ifname="dummy0", kind="dummy")
     except CreateException:
         pass
     except Exception:
         raise
     finally:
         ip.interfaces[ifA].remove().commit()
         ip.release()
Ejemplo n.º 11
0
class TestDhcpClient(object):
    def setup(self):
        require_user("root")
        require_executable("busybox")
        self.ip = IPDB()
        # create internal network
        self.if1 = "dh1-%i" % os.getpid()
        self.if2 = "dh2-%i" % os.getpid()
        self.ip.create(kind="veth", ifname=self.if1, peer=self.if2).commit()
        # set interfaces up
        with self.ip.interfaces[self.if1] as i:
            i.add_ip("172.16.101.1/24")
            i.up()

        with self.ip.interfaces[self.if2] as i:
            i.up()
        # prepare configuration for udhcpd
        with open("udhcpd.conf.in", "r") as conf_in:
            with open("udhcpd.conf", "w") as conf_out:
                conf_out.write("interface %s\n" % self.if1)
                conf_out.write(conf_in.read())
        # run busybox dhcp server on $if1
        with open(os.devnull, "w") as fnull:
            subprocess.check_call(["busybox", "udhcpd", "udhcpd.conf"], stdout=fnull, stderr=fnull)

    def teardown(self):
        # read pid from file and kill the server
        with open("udhcpd.pid", "r") as pid_file:
            pid = int(pid_file.read())
            os.kill(pid, 15)
        # teardown interfaces (enough to remove only master)
        self.ip.interfaces[self.if1].remove().commit()
        # release IPDB
        self.ip.release()
        # remove configuration file
        os.unlink("udhcpd.conf")

    def test_defaults(self):
        msg = dhclient.action(self.if2)
        assert msg["yiaddr"].startswith("172.16.101.")
        assert msg["op"] == BOOTREPLY
        assert msg["options"]["message_type"] == DHCPACK
        assert msg["options"]["router"] == ["172.16.101.1"]
        assert msg["options"]["server_id"] == "172.16.101.1"
        assert msg["options"]["subnet_mask"] == "255.255.255.0"
        assert set(msg["options"]["name_server"]) == set(("172.16.101.1", "172.16.101.2"))
Ejemplo n.º 12
0
    def test_rename_plus_ipv6(self):
        require_user('root')

        mtu = 1280  # mtu must be >= 1280 if you plan to use IPv6
        txqlen = 2000
        nsid = str(uuid4())
        ipdb_main = IPDB()
        ipdb_test = IPDB(nl=NetNS(nsid))
        if1 = uifname()
        if2 = uifname()
        if3 = uifname()

        # create
        ipdb_main.create(kind='veth',
                         ifname=if1,
                         peer=if2,
                         mtu=mtu,
                         txqlen=txqlen).commit()

        # move
        with ipdb_main.interfaces[if2] as veth:
            veth.net_ns_fd = nsid

        # set it up
        with ipdb_test.interfaces[if2] as veth:
            veth.add_ip('fdb3:84e5:4ff4:55e4::1/64')
            veth.add_ip('fdff:ffff:ffff:ffc0::1/64')
            veth.mtu = mtu
            veth.txqlen = txqlen
            veth.up()
            veth.ifname = if3

        veth = ipdb_test.interfaces.get(if3, None)
        ipdb_main.release()
        ipdb_test.release()
        netnsmod.remove(nsid)

        # check everything
        assert ('fdb3:84e5:4ff4:55e4::1', 64) in veth.ipaddr
        assert ('fdff:ffff:ffff:ffc0::1', 64) in veth.ipaddr
        assert veth.flags & 1
        assert veth.mtu == mtu
        assert veth.txqlen == txqlen
Ejemplo n.º 13
0
    def test_rename_plus_ipv6(self):
        require_user('root')

        mtu = 1280  # mtu must be >= 1280 if you plan to use IPv6
        txqlen = 2000
        nsid = str(uuid4())
        ipdb_main = IPDB()
        ipdb_test = IPDB(nl=NetNS(nsid))
        if1 = uifname()
        if2 = uifname()
        if3 = uifname()

        # create
        ipdb_main.create(kind='veth',
                         ifname=if1,
                         peer=if2,
                         mtu=mtu,
                         txqlen=txqlen).commit()

        # move
        with ipdb_main.interfaces[if2] as veth:
            veth.net_ns_fd = nsid

        # set it up
        with ipdb_test.interfaces[if2] as veth:
            veth.add_ip('fdb3:84e5:4ff4:55e4::1/64')
            veth.add_ip('fdff:ffff:ffff:ffc0::1/64')
            veth.mtu = mtu
            veth.txqlen = txqlen
            veth.up()
            veth.ifname = if3

        veth = ipdb_test.interfaces.get(if3, None)
        ipdb_main.release()
        ipdb_test.release()
        netnsmod.remove(nsid)

        # check everything
        assert ('fdb3:84e5:4ff4:55e4::1', 64) in veth.ipaddr
        assert ('fdff:ffff:ffff:ffc0::1', 64) in veth.ipaddr
        assert veth.flags & 1
        assert veth.mtu == mtu
        assert veth.txqlen == txqlen
Ejemplo n.º 14
0
 def create(self):
     iface = self.containerName + 'veth0'
     ifacePeer = self.containerName + 'veth1'
     ip_main = IPDB()
     ip_sub = IPDB(nl=NetNS(self.containerName))
     ip_main.create(ifname=iface, kind='veth', peer=ifacePeer).commit()
     with ip_main.interfaces[ifacePeer] as veth:
         veth.net_ns_fd = self.containerName
     with ip_main.interfaces[iface] as veth:
         veth.up()
     ip_main.release()
     with ip_sub.interfaces[ifacePeer] as veth:
         #if not self.containerDhcp:
         if not hasattr(self, 'containerDhcp'):
             veth.add_ip(self.containerIp)
         if hasattr(self, 'containerMac'):
             veth.address = self.containerMac
     ip_sub.release()
     ns = NetNS(self.containerName)
     idx = ns.link_lookup(ifname=ifacePeer)[0]
     ns.link('set', index=idx, net_ns_fs=self.containerName, ifname='eth0')
     ns.link('set', index=idx, net_ns_fs=self.containerName, state='up')
     if hasattr(self, 'containerGateway'):
         request = {"dst": "0.0.0.0/0", "gateway": self.containerGateway}
         ns.route("add", **IPRouteRequest(request))
     ns.close()
     subprocess.call(["ovs-vsctl", "add-port", "br0", iface])
     dockerControl = DockerControl(self.containerObject)
     if hasattr(self, 'containerDhcp'):
         dhcpCmd = 'dhclient eth0'
         dockerControl.runCmd(dhcpCmd)
     addressCmd = 'ip address show dev eth0'
     addressInfo = dockerControl.runCmd(addressCmd)
     addressInfoList = addressInfo.splitlines()
     macAddressInfo = addressInfoList[1].split()[1]
     ipAddressInfo = addressInfoList[2].split()[1]
     ipAddressInfoDict = dict({
         'containerName': self.containerName,
         'macAddress': macAddressInfo,
         'ipAddress': ipAddressInfo
     })
     return json.dumps(ipAddressInfoDict)
Ejemplo n.º 15
0
    def create_interface(self):
        ifname = self.__intf_info["ifname"]
        IP_ROUTE = IPRoute()
        if len(IP_ROUTE.link_lookup(ifname=ifname)) > 0:
            self.logger_topo.warning("ip link {} exists so not create it.".format(ifname))
            IP_ROUTE.close()
            return

        if self.__peer:
            if len(IP_ROUTE.link_lookup(ifname=self.__peer)) > 0:
                self.logger_topo.warning("ip link {} exists so not create it.".format(ifname))
                IP_ROUTE.close()
                return
        else:
            # Close IP_ROUTE first anyway
            IP_ROUTE.close()
            ps_intf = r"^\d+: (?P<intf>[\w-]+): "
            p_intf = re.compile(ps_intf, re.MULTILINE)
            _, out, _ = exec_cmd_in_namespace(self.__namespace, ["ip", "link"])
            m_intf = p_intf.findall(out)
            if ifname in m_intf:
                self.logger_topo.warning("ip link {} exists in namespace {} so not create it.".
                                         format(ifname, self.__namespace))
                return

        MAIN_IPDB = IPDB()
        MAIN_IPDB.create(ifname=ifname,
                         kind="veth" if self.__peer else "dummy",
                         peer=self.__peer).commit()
        with MAIN_IPDB.interfaces[ifname] as veth:
            try:
                veth.net_ns_fd = self.__namespace
            except netlink.exceptions.NetlinkError as e:
                MAIN_IPDB.release()
                if e.code == 17:  # "File exists"
                    pass
                else:
                    raise e

        MAIN_IPDB.release()
        self.logger_topo.info("interface {} in namespace {} is created, peer: {}.".
                              format(ifname, self.__namespace, self.__peer))
Ejemplo n.º 16
0
def createInterfaces():
    ip = IPDB() 
    ifdb = ip.interfaces
    tunGW = None
    while tunGW == None:
        tunGW = getTunGW()
    
    #Create VXLAN.
    with ip.create(ifname='vxlan0', kind='vxlan', vxlan_id=42, vxlan_group=str(tunGW), vxlan_port=4789) as vxlan:
        vxlan.up()
        
    #Make sure the ethernet interface is up 
    ifdb.eth0.up()
    
    #Create a bridge interface that will bridge the eth0 interface with the vxlan
    with ip.create(kind='bridge', ifname='br0') as br:
        br.add_port(ifdb.eth0)
        br.add_port(ifdb.vxlan0)
        br.up()
    return 0
Ejemplo n.º 17
0
 def create(self):
     iface = self.containerName + "veth0"
     ifacePeer = self.containerName + "veth1"
     ip_main = IPDB()
     ip_sub = IPDB(nl=NetNS(self.containerName))
     ip_main.create(ifname=iface, kind="veth", peer=ifacePeer).commit()
     with ip_main.interfaces[ifacePeer] as veth:
         veth.net_ns_fd = self.containerName
     with ip_main.interfaces[iface] as veth:
         veth.up()
     ip_main.release()
     with ip_sub.interfaces[ifacePeer] as veth:
         # if not self.containerDhcp:
         if not hasattr(self, "containerDhcp"):
             veth.add_ip(self.containerIp)
         if hasattr(self, "containerMac"):
             veth.address = self.containerMac
     ip_sub.release()
     ns = NetNS(self.containerName)
     idx = ns.link_lookup(ifname=ifacePeer)[0]
     ns.link("set", index=idx, net_ns_fs=self.containerName, ifname="eth0")
     ns.link("set", index=idx, net_ns_fs=self.containerName, state="up")
     if hasattr(self, "containerGateway"):
         request = {"dst": "0.0.0.0/0", "gateway": self.containerGateway}
         ns.route("add", **IPRouteRequest(request))
     ns.close()
     subprocess.call(["ovs-vsctl", "add-port", "br0", iface])
     dockerControl = DockerControl(self.containerObject)
     if hasattr(self, "containerDhcp"):
         dhcpCmd = "dhclient eth0"
         dockerControl.runCmd(dhcpCmd)
     addressCmd = "ip address show dev eth0"
     addressInfo = dockerControl.runCmd(addressCmd)
     addressInfoList = addressInfo.splitlines()
     macAddressInfo = addressInfoList[1].split()[1]
     ipAddressInfo = addressInfoList[2].split()[1]
     ipAddressInfoDict = dict(
         {"containerName": self.containerName, "macAddress": macAddressInfo, "ipAddress": ipAddressInfo}
     )
     return json.dumps(ipAddressInfoDict)
Ejemplo n.º 18
0
def create_bridge(br_name, phy_ip):
    """
    Create a bridge for connecting the container clients to the network.

    :param br_name: Name of the bridge to create.
    :param phy_ip: IP of the physical interface to include in the bridge.
    :return: True if success, False if failure
    """

    log.info("Creating bridge %s." % br_name)

    assert (phy_ip.startswith('10.') or phy_ip.startswith('192.'))

    ipdb = IPDB()

    if br_name in ipdb.interfaces.keys():
        log.fatal("A bridge/interface with the name %s already exists!" %
                  br_name)
        return False

    phy_eth = None

    for eth in ipdb.interfaces.keys():
        if type(eth) is int: continue
        for ip, netmask in ipdb.interfaces[eth]['ipaddr']:
            log.debug("%s: %s" % (eth, ip))
            if ip == phy_ip:
                phy_eth = (eth, ip, netmask)
                break

    if phy_eth is None:
        log.fatal("Could not find an interface with IP '%s'!" % phy_ip)
        return False

    log.info("Using interface %s for the bridge." % str(phy_eth))

    log.debug("Creating bridge with ifname %s." % br_name)

    with ipdb.create(kind='bridge', ifname=br_name) as br:
        br.add_port(ipdb.interfaces[phy_eth[0]])
        br.up()
        br.add_ip('%s/%s' % (phy_eth[1], phy_eth[2]))

    log.debug("Removing IP %s from interface %s." % (phy_eth[1], phy_eth))

    with ipdb.interfaces[phy_eth[0]] as i:
        i.del_ip('%s/%s' % (phy_eth[1], phy_eth[2]))

    ipdb.commit()
    ipdb.release()

    return True
Ejemplo n.º 19
0
    def test_vrouter(self):
        require_user('root')
        nsid = str(uuid.uuid4())
        ns = NetNS(nsid)
        ipdb = IPDB()
        ipns = IPDB(nl=ns)
        try:
            ipdb.create(ifname='ve0p0', peer='ve0p1', kind='veth').commit()
            ipdb.interfaces.ve0p1.net_ns_fd = nsid
            ipdb.commit()

            with ipns.interfaces.ve0p1 as i:
                i.set_ifname('eth0')
                i.up()

        except:
            raise
        finally:
            ipdb.interfaces.ve0p0.remove()
            ipdb.commit()
            ipdb.release()
            ipns.release()
            ns.remove()
Ejemplo n.º 20
0
    def test_vrouter(self):
        require_user('root')
        nsid = str(uuid.uuid4())
        ns = NetNS(nsid)
        ipdb = IPDB()
        ipns = IPDB(nl=ns)
        try:
            ipdb.create(ifname='ve0p0', peer='ve0p1', kind='veth').commit()
            ipdb.interfaces.ve0p1.net_ns_fd = nsid
            ipdb.commit()

            with ipns.interfaces.ve0p1 as i:
                i.set_ifname('eth0')
                i.up()

        except:
            raise
        finally:
            ipdb.interfaces.ve0p0.remove()
            ipdb.commit()
            ipdb.release()
            ipns.release()
            ns.remove()
Ejemplo n.º 21
0
class _TestIPDBRaces(object):
    def setup(self):
        self.ip = IPDB()

    def teardown(self):
        self.ip.release()

    def test_initdb(self):
        tnum = len(threading.enumerate())
        for _ in range(RESPAWNS):
            len(self.ip.interfaces.keys())
            len(self.ip.routes.keys())
            len(self.ip.rules.keys())
            self.ip.initdb()
            assert len(threading.enumerate()) <= tnum

    def _ports_mtu_race(self, kind):
        port1 = (self.ip.create(ifname=uifname(), kind='dummy',
                                mtu=1280).commit())
        port2 = (self.ip.create(ifname=uifname(), kind='dummy').commit())
        master = (self.ip.create(ifname=uifname(), kind=kind).commit())

        try:
            master.add_port(port1).commit()
            master.add_port(port2).commit()
        except:
            raise
        finally:
            port1.remove().commit()
            port2.remove().commit()
            master.remove().commit()

    def test_bridge_mtu(self):
        require_user('root')
        for _ in range(300):
            self._ports_mtu_race('bridge')
Ejemplo n.º 22
0
class TestExplicit(object):
    ip = None
    mode = "explicit"

    def setup(self):
        self.ifaces = []
        self.ifd = self.get_ifname()
        create_link(self.ifd, kind="dummy")
        self.ip = IPDB(mode=self.mode)

    def get_ifname(self):
        ifname = uifname()
        self.ifaces.append(ifname)
        return ifname

    def teardown(self):
        for name in self.ifaces:
            try:
                # just a hardcore removal
                self.ip.nl.link_remove(self.ip.interfaces[name].index)
            except Exception:
                pass
        self.ip.release()
        self.ifaces = []

    def test_simple(self):
        assert len(list(self.ip.interfaces.keys())) > 0

    def test_empty_transaction(self):
        assert "lo" in self.ip.interfaces
        with self.ip.interfaces.lo as i:
            assert isinstance(i.mtu, int)

    def test_idx_len(self):
        assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys())

    def test_idx_set(self):
        assert set(self.ip.by_name.values()) == set(self.ip.by_index.values())

    def test_idx_types(self):
        assert all(isinstance(i, int) for i in self.ip.by_index.keys())
        assert all(isinstance(i, basestring) for i in self.ip.by_name.keys())

    def test_addr_attributes(self):
        require_user("root")

        if1 = self.get_ifname()
        if2 = self.get_ifname()

        with self.ip.create(ifname=if1, kind="dummy") as i:
            # +scope host (=> broadcast == None)
            i.add_ip("172.16.102.1/24", scope=254)

        with self.ip.create(ifname=if2, kind="dummy") as i:
            # +broadcast (default scope == 0)
            i.add_ip("172.16.103.1/24", broadcast="172.16.103.128")

        index = self.ip.interfaces[if1]["index"]
        addr = self.ip.nl.get_addr(index=index)[0]
        assert addr["scope"] == 254
        assert addr.get_attr("IFA_BROADCAST") is None

        index = self.ip.interfaces[if2]["index"]
        addr = self.ip.nl.get_addr(index=index)[0]
        assert addr["scope"] == 0
        assert addr.get_attr("IFA_BROADCAST") == "172.16.103.128"

    def test_addr_loaded(self):
        for name in self.ip.by_name:
            assert len(self.ip.interfaces[name]["ipaddr"]) == len(get_ip_addr(name))

    def test_reprs(self):
        assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring)
        assert isinstance(repr(self.ip.interfaces.lo), basestring)

    def test_dotkeys(self):
        # self.ip.lo hint for ipython
        assert "lo" in dir(self.ip.interfaces)
        assert "lo" in self.ip.interfaces
        assert self.ip.interfaces.lo == self.ip.interfaces["lo"]
        # create attribute
        self.ip.interfaces["newitem"] = True
        self.ip.interfaces.newattr = True
        self.ip.interfaces.newitem = None
        assert self.ip.interfaces.newitem == self.ip.interfaces["newitem"]
        assert self.ip.interfaces.newitem is None
        # delete attribute
        del self.ip.interfaces.newitem
        del self.ip.interfaces.newattr
        assert "newattr" not in dir(self.ip.interfaces)
        # test hasattr protocol
        assert hasattr(self.ip.interfaces, "nonexistinginterface") is False

    @skip_if_not_supported
    def test_vlan_slave_bridge(self):
        # https://github.com/svinota/pyroute2/issues/58
        # based on the code by Petr Horáček
        dXname = self.get_ifname()
        vXname = self.get_ifname()
        vYname = self.get_ifname()
        brname = self.get_ifname()

        require_user("root")
        dX = self.ip.create(ifname=dXname, kind="dummy").commit()
        vX = self.ip.create(ifname=vXname, kind="vlan", link=dX, vlan_id=101).commit()
        vY = self.ip.create(ifname=vYname, kind="vlan", link=dX, vlan_id=102).commit()
        with self.ip.create(ifname=brname, kind="bridge") as i:
            i.add_port(vX)
            i.add_port(vY["index"])

        assert vX["index"] in self.ip.interfaces[brname]["ports"]
        assert vY["index"] in self.ip.interfaces[brname].ports
        assert vX["link"] == dX["index"]
        assert vY["link"] == dX["index"]
        assert vX["master"] == self.ip.interfaces[brname]["index"]
        assert vY["master"] == self.ip.interfaces[brname].index

    def _test_commit_hook_positive(self):
        require_user("root")

        # test callback, that adds an address by itself --
        # just to check the possibility
        def cb(interface, snapshot, transaction):
            self.ip.nl.addr("add", self.ip.interfaces[self.ifd].index, address="172.16.22.1", mask=24)

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it
        if self.ip.interfaces[self.ifd]._mode == "explicit":
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip("172.16.21.1/24")
        self.ip.interfaces[self.ifd].commit()

        # added address should be there
        assert ("172.16.21.1", 24) in self.ip.interfaces[self.ifd].ipaddr
        # and the one, added by the callback, too
        assert ("172.16.22.1", 24) in self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def _test_commit_hook_negative(self):
        require_user("root")

        # test exception to differentiate
        class CBException(Exception):
            pass

        # test callback, that always fail
        def cb(interface, snapshot, transaction):
            raise CBException()

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it; should fail
        # 'cause of the callback
        if self.ip.interfaces[self.ifd]._mode == "explicit":
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip("172.16.21.1/24")
        try:
            self.ip.interfaces[self.ifd].commit()
        except CBException:
            pass

        # added address should be removed
        assert ("172.16.21.1", 24) not in self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def test_review(self):
        assert len(self.ip.interfaces.lo._tids) == 0
        if self.ip.interfaces.lo._mode == "explicit":
            self.ip.interfaces.lo.begin()
        self.ip.interfaces.lo.add_ip("172.16.21.1/24")
        r = self.ip.interfaces.lo.review()
        assert len(r["+ipaddr"]) == 1
        assert len(r["-ipaddr"]) == 0
        assert len(r["+ports"]) == 0
        assert len(r["-ports"]) == 0
        # +/-ipaddr, +/-ports
        assert len([i for i in r if r[i] is not None]) == 4
        self.ip.interfaces.lo.drop()

    def test_rename(self):
        require_user("root")

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind="dummy").commit()

        if self.ip.interfaces[ifA]._mode == "explicit":
            self.ip.interfaces[ifA].begin()
        self.ip.interfaces[ifA].ifname = ifB
        self.ip.interfaces[ifA].commit()

        assert ifB in self.ip.interfaces
        assert ifA not in self.ip.interfaces

        if self.ip.interfaces[ifB]._mode == "explicit":
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifB].ifname = ifA
        self.ip.interfaces[ifB].commit()

        assert ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces

    def test_routes_keys(self):
        assert "172.16.0.0/24" not in self.ip.routes
        # create but not commit
        self.ip.routes.add(dst="172.16.0.0/24", gateway="127.0.0.1")
        # checks
        assert "172.16.0.0/24" in self.ip.routes
        assert "172.16.0.0/24" in list(self.ip.routes.keys())

    def test_routes(self):
        require_user("root")
        assert "172.16.0.0/24" not in self.ip.routes

        # create a route
        with self.ip.routes.add({"dst": "172.16.0.0/24", "gateway": "127.0.0.1"}) as r:
            pass
        assert "172.16.0.0/24" in self.ip.routes.keys()
        assert grep("ip ro", pattern="172.16.0.0/24.*127.0.0.1")

        # change the route
        with self.ip.routes["172.16.0.0/24"] as r:
            r.gateway = "127.0.0.2"
        assert self.ip.routes["172.16.0.0/24"].gateway == "127.0.0.2"
        assert grep("ip ro", pattern="172.16.0.0/24.*127.0.0.2")

        # delete the route
        with self.ip.routes["172.16.0.0/24"] as r:
            r.remove()
        assert "172.16.0.0/24" not in self.ip.routes.keys()
        assert not grep("ip ro", pattern="172.16.0.0/24")

    def test_routes_multipath_gateway(self):
        require_user("root")
        ifR = self.get_ifname()

        with self.ip.create(ifname=ifR, kind="dummy") as i:
            i.add_ip("172.16.231.1/24")
            i.up()

        r = self.ip.routes.add(
            {
                "dst": "172.16.232.0/24",
                "multipath": [
                    {"gateway": "172.16.231.2", "hops": 20},
                    {"gateway": "172.16.231.3", "hops": 30},
                    {"gateway": "172.16.231.4"},
                ],
            }
        )
        r.commit()
        assert grep("ip ro", pattern="172.16.232.0/24")
        assert grep("ip ro", pattern="nexthop.*172.16.231.2.*weight.*21")
        assert grep("ip ro", pattern="nexthop.*172.16.231.3.*weight.*31")
        assert grep("ip ro", pattern="nexthop.*172.16.231.4.*weight.*1")

        with self.ip.routes["172.16.232.0/24"] as r:
            r.add_nh({"gateway": "172.16.231.5", "hops": 50})
            r.del_nh({"gateway": "172.16.231.2"})
        assert grep("ip ro", pattern="172.16.232.0/24")
        assert grep("ip ro", pattern="nexthop.*172.16.231.5.*weight.*51")
        assert grep("ip ro", pattern="nexthop.*172.16.231.3.*weight.*31")
        assert grep("ip ro", pattern="nexthop.*172.16.231.4.*weight.*1")

    def test_routes_metrics(self):
        require_user("root")
        assert "172.16.0.0/24" not in self.ip.routes.keys()

        # create a route
        self.ip.routes.add({"dst": "172.16.0.0/24", "gateway": "127.0.0.1", "metrics": {"mtu": 1360}}).commit()
        assert grep("ip ro", pattern="172.16.0.0/24.*mtu 1360")

        # change metrics
        with self.ip.routes["172.16.0.0/24"] as r:
            r.metrics.mtu = 1400
        assert self.ip.routes["172.16.0.0/24"]["metrics"]["mtu"] == 1400
        assert grep("ip ro", pattern="172.16.0.0/24.*mtu 1400")

        # delete the route
        with self.ip.routes["172.16.0.0/24"] as r:
            r.remove()

        assert "172.16.0.0/24" not in self.ip.routes.keys()
        assert not grep("ip ro", pattern="172.16.0.0/24")

    def test_wait_ip_exact(self):
        ts = time.time()
        ret = self.ip.interfaces.lo.wait_ip("127.0.0.1", timeout=2)
        assert (time.time() - ts) < 2
        assert ret

    def test_wait_ip_net(self):
        ts = time.time()
        ret = self.ip.interfaces.lo.ipaddr.wait_ip("127.0.0.0", 8, timeout=2)
        assert (time.time() - ts) < 2
        assert ret

    def test_wait_ip_exact_fail(self):
        ts = time.time()
        ret = self.ip.interfaces.lo.wait_ip("1.1.1.1", timeout=2)
        assert (time.time() - ts) >= 2
        assert not ret

    def test_wait_ip_net_fail(self):
        ts = time.time()
        ret = self.ip.interfaces.lo.ipaddr.wait_ip("172.6.0.0", 24, timeout=2)
        assert (time.time() - ts) >= 2
        assert not ret

    @skip_if_not_supported
    def _test_shadow(self, kind):
        ifA = self.get_ifname()

        a = self.ip.create(ifname=ifA, kind=kind).commit()
        if a._mode == "explicit":
            a.begin()
        a.shadow().commit()
        assert ifA in self.ip.interfaces
        assert not grep("ip link", pattern=ifA)
        time.sleep(0.5)
        b = self.ip.create(ifname=ifA, kind=kind).commit()
        assert a == b
        assert grep("ip link", pattern=ifA)

    def test_shadow_bond(self):
        require_user("root")
        self._test_shadow("bond")

    def test_shadow_bridge(self):
        require_user("root")
        self._test_shadow("bridge")

    def test_shadow_dummy(self):
        require_user("root")
        self._test_shadow("dummy")

    def test_updown(self):
        require_user("root")

        if self.ip.interfaces[self.ifd]._mode == "explicit":
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].up()
        self.ip.interfaces[self.ifd].commit()
        assert self.ip.interfaces[self.ifd].flags & 1

        if self.ip.interfaces[self.ifd]._mode == "explicit":
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].down()
        self.ip.interfaces[self.ifd].commit()
        assert not (self.ip.interfaces[self.ifd].flags & 1)

    def test_slave_data(self):
        require_user("root")

        ifBR = self.get_ifname()
        ifP = self.get_ifname()
        self.ip.debug = True

        bridge = self.ip.create(ifname=ifBR, kind="bridge").commit()
        port = self.ip.create(ifname=ifP, kind="dummy").commit()

        if self.ip.mode == "explicit":
            bridge.begin()
        bridge.add_port(port)
        bridge.up()
        bridge.commit()

        li = port.nlmsg.get_attr("IFLA_LINKINFO")
        skind = li.get_attr("IFLA_INFO_SLAVE_KIND")
        sdata = li.get_attr("IFLA_INFO_SLAVE_DATA")
        self.ip.debug = False
        if skind is None or sdata is None:
            raise SkipTest("slave data not provided")

        assert sdata.get_attr("IFLA_BRPORT_STATE") is not None
        assert sdata.get_attr("IFLA_BRPORT_MODE") is not None

    def test_fail_ipaddr(self):
        require_user("root")

        ifA = self.get_ifname()

        i = self.ip.create(ifname=ifA, kind="dummy").commit()
        assert not len(i.ipaddr)
        if i._mode == "explicit":
            i.begin()
        i.add_ip("123.456.789.1024/153")
        try:
            i.commit()
        except socket.error as e:
            if not e.args[0].startswith("illegal IP"):
                raise
        assert not len(i.ipaddr)
        if i._mode == "explicit":
            i.begin()
        i.remove().commit()
        assert ifA not in self.ip.interfaces

    def test_multiple_ips_one_transaction(self):
        require_user("root")

        ifA = self.get_ifname()
        with self.ip.create(kind="dummy", ifname=ifA) as i:
            for x in range(1, 255):
                i.add_ip("172.16.0.%i/24" % x)
            i.up()

        idx = self.ip.interfaces[ifA].index
        assert len(self.ip.nl.get_addr(index=idx, family=2)) == 254

    def test_json_dump(self):
        require_user("root")

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        # set up the interface
        with self.ip.create(kind="dummy", ifname=ifA) as i:
            i.add_ip("172.16.0.1/24")
            i.up()

        # imitate some runtime
        time.sleep(2)

        # make a backup
        backup = self.ip.interfaces[ifA].dump()
        assert isinstance(backup, dict)

        # remove index and protinfo -- make it portable
        del backup["index"]
        if "protinfo" in backup:
            del backup["protinfo"]

        # serialize
        backup = json.dumps(backup)

        # remove the interface
        with self.ip.interfaces[ifA] as i:
            i.remove()

        # create again, but with different name
        self.ip.create(kind="dummy", ifname=ifB).commit()

        # load the backup
        # 1. prepare to the restore: bring it down
        with self.ip.interfaces[ifB] as i:
            i.down()
        # 2. please notice, the interface will be renamed after the backup
        with self.ip.interfaces[ifB] as i:
            i.load(json.loads(backup))

        # check :)
        assert ifA in self.ip.interfaces
        assert ifB not in self.ip.interfaces
        for ipaddr in json.loads(backup)["ipaddr"]:
            assert tuple(ipaddr) in self.ip.interfaces[ifA].ipaddr
        assert self.ip.interfaces[ifA].flags & 1

    def test_freeze_del(self):
        require_user("root")

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip("172.16.0.1/24")
            i.add_ip("172.16.1.1/24")
            i.up()

        # check
        assert ("172.16.0.1", 24) in interface.ipaddr
        assert ("172.16.1.1", 24) in interface.ipaddr
        assert interface.flags & 1

        interface.freeze()

        # delete interface with an external routine
        remove_link(interface.ifname)

        # wait for a second
        time.sleep(1)

        # check if it is back
        ipdb = IPDB()
        try:
            ifc = ipdb.interfaces[self.ifd]
            assert ("172.16.0.1", 24) in ifc.ipaddr
            assert ("172.16.1.1", 24) in ifc.ipaddr
            assert ifc.flags & 1
        except:
            raise
        finally:
            interface.unfreeze()
            ipdb.release()

    def test_freeze(self):
        require_user("root")

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip("172.16.0.1/24")
            i.add_ip("172.16.1.1/24")
            i.up()

        # check
        assert ("172.16.0.1", 24) in interface.ipaddr
        assert ("172.16.1.1", 24) in interface.ipaddr
        assert interface.flags & 1

        # assert routine
        def probe():
            # The freeze results are dynamic: it is not a real freeze,
            # it is a restore routine. So it takes time for results
            # to stabilize
            err = None
            for _ in range(3):
                err = None
                interface.ipaddr.set_target((("172.16.0.1", 24), ("172.16.1.1", 24)))
                interface.ipaddr.target.wait()
                try:
                    assert ("172.16.0.1", 24) in interface.ipaddr
                    assert ("172.16.1.1", 24) in interface.ipaddr
                    assert interface.flags & 1
                    break
                except AssertionError as e:
                    err = e
                    continue
                except Exception as e:
                    err = e
                    break
            if err is not None:
                interface.unfreeze()
                i2.close()
                raise err

        # freeze
        interface.freeze()

        # change the interface somehow
        i2 = IPRoute()
        i2.addr("delete", interface.index, "172.16.0.1", 24)
        i2.addr("delete", interface.index, "172.16.1.1", 24)
        probe()

        # unfreeze
        self.ip.interfaces[self.ifd].unfreeze()

        try:
            i2.addr("delete", interface.index, "172.16.0.1", 24)
            i2.addr("delete", interface.index, "172.16.1.1", 24)
        except:
            pass
        finally:
            i2.close()

        # should be up, but w/o addresses
        interface.ipaddr.set_target(set())
        interface.ipaddr.target.wait(3)
        assert ("172.16.0.1", 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert ("172.16.1.1", 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    def test_snapshots(self):
        require_user("root")

        ifB = self.get_ifname()

        # set up the interface
        with self.ip.interfaces[self.ifd] as i:
            i.add_ip("172.16.0.1/24")
            i.up()

        # check it
        assert ("172.16.0.1", 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

        # make a snapshot
        s = self.ip.interfaces[self.ifd].snapshot()
        i = self.ip.interfaces[self.ifd]

        # check it
        assert i.last_snapshot_id() == s

        # unset the interface
        with self.ip.interfaces[self.ifd] as i:
            i.del_ip("172.16.0.1/24")
            i.down()

        # we can not rename the interface while it is up,
        # so do it in two turns
        with self.ip.interfaces[self.ifd] as i:
            i.ifname = ifB

        # check it
        assert ifB in self.ip.interfaces
        assert self.ifd not in self.ip.interfaces
        y = self.ip.interfaces[ifB]
        assert i == y
        assert ("172.16.0.1", 24) not in y.ipaddr
        assert not (y.flags & 1)

        # revert snapshot
        y.revert(s).commit()

        # check it
        assert ifB not in self.ip.interfaces
        assert self.ifd in self.ip.interfaces
        assert ("172.16.0.1", 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    @skip_if_not_supported
    def _test_ipv(self, ipv, kind):
        require_user("root")

        ifA = self.get_ifname()

        i = self.ip.create(kind=kind, ifname=ifA).commit()
        if self.ip.interfaces[ifA]._mode == "explicit":
            self.ip.interfaces[ifA].begin()

        if ipv == 4:
            addr = "172.16.0.1/24"
        elif ipv == 6:
            addr = "fdb3:84e5:4ff4:55e4::1/64"
        else:
            raise Exception("bad IP version")

        i.add_ip(addr).commit()
        pre_target = addr.split("/")
        target = (pre_target[0], int(pre_target[1]))
        assert target in i["ipaddr"]

    def test_ipv4_dummy(self):
        self._test_ipv(4, "dummy")

    def test_ipv4_bond(self):
        self._test_ipv(4, "bond")

    def test_ipv4_bridge(self):
        self._test_ipv(4, "bridge")

    def test_ipv6_dummy(self):
        self._test_ipv(6, "dummy")

    def test_ipv6_bond(self):
        self._test_ipv(6, "bond")

    def test_ipv6_bridge(self):
        self._test_ipv(6, "bridge")

    @skip_if_not_supported
    def test_create_tuntap_fail(self):
        try:
            self.ip.create(ifname="fAiL", kind="tuntap", mode="fail").commit()
        except:
            assert not grep("ip link", pattern="fAiL")
            return
        raise Exception("tuntap create succeded")

    @skip_if_not_supported
    def test_create_tuntap(self):
        require_user("root")

        ifA = self.get_ifname()
        self.ip.create(ifname=ifA, kind="tuntap", mode="tap", uid=1, gid=1).commit()

        assert ifA in self.ip.interfaces
        assert grep("ip link", pattern=ifA)

    def test_global_create(self):
        require_user("root")

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, kind="dummy")
        self.ip.create(ifname=ifB, kind="dummy")
        self.ip.commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert grep("ip link", pattern=ifA)
        assert grep("ip link", pattern=ifB)

    def test_global_priorities(self):
        require_user("root")
        ifA = self.get_ifname()
        ifB = self.get_ifname()
        ifC = self.get_ifname()
        a = self.ip.create(ifname=ifA, kind="dummy").commit()
        #
        if a._mode == "explicit":
            a.begin()

        # prepare transaction: two interface creations
        # and one failure on an existing interface
        a.set_address("11:22:33:44:55:66")
        b = self.ip.create(ifname=ifB, kind="dummy")
        c = self.ip.create(ifname=ifC, kind="dummy")
        # now assign priorities
        b.ipdb_priority = 15  # will be execute first
        a.ipdb_priority = 10  # second -- and fail
        c.ipdb_priority = 5  # should not be executed
        # prepare watchdogs
        wdb = self.ip.watchdog(ifname=ifB)
        wdc = self.ip.watchdog(ifname=ifC)
        # run the transaction
        try:
            self.ip.commit()
        except NetlinkError:
            pass
        # control system state
        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert ifC in self.ip.interfaces
        assert a.ipdb_scope == "system"
        assert b.ipdb_scope == "create"
        assert c.ipdb_scope == "create"
        assert a.address != "11:22:33:44:55:66"
        assert grep("ip link", pattern=ifA)
        assert not grep("ip link", pattern=ifB)
        assert not grep("ip link", pattern=ifC)
        wdb.wait(1)
        wdc.wait(1)
        assert wdb.is_set
        assert not wdc.is_set

    def test_global_rollback(self):
        require_user("root")

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        a = self.ip.create(ifname=ifA, kind="dummy").commit()
        #
        if a._mode == "explicit":
            a.begin()
        a.remove()
        b = self.ip.create(ifname=ifB, kind="dummy")
        b.set_mtu(1500).set_address("11:22:33:44:55:66")
        try:
            self.ip.commit()
        except NetlinkError:
            pass

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert b.ipdb_scope == "create"
        assert grep("ip link", pattern=ifA)
        assert not grep("ip link", pattern=ifB)

    def test_global_netns(self):
        require_user("root")

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        ns = str(uuid.uuid4())

        with IPDB(nl=NetNS(ns)) as nsdb:
            v1 = self.ip.create(ifname="x" + ifA, kind="veth", peer=ifA)
            v2 = self.ip.create(ifname="x" + ifB, kind="veth", peer=ifB)
            if v1._mode == "explicit":
                v1.begin()
                v2.begin()
            v1.net_ns_fd = ns
            v2.net_ns_fd = ns
            self.ip.commit()
            nsdb.interfaces["x" + ifA].ifname = "eth0"
            nsdb.interfaces["x" + ifB].ifname = "eth1"
            nsdb.commit()
            if self.ip.interfaces[ifA]._mode == "explicit":
                self.ip.interfaces[ifA].begin()
                self.ip.interfaces[ifB].begin()
            self.ip.interfaces[ifA].up()
            self.ip.interfaces[ifB].up()
            self.ip.commit()

        assert "x" + ifA not in self.ip.interfaces
        assert "x" + ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert self.ip.interfaces[ifA].flags & 1
        assert self.ip.interfaces[ifB].flags & 1

        if self.ip.interfaces[ifA]._mode == "explicit":
            self.ip.interfaces[ifA].begin()
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifA].remove()
        self.ip.interfaces[ifB].remove()
        self.ip.commit()
        netns.remove(ns)

    @skip_if_not_supported
    def test_create_veth(self):
        require_user("root")

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind="veth", peer=ifB).commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces

    def test_create_fail(self):
        require_user("root")

        ifA = self.get_ifname()

        # create with mac 11:22:33:44:55:66 should fail
        i = self.ip.create(kind="dummy", ifname=ifA, address="11:22:33:44:55:66")
        try:
            i.commit()
        except NetlinkError:
            pass

        assert i._mode == "invalid"
        assert ifA not in self.ip.interfaces

    def test_create_dqn(self):
        require_user("root")
        ifA = self.get_ifname()

        i = self.ip.create(kind="dummy", ifname=ifA)
        i.add_ip("172.16.0.1/255.255.255.0")
        i.commit()
        assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr
        assert "172.16.0.1/24" in get_ip_addr(interface=ifA)

    def test_create_double_reuse(self):
        require_user("root")

        ifA = self.get_ifname()
        # create an interface
        i1 = self.ip.create(kind="dummy", ifname=ifA).commit()
        try:
            # this call should fail on the very first step:
            # `bala` interface already exists
            self.ip.create(kind="dummy", ifname=ifA)
        except CreateException:
            pass
        # add `reuse` keyword -- now should pass
        i2 = self.ip.create(kind="dummy", ifname=ifA, reuse=True).commit()
        # assert that we have got references to the same interface
        assert i1 == i2

    @skip_if_not_supported
    def _create_double(self, kind):
        require_user("root")
        ifA = self.get_ifname()

        self.ip.create(kind=kind, ifname=ifA).commit()
        try:
            self.ip.create(kind=kind, ifname=ifA).commit()
        except CreateException:
            pass

    def test_create_double_dummy(self):
        self._create_double("dummy")

    def test_create_double_bridge(self):
        self._create_double("bridge")

    def test_create_double_bond(self):
        self._create_double("bond")

    def test_create_plain(self):
        require_user("root")
        ifA = self.get_ifname()

        i = self.ip.create(kind="dummy", ifname=ifA)
        i.add_ip("172.16.0.1/24")
        i.commit()
        assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr
        assert "172.16.0.1/24" in get_ip_addr(interface=ifA)

    def test_create_and_remove(self):
        require_user("root")

        ifA = self.get_ifname()

        with self.ip.create(kind="dummy", ifname=ifA) as i:
            i.add_ip("172.16.0.1/24")
        assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr
        assert "172.16.0.1/24" in get_ip_addr(interface=ifA)

        with self.ip.interfaces[ifA] as i:
            i.remove()
        assert ifA not in self.ip.interfaces

    def test_dqn_mask(self):
        require_user("root")

        iface = self.ip.interfaces[self.ifd]
        with iface as i:
            i.add_ip("172.16.0.1/24")
            i.add_ip("172.16.0.2", mask=24)
            i.add_ip("172.16.0.3/255.255.255.0")
            i.add_ip("172.16.0.4", mask="255.255.255.0")

        assert ("172.16.0.1", 24) in iface.ipaddr
        assert ("172.16.0.2", 24) in iface.ipaddr
        assert ("172.16.0.3", 24) in iface.ipaddr
        assert ("172.16.0.4", 24) in iface.ipaddr

    @skip_if_not_supported
    def test_master_cleanup_del_port(self):
        require_user("root")

        ifMname = self.get_ifname()
        ifPname = self.get_ifname()

        ifM = self.ip.create(ifname=ifMname, kind="bridge").commit()
        ifP = self.ip.create(ifname=ifPname, kind="dummy").commit()

        if self.ip.mode == "explicit":
            ifM.begin()
        ifM.add_port(ifP).commit()

        assert ifP.index in ifM.ports
        assert ifP.master == ifM.index

        if self.ip.mode == "explicit":
            ifM.begin()
        ifM.del_port(ifP).commit()

        assert ifPname in self.ip.interfaces
        assert ifP.index not in ifM.ports
        assert ifP.master is None

    @skip_if_not_supported
    def _create_master(self, kind, **kwarg):

        ifM = self.get_ifname()
        ifP1 = self.get_ifname()
        ifP2 = self.get_ifname()

        self.ip.create(kind="dummy", ifname=ifP1).commit()
        self.ip.create(kind="dummy", ifname=ifP2).commit()

        with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i:
            i.add_port(self.ip.interfaces[ifP1])
            i.add_ip("172.16.0.1/24")

        with self.ip.interfaces[ifM] as i:
            i.add_port(self.ip.interfaces[ifP2])
            i.add_ip("172.16.0.2/24")

        assert ("172.16.0.1", 24) in self.ip.interfaces[ifM].ipaddr
        assert ("172.16.0.2", 24) in self.ip.interfaces[ifM].ipaddr
        assert "172.16.0.1/24" in get_ip_addr(interface=ifM)
        assert "172.16.0.2/24" in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master == self.ip.interfaces[ifM].index
        assert self.ip.interfaces[ifP2].if_master == self.ip.interfaces[ifM].index

        with self.ip.interfaces[ifM] as i:
            i.del_port(self.ip.interfaces[ifP1])
            i.del_port(self.ip.interfaces[ifP2])
            i.del_ip("172.16.0.1/24")
            i.del_ip("172.16.0.2/24")

        assert ("172.16.0.1", 24) not in self.ip.interfaces[ifM].ipaddr
        assert ("172.16.0.2", 24) not in self.ip.interfaces[ifM].ipaddr
        assert "172.16.0.1/24" not in get_ip_addr(interface=ifM)
        assert "172.16.0.2/24" not in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master is None
        assert self.ip.interfaces[ifP2].if_master is None

    def test_create_bridge(self):
        require_user("root")
        self._create_master("bridge")

    def test_create_bond(self):
        require_user("root")
        self._create_master("bond")

    def test_create_team(self):
        require_user("root")
        self._create_master("team")

    def test_create_bond2(self):
        require_user("root")
        self._create_master("bond", bond_mode=2)

    @skip_if_not_supported
    def _create_macvx_mode(self, kind, mode):
        require_user("root")
        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind="dummy", ifname=ifL).commit()
        self.ip.create(**{"kind": kind, "link": ifdb[ifL], "ifname": ifV, "%s_mode" % kind: mode}).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].link == ifdb[ifL].index
            assert ifdb[ifV]["%s_mode" % kind] == mode
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_macvtap_vepa(self):
        return self._create_macvx_mode("macvtap", "vepa")

    def test_create_macvtap_bridge(self):
        return self._create_macvx_mode("macvtap", "bridge")

    def test_create_macvlan_vepa(self):
        return self._create_macvx_mode("macvlan", "vepa")

    def test_create_macvlan_bridge(self):
        return self._create_macvx_mode("macvlan", "bridge")

    def test_create_utf_name(self):
        require_user("root")
        ifO = "ༀ"
        self.ip.create(kind="dummy", ifname=ifO).commit()
        assert ifO in self.ip.interfaces
        assert self.ip.nl.link_lookup(ifname=ifO)
        if self.ip.interfaces[ifO]._mode == "explicit":
            self.ip.interfaces[ifO].begin()
        self.ip.interfaces[ifO].remove().commit()

    @skip_if_not_supported
    def test_create_gre(self):
        require_user("root")

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        with self.ip.create(kind="dummy", ifname=ifL) as i:
            i.add_ip("172.16.0.1/24")
            i.up()

        self.ip.create(kind="gre", ifname=ifV, gre_local="172.16.0.1", gre_remote="172.16.0.2", gre_ttl=16).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].gre_local == "172.16.0.1"
            assert ifdb[ifV].gre_remote == "172.16.0.2"
            assert ifdb[ifV].gre_ttl == 16
        except Exception:
            raise
        finally:
            ip2.release()

    @skip_if_not_supported
    def test_create_gretap(self):
        require_user("root")

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        with self.ip.create(kind="dummy", ifname=ifL) as i:
            i.add_ip("172.16.0.1/24")
            i.up()

        self.ip.create(
            kind="gretap",
            ifname=ifV,
            gre_local="172.16.0.1",
            gre_ikey=1,
            gre_okey=2,
            gre_iflags=0x0020,
            gre_oflags=0x0020,
            gre_collect_metadata=True,
            gre_ttl=16,
        ).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].gre_local == "172.16.0.1"
            assert ifdb[ifV].gre_ikey == 1
            assert ifdb[ifV].gre_okey == 2
            assert ifdb[ifV].gre_iflags == 0x0020
            assert ifdb[ifV].gre_oflags == 0x0020
            if kernel_version_ge(4, 3):
                assert ifdb[ifV].gre_collect_metadata
            assert ifdb[ifV].gre_ttl == 16
        except Exception:
            raise
        finally:
            ip2.release()

    @skip_if_not_supported
    def test_create_vxlan(self):
        require_user("root")

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind="dummy", ifname=ifL).commit()
        self.ip.create(kind="vxlan", ifname=ifV, vxlan_link=ifdb[ifL], vxlan_id=101, vxlan_group="239.1.1.1").commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces

        try:
            assert ifdb[ifV].vxlan_link == ifdb[ifL].index
            assert ifdb[ifV].vxlan_group == "239.1.1.1"
            assert ifdb[ifV].vxlan_id == 101
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_vlan_by_interface(self):
        require_user("root")
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind="dummy", ifname=ifL).commit()
        self.ip.create(kind="vlan", ifname=ifV, link=self.ip.interfaces[ifL], vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == self.ip.interfaces[ifL].index

    def test_create_vlan_by_index(self):
        require_user("root")
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind="dummy", ifname=ifL).commit()
        self.ip.create(kind="vlan", ifname=ifV, link=self.ip.interfaces[ifL].index, vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == self.ip.interfaces[ifL].index

    def test_remove_secondaries(self):
        require_user("root")

        ifA = self.get_ifname()

        with self.ip.create(kind="dummy", ifname=ifA) as i:
            i.add_ip("172.16.0.1", 24)
            i.add_ip("172.16.0.2", 24)

        assert ifA in self.ip.interfaces
        assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr
        assert ("172.16.0.2", 24) in self.ip.interfaces[ifA].ipaddr
        assert "172.16.0.1/24" in get_ip_addr(interface=ifA)
        assert "172.16.0.2/24" in get_ip_addr(interface=ifA)

        if i._mode == "explicit":
            i.begin()

        i.del_ip("172.16.0.1", 24)
        i.del_ip("172.16.0.2", 24)
        i.commit()

        assert ("172.16.0.1", 24) not in self.ip.interfaces[ifA].ipaddr
        assert ("172.16.0.2", 24) not in self.ip.interfaces[ifA].ipaddr
        assert "172.16.0.1/24" not in get_ip_addr(interface=ifA)
        assert "172.16.0.2/24" not in get_ip_addr(interface=ifA)
Ejemplo n.º 23
0
# An example how to use command chaining in IPDB

from pyroute2 import IPDB

ip = IPDB()
# create slave ports
ip.create(ifname='bo0p0', kind='dummy').commit()
ip.create(ifname='bo0p1', kind='dummy').commit()
# set up bonding
ip.create(ifname='bo0', kind='bond', bond_mode=2).\
    add_port(ip.interfaces.bo0p0).\
    add_port(ip.interfaces.bo0p1).\
    add_ip('172.16.0.1/24').\
    add_ip('172.16.0.2/24').\
    option('mtu', 1400).\
    up().\
    commit()

for i in ('bo0p0', 'bo0p1', 'bo0'):
    try:
        ip.interfaces[i].remove().commit()
    except:
        pass
ip.release()
Ejemplo n.º 24
0
class TestExplicit(object):
    ip = None
    mode = 'explicit'

    def setup(self):
        self.ap = AddrPool()
        self.iftmp = 'pr2x{0}'
        self.ifaces = []
        self.ifd = self.get_ifname()
        create_link(self.ifd, kind='dummy')
        self.ip = IPDB(mode=self.mode)

    def get_ifname(self):
        naddr = self.ap.alloc()
        ifname = self.iftmp.format(naddr)
        self.ifaces.append(ifname)
        return ifname

    def teardown(self):
        for name in self.ifaces:
            try:
                with self.ip.interfaces[name] as i:
                    i.remove()
            except:
                pass
        self.ip.release()
        self.ifaces = []

    def test_simple(self):
        assert len(list(self.ip.interfaces.keys())) > 0

    def test_empty_transaction(self):
        assert 'lo' in self.ip.interfaces
        with self.ip.interfaces.lo as i:
            assert isinstance(i.mtu, int)

    def test_idx_len(self):
        assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys())

    def test_idx_set(self):
        assert set(self.ip.by_name.values()) == set(self.ip.by_index.values())

    def test_idx_types(self):
        assert all(isinstance(i, int) for i in self.ip.by_index.keys())
        assert all(isinstance(i, basestring) for i in self.ip.by_name.keys())

    def test_ips(self):
        for name in self.ip.by_name:
            assert len(self.ip.interfaces[name]['ipaddr']) == \
                len(get_ip_addr(name))

    def test_reprs(self):
        assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring)
        assert isinstance(repr(self.ip.interfaces.lo), basestring)

    def test_dotkeys(self):
        # self.ip.lo hint for ipython
        assert 'lo' in dir(self.ip.interfaces)
        assert 'lo' in self.ip.interfaces
        assert self.ip.interfaces.lo == self.ip.interfaces['lo']
        # create attribute
        self.ip.interfaces['newitem'] = True
        self.ip.interfaces.newattr = True
        self.ip.interfaces.newitem = None
        assert self.ip.interfaces.newitem == self.ip.interfaces['newitem']
        assert self.ip.interfaces.newitem is None
        # delete attribute
        del self.ip.interfaces.newitem
        del self.ip.interfaces.newattr
        assert 'newattr' not in dir(self.ip.interfaces)

    def test_vlan_slave_bridge(self):
        # https://github.com/svinota/pyroute2/issues/58
        # based on the code by Petr Horáček
        dXname = self.get_ifname()
        vXname = self.get_ifname()
        vYname = self.get_ifname()
        brname = self.get_ifname()

        require_user('root')
        dX = self.ip.create(ifname=dXname, kind='dummy').commit()
        vX = self.ip.create(ifname=vXname, kind='vlan', link=dX,
                            vlan_id=101).commit()
        vY = self.ip.create(ifname=vYname, kind='vlan', link=dX,
                            vlan_id=102).commit()
        with self.ip.create(ifname=brname, kind='bridge') as i:
            i.add_port(vX)
            i.add_port(vY['index'])

        assert vX['index'] in self.ip.interfaces[brname]['ports']
        assert vY['index'] in self.ip.interfaces[brname].ports
        assert vX['link'] == dX['index']
        assert vY['link'] == dX['index']
        assert vX['master'] == self.ip.interfaces[brname]['index']
        assert vY['master'] == self.ip.interfaces[brname].index

    def _test_commit_hook_positive(self):
        require_user('root')

        # test callback, that adds an address by itself --
        # just to check the possibility
        def cb(interface, snapshot, transaction):
            self.ip.nl.addr('add',
                            self.ip.interfaces[self.ifd].index,
                            address='172.16.22.1',
                            mask=24)

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        self.ip.interfaces[self.ifd].commit()

        # added address should be there
        assert ('172.16.21.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr
        # and the one, added by the callback, too
        assert ('172.16.22.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def _test_commit_hook_negative(self):
        require_user('root')

        # test exception to differentiate
        class CBException(Exception):
            pass

        # test callback, that always fail
        def cb(interface, snapshot, transaction):
            raise CBException()

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it; should fail
        # 'cause of the callback
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        try:
            self.ip.interfaces[self.ifd].commit()
        except CBException:
            pass

        # added address should be removed
        assert ('172.16.21.1', 24) not in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def test_review(self):
        assert len(self.ip.interfaces.lo._tids) == 0
        if self.ip.interfaces.lo._mode == 'explicit':
            self.ip.interfaces.lo.begin()
        self.ip.interfaces.lo.add_ip('172.16.21.1/24')
        r = self.ip.interfaces.lo.review()
        assert len(r['+ipaddr']) == 1
        assert len(r['-ipaddr']) == 0
        assert len(r['+ports']) == 0
        assert len(r['-ports']) == 0
        # +/-ipaddr, +/-ports
        assert len([i for i in r if r[i] is not None]) == 4
        self.ip.interfaces.lo.drop()

    def test_rename(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='dummy').commit()

        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()
        self.ip.interfaces[ifA].ifname = ifB
        self.ip.interfaces[ifA].commit()

        assert ifB in self.ip.interfaces
        assert ifA not in self.ip.interfaces

        if self.ip.interfaces[ifB]._mode == 'explicit':
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifB].ifname = ifA
        self.ip.interfaces[ifB].commit()

        assert ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces

    def test_routes(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes

        # create a route
        with self.ip.routes.add({
                'dst': '172.16.0.0/24',
                'gateway': '127.0.0.1'
        }) as r:
            pass
        assert '172.16.0.0/24' in self.ip.routes.keys()
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1')

        # change the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.gateway = '127.0.0.2'
        assert self.ip.routes['172.16.0.0/24'].gateway == '127.0.0.2'
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.2')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()
        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    def test_route_metrics(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes.keys()

        # create a route
        self.ip.routes.add({
            'dst': '172.16.0.0/24',
            'gateway': '127.0.0.1',
            'metrics': {
                'mtu': 1360
            }
        }).commit()
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1360')

        # change metrics
        with self.ip.routes['172.16.0.0/24'] as r:
            r.metrics.mtu = 1400
        assert self.ip.routes['172.16.0.0/24']['metrics']['mtu'] == 1400
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1400')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()

        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    def _test_shadow(self, kind):
        ifA = self.get_ifname()

        a = self.ip.create(ifname=ifA, kind=kind).commit()
        if a._mode == 'explicit':
            a.begin()
        a.shadow().commit()
        assert ifA in self.ip.interfaces
        assert not grep('ip link', pattern=ifA)
        b = self.ip.create(ifname=ifA, kind=kind).commit()
        assert a == b
        assert grep('ip link', pattern=ifA)

    def test_shadow_bond(self):
        require_user('root')
        require_bond()
        self._test_shadow('bond')

    def test_shadow_bridge(self):
        require_user('root')
        require_bridge()
        self._test_shadow('bridge')

    def test_shadow_dummy(self):
        require_user('root')
        self._test_shadow('dummy')

    def test_updown(self):
        require_user('root')

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].up()
        self.ip.interfaces[self.ifd].commit()
        assert self.ip.interfaces[self.ifd].flags & 1

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].down()
        self.ip.interfaces[self.ifd].commit()
        assert not (self.ip.interfaces[self.ifd].flags & 1)

    def test_fail_ipaddr(self):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(ifname=ifA, kind='dummy').commit()
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.add_ip('123.456.789.1024/153')
        try:
            i.commit()
        except socket.error as e:
            if not e.args[0].startswith('illegal IP'):
                raise
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.remove().commit()
        assert ifA not in self.ip.interfaces

    def test_json_dump(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        # set up the interface
        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2/24')
            i.up()

        # make a backup
        backup = self.ip.interfaces[ifA].dump()
        assert isinstance(backup, dict)

        # remove index -- make it portable
        del backup['index']
        # serialize
        backup = json.dumps(backup)

        # remove the interface
        with self.ip.interfaces[ifA] as i:
            i.remove()

        # create again, but with different name
        self.ip.create(kind='dummy', ifname=ifB).commit()

        # load the backup
        # 1. prepare to the restore: bring it down
        with self.ip.interfaces[ifB] as i:
            i.down()
        # 2. please notice, the interface will be renamed after the backup
        t = self.ip.interfaces[ifB].load(json.loads(backup))
        self.ip.interfaces[ifB].commit(transaction=t)

        # check :)
        assert ifA in self.ip.interfaces
        assert ifB not in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert self.ip.interfaces[ifA].flags & 1

    def test_freeze(self):
        require_user('root')

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.1.1/24')
            i.up()

        # check
        assert ('172.16.0.1', 24) in interface.ipaddr
        assert ('172.16.1.1', 24) in interface.ipaddr
        assert interface.flags & 1

        # assert routine
        def probe():
            # The freeze results are dynamic: it is not a real freeze,
            # it is a restore routine. So it takes time for results
            # to stabilize
            err = None
            for _ in range(3):
                err = None
                interface.ipaddr.set_target(
                    (('172.16.0.1', 24), ('172.16.1.1', 24)))
                interface.ipaddr.target.wait()
                try:
                    assert ('172.16.0.1', 24) in interface.ipaddr
                    assert ('172.16.1.1', 24) in interface.ipaddr
                    assert interface.flags & 1
                    break
                except AssertionError as e:
                    err = e
                    continue
                except Exception as e:
                    err = e
                    break
            if err is not None:
                interface.unfreeze()
                i2.close()
                raise err

        # freeze
        interface.freeze()

        # change the interface somehow
        i2 = IPRoute()
        i2.addr('delete', interface.index, '172.16.0.1', 24)
        i2.addr('delete', interface.index, '172.16.1.1', 24)
        probe()

        # unfreeze
        self.ip.interfaces[self.ifd].unfreeze()

        try:
            i2.addr('delete', interface.index, '172.16.0.1', 24)
            i2.addr('delete', interface.index, '172.16.1.1', 24)
        except:
            pass
        finally:
            i2.close()

        # should be up, but w/o addresses
        interface.ipaddr.set_target(set())
        interface.ipaddr.target.wait(3)
        assert ('172.16.0.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert ('172.16.1.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    def test_snapshots(self):
        require_user('root')

        ifB = self.get_ifname()

        # set up the interface
        with self.ip.interfaces[self.ifd] as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        # check it
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

        # make a snapshot
        s = self.ip.interfaces[self.ifd].snapshot()
        i = self.ip.interfaces[self.ifd]

        # check it
        assert i.last_snapshot_id() == s

        # unset the interface
        with self.ip.interfaces[self.ifd] as i:
            i.del_ip('172.16.0.1/24')
            i.down()

        # we can not rename the interface while it is up,
        # so do it in two turns
        with self.ip.interfaces[self.ifd] as i:
            i.ifname = ifB

        # check it
        assert ifB in self.ip.interfaces
        assert self.ifd not in self.ip.interfaces
        y = self.ip.interfaces[ifB]
        assert i == y
        assert ('172.16.0.1', 24) not in y.ipaddr
        assert not (y.flags & 1)

        # revert snapshot
        y.revert(s).commit()

        # check it
        assert ifB not in self.ip.interfaces
        assert self.ifd in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    def _test_ipv(self, ipv, kind):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(kind=kind, ifname=ifA).commit()
        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()

        if ipv == 4:
            addr = '172.16.0.1/24'
        elif ipv == 6:
            addr = 'fdb3:84e5:4ff4:55e4::1/64'
        else:
            raise Exception('bad IP version')

        i.add_ip(addr).commit()
        pre_target = addr.split('/')
        target = (pre_target[0], int(pre_target[1]))
        assert target in i['ipaddr']

    def test_ipv4_dummy(self):
        self._test_ipv(4, 'dummy')

    def test_ipv4_bond(self):
        self._test_ipv(4, 'bond')

    def test_ipv4_bridge(self):
        self._test_ipv(4, 'bridge')

    def test_ipv6_dummy(self):
        self._test_ipv(6, 'dummy')

    def test_ipv6_bond(self):
        self._test_ipv(6, 'bond')

    def test_ipv6_bridge(self):
        self._test_ipv(6, 'bridge')

    def test_create_tuntap_fail(self):
        try:
            self.ip.create(ifname='fAiL', kind='tuntap', mode='fail').commit()
        except:
            assert not grep('ip link', pattern='fAiL')
            return
        raise Exception('tuntap create succeded')

    def test_create_tuntap(self):
        require_user('root')

        ifA = self.get_ifname()
        self.ip.create(ifname=ifA, kind='tuntap', mode='tap', uid=1,
                       gid=1).commit()

        assert ifA in self.ip.interfaces
        assert grep('ip link', pattern=ifA)

    def test_ovs_kind_aliases(self):
        require_user('root')
        require_executable('ovs-vsctl')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, kind='ovs-bridge').commit()
        self.ip.create(ifname=ifB, kind='openvswitch').commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert grep('ip link', pattern=ifA)
        assert grep('ip link', pattern=ifB)

    def test_create_veth(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='veth', peer=ifB).commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces

    def test_create_fail(self):
        require_user('root')

        ifA = self.get_ifname()

        # create with mac 11:22:33:44:55:66 should fail
        i = self.ip.create(kind='dummy',
                           ifname=ifA,
                           address='11:22:33:44:55:66')
        try:
            i.commit()
        except NetlinkError:
            pass

        assert i._mode == 'invalid'
        assert ifA not in self.ip.interfaces

    def test_create_dqn(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/255.255.255.0')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_double_reuse(self):
        require_user('root')

        ifA = self.get_ifname()
        # create an interface
        i1 = self.ip.create(kind='dummy', ifname=ifA).commit()
        try:
            # this call should fail on the very first step:
            # `bala` interface already exists
            self.ip.create(kind='dummy', ifname=ifA)
        except CreateException:
            pass
        # add `reuse` keyword -- now should pass
        i2 = self.ip.create(kind='dummy', ifname=ifA, reuse=True).commit()
        # assert that we have got references to the same interface
        assert i1 == i2

    def _create_double(self, kind):
        require_user('root')
        ifA = self.get_ifname()

        self.ip.create(kind=kind, ifname=ifA).commit()
        try:
            self.ip.create(kind=kind, ifname=ifA).commit()
        except CreateException:
            pass

    def test_create_double_dummy(self):
        self._create_double('dummy')

    def test_create_double_bridge(self):
        self._create_double('bridge')

    def test_create_double_bond(self):
        self._create_double('bond')

    def test_create_plain(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/24')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_and_remove(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

        with self.ip.interfaces[ifA] as i:
            i.remove()
        assert ifA not in self.ip.interfaces

    def test_dqn_mask(self):
        require_user('root')

        iface = self.ip.interfaces[self.ifd]
        with iface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2', mask=24)
            i.add_ip('172.16.0.3/255.255.255.0')
            i.add_ip('172.16.0.4', mask='255.255.255.0')

        assert ('172.16.0.1', 24) in iface.ipaddr
        assert ('172.16.0.2', 24) in iface.ipaddr
        assert ('172.16.0.3', 24) in iface.ipaddr
        assert ('172.16.0.4', 24) in iface.ipaddr

    def _create_master(self, kind, **kwarg):

        ifM = self.get_ifname()
        ifP1 = self.get_ifname()
        ifP2 = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifP1).commit()
        self.ip.create(kind='dummy', ifname=ifP2).commit()

        with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i:
            i.add_port(self.ip.interfaces[ifP1])
            i.add_ip('172.16.0.1/24')

        with self.ip.interfaces[ifM] as i:
            i.add_port(self.ip.interfaces[ifP2])
            i.add_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master == \
            self.ip.interfaces[ifM].index
        assert self.ip.interfaces[ifP2].if_master == \
            self.ip.interfaces[ifM].index

        with self.ip.interfaces[ifM] as i:
            i.del_port(self.ip.interfaces[ifP1])
            i.del_port(self.ip.interfaces[ifP2])
            i.del_ip('172.16.0.1/24')
            i.del_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master is None
        assert self.ip.interfaces[ifP2].if_master is None

    def test_create_bridge(self):
        require_user('root')
        require_bridge()
        self._create_master('bridge')

    def test_create_bond(self):
        require_user('root')
        require_bond()
        self._create_master('bond')

    def test_create_team(self):
        require_user('root')
        require_executable('teamd')
        require_executable('teamdctl')
        self._create_master('team')

    def test_create_ovs(self):
        require_user('root')
        require_executable('ovs-vsctl')
        self._create_master('openvswitch')

    def test_create_bond2(self):
        require_user('root')
        require_bond()
        self._create_master('bond', bond_mode=2)

    def _create_macvx_mode(self, kind, mode):
        require_user('root')
        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(**{
            'kind': kind,
            'link': ifdb[ifL],
            'ifname': ifV,
            '%s_mode' % kind: mode
        }).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].link == ifdb[ifL].index
            assert ifdb[ifV]['%s_mode' % kind] == mode
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_macvtap_vepa(self):
        return self._create_macvx_mode('macvtap', 'vepa')

    def test_create_macvtap_bridge(self):
        return self._create_macvx_mode('macvtap', 'bridge')

    def test_create_macvlan_vepa(self):
        return self._create_macvx_mode('macvlan', 'vepa')

    def test_create_macvlan_bridge(self):
        return self._create_macvx_mode('macvlan', 'bridge')

    def test_create_gre(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        with self.ip.create(kind='dummy', ifname=ifL) as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        self.ip.create(kind='gre',
                       ifname=ifV,
                       gre_local='172.16.0.1',
                       gre_remote='172.16.0.2',
                       gre_ttl=16).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].gre_local == '172.16.0.1'
            assert ifdb[ifV].gre_remote == '172.16.0.2'
            assert ifdb[ifV].gre_ttl == 16
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_vxlan(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(kind='vxlan',
                       ifname=ifV,
                       vxlan_link=ifdb[ifL],
                       vxlan_id=101,
                       vxlan_group='239.1.1.1').commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces

        try:
            assert ifdb[ifV].vxlan_link == ifdb[ifL].index
            assert ifdb[ifV].vxlan_group == '239.1.1.1'
            assert ifdb[ifV].vxlan_id == 101
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_vlan_by_interface(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL],
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_create_vlan_by_index(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL].index,
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_remove_secondaries(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1', 24)
            i.add_ip('172.16.0.2', 24)

        assert ifA in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifA)

        if i._mode == 'explicit':
            i.begin()

        i.del_ip('172.16.0.1', 24)
        i.del_ip('172.16.0.2', 24)
        i.commit()

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifA)
    def execRequest(self, action, data):

        if action == 'NetworkDriver.DiscoverNew':
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.DiscoverDelete':
            return HttpResponse(200,'json',{ }).response
        
        if action == 'Plugin.Activate':
            return HttpResponse(200,'json',{ 'Implements': ['NetworkDriver','IPAM'] }).response

        if action == 'NetworkDriver.GetCapabilities':
            return HttpResponse(200,'json',{ 'Scope':scope}).response

        if action == 'IPAM.GetDefaultAddressSpaces':
            requestPool = {}
            return HttpResponse(200,'json',requestPool).response

        if action == 'NetworkDriver.CreateNetwork':
            networkId = data['NetworkID'][:8]
            pool = data['IPv4Data'][0]['Pool']
            gateway = data['IPv4Data'][0]['Gateway'].split('/')[0]
            displayName = ''
            if len(data['IPv6Data']) > 0:
                v6pool = data['IPv6Data'][0]['Pool']
                v6gateway = data['IPv6Data'][0]['Gateway']
            if 'name' in data['Options']['com.docker.network.generic']:
                displayName = data['Options']['com.docker.network.generic']['name']
            if 'rt' in data['Options']['com.docker.network.generic']:
                rtList = data['Options']['com.docker.network.generic']['rt'].split(',')
                if len(data['IPv6Data']) > 0:
                    openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, v6subnet=v6pool, v6gateway = v6gateway, rtList = rtList, displayName = displayName)
                else:
                    openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, rtList = rtList, displayName = displayName)
            else:
                if len(data['IPv6Data']) > 0:
                    openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, v6subnet=v6pool, v6gateway = v6gateway, displayName = displayName)
                else:
                    openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, displayName = displayName)
            networkInfo = {}
            networkInfo['NetworkID'] = data['NetworkID']
            return HttpResponse(200,'json',networkInfo).response

        if action == 'NetworkDriver.DeleteNetwork':
            networkId = data['NetworkID'][:8]
            openContrailVN = OpenContrailVN(networkId).delete()
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.CreateEndpoint':
            networkId = data['NetworkID'][:8]
            endpointId = data['EndpointID']
            ipAddress = data['Interface']['Address']
            if data['Interface']['AddressIPv6']:
                ipv6Address = data['Interface']['AddressIPv6']
                OpenContrailEndpoint(endpointId).create(networkId, ipAddress, ipv6Address)
            else:
                OpenContrailEndpoint(endpointId).create(networkId, ipAddress)
            interface = {}
            interface['Interface'] = {} 
            return HttpResponse(200,'json',interface).response

        if action == 'NetworkDriver.DeleteEndpoint':
            endpointId = data['EndpointID']
            OpenContrailEndpoint(endpointId).delete()
            vethIdHost = 'veth' + endpointId[:8] + 'p0'
            ip = IPDB()
            with ip.interfaces[vethIdHost] as veth:
                veth.remove()
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.EndpointOperInfo':
            endpointInfo = {}
            endpointInfo['NetworkID'] = data['NetworkID']
            endpointInfo['EndpointID'] = data['EndpointID']
            return HttpResponse(200,'json',endpointInfo).response

        if action == 'NetworkDriver.Join':
            networkId = data['NetworkID'][:8]
            endpointId = data['EndpointID']
            sandboxKey = data['SandboxKey'].split("/")[5]
            hostId = endpointId[:8]
            vethIdHost = 'veth' + hostId + 'p0'
            vethIdContainer = 'veth' + hostId
            vn = OpenContrailVN(networkId).VNget()
            subnet = vn.network_ipam_refs[0]['attr'].ipam_subnets[0]
            gateway = subnet.default_gateway
            result = OpenContrailEndpoint(endpointId).join(networkId, sandboxKey)
            mac = result['mac']
            ip = IPDB()
            ip.create(ifname=vethIdHost, kind='veth', peer=vethIdContainer).commit()
            with ip.interfaces[vethIdHost] as veth:
                veth.up()
            with ip.interfaces[vethIdContainer] as veth:
                veth.address = mac
            OpenContrailEndpoint(endpointId).vrouterPortControl(result, 'add')
            joinInfo = {}
            joinInfo['InterfaceName'] = {}
            joinInfo['InterfaceName']['SrcName'] = vethIdContainer
            joinInfo['InterfaceName']['DstPrefix'] = 'eth'
            joinInfo['Gateway'] = gateway
            joinInfo['StaticRoutes'] = []
            #ipAddress = data['Interface']['Address']
            return HttpResponse(200,'json',joinInfo).response
 
        if action == 'NetworkDriver.ProgramExternalConnectivity':
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.RevokeExternalConnectivity':
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.Leave':
            return HttpResponse(200,'json',{ }).response
Ejemplo n.º 26
0
Master is an interface to add VLAN to, e.g. eth0 or tap0 or
whatever else. Without parameters use tap0 as the default.
'''
import sys
from pyroute2 import IPDB

ip = IPDB()

try:
    if len(sys.argv) == 2:
        # Get master interface from the command line
        master = ip[sys.argv[1]]['index']
    else:
        # Or use tap0 interface as an example
        master = ip.tap0.index  # or the same: master = ip['tap0']['index']

    with ip.create(kind='vlan', ifname='v101', link=master, vlan_id=101) as i:
        # Arguments for ip.create() are executed before the transaction,
        # in the IPRoute.link('add', ...) call. If create() fails, the
        # interface became invalid and is not operable, you can safely
        # drop it.
        #
        # Here goes the rest of transaction. If it fails, the interface
        # continues to work, only failed transaction gets dropped.
        i.add_ip('10.251.0.1', 24)
        i.add_ip('10.251.0.2', 24)
        i.mtu = 1400

finally:
    ip.release()
Ejemplo n.º 27
0
class TestExplicit(object):
    ip = None
    mode = 'explicit'

    def setup(self):
        self.ap = AddrPool()
        self.iftmp = 'pr2x{0}'
        self.ifaces = []
        self.ifd = self.get_ifname()
        create_link(self.ifd, kind='dummy')
        self.ip = IPDB(mode=self.mode)

    def get_ifname(self):
        naddr = self.ap.alloc()
        ifname = self.iftmp.format(naddr)
        self.ifaces.append(ifname)
        return ifname

    def teardown(self):
        for name in self.ifaces:
            try:
                with self.ip.interfaces[name] as i:
                    i.remove()
            except:
                pass
        self.ip.release()
        self.ifaces = []

    def test_simple(self):
        assert len(list(self.ip.interfaces.keys())) > 0

    def test_empty_transaction(self):
        assert 'lo' in self.ip.interfaces
        with self.ip.interfaces.lo as i:
            assert isinstance(i.mtu, int)

    def test_idx_len(self):
        assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys())

    def test_idx_set(self):
        assert set(self.ip.by_name.values()) == set(self.ip.by_index.values())

    def test_idx_types(self):
        assert all(isinstance(i, int) for i in self.ip.by_index.keys())
        assert all(isinstance(i, basestring) for i in self.ip.by_name.keys())

    def test_ips(self):
        for name in self.ip.by_name:
            assert len(self.ip.interfaces[name]['ipaddr']) == \
                len(get_ip_addr(name))

    def test_reprs(self):
        assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring)
        assert isinstance(repr(self.ip.interfaces.lo), basestring)

    def test_dotkeys(self):
        # self.ip.lo hint for ipython
        assert 'lo' in dir(self.ip.interfaces)
        assert 'lo' in self.ip.interfaces
        assert self.ip.interfaces.lo == self.ip.interfaces['lo']
        # create attribute
        self.ip.interfaces['newitem'] = True
        self.ip.interfaces.newattr = True
        self.ip.interfaces.newitem = None
        assert self.ip.interfaces.newitem == self.ip.interfaces['newitem']
        assert self.ip.interfaces.newitem is None
        # delete attribute
        del self.ip.interfaces.newitem
        del self.ip.interfaces.newattr
        assert 'newattr' not in dir(self.ip.interfaces)

    def test_vlan_slave_bridge(self):
        # https://github.com/svinota/pyroute2/issues/58
        # based on the code by Petr Horáček
        dXname = self.get_ifname()
        vXname = self.get_ifname()
        vYname = self.get_ifname()
        brname = self.get_ifname()

        require_user('root')
        dX = self.ip.create(ifname=dXname, kind='dummy').commit()
        vX = self.ip.create(ifname=vXname, kind='vlan',
                            link=dX, vlan_id=101).commit()
        vY = self.ip.create(ifname=vYname, kind='vlan',
                            link=dX, vlan_id=102).commit()
        with self.ip.create(ifname=brname, kind='bridge') as i:
            i.add_port(vX)
            i.add_port(vY['index'])

        assert vX['index'] in self.ip.interfaces[brname]['ports']
        assert vY['index'] in self.ip.interfaces[brname].ports
        assert vX['link'] == dX['index']
        assert vY['link'] == dX['index']
        assert vX['master'] == self.ip.interfaces[brname]['index']
        assert vY['master'] == self.ip.interfaces[brname].index

    def _test_commit_hook_positive(self):
        require_user('root')

        # test callback, that adds an address by itself --
        # just to check the possibility
        def cb(interface, snapshot, transaction):
            self.ip.nl.addr('add',
                            self.ip.interfaces[self.ifd].index,
                            address='172.16.22.1',
                            mask=24)

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        self.ip.interfaces[self.ifd].commit()

        # added address should be there
        assert ('172.16.21.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr
        # and the one, added by the callback, too
        assert ('172.16.22.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def _test_commit_hook_negative(self):
        require_user('root')

        # test exception to differentiate
        class CBException(Exception):
            pass

        # test callback, that always fail
        def cb(interface, snapshot, transaction):
            raise CBException()

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it; should fail
        # 'cause of the callback
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        try:
            self.ip.interfaces[self.ifd].commit()
        except CBException:
            pass

        # added address should be removed
        assert ('172.16.21.1', 24) not in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def test_review(self):
        assert len(self.ip.interfaces.lo._tids) == 0
        if self.ip.interfaces.lo._mode == 'explicit':
            self.ip.interfaces.lo.begin()
        self.ip.interfaces.lo.add_ip('172.16.21.1/24')
        r = self.ip.interfaces.lo.review()
        assert len(r['+ipaddr']) == 1
        assert len(r['-ipaddr']) == 0
        assert len(r['+ports']) == 0
        assert len(r['-ports']) == 0
        # +/-ipaddr, +/-ports
        assert len([i for i in r if r[i] is not None]) == 4
        self.ip.interfaces.lo.drop()

    def test_rename(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='dummy').commit()

        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()
        self.ip.interfaces[ifA].ifname = ifB
        self.ip.interfaces[ifA].commit()

        assert ifB in self.ip.interfaces
        assert ifA not in self.ip.interfaces

        if self.ip.interfaces[ifB]._mode == 'explicit':
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifB].ifname = ifA
        self.ip.interfaces[ifB].commit()

        assert ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces

    def test_routes(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes

        # create a route
        with self.ip.routes.add({'dst': '172.16.0.0/24',
                                 'gateway': '127.0.0.1'}) as r:
            pass
        assert '172.16.0.0/24' in self.ip.routes.keys()
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1')

        # change the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.gateway = '127.0.0.2'
        assert self.ip.routes['172.16.0.0/24'].gateway == '127.0.0.2'
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.2')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()
        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    def test_route_metrics(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes.keys()

        # create a route
        self.ip.routes.add({'dst': '172.16.0.0/24',
                            'gateway': '127.0.0.1',
                            'metrics': {'mtu': 1360}}).commit()
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1360')

        # change metrics
        with self.ip.routes['172.16.0.0/24'] as r:
            r.metrics.mtu = 1400
        assert self.ip.routes['172.16.0.0/24']['metrics']['mtu'] == 1400
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1400')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()

        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    def _test_shadow(self, kind):
        ifA = self.get_ifname()

        a = self.ip.create(ifname=ifA, kind=kind).commit()
        if a._mode == 'explicit':
            a.begin()
        a.shadow().commit()
        assert ifA in self.ip.interfaces
        assert not grep('ip link', pattern=ifA)
        b = self.ip.create(ifname=ifA, kind=kind).commit()
        assert a == b
        assert grep('ip link', pattern=ifA)

    def test_shadow_bond(self):
        require_user('root')
        require_bond()
        self._test_shadow('bond')

    def test_shadow_bridge(self):
        require_user('root')
        require_bridge()
        self._test_shadow('bridge')

    def test_shadow_dummy(self):
        require_user('root')
        self._test_shadow('dummy')

    def test_updown(self):
        require_user('root')

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].up()
        self.ip.interfaces[self.ifd].commit()
        assert self.ip.interfaces[self.ifd].flags & 1

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].down()
        self.ip.interfaces[self.ifd].commit()
        assert not (self.ip.interfaces[self.ifd].flags & 1)

    def test_fail_ipaddr(self):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(ifname=ifA, kind='dummy').commit()
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.add_ip('123.456.789.1024/153')
        try:
            i.commit()
        except socket.error as e:
            if not e.args[0].startswith('illegal IP'):
                raise
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.remove().commit()
        assert ifA not in self.ip.interfaces

    def test_json_dump(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        # set up the interface
        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2/24')
            i.up()

        # make a backup
        backup = self.ip.interfaces[ifA].dump()
        assert isinstance(backup, dict)

        # remove index -- make it portable
        del backup['index']
        # serialize
        backup = json.dumps(backup)

        # remove the interface
        with self.ip.interfaces[ifA] as i:
            i.remove()

        # create again, but with different name
        self.ip.create(kind='dummy', ifname=ifB).commit()

        # load the backup
        # 1. prepare to the restore: bring it down
        with self.ip.interfaces[ifB] as i:
            i.down()
        # 2. please notice, the interface will be renamed after the backup
        t = self.ip.interfaces[ifB].load(json.loads(backup))
        self.ip.interfaces[ifB].commit(transaction=t)

        # check :)
        assert ifA in self.ip.interfaces
        assert ifB not in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert self.ip.interfaces[ifA].flags & 1

    def test_freeze(self):
        require_user('root')

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.1.1/24')
            i.up()

        # check
        assert ('172.16.0.1', 24) in interface.ipaddr
        assert ('172.16.1.1', 24) in interface.ipaddr
        assert interface.flags & 1

        # assert routine
        def probe():
            # The freeze results are dynamic: it is not a real freeze,
            # it is a restore routine. So it takes time for results
            # to stabilize
            err = None
            for _ in range(3):
                err = None
                interface.ipaddr.set_target((('172.16.0.1', 24),
                                             ('172.16.1.1', 24)))
                interface.ipaddr.target.wait()
                try:
                    assert ('172.16.0.1', 24) in interface.ipaddr
                    assert ('172.16.1.1', 24) in interface.ipaddr
                    assert interface.flags & 1
                    break
                except AssertionError as e:
                    err = e
                    continue
                except Exception as e:
                    err = e
                    break
            if err is not None:
                interface.unfreeze()
                i2.close()
                raise err

        # freeze
        interface.freeze()

        # change the interface somehow
        i2 = IPRoute()
        i2.addr('delete', interface.index, '172.16.0.1', 24)
        i2.addr('delete', interface.index, '172.16.1.1', 24)
        probe()

        # unfreeze
        self.ip.interfaces[self.ifd].unfreeze()

        try:
            i2.addr('delete', interface.index, '172.16.0.1', 24)
            i2.addr('delete', interface.index, '172.16.1.1', 24)
        except:
            pass
        finally:
            i2.close()

        # should be up, but w/o addresses
        interface.ipaddr.set_target(set())
        interface.ipaddr.target.wait(3)
        assert ('172.16.0.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert ('172.16.1.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    def test_snapshots(self):
        require_user('root')

        ifB = self.get_ifname()

        # set up the interface
        with self.ip.interfaces[self.ifd] as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        # check it
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

        # make a snapshot
        s = self.ip.interfaces[self.ifd].snapshot()
        i = self.ip.interfaces[self.ifd]

        # check it
        assert i.last_snapshot_id() == s

        # unset the interface
        with self.ip.interfaces[self.ifd] as i:
            i.del_ip('172.16.0.1/24')
            i.down()

        # we can not rename the interface while it is up,
        # so do it in two turns
        with self.ip.interfaces[self.ifd] as i:
            i.ifname = ifB

        # check it
        assert ifB in self.ip.interfaces
        assert self.ifd not in self.ip.interfaces
        y = self.ip.interfaces[ifB]
        assert i == y
        assert ('172.16.0.1', 24) not in y.ipaddr
        assert not (y.flags & 1)

        # revert snapshot
        y.revert(s).commit()

        # check it
        assert ifB not in self.ip.interfaces
        assert self.ifd in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    def _test_ipv(self, ipv, kind):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(kind=kind, ifname=ifA).commit()
        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()

        if ipv == 4:
            addr = '172.16.0.1/24'
        elif ipv == 6:
            addr = 'fdb3:84e5:4ff4:55e4::1/64'
        else:
            raise Exception('bad IP version')

        i.add_ip(addr).commit()
        pre_target = addr.split('/')
        target = (pre_target[0], int(pre_target[1]))
        assert target in i['ipaddr']

    def test_ipv4_dummy(self):
        self._test_ipv(4, 'dummy')

    def test_ipv4_bond(self):
        self._test_ipv(4, 'bond')

    def test_ipv4_bridge(self):
        self._test_ipv(4, 'bridge')

    def test_ipv6_dummy(self):
        self._test_ipv(6, 'dummy')

    def test_ipv6_bond(self):
        self._test_ipv(6, 'bond')

    def test_ipv6_bridge(self):
        self._test_ipv(6, 'bridge')

    def test_create_tuntap_fail(self):
        try:
            self.ip.create(ifname='fAiL',
                           kind='tuntap',
                           mode='fail').commit()
        except:
            assert not grep('ip link', pattern='fAiL')
            return
        raise Exception('tuntap create succeded')

    def test_create_tuntap(self):
        require_user('root')

        ifA = self.get_ifname()
        self.ip.create(ifname=ifA,
                       kind='tuntap',
                       mode='tap',
                       uid=1,
                       gid=1).commit()

        assert ifA in self.ip.interfaces
        assert grep('ip link', pattern=ifA)

    def test_ovs_kind_aliases(self):
        require_user('root')
        require_executable('ovs-vsctl')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA,
                       kind='ovs-bridge').commit()
        self.ip.create(ifname=ifB,
                       kind='openvswitch').commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert grep('ip link', pattern=ifA)
        assert grep('ip link', pattern=ifB)

    def test_create_veth(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='veth', peer=ifB).commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces

    def test_create_fail(self):
        require_user('root')

        ifA = self.get_ifname()

        # create with mac 11:22:33:44:55:66 should fail
        i = self.ip.create(kind='dummy',
                           ifname=ifA,
                           address='11:22:33:44:55:66')
        try:
            i.commit()
        except NetlinkError:
            pass

        assert i._mode == 'invalid'
        assert ifA not in self.ip.interfaces

    def test_create_dqn(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/255.255.255.0')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_double_reuse(self):
        require_user('root')

        ifA = self.get_ifname()
        # create an interface
        i1 = self.ip.create(kind='dummy', ifname=ifA).commit()
        try:
            # this call should fail on the very first step:
            # `bala` interface already exists
            self.ip.create(kind='dummy', ifname=ifA)
        except CreateException:
            pass
        # add `reuse` keyword -- now should pass
        i2 = self.ip.create(kind='dummy',
                            ifname=ifA,
                            reuse=True).commit()
        # assert that we have got references to the same interface
        assert i1 == i2

    def _create_double(self, kind):
        require_user('root')
        ifA = self.get_ifname()

        self.ip.create(kind=kind, ifname=ifA).commit()
        try:
            self.ip.create(kind=kind, ifname=ifA).commit()
        except CreateException:
            pass

    def test_create_double_dummy(self):
        self._create_double('dummy')

    def test_create_double_bridge(self):
        self._create_double('bridge')

    def test_create_double_bond(self):
        self._create_double('bond')

    def test_create_plain(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/24')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_and_remove(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

        with self.ip.interfaces[ifA] as i:
            i.remove()
        assert ifA not in self.ip.interfaces

    def test_dqn_mask(self):
        require_user('root')

        iface = self.ip.interfaces[self.ifd]
        with iface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2', mask=24)
            i.add_ip('172.16.0.3/255.255.255.0')
            i.add_ip('172.16.0.4', mask='255.255.255.0')

        assert ('172.16.0.1', 24) in iface.ipaddr
        assert ('172.16.0.2', 24) in iface.ipaddr
        assert ('172.16.0.3', 24) in iface.ipaddr
        assert ('172.16.0.4', 24) in iface.ipaddr

    def _create_master(self, kind, **kwarg):

        ifM = self.get_ifname()
        ifP1 = self.get_ifname()
        ifP2 = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifP1).commit()
        self.ip.create(kind='dummy', ifname=ifP2).commit()

        with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i:
            i.add_port(self.ip.interfaces[ifP1])
            i.add_ip('172.16.0.1/24')

        with self.ip.interfaces[ifM] as i:
            i.add_port(self.ip.interfaces[ifP2])
            i.add_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master == \
            self.ip.interfaces[ifM].index
        assert self.ip.interfaces[ifP2].if_master == \
            self.ip.interfaces[ifM].index

        with self.ip.interfaces[ifM] as i:
            i.del_port(self.ip.interfaces[ifP1])
            i.del_port(self.ip.interfaces[ifP2])
            i.del_ip('172.16.0.1/24')
            i.del_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master is None
        assert self.ip.interfaces[ifP2].if_master is None

    def test_create_bridge(self):
        require_user('root')
        require_bridge()
        self._create_master('bridge')

    def test_create_bond(self):
        require_user('root')
        require_bond()
        self._create_master('bond')

    def test_create_team(self):
        require_user('root')
        require_executable('teamd')
        require_executable('teamdctl')
        self._create_master('team')

    def test_create_ovs(self):
        require_user('root')
        require_executable('ovs-vsctl')
        self._create_master('openvswitch')

    def test_create_bond2(self):
        require_user('root')
        require_bond()
        self._create_master('bond', bond_mode=2)

    def _create_macvx_mode(self, kind, mode):
        require_user('root')
        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(**{'kind': kind,
                          'link': ifdb[ifL],
                          'ifname': ifV,
                          '%s_mode' % kind: mode}).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].link == ifdb[ifL].index
            assert ifdb[ifV]['%s_mode' % kind] == mode
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_macvtap_vepa(self):
        return self._create_macvx_mode('macvtap', 'vepa')

    def test_create_macvtap_bridge(self):
        return self._create_macvx_mode('macvtap', 'bridge')

    def test_create_macvlan_vepa(self):
        return self._create_macvx_mode('macvlan', 'vepa')

    def test_create_macvlan_bridge(self):
        return self._create_macvx_mode('macvlan', 'bridge')

    def test_create_gre(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        with self.ip.create(kind='dummy', ifname=ifL) as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        self.ip.create(kind='gre',
                       ifname=ifV,
                       gre_local='172.16.0.1',
                       gre_remote='172.16.0.2',
                       gre_ttl=16).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].gre_local == '172.16.0.1'
            assert ifdb[ifV].gre_remote == '172.16.0.2'
            assert ifdb[ifV].gre_ttl == 16
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_vxlan(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(kind='vxlan',
                       ifname=ifV,
                       vxlan_link=ifdb[ifL],
                       vxlan_id=101,
                       vxlan_group='239.1.1.1').commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces

        try:
            assert ifdb[ifV].vxlan_link == ifdb[ifL].index
            assert ifdb[ifV].vxlan_group == '239.1.1.1'
            assert ifdb[ifV].vxlan_id == 101
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_vlan_by_interface(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL],
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_create_vlan_by_index(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL].index,
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_remove_secondaries(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1', 24)
            i.add_ip('172.16.0.2', 24)

        assert ifA in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifA)

        if i._mode == 'explicit':
            i.begin()

        i.del_ip('172.16.0.1', 24)
        i.del_ip('172.16.0.2', 24)
        i.commit()

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifA)
Ejemplo n.º 28
0
#!/usr/bin/python

from pprint import pprint
from pyroute2 import IPRoute
from pyroute2 import IPDB
from pyroute2.common import uifname

# high-level interface
ipdb = IPDB()

interface = ipdb.create(ifname=uifname(), kind='dummy').\
    commit().\
    add_ip('172.16.0.1/24').\
    add_ip('172.16.0.2/24').\
    commit()

# low-level interface just to get raw messages
ip = IPRoute()
a = [x for x in ip.get_addr() if x['index'] == interface['index']]
print('\n8<--------------------- left operand')
pprint(a[0])
print('\n8<--------------------- right operand')
pprint(a[1])
print('\n8<--------------------- complement')
pprint(a[0] - a[1])
print('\n8<--------------------- intersection')
pprint(a[0] & a[1])

interface.remove().commit()

ip.close()
Ejemplo n.º 29
0
class TestExplicit(object):
    ip = None
    mode = 'explicit'

    def setup(self):
        create_link('dummyX', 'dummy')
        self.ip = IPDB(mode=self.mode)

    def teardown(self):
        for name in ('bala_port0', 'bala_port1', 'dummyX',
                     'bala', 'bv101'):
            try:
                with self.ip.interfaces[name] as i:
                    i.remove()
            except KeyError:
                pass
            except NetlinkError as e:
                if e.code != 19:  # No such device
                    raise
        self.ip.release()

    def test_simple(self):
        assert len(list(self.ip.interfaces.keys())) > 0

    def test_empty_transaction(self):
        assert 'lo' in self.ip.interfaces
        with self.ip.interfaces.lo as i:
            assert isinstance(i.mtu, int)

    def test_idx_len(self):
        assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys())

    def test_idx_set(self):
        assert set(self.ip.by_name.values()) == set(self.ip.by_index.values())

    def test_idx_types(self):
        assert all(isinstance(i, int) for i in self.ip.by_index.keys())
        assert all(isinstance(i, basestring) for i in self.ip.by_name.keys())

    def test_ips(self):
        for name in self.ip.by_name:
            assert len(self.ip.interfaces[name]['ipaddr']) == \
                len(get_ip_addr(name))

    def test_reprs(self):
        assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring)
        assert isinstance(repr(self.ip.interfaces.lo), basestring)

    def test_dotkeys(self):
        # self.ip.lo hint for ipython
        assert 'lo' in dir(self.ip.interfaces)
        assert 'lo' in self.ip.interfaces
        assert self.ip.interfaces.lo == self.ip.interfaces['lo']
        # create attribute
        self.ip.interfaces['newitem'] = True
        self.ip.interfaces.newattr = True
        self.ip.interfaces.newitem = None
        assert self.ip.interfaces.newitem == self.ip.interfaces['newitem']
        assert self.ip.interfaces.newitem is None
        # delete attribute
        del self.ip.interfaces.newitem
        del self.ip.interfaces.newattr
        assert 'newattr' not in dir(self.ip.interfaces)

    def test_callback_positive(self):
        require_user('root')
        assert 'dummyX' in self.ip.interfaces

        # test callback, that adds an address by itself --
        # just to check the possibility
        def cb(snapshot, transaction):
            self.ip.nl.addr('add',
                            self.ip.interfaces.dummyX.index,
                            address='172.16.22.1',
                            mask=24)

        # register callback and check CB chain length
        self.ip.interfaces.dummyX.register_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 1

        # create a transaction and commit it
        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.add_ip('172.16.21.1/24')
        self.ip.interfaces.dummyX.commit()

        # the second address added w/o watchdogs,
        # so we have to wait
        time.sleep(1)

        # added address should be there
        assert ('172.16.21.1', 24) in self.ip.interfaces.dummyX.ipaddr
        # and the one, added by the callback, too
        assert ('172.16.22.1', 24) in self.ip.interfaces.dummyX.ipaddr

        # unregister callback
        self.ip.interfaces.dummyX.unregister_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 0

    def test_callback_negative(self):
        require_user('root')
        assert 'dummyX' in self.ip.interfaces

        # test exception to differentiate
        class CBException(Exception):
            pass

        # test callback, that always fail
        def cb(snapshot, transaction):
            raise CBException()

        # register callback and check CB chain length
        self.ip.interfaces.dummyX.register_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 1

        # create a transaction and commit it; should fail
        # 'cause of the callback
        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.add_ip('172.16.21.1/24')
        try:
            self.ip.interfaces.dummyX.commit()
        except CBException:
            pass

        # added address should be removed
        assert ('172.16.21.1', 24) not in self.ip.interfaces.dummyX.ipaddr

        # unregister callback
        self.ip.interfaces.dummyX.unregister_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 0

    def test_review(self):
        assert len(self.ip.interfaces.lo._tids) == 0
        if self.ip.interfaces.lo._mode == 'explicit':
            self.ip.interfaces.lo.begin()
        self.ip.interfaces.lo.add_ip('172.16.21.1/24')
        r = self.ip.interfaces.lo.review()
        assert len(r['+ipaddr']) == 1
        assert len(r['-ipaddr']) == 0
        assert len(r['+ports']) == 0
        assert len(r['-ports']) == 0
        # +/-ipaddr, +/-ports
        assert len([i for i in r if r[i] is not None]) == 4
        self.ip.interfaces.lo.drop()

    def test_rename(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        assert 'dummyX' in self.ip.interfaces

        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.ifname = 'bala'
        self.ip.interfaces.dummyX.commit()

        assert 'bala' in self.ip.interfaces
        assert 'dummyX' not in self.ip.interfaces

        if self.ip.interfaces.bala._mode == 'explicit':
            self.ip.interfaces.bala.begin()
        self.ip.interfaces.bala.ifname = 'dummyX'
        self.ip.interfaces.bala.commit()

        assert 'bala' not in self.ip.interfaces
        assert 'dummyX' in self.ip.interfaces

    def test_routes(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes

        # create a route
        with self.ip.routes.add({'dst': '172.16.0.0/24',
                                 'gateway': '127.0.0.1'}) as r:
            pass
        assert '172.16.0.0/24' in self.ip.routes
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1')

        # change a route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.gateway = '127.0.0.2'
        assert self.ip.routes['172.16.0.0/24'].gateway == '127.0.0.2'
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.2')

        # delete a route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()
        assert '172.16.0.0/24' not in self.ip.routes
        assert not grep('ip ro', pattern='172.16.0.0/24')

    def _test_shadow(self, kind):
        a = self.ip.create(ifname='bala', kind=kind).commit()
        if a._mode == 'explicit':
            a.begin()
        a.shadow().commit()
        assert 'bala' in self.ip.interfaces
        assert not grep('ip link', pattern='bala')
        b = self.ip.create(ifname='bala', kind=kind).commit()
        assert a == b
        assert grep('ip link', pattern='bala')

    def test_shadow_bond(self):
        require_user('root')
        require_bond()
        self._test_shadow('bond')

    def test_shadow_bridge(self):
        require_user('root')
        require_bridge()
        self._test_shadow('bridge')

    def test_shadow_dummy(self):
        require_user('root')
        self._test_shadow('dummy')

    def test_updown(self):
        require_user('root')
        assert not (self.ip.interfaces.dummyX.flags & 1)

        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.up()
        self.ip.interfaces.dummyX.commit()
        assert self.ip.interfaces.dummyX.flags & 1

        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.down()
        self.ip.interfaces.dummyX.commit()
        assert not (self.ip.interfaces.dummyX.flags & 1)

    def test_cfail_rollback(self):
        require_user('root')
        require_bridge()

        # create ports
        with self.ip.create(kind='dummy', ifname='bala_port0'):
            pass
        with self.ip.create(kind='dummy', ifname='bala_port1'):
            pass
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces

        # commits should fail
        clear_fail_bit(_FAIL_COMMIT)
        clear_fail_bit(_FAIL_ROLLBACK)
        try:
            # create bridge
            with self.ip.create(kind='bridge', ifname='bala') as i:
                i.add_ip('172.16.0.1/24')
                i.add_ip('172.16.0.2/24')
                i.add_port(self.ip.interfaces.bala_port0)
                i.add_port(self.ip.interfaces.bala_port1)

        except RuntimeError:
            pass

        finally:
            # set bit again
            set_fail_bit(_FAIL_COMMIT)
            set_fail_bit(_FAIL_ROLLBACK)

        # expected results:
        # 1. interface created
        # 2. no addresses
        # 3. no ports
        assert 'bala' in self.ip.interfaces
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces
        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr
        assert self.ip.interfaces.bala_port0.index not in \
            self.ip.interfaces.bala.ports
        assert self.ip.interfaces.bala_port1.index not in \
            self.ip.interfaces.bala.ports

    def test_cfail_commit(self):
        require_user('root')
        require_bridge()

        # create ports
        with self.ip.create(kind='dummy', ifname='bala_port0'):
            pass
        with self.ip.create(kind='dummy', ifname='bala_port1'):
            pass
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces

        # commits should fail
        clear_fail_bit(_FAIL_COMMIT)
        try:
            # create bridge
            with self.ip.create(kind='bridge', ifname='bala') as i:
                i.add_ip('172.16.0.1/24')
                i.add_ip('172.16.0.2/24')
                i.add_port(self.ip.interfaces.bala_port0)
                i.add_port(self.ip.interfaces.bala_port1)

        except AssertionError:
            pass

        finally:
            # set bit again
            set_fail_bit(_FAIL_COMMIT)

        # expected results:
        # 1. interface created
        # 2. no addresses
        # 3. no ports
        assert 'bala' in self.ip.interfaces
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces
        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr
        assert self.ip.interfaces.bala_port0.index not in \
            self.ip.interfaces.bala.ports
        assert self.ip.interfaces.bala_port1.index not in \
            self.ip.interfaces.bala.ports

    def test_fail_ipaddr(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        i = self.ip.create(ifname='bala', kind='dummy').commit()
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.add_ip('123.456.789.1024/153')
        try:
            i.commit()
        except socket.error as e:
            if not e.args[0].startswith('illegal IP'):
                raise
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.remove().commit()
        assert 'bala' not in self.ip.interfaces

    def test_create_fail(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        # create with mac 11:22:33:44:55:66 should fail
        i = self.ip.create(kind='dummy',
                           ifname='bala',
                           address='11:22:33:44:55:66')
        try:
            i.commit()
        except NetlinkError:
            pass

        assert i._mode == 'invalid'
        assert 'bala' not in self.ip.interfaces

    def test_create_dqn(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        i = self.ip.create(kind='dummy', ifname='bala')
        i.add_ip('172.16.0.1/255.255.255.0')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')

    def test_create_plain(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        i = self.ip.create(kind='dummy', ifname='bala')
        i.add_ip('172.16.0.1/24')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')

    def test_create_and_remove(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces

        with self.ip.create(kind='dummy', ifname='bala') as i:
            i.add_ip('172.16.0.1/24')
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')

        with self.ip.interfaces.bala as i:
            i.remove()
        assert 'bala' not in self.ip.interfaces

    def _create_master(self, kind, **kwarg):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        assert 'bala_port0' not in self.ip.interfaces
        assert 'bala_port1' not in self.ip.interfaces

        self.ip.create(kind='dummy', ifname='bala_port0').commit()
        self.ip.create(kind='dummy', ifname='bala_port1').commit()

        with self.ip.create(kind=kind, ifname='bala', **kwarg) as i:
            i.add_port(self.ip.interfaces.bala_port0)
            i.add_port(self.ip.interfaces.bala_port1)
            i.add_ip('172.16.0.1/24')

        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')
        assert self.ip.interfaces.bala_port0.if_master == \
            self.ip.interfaces.bala.index
        assert self.ip.interfaces.bala_port1.if_master == \
            self.ip.interfaces.bala.index

        with self.ip.interfaces.bala as i:
            i.del_port(self.ip.interfaces.bala_port0)
            i.del_port(self.ip.interfaces.bala_port1)
            i.del_ip('172.16.0.1/24')

        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface='bala')
        assert self.ip.interfaces.bala_port0.if_master is None
        assert self.ip.interfaces.bala_port1.if_master is None

    def test_create_bridge(self):
        require_bridge()
        self._create_master('bridge')

    def test_create_bond(self):
        require_bond()
        self._create_master('bond')

    def test_create_bond2(self):
        require_bond()
        self._create_master('bond', bond_mode=2)

    def test_create_vlan_by_interface(self):
        require_user('root')
        require_8021q()
        assert 'bala' not in self.ip.interfaces
        assert 'bv101' not in self.ip.interfaces

        self.ip.create(kind='dummy',
                       ifname='bala').commit()
        self.ip.create(kind='vlan',
                       ifname='bv101',
                       link=self.ip.interfaces.bala,
                       vlan_id=101).commit()

        assert self.ip.interfaces.bv101.if_master == \
            self.ip.interfaces.bala.index

    def test_create_vlan_by_index(self):
        require_user('root')
        require_8021q()
        assert 'bala' not in self.ip.interfaces
        assert 'bv101' not in self.ip.interfaces

        self.ip.create(kind='dummy',
                       ifname='bala').commit()
        self.ip.create(kind='vlan',
                       ifname='bv101',
                       link=self.ip.interfaces.bala.index,
                       vlan_id=101).commit()

        assert self.ip.interfaces.bv101.if_master == \
            self.ip.interfaces.bala.index

    def test_remove_secondaries(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces

        with self.ip.create(kind='dummy', ifname='bala') as i:
            i.add_ip('172.16.0.1', 24)
            i.add_ip('172.16.0.2', 24)

        assert 'bala' in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')
        assert '172.16.0.2/24' in get_ip_addr(interface='bala')

        if i._mode == 'explicit':
            i.begin()

        i.del_ip('172.16.0.1', 24)
        i.del_ip('172.16.0.2', 24)
        i.commit()

        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface='bala')
        assert '172.16.0.2/24' not in get_ip_addr(interface='bala')
Ejemplo n.º 30
0
from pprint import pprint
from pyroute2 import IPDB

ip = IPDB()

# create an interface
i = ip.create(kind='dummy', ifname='pr2test').commit()
prev_state = i.nlmsg

# change the state
i.address = '00:11:22:33:44:55'
i.up()
i.commit()

# show, what has been changed, excluding statistics --
# it changes all the time
pprint((i.nlmsg - prev_state).strip(
    ('IFLA_AF_SPEC', 'IFLA_STATS', 'IFLA_STATS64', 'IFLA_LINKINFO',
     'IFLA_MAP')))

i.remove().commit()

ip.release()
Ejemplo n.º 31
0
        # add it as a port to the bridge
        ipdb.interfaces.br0.add_port(interface)
        try:
            ipdb.interfaces.br0.commit()
        except Exception:
            pass


# create IPDB instance
ip = IPDB()
# create watchdogs
wd0 = ip.watchdog(ifname='br0')
wd1 = ip.watchdog(ifname='bala_port0')
wd2 = ip.watchdog(ifname='bala_port1')
# create bridge
ip.create(kind='bridge', ifname='br0').commit()
# wait the bridge to be created
wd0.wait()
# register callback
ip.register_callback(cb)
# create ports
ip.create(kind='dummy', ifname='bala_port0').commit()
ip.create(kind='dummy', ifname='bala_port1').commit()
# sleep for interfaces
wd1.wait()
wd2.wait()

ip.unregister_callback(cb)

# cleanup
for i in ('bala_port0', 'bala_port1', 'br0'):
Ejemplo n.º 32
0
from pyroute2.common import uifname

p0 = uifname()


###
#
# "Pre" callbacks are executed before the message
# gets processed by IPDB, and in synchronous manner.
# Normally, you will not need these callbacks, but
# they can be useful to perform some hacks
#
def cb(ipdb, msg, action):
    if action == 'RTM_NEWLINK':
        msg['flags'] = 1234


# create IPDB instance
ip = IPDB()
# register "pre" callback
ip.register_callback(cb, mode='pre')
# create an interface
ip.create(kind='dummy', ifname=p0).commit()
# assert flags
assert ip.interfaces[p0].flags == 1234
# cleanup
ip.interfaces[p0].remove()
ip.interfaces[p0].commit()
# release Netlink socket
ip.release()
Ejemplo n.º 33
0
class Ipdb:
    def __init__(self):
        self.ipdb_controller = None

    def connect(self, netnspath=None):
        """Initializa a IPDB object local or over remote netns
        
        Args:
            param1 (string): The netns path to connect for remote management
        """

        try:
            if netnspath:
                self.ipdb_controller = IPDB(nl=NetNS(netnspath))
            else:
                self.ipdb_controller = IPDB()
        except Exception:
            logging.error('Cannot connect to the namespace indicate')
            return

    def create_interface_bridge(self, name):
        """Create a linux bridge interface over ipdb, 

        Args:
           name (string): iface name to create
                        
        """
        try:
            if self.ipdb_controller:
                self.ipdb_controller.create(ifname=name,
                                            kind='bridge').commit()
        except Exception:
            logging.error('Cannot create linux bridge interface')
            return

    def create_interface(self, name, peer_id=None):
        """Create interface veth over ipdb, returning a tuple of the iface names created

        Args:
           name (string): iface name to create
           peer_id (string)(optional): According to the type, it is used to compose the iface name of the peer associated

        Returns:
           attr1, attr2 (string, string): tuple of interface names created
            
        """
        try:
            if self.ipdb_controller:
                name_iface_peer = name + '_' + peer_id
                self.ipdb_controller.create(ifname=name,
                                            kind='veth',
                                            peer=name_iface_peer).commit()
                return name, name_iface_peer
        except Exception:
            logging.error('Cannot create interface')
            return '', ''

    def change_status_interface(self, name, status):
        """Change the status of interface to up|down

        Args:
           name (string): iface name to create
           status (string): status change to (up|down)
            
        """

        try:
            with self.ipdb_controller.interfaces[name] as iface:
                if status == 'up':
                    iface.up()
                if status == 'down':
                    iface.down()
        except Exception:
            logging.error('Cannot change interface status')
            return

    def move_interface_tonetns(self, name, netns):
        """Move inteface to another namespace

        Args:
           name (string): iface name to create
           status (string): status change to (up|down)
            
        """

        try:
            with self.ipdb_controller.interfaces[name] as iface:
                iface.net_ns_fd = netns
        except Exception:
            logging.error('Cannot change interface to ' + netns + ' namespace')
            return

    def add_port_interface(self, name, iface_port):
        """Add port to interface (normally for bridge ones)
        
        Args:
           name (string): iface name to attach port
           iface_port (string): iface name to be attached
            
        """

        try:
            with self.ipdb_controller.interfaces[name] as iface:
                iface.add_port(iface_port)
        except Exception:
            logging.error('Cannot add port to interface')
            return

    def change_addr_interface(self, name, ip, mask):
        """Change addr to interface
        
        Args:
           name (string): iface name modify ip_addr
           ip (string): ip address to establish
           mask (string): netmask to establish
           
        """

        try:
            with self.ipdb_controller.interfaces[name] as iface:
                iface.add_ip(ip + '/' + mask)
        except Exception:
            logging.error('Cannot add port to interface')
            return
Ejemplo n.º 34
0
#!/usr/bin/python

from pprint import pprint
from pyroute2 import IPRoute
from pyroute2 import IPDB

# high-level interface
ipdb = IPDB()

interface = ipdb.create(ifname='pr2test', kind='dummy').\
    commit().\
    add_ip('172.16.0.1/24').\
    add_ip('172.16.0.2/24').\
    commit()

# low-level interface just to get raw messages
ip = IPRoute()
a = [x for x in ip.get_addr() if x['index'] == interface['index']]
print('\n8<--------------------- left operand')
pprint(a[0])
print('\n8<--------------------- right operand')
pprint(a[1])
print('\n8<--------------------- complement')
pprint(a[0] - a[1])
print('\n8<--------------------- intersection')
pprint(a[0] & a[1])

interface.remove().commit()

ip.release()
ipdb.release()
Ejemplo n.º 35
0
from pyroute2 import IPDB

ip = IPDB()

# create dummy interface to host routes on
ip.create(kind='dummy', ifname='pr2test').\
    add_ip('172.16.1.1/24').\
    up().\
    commit()

# create a route
with ip.routes.add({'dst': '172.16.0.0/24',
                    'gateway': '172.16.1.2'}) as r:
    pass

# modify it
with ip.routes['172.16.0.0/24'] as r:
    r.gateway = '172.16.1.3'

# cleanup
with ip.routes['172.16.0.0/24'] as r:
    r.remove()

ip.interfaces.pr2test.remove().commit()

ip.release()
Ejemplo n.º 36
0
class ConfigApplier(object):
    def __init__(self):
        self.ip = IPDB()

    def _setIpConfig(self, iface):
        ipConfig = iface.ipConfig
        if ipConfig.ipaddr:
            self.removeIpConfig(iface)
            with self.ip.interfaces[iface.name] as i:
                i.add_ip('%s/%s' % (ipConfig.ipaddr, ipConfig.netmask))
            if ipConfig.gateway and ipConfig.defaultRoute:
                ipwrapper.routeAdd(['default', 'via', ipConfig.gateway])

    def removeIpConfig(self, iface):
        ipwrapper.addrFlush(iface.name)

    def setIfaceMtu(self, iface, mtu):
        with self.ip.interfaces[iface] as i:
            i['mtu'] = int(mtu)

    def setBondingMtu(self, iface, mtu):
        self.setIfaceMtu(iface, mtu)

    def ifup(self, iface):
        with self.ip.interfaces[iface.name] as i:
            i.up()
        if iface.ipConfig.bootproto == 'dhcp':
            dhclient = DhcpClient(iface.name)
            dhclient.start(iface.ipConfig.async)

    def ifdown(self, iface):
        with self.ip.interfaces[iface.name] as i:
            i.down()
        dhclient = DhcpClient(iface.name)
        dhclient.shutdown()

    def setIfaceConfigAndUp(self, iface):
        if iface.ip:
            self._setIpConfig(iface)
        if iface.mtu:
            self.setIfaceMtu(iface.name, iface.mtu)
        self.ifup(iface)

    def addBridge(self, bridge):
        self.ip.create(kind='bridge', ifname=bridge.name).commit()

    def addBridgePort(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.add_port(self.ip.interfaces[bridge.port.name])

    def removeBridge(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.remove()

    def removeBridgePort(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.del_port(self.ip.interfaces[bridge.port.name])

    def addVlan(self, vlan):
        link = self.ip.interfaces[vlan.device.name].index
        self.ip.create(kind='vlan', ifname=vlan.name,
                       link=link, vlan_id=vlan.tag).commit()

    def removeVlan(self, vlan):
        with self.ip.interfaces[vlan.name] as i:
            i.remove()

    def addBond(self, bond):
        if bond.name not in netinfo.bondings():
            self.ip.create(kind='bond', ifname=bond.name).commit()

    def removeBond(self, bond):
        with self.ip.interfaces[bond.name] as i:
            i.remove()

    def addBondSlave(self, bond, slave):
        self.ifdown(slave)
        with self.ip.interfaces[bond.name] as i:
            i.add_port(self.ip.interfaces[slave.name])
        self.ifup(slave)

    def removeBondSlave(self, bond, slave):
        with self.ip.interfaces[bond.name] as i:
            i.del_port(self.ip.interfaces[slave.name])

    def addBondOptions(self, bond):
        logging.debug('Add bond options %s', bond.options)
        for option in bond.options.split():
            key, value = option.split('=')
            with open(netinfo.BONDING_OPT % (bond.name, key), 'w') as f:
                f.write(value)

    def createLibvirtNetwork(self, network, bridged, iface, qosInbound=None,
                             qosOutbound=None):
        netXml = libvirt.createNetworkDef(network, bridged, iface,
                                          qosInbound, qosOutbound)
        libvirt.createNetwork(netXml)

    def removeLibvirtNetwork(self, network):
        libvirt.removeNetwork(network)

    def releaseSocket(self):
        self.ip.release()
Ejemplo n.º 37
0
class TestExplicit(object):
    ip = None
    mode = 'explicit'

    def setup(self):
        create_link('dummyX', 'dummy')
        self.ip = IPDB(mode=self.mode)

    def teardown(self):
        self.ip.release()
        remove_link('bala_port0')
        remove_link('bala_port1')
        remove_link('dummyX')
        remove_link('bala')
        remove_link('bv101')

    def test_simple(self):
        assert len(list(self.ip.interfaces.keys())) > 0

    def test_empty_transaction(self):
        assert 'lo' in self.ip.interfaces
        with self.ip.interfaces.lo as i:
            assert isinstance(i.mtu, int)

    def test_idx_len(self):
        assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys())

    def test_idx_set(self):
        assert set(self.ip.by_name.values()) == set(self.ip.by_index.values())

    def test_idx_types(self):
        assert all(isinstance(i, int) for i in self.ip.by_index.keys())
        assert all(isinstance(i, basestring) for i in self.ip.by_name.keys())

    def test_ips(self):
        for name in self.ip.by_name:
            assert len(self.ip.interfaces[name]['ipaddr']) == \
                len(get_ip_addr(name))

    def test_reprs(self):
        assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring)
        assert isinstance(repr(self.ip.interfaces.lo), basestring)

    def test_dotkeys(self):
        # self.ip.lo hint for ipython
        assert 'lo' in dir(self.ip.interfaces)
        assert 'lo' in self.ip.interfaces
        assert self.ip.interfaces.lo == self.ip.interfaces['lo']
        # create attribute
        self.ip.interfaces['newitem'] = True
        self.ip.interfaces.newattr = True
        self.ip.interfaces.newitem = None
        assert self.ip.interfaces.newitem == self.ip.interfaces['newitem']
        assert self.ip.interfaces.newitem is None
        # delete attribute
        del self.ip.interfaces.newitem
        del self.ip.interfaces.newattr
        assert 'newattr' not in dir(self.ip.interfaces)

    def test_callback_positive(self):
        require_user('root')
        assert 'dummyX' in self.ip.interfaces

        # test callback, that adds an address by itself --
        # just to check the possibility
        def cb(snapshot, transaction):
            self.ip.nl.addr('add',
                            self.ip.interfaces.dummyX.index,
                            address='172.16.22.1',
                            mask=24)

        # register callback and check CB chain length
        self.ip.interfaces.dummyX.register_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 1

        # create a transaction and commit it
        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.add_ip('172.16.21.1/24')
        self.ip.interfaces.dummyX.commit()

        # added address should be there
        assert ('172.16.21.1', 24) in self.ip.interfaces.dummyX.ipaddr
        # and the one, added by the callback, too
        assert ('172.16.22.1', 24) in self.ip.interfaces.dummyX.ipaddr

        # unregister callback
        self.ip.interfaces.dummyX.unregister_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 0

    def test_callback_negative(self):
        require_user('root')
        assert 'dummyX' in self.ip.interfaces

        # test exception to differentiate
        class CBException(Exception):
            pass

        # test callback, that always fail
        def cb(snapshot, transaction):
            raise CBException()

        # register callback and check CB chain length
        self.ip.interfaces.dummyX.register_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 1

        # create a transaction and commit it; should fail
        # 'cause of the callback
        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.add_ip('172.16.21.1/24')
        try:
            self.ip.interfaces.dummyX.commit()
        except CBException:
            pass

        # added address should be removed
        assert ('172.16.21.1', 24) not in self.ip.interfaces.dummyX.ipaddr

        # unregister callback
        self.ip.interfaces.dummyX.unregister_callback(cb)
        assert len(self.ip.interfaces.dummyX._callbacks) == 0

    def test_review(self):
        assert len(self.ip.interfaces.lo._tids) == 0
        if self.ip.interfaces.lo._mode == 'explicit':
            self.ip.interfaces.lo.begin()
        self.ip.interfaces.lo.add_ip('172.16.21.1/24')
        r = self.ip.interfaces.lo.review()
        assert len(r['+ipaddr']) == 1
        assert len(r['-ipaddr']) == 0
        assert len(r['+ports']) == 0
        assert len(r['-ports']) == 0
        # +/-ipaddr, +/-ports
        assert len([i for i in r if r[i] is not None]) == 4
        self.ip.interfaces.lo.drop()

    def test_rename(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        assert 'dummyX' in self.ip.interfaces

        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.ifname = 'bala'
        self.ip.interfaces.dummyX.commit()

        assert 'bala' in self.ip.interfaces
        assert 'dummyX' not in self.ip.interfaces

        if self.ip.interfaces.bala._mode == 'explicit':
            self.ip.interfaces.bala.begin()
        self.ip.interfaces.bala.ifname = 'dummyX'
        self.ip.interfaces.bala.commit()

        assert 'bala' not in self.ip.interfaces
        assert 'dummyX' in self.ip.interfaces

    def test_updown(self):
        require_user('root')
        assert not (self.ip.interfaces.dummyX.flags & 1)

        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.up()
        self.ip.interfaces.dummyX.commit()
        assert self.ip.interfaces.dummyX.flags & 1

        if self.ip.interfaces.dummyX._mode == 'explicit':
            self.ip.interfaces.dummyX.begin()
        self.ip.interfaces.dummyX.down()
        self.ip.interfaces.dummyX.commit()
        assert not (self.ip.interfaces.dummyX.flags & 1)

    def test_ancient_bridge(self):
        require_user('root')

        # create ports
        with self.ip.create(kind='dummy', ifname='bala_port0'):
            pass
        with self.ip.create(kind='dummy', ifname='bala_port1'):
            pass
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces

        set_ancient(True)

        # create bridge
        try:
            with self.ip.create(kind='bridge', ifname='bala') as i:
                i.add_ip('172.16.0.1/24')
                i.add_ip('172.16.0.2/24')
                i.add_port(self.ip.interfaces.bala_port0)
                i.add_port(self.ip.interfaces.bala_port1)
        finally:
            set_ancient(False)

        assert 'bala' in self.ip.interfaces
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces.bala.ipaddr
        assert self.ip.interfaces.bala_port0.index in \
            self.ip.interfaces.bala.ports
        assert self.ip.interfaces.bala_port1.index in \
            self.ip.interfaces.bala.ports

    def test_cfail_rollback(self):
        require_user('root')

        # create ports
        with self.ip.create(kind='dummy', ifname='bala_port0'):
            pass
        with self.ip.create(kind='dummy', ifname='bala_port1'):
            pass
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces

        # commits should fail
        clear_fail_bit(_FAIL_COMMIT)
        clear_fail_bit(_FAIL_ROLLBACK)
        try:
            # create bridge
            with self.ip.create(kind='bridge', ifname='bala') as i:
                i.add_ip('172.16.0.1/24')
                i.add_ip('172.16.0.2/24')
                i.add_port(self.ip.interfaces.bala_port0)
                i.add_port(self.ip.interfaces.bala_port1)

        except RuntimeError:
            pass

        finally:
            # set bit again
            set_fail_bit(_FAIL_COMMIT)
            set_fail_bit(_FAIL_ROLLBACK)

        # expected results:
        # 1. interface created
        # 2. no addresses
        # 3. no ports
        assert 'bala' in self.ip.interfaces
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces
        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr
        assert self.ip.interfaces.bala_port0.index not in \
            self.ip.interfaces.bala.ports
        assert self.ip.interfaces.bala_port1.index not in \
            self.ip.interfaces.bala.ports

    def test_cfail_commit(self):
        require_user('root')

        # create ports
        with self.ip.create(kind='dummy', ifname='bala_port0'):
            pass
        with self.ip.create(kind='dummy', ifname='bala_port1'):
            pass
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces

        # commits should fail
        clear_fail_bit(_FAIL_COMMIT)
        try:
            # create bridge
            with self.ip.create(kind='bridge', ifname='bala') as i:
                i.add_ip('172.16.0.1/24')
                i.add_ip('172.16.0.2/24')
                i.add_port(self.ip.interfaces.bala_port0)
                i.add_port(self.ip.interfaces.bala_port1)

        except AssertionError:
            pass

        finally:
            # set bit again
            set_fail_bit(_FAIL_COMMIT)

        # expected results:
        # 1. interface created
        # 2. no addresses
        # 3. no ports
        assert 'bala' in self.ip.interfaces
        assert 'bala_port0' in self.ip.interfaces
        assert 'bala_port1' in self.ip.interfaces
        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr
        assert self.ip.interfaces.bala_port0.index not in \
            self.ip.interfaces.bala.ports
        assert self.ip.interfaces.bala_port1.index not in \
            self.ip.interfaces.bala.ports

    def test_create_fail(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        # create with mac 11:22:33:44:55:66 should fail
        i = self.ip.create(kind='dummy',
                           ifname='bala',
                           address='11:22:33:44:55:66')
        try:
            i.commit()
        except NetlinkError:
            pass

        assert i._mode == 'invalid'
        assert 'bala' not in self.ip.interfaces

    def test_create_plain(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        i = self.ip.create(kind='dummy', ifname='bala')
        i.add_ip('172.16.0.1/24')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')

    def test_create_and_remove(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces

        with self.ip.create(kind='dummy', ifname='bala') as i:
            i.add_ip('172.16.0.1/24')
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')

        with self.ip.interfaces.bala as i:
            i.remove()
        assert 'bala' not in self.ip.interfaces

    def _create_master(self, kind):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        assert 'bala_port0' not in self.ip.interfaces
        assert 'bala_port1' not in self.ip.interfaces

        self.ip.create(kind='dummy', ifname='bala_port0').commit()
        self.ip.create(kind='dummy', ifname='bala_port1').commit()

        with self.ip.create(kind=kind, ifname='bala') as i:
            i.add_port(self.ip.interfaces.bala_port0)
            i.add_port(self.ip.interfaces.bala_port1)
            i.add_ip('172.16.0.1/24')

        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')
        assert self.ip.interfaces.bala_port0.if_master == \
            self.ip.interfaces.bala.index
        assert self.ip.interfaces.bala_port1.if_master == \
            self.ip.interfaces.bala.index

        with self.ip.interfaces.bala as i:
            i.del_port(self.ip.interfaces.bala_port0)
            i.del_port(self.ip.interfaces.bala_port1)
            i.del_ip('172.16.0.1/24')

        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface='bala')
        assert self.ip.interfaces.bala_port0.if_master is None
        assert self.ip.interfaces.bala_port1.if_master is None

    def test_create_bridge(self):
        self._create_master('bridge')

    def test_create_bond(self):
        self._create_master('bond')

    def test_create_vlan(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces
        assert 'bv101' not in self.ip.interfaces

        self.ip.create(kind='dummy',
                       ifname='bala').commit()
        self.ip.create(kind='vlan',
                       ifname='bv101',
                       link=self.ip.interfaces.bala.index,
                       vlan_id=101).commit()

        assert self.ip.interfaces.bv101.if_master == \
            self.ip.interfaces.bala.index

    def test_remove_secondaries(self):
        require_user('root')
        assert 'bala' not in self.ip.interfaces

        with self.ip.create(kind='dummy', ifname='bala') as i:
            i.add_ip('172.16.0.1', 24)
            i.add_ip('172.16.0.2', 24)

        assert 'bala' in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface='bala')
        assert '172.16.0.2/24' in get_ip_addr(interface='bala')

        if i._mode == 'explicit':
            i.begin()

        i.del_ip('172.16.0.1', 24)
        i.del_ip('172.16.0.2', 24)
        i.commit()

        assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface='bala')
        assert '172.16.0.2/24' not in get_ip_addr(interface='bala')
Ejemplo n.º 38
0
'''
Example: python ./examples/create_bond.py

Creates bond interface.
'''
from pyroute2 import IPDB

ip = IPDB()

try:

    # The same scheme works for bridge interfaces too: you
    # can create a bridge interface and enslave some ports
    # to it just as below.
    ip.create(kind='dummy', ifname='port0').commit()
    ip.create(kind='dummy', ifname='port1').commit()

    with ip.create(kind='bond', ifname='bond,james') as i:
        # enslave two interfaces: tap0 and tap1
        i.add_port(ip.interfaces.port0)
        i.add_port(ip.interfaces.port1)
        # make an example more scary: add IPs to the bond,james
        i.add_ip('10.251.0.1/24')
        i.add_ip('10.251.0.2/24')

finally:
    for i in ('port0', 'port1', 'bond,james'):
        try:
            ip.interfaces[i].remove().commit()
        except:
            pass
Ejemplo n.º 39
0
from pyroute2 import IPDB

ip = IPDB()

# create dummy interface to host routes on
ip.create(kind='dummy', ifname='pr2test').\
    add_ip('172.16.1.1/24').\
    up().\
    commit()

# create a route
with ip.routes.add({'dst': '172.16.0.0/24', 'gateway': '172.16.1.2'}) as r:
    pass

# modify it
with ip.routes['172.16.0.0/24'] as r:
    r.gateway = '172.16.1.3'

# cleanup
with ip.routes['172.16.0.0/24'] as r:
    r.remove()

ip.interfaces.pr2test.remove().commit()

ip.release()
Ejemplo n.º 40
0
    def execRequest(self, action, data):

        if action == 'Plugin.Activate':
            return HttpResponse(200, 'json', {
                'Implements': ['NetworkDriver', 'IPAM']
            }).response

        if action == 'NetworkDriver.GetCapabilities':
            return HttpResponse(200, 'json', {'Scope': 'local'}).response

        if action == 'IPAM.GetDefaultAddressSpaces':
            requestPool = {}
            return HttpResponse(200, 'json', requestPool).response

        if action == 'IPAM.RequestPool':
            self.subnet = data['Pool']
            requestPool = {}
            requestPool['Pool'] = self.subnet
            return HttpResponse(200, 'json', requestPool).response

        if action == 'IPAM.RequestAddress':
            plen = self.subnet.split('/')[1]
            requestAddress = {}
            if 'Address' not in data:
                reply = {
                    'error': 'missing gateway, specify one with --gateway'
                }
                return HttpResponse(500, 'json', reply).response
            requestAddress['Address'] = data['Address'] + '/' + plen
            return HttpResponse(200, 'json', requestAddress).response

        if action == 'IPAM.ReleaseAddress':
            address = {}
            address['Address'] = data['Address']
            return HttpResponse(200, 'json', address).response

        if action == 'IPAM.ReleasePool':
            pool = {}
            return HttpResponse(200, 'json', pool).response

        if action == 'NetworkDriver.CreateNetwork':
            subnet = data['IPv4Data'][0]['Pool']
            gateway = data['IPv4Data'][0]['Gateway'].split('/')[0]
            rtList = []
            if 'rt' in data['Options']['com.docker.network.generic']:
                rt = data['Options']['com.docker.network.generic']['rt']
                rtList = rt.split(',')
            openContrailVN = OpenContrailVN(data['NetworkID']).createNw(
                subnet, gateway, rtList)
            return HttpResponse(200, 'json', {}).response

        if action == 'NetworkDriver.DeleteNetwork':
            openContrailVN = OpenContrailVN(data['NetworkID']).deleteNw()
            return HttpResponse(200, 'json', {}).response

        if action == 'NetworkDriver.CreateEndpoint':
            networkId = data['NetworkID']
            endpointId = data['EndpointID']
            hostId = endpointId[:8]
            ipAddress = data['Interface']['Address']
            result = OpenContrailVirtualMachineInterface(hostId).createVmi(
                networkId, ipAddress)
            interface = {}
            interface['Interface'] = {}
            interface['Interface']['MacAddress'] = result['mac']
            return HttpResponse(200, 'json', interface).response

        if action == 'NetworkDriver.DeleteEndpoint':
            endpointId = data['EndpointID']
            hostId = endpointId[:8]
            OpenContrailVirtualMachineInterface(hostId).deleteVmi()
            endpointId = data['EndpointID']
            vethIdHost = 'veth' + endpointId[:8] + 'p0'
            ip = IPDB()
            with ip.interfaces[vethIdHost] as veth:
                veth.remove()
            return HttpResponse(200, 'json', {}).response

        if action == 'NetworkDriver.EndpointOperInfo':
            endpointInfo = {}
            endpointInfo['NetworkID'] = data['NetworkID']
            endpointInfo['EndpointID'] = data['EndpointID']
            return HttpResponse(200, 'json', endpointInfo).response

        if action == 'NetworkDriver.Join':
            endpointId = data['EndpointID']
            hostId = endpointId[:8]
            networkId = data['NetworkID']
            vethIdHost = 'veth' + endpointId[:8] + 'p0'
            vethIdContainer = 'veth' + endpointId[:8]
            vn = OpenContrailVN(networkId).VNget()
            subnet = vn.network_ipam_refs[0]['attr'].ipam_subnets[0]
            gateway = subnet.default_gateway
            mac = OpenContrailVirtualMachineInterface(hostId).getMac()
            ip = IPDB()
            ip.create(ifname=vethIdHost, kind='veth',
                      peer=vethIdContainer).commit()
            with ip.interfaces[vethIdHost] as veth:
                veth.up()
            with ip.interfaces[vethIdContainer] as veth:
                veth.address = mac
            joinInfo = {}
            joinInfo['InterfaceName'] = {}
            joinInfo['InterfaceName']['SrcName'] = vethIdContainer
            joinInfo['InterfaceName']['DstPrefix'] = 'eth'
            joinInfo['Gateway'] = gateway
            #joinInfo['GatewayIPv6'] = '2000::2'
            joinInfo['StaticRoutes'] = []
            #staticRoute = {}
            #staticRoute['Destination'] = '2.2.2.0/24'
            #staticRoute['RouteType'] = 0
            #staticRoute['NextHop'] = '1.1.1.1'
            #joinInfo['StaticRoutes'].append(staticRoute)
            return HttpResponse(200, 'json', joinInfo).response

        if action == 'NetworkDriver.Leave':
            return HttpResponse(200, 'json', {}).response
Ejemplo n.º 41
0
def prepare_namespaces(graph, dry_run=False, instance_id=None):
    """
    Create a veth-connected mesh from :data:`graph`

    :param networkx.Graph graph: The graph defining the test mesh
    :param bool dry_run: If set makes Meshinery not touch any namespaces
    :param str instance_id: If set changes the middle section of each
    namespace's name; current PID by default
    :return networkx.Graph: The same graph containing runtime attributes
    """
    if instance_id is None:
        instance_id = os.getpid()
    # Create namespaces
    for node_name in graph.nodes:
        ns_name = 'meshinery-{}-{}'.format(instance_id, node_name)
        logging.info('Adding namespace "{}"'.format(ns_name))
        if not dry_run:
            # Establish the namespace
            ns = NetNS(ns_name)
            ipdb = IPDB(nl=ns)
            ipdb.interfaces['lo'].up().commit()
            ipdb.commit()
            ipdb.release()

            # Enable forwarding
            sysctl_cmd = shlex.split(
                'sysctl -w net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1'
            )
            subprocess.run(sysctl_cmd,
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE).check_returncode()

            graph.node[node_name]['netns'] = ns_name
            graph.node[node_name]['interfaces'] = [
            ]  # Needed so that we can safely append later

    # Create veth bridges
    for node_name, neigh_name in graph.edges:
        neighbors = graph[node_name]

        node = graph.node[node_name]
        neigh = graph.node[neigh_name]

        # If an edge hasn't been created yet
        node_iface = '{}-{}'.format(node_name, neigh_name)
        neigh_iface = '{}-{}'.format(neigh_name, node_name)

        if not dry_run:
            node_ns_handle = NetNS(node['netns'])
            neigh_ns_handle = NetNS(neigh['netns'])

            ipdb = IPDB()

            # Create namespace-aware IPDB handles
            node_ipdb = IPDB(nl=node_ns_handle)
            neigh_ipdb = IPDB(nl=neigh_ns_handle)

            # Create a veth pair
            ipdb.create(ifname=node_iface, kind='veth',
                        peer=neigh_iface).commit()

            # Assign node IP
            ipdb.interfaces[node_iface]['net_ns_fd'] = node['netns']
            ipdb.commit()
            node_ipdb.interfaces[node_iface].add_ip(node['ip'])
            node_ipdb.interfaces[node_iface].up().commit()

            # Assign neighbor IP
            ipdb.interfaces[neigh_iface].add_ip(neigh['ip'])
            ipdb.interfaces[neigh_iface]['net_ns_fd'] = neigh['netns']
            ipdb.commit()
            neigh_ipdb.interfaces[neigh_iface].add_ip(neigh['ip'])
            neigh_ipdb.interfaces[neigh_iface].up().commit()

            ipdb.release()

            node_ipdb.release()
            neigh_ipdb.release()

            node['interfaces'].append(node_iface)
            neigh['interfaces'].append(neigh_iface)

        logging.debug('Created %s and %s interfaces' %
                      (node_iface, neigh_iface))

    ipdb.release()
Ejemplo n.º 42
0
                        i.remove()
            if 'tap' + args.ifname in ip.interfaces:
                with ip.interfaces['tap' + args.ifname] as i:
                    i.remove()
            if brige_name in ip.interfaces:
                with ip.interfaces[brige_name] as i:
                    i.remove()
            for ifn in range(args.ifnum):
                netns = NetNS('node' + str(ifn))
                netns.close()
                netns.remove()
        else:
            for ifn in range(args.ifnum):
                iface = args.ifname + str(ifn)
                if not iface in ip.interfaces:
                    ip.create(kind='veth', ifname=iface,
                              peer=iface + '.1').commit()

            ip.create(kind='tuntap', ifname='tap' + args.ifname,
                      mode='tap').commit()

            with ip.create(kind='bridge', ifname=brige_name) as i:
                for ifn in range(args.ifnum):
                    iface = args.ifname + str(ifn)
                    i.add_port(ip.interfaces[iface])
                i.add_port(ip.interfaces['tap' + args.ifname])
                if args.ipv4:
                    i.add_ip(local_addr4 + '1/24')
                if args.ipv6:
                    i.add_ip(local_addr6 + '1/64')
                i.up()
Ejemplo n.º 43
0
Creates dummy interface.
'''
from pyroute2 import IPDB

ip = IPDB()

try:

    # dummy, bridge and bond interfaces are created in the
    # same way -- just use appropriate name
    #
    # Warning! do not use name 'bond0'
    # Warning! do not use name 'dummy0'
    # details of this restriction are in the documentation
    #
    # possible kinds:
    #  * bond
    #  * bridge
    #  * dummy
    #  * vlan -- see /examples/create_vlan.py
    #
    dummy = ip.create(kind='dummy', ifname='dummy_name')
    dummy.commit()

finally:
    try:
        dummy.remove().commit()
    except:
        pass
    ip.release()
Ejemplo n.º 44
0
        interface = ipdb.interfaces[msg['index']]
        # add it as a port to the bridge
        ipdb.interfaces.br0.add_port(interface)
        try:
            ipdb.interfaces.br0.commit()
        except Exception:
            pass

# create IPDB instance
ip = IPDB()
# create watchdogs
wd0 = ip.watchdog(ifname='br0')
wd1 = ip.watchdog(ifname='bala_port0')
wd2 = ip.watchdog(ifname='bala_port1')
# create bridge
ip.create(kind='bridge', ifname='br0').commit()
# wait the bridge to be created
wd0.wait()
# register callback
ip.register_callback(cb)
# create ports
ip.create(kind='dummy', ifname='bala_port0').commit()
ip.create(kind='dummy', ifname='bala_port1').commit()
# sleep for interfaces
wd1.wait()
wd2.wait()

ip.unregister_callback(cb)

# cleanup
for i in ('bala_port0', 'bala_port1', 'br0'):
Ejemplo n.º 45
0
class InfrasimNamespace(object):
    def __init__(self, vswitch_instance, ns_info):
        self.__ns_info = ns_info
        self.name = ns_info['name']
        self.ip = IPRoute()
        # self.ipdb = IPDB(nl=NetNS(self.name))
        self.main_ipdb = IPDB()
        self.__vswitch = vswitch_instance

    @staticmethod
    def get_namespaces_list():
        return netns.listnetns()

    def build_one_namespace(self):
        self._create_namespace()

        for intf in self.__ns_info["interfaces"]:
            # get name
            ifname = intf["ifname"]
            if intf.get("pair") is False:
                self.create_single_virtual_intf_in_ns(intf)
            else:
                global interface_index
                self.create_ip_link_in_ns(ifname,
                                          "veth{}".format(interface_index))
                if 'bridge' in intf:
                    self.create_bridge(intf=ifname,
                                       br_name=intf['bridge']['ifname'])
                self.__vswitch.add_port("veth{}".format(interface_index))
                idx = self.ip.link_lookup(
                    ifname="veth{}".format(interface_index))[0]
                self.ip.link("set", index=idx, state="up")
                interface_index += 1

    def _create_namespace(self):
        if self.name in self.get_namespaces_list():
            print "name space {} exists.".format(self.name)
            return
        netns.create(self.name)

    def del_namespace(self):
        if self.name in netns.listnetns():
            netns.remove(self.name)

    def create_single_virtual_intf_in_ns(self, intf):
        ifname = intf['ifname']
        if len(self.ip.link_lookup(ifname=ifname)) > 0:
            print "ip link {} exists so not create it.".format(ifname)
            return

        self.main_ipdb.create(ifname=ifname, kind="dummy").commit()
        with self.main_ipdb.interfaces[ifname] as veth:
            veth.net_ns_fd = self.name

        if 'bridge' in intf:
            self.create_bridge(intf=ifname, br_name=intf['bridge']['ifname'])

    def create_ip_link_in_ns(self, ifname, peername):
        if len(self.ip.link_lookup(ifname=ifname)) > 0:
            print "ip link {} exists so not create it.".format(ifname)
            return

        if len(self.ip.link_lookup(ifname=peername)) > 0:
            print "ip link {} exists so not create it.".format(peername)
            return

        # create link peer
        self.main_ipdb.create(ifname=ifname, kind="veth",
                              peer=peername).commit()
        with self.main_ipdb.interfaces[ifname] as veth:
            veth.net_ns_fd = self.name

    def exec_cmd_in_namespace(self, cmd):
        start_process(["ip", "netns", "exec", self.name] + cmd)

    def link_up_all(self):
        # setup lo
        # self.exec_cmd_in_namespace(["ifdown", "lo"])
        # self.exec_cmd_in_namespace(["ifup", "lo"])
        self.exec_cmd_in_namespace(["ip", "link", "set", "dev", "lo", "up"])

        for intf_info in self.__ns_info["interfaces"]:
            if "bridge" in intf_info:
                self.exec_cmd_in_namespace(
                    ["ip", "link", "set", "dev", intf_info["ifname"], "up"])
                self.exec_cmd_in_namespace(
                    ["ifdown", intf_info["bridge"]["ifname"]])
                self.exec_cmd_in_namespace(
                    ["ifup", intf_info["bridge"]["ifname"]])
            else:
                self.exec_cmd_in_namespace(["ifdown", intf_info["ifname"]])
                self.exec_cmd_in_namespace(["ifup", intf_info["ifname"]])

    def create_bridge(self, intf="einf0", br_name="br0"):
        self.exec_cmd_in_namespace(["brctl", "addbr", "{}".format(br_name)])
        self.exec_cmd_in_namespace(
            ["brctl", "addif", "{}".format(br_name), intf])
        self.exec_cmd_in_namespace(
            ["brctl", "setfd", "{}".format(br_name), "0"])
        self.exec_cmd_in_namespace(
            ["brctl", "sethello", "{}".format(br_name), "1"])
        self.exec_cmd_in_namespace(
            ["brctl", "stp", "{}".format(br_name), "no"])
        self.exec_cmd_in_namespace(["ifconfig", intf, "promisc"])

    def build_ns_configuration(self):
        netns_path = "/etc/netns"
        ns_network_dir = os.path.join(netns_path, self.name, "network")

        if_down_dir = os.path.join(ns_network_dir, "if-down.d")
        if not os.path.exists(if_down_dir):
            os.makedirs(if_down_dir)

        if_post_down_dir = os.path.join(ns_network_dir, "if-post-down.d")
        if not os.path.exists(if_post_down_dir):
            os.makedirs(if_post_down_dir)

        if_pre_up_dir = os.path.join(ns_network_dir, "if-pre-up.d")
        if not os.path.exists(if_pre_up_dir):
            os.makedirs(if_pre_up_dir)

        if_up_dir = os.path.join(ns_network_dir, "if-up.d")
        if not os.path.exists(if_up_dir):
            os.makedirs(if_up_dir)

        content = ""
        content += "auto lo\n"
        content += "iface lo inet loopback\n"
        content += "\n"

        intf_list = []
        for intf_info in self.__ns_info["interfaces"]:
            intf_obj = Interface(intf_info)
            intf_list.append(intf_obj)

        for iobj in intf_list:
            content += iobj.compose()

        with open(os.path.join(ns_network_dir, "interfaces"), "w") as f:
            f.write(content)
Ejemplo n.º 46
0
class ConfigApplier(object):
    def __init__(self):
        self.ip = IPDB()

    def _setIpConfig(self, iface):
        ipv4 = iface.ipv4
        ipv6 = iface.ipv6
        if ipv4.address or ipv6.address:
            self.removeIpConfig(iface)
        if ipv4.address:
            with self.ip.interfaces[iface.name] as i:
                i.add_ip(ipv4.address + '/' + ipv4.netmask)
            if ipv4.gateway and ipv4.defaultRoute:
                self.ip.routes.add({'dst': 'default',
                                    'gateway': ipv4.gateway}).commit()
        if ipv6.address:
            with self.ip.interfaces[iface.name] as i:
                i.add_ip(ipv6.address)
            if ipv6.gateway:
                self.ip.routes.add({'dst': 'default',
                                    'gateway': ipv6.gateway}).commit()
        if ipv6.ipv6autoconf is not None:
            with open('/proc/sys/net/ipv6/conf/%s/autoconf' % iface.name,
                      'w') as ipv6_autoconf:
                ipv6_autoconf.write('1' if ipv6.ipv6autoconf else '0')

    def removeIpConfig(self, iface):
        ipwrapper.addrFlush(iface.name)

    def setIfaceMtu(self, iface, mtu):
        with self.ip.interfaces[iface] as i:
            i['mtu'] = int(mtu)

    def setBondingMtu(self, iface, mtu):
        self.setIfaceMtu(iface, mtu)

    def ifup(self, iface):
        with self.ip.interfaces[iface.name] as i:
            i.up()
        if iface.ipv4.bootproto == 'dhcp':
            runDhclient(iface)
        if iface.ipv6.dhcpv6:
            runDhclient(iface, 6)

    def ifdown(self, iface):
        with self.ip.interfaces[iface.name] as i:
            i.down()
        dhclient = DhcpClient(iface.name)
        dhclient.shutdown()

    def setIfaceConfigAndUp(self, iface):
        if iface.ipv4 or iface.ipv6:
            self._setIpConfig(iface)
        if iface.mtu:
            self.setIfaceMtu(iface.name, iface.mtu)
        self.ifup(iface)

    def addBridge(self, bridge):
        self.ip.create(kind='bridge', ifname=bridge.name).commit()

    def addBridgePort(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.add_port(self.ip.interfaces[bridge.port.name])

    def removeBridge(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.remove()

    def removeBridgePort(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.del_port(self.ip.interfaces[bridge.port.name])

    def addVlan(self, vlan):
        link = self.ip.interfaces[vlan.device.name].index
        self.ip.create(kind='vlan', ifname=vlan.name,
                       link=link, vlan_id=vlan.tag).commit()

    def removeVlan(self, vlan):
        with self.ip.interfaces[vlan.name] as i:
            i.remove()

    def addBond(self, bond):
        if bond.name not in netinfo.bondings():
            self.ip.create(kind='bond', ifname=bond.name).commit()

    def removeBond(self, bond):
        with self.ip.interfaces[bond.name] as i:
            i.remove()

    def addBondSlave(self, bond, slave):
        self.ifdown(slave)
        with self.ip.interfaces[bond.name] as i:
            i.add_port(self.ip.interfaces[slave.name])
        self.ifup(slave)

    def removeBondSlave(self, bond, slave):
        with self.ip.interfaces[bond.name] as i:
            i.del_port(self.ip.interfaces[slave.name])

    def addBondOptions(self, bond):
        logging.debug('Add bond options %s', bond.options)
        for option in bond.options.split():
            key, value = option.split('=')
            with open(netinfo.BONDING_OPT % (bond.name, key), 'w') as f:
                f.write(value)

    def createLibvirtNetwork(self, network, bridged=True, iface=None):
        netXml = libvirt.createNetworkDef(network, bridged, iface)
        libvirt.createNetwork(netXml)

    def removeLibvirtNetwork(self, network):
        libvirt.removeNetwork(network)

    def releaseSocket(self):
        self.ip.release()
Ejemplo n.º 47
0
from pyroute2 import IPDB
from pyroute2.common import uifname

p0 = uifname()
ip = IPDB()

# create dummy interface to host routes on
ip.create(kind='dummy', ifname=p0).add_ip('172.16.1.1/24').up().commit()

# create a route
with ip.routes.add({'dst': '172.16.0.0/24', 'gateway': '172.16.1.2'}) as r:
    pass

# modify it
with ip.routes['172.16.0.0/24'] as r:
    r.gateway = '172.16.1.3'

# cleanup
with ip.routes['172.16.0.0/24'] as r:
    r.remove()

ip.interfaces[p0].remove().commit()

ip.release()
Ejemplo n.º 48
0
from pprint import pprint
from pyroute2 import IPDB
from pyroute2.common import uifname

ip = IPDB(debug=True)

# create an interface
i = ip.create(kind='dummy', ifname=uifname()).commit()
prev_state = i.nlmsg

# change the state
i.address = '00:11:22:33:44:55'
i.up()
i.commit()

# show, what has been changed, excluding statistics --
# it changes all the time
pprint((i.nlmsg - prev_state).strip(('IFLA_AF_SPEC',
                                     'IFLA_STATS',
                                     'IFLA_STATS64',
                                     'IFLA_LINKINFO',
                                     'IFLA_MAP')))

i.remove().commit()

ip.release()
Ejemplo n.º 49
0
    def execRequest(self, action, data):
        
        if action == 'Plugin.Activate':
            return HttpResponse(200,'json',{ 'Implements': ['NetworkDriver','IPAM'] }).response

        if action == 'NetworkDriver.GetCapabilities':
            return HttpResponse(200,'json',{ 'Scope':'local'}).response

        if action == 'IPAM.GetDefaultAddressSpaces':
            requestPool = {}
            return HttpResponse(200,'json',requestPool).response

        if action == 'IPAM.RequestPool':
            self.subnet = data['Pool']
            requestPool = {}
            requestPool['Pool'] = self.subnet
            return HttpResponse(200,'json',requestPool).response

        if action == 'IPAM.RequestAddress':
            plen = self.subnet.split('/')[1]
            requestAddress = {}
            if 'Address' not in data:
                reply = { 'error':'missing gateway, specify one with --gateway' }
                return HttpResponse(500,'json',reply).response
            requestAddress['Address'] = data['Address'] + '/' + plen
            return HttpResponse(200,'json',requestAddress).response

        if action == 'IPAM.ReleaseAddress':
            address = {}
            address['Address']  = data['Address']
            return HttpResponse(200,'json',address).response

        if action == 'IPAM.ReleasePool':
            pool = {}
            return HttpResponse(200,'json',pool).response

        if action == 'NetworkDriver.CreateNetwork':
            subnet  = data['IPv4Data'][0]['Pool']
            gateway = data['IPv4Data'][0]['Gateway'].split('/')[0]
            rtList = []
            if 'rt' in data['Options']['com.docker.network.generic']:
                rt = data['Options']['com.docker.network.generic']['rt']
                rtList = rt.split(',')
            openContrailVN = OpenContrailVN(data['NetworkID']).createNw(subnet, gateway, rtList)
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.DeleteNetwork':
            openContrailVN = OpenContrailVN(data['NetworkID']).deleteNw()
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.CreateEndpoint':
            networkId = data['NetworkID']
            endpointId = data['EndpointID']
            hostId = endpointId[:8]
            ipAddress = data['Interface']['Address']
            result  = OpenContrailVirtualMachineInterface(hostId).createVmi(networkId, ipAddress)
            interface = {}
            interface['Interface'] = {} 
            interface['Interface']['MacAddress'] = result['mac']
            return HttpResponse(200,'json',interface).response

        if action == 'NetworkDriver.DeleteEndpoint':
            endpointId = data['EndpointID']
            hostId = endpointId[:8]
            OpenContrailVirtualMachineInterface(hostId).deleteVmi()
            endpointId = data['EndpointID']
            vethIdHost = 'veth' + endpointId[:8] + 'p0'
            ip = IPDB()
            with ip.interfaces[vethIdHost] as veth:
                veth.remove()
            return HttpResponse(200,'json',{ }).response

        if action == 'NetworkDriver.EndpointOperInfo':
            endpointInfo = {}
            endpointInfo['NetworkID'] = data['NetworkID']
            endpointInfo['EndpointID'] = data['EndpointID']
            return HttpResponse(200,'json',endpointInfo).response

        if action == 'NetworkDriver.Join':
            endpointId = data['EndpointID']
            hostId = endpointId[:8]
            networkId = data['NetworkID']
            vethIdHost = 'veth' + endpointId[:8] + 'p0'
            vethIdContainer = 'veth' + endpointId[:8]
            vn = OpenContrailVN(networkId).VNget()
            subnet = vn.network_ipam_refs[0]['attr'].ipam_subnets[0]
            gateway = subnet.default_gateway
            mac = OpenContrailVirtualMachineInterface(hostId).getMac()
            ip = IPDB()
            ip.create(ifname=vethIdHost, kind='veth', peer=vethIdContainer).commit()
            with ip.interfaces[vethIdHost] as veth:
                veth.up()
            with ip.interfaces[vethIdContainer] as veth:
                veth.address = mac
            joinInfo = {}
            joinInfo['InterfaceName'] = {}
            joinInfo['InterfaceName']['SrcName'] = vethIdContainer
            joinInfo['InterfaceName']['DstPrefix'] = 'eth'
            joinInfo['Gateway'] = gateway
            #joinInfo['GatewayIPv6'] = '2000::2'
            joinInfo['StaticRoutes'] = []
            #staticRoute = {}
            #staticRoute['Destination'] = '2.2.2.0/24'
            #staticRoute['RouteType'] = 0
            #staticRoute['NextHop'] = '1.1.1.1'
            #joinInfo['StaticRoutes'].append(staticRoute)
            return HttpResponse(200,'json',joinInfo).response

        if action == 'NetworkDriver.Leave':
            return HttpResponse(200,'json',{ }).response
Ejemplo n.º 50
0
'''
Example: python ./examples/create_bond.py

Creates bond interface.
'''
from pyroute2 import IPDB

ip = IPDB(mode='explicit')

try:

    # The same scheme works for bridge interfaces too: you
    # can create a bridge interface and enslave some ports
    # to it just as below.

    with ip.create(kind='bond', ifname='bond,james') as i:
        # enslave two interfaces: tap0 and tap1
        i.add_port(ip.interfaces.tap0)
        i.add_port(ip.interfaces.tap1)
        # make an example more scary: add IPs to the bond,james
        i.add_ip('10.251.0.1/24')
        i.add_ip('10.251.0.2/24')

finally:
    ip.release()
Ejemplo n.º 51
0
Master is an interface to add VLAN to, e.g. eth0 or tap0 or
whatever else. Without parameters use tap0 as the default.
'''
from pyroute2 import IPDB
from pyroute2.common import uifname

ip = IPDB()

try:

    # unique interface names
    ms = uifname()
    vn = uifname()

    master = ip.create(ifname=ms, kind='dummy').commit()

    with ip.create(kind='vlan', ifname=vn, link=master, vlan_id=101) as i:
        # Arguments for ip.create() are executed before the transaction,
        # in the IPRoute.link('add', ...) call. If create() fails, the
        # interface became invalid and is not operable, you can safely
        # drop it.
        #
        # Here goes the rest of transaction. If it fails, the interface
        # continues to work, only failed transaction gets dropped.
        i.add_ip('10.251.0.1', 24)
        i.add_ip('10.251.0.2', 24)
        i.mtu = 1400

finally:
    try:
Ejemplo n.º 52
0
class TestExplicit(object):
    ip = None
    mode = 'explicit'

    def setup(self):
        self.ifaces = []
        self.ifd = self.get_ifname()
        create_link(self.ifd, kind='dummy')
        self.ip = IPDB(mode=self.mode)

    def get_ifname(self):
        ifname = uifname()
        self.ifaces.append(ifname)
        return ifname

    def teardown(self):
        for name in self.ifaces:
            try:
                # just a hardcore removal
                self.ip.nl.link_remove(self.ip.interfaces[name].index)
            except Exception:
                pass
        self.ip.release()
        self.ifaces = []

    def test_simple(self):
        assert len(list(self.ip.interfaces.keys())) > 0

    def test_empty_transaction(self):
        assert 'lo' in self.ip.interfaces
        with self.ip.interfaces.lo as i:
            assert isinstance(i.mtu, int)

    def test_idx_len(self):
        assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys())

    def test_idx_set(self):
        assert set(self.ip.by_name.values()) == set(self.ip.by_index.values())

    def test_idx_types(self):
        assert all(isinstance(i, int) for i in self.ip.by_index.keys())
        assert all(isinstance(i, basestring) for i in self.ip.by_name.keys())

    def test_addr_attributes(self):
        require_user('root')

        if1 = self.get_ifname()
        if2 = self.get_ifname()

        with self.ip.create(ifname=if1, kind='dummy') as i:
            # +scope host (=> broadcast == None)
            i.add_ip('172.16.102.1/24', scope=254)

        with self.ip.create(ifname=if2, kind='dummy') as i:
            # +broadcast (default scope == 0)
            i.add_ip('172.16.103.1/24', broadcast='172.16.103.128')

        index = self.ip.interfaces[if1]['index']
        addr = self.ip.nl.get_addr(index=index)[0]
        assert addr['scope'] == 254
        assert addr.get_attr('IFA_BROADCAST') is None

        index = self.ip.interfaces[if2]['index']
        addr = self.ip.nl.get_addr(index=index)[0]
        assert addr['scope'] == 0
        assert addr.get_attr('IFA_BROADCAST') == '172.16.103.128'

    def test_addr_loaded(self):
        for name in self.ip.by_name:
            assert len(self.ip.interfaces[name]['ipaddr']) == \
                len(get_ip_addr(name))

    def test_reprs(self):
        assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring)
        assert isinstance(repr(self.ip.interfaces.lo), basestring)

    def test_dotkeys(self):
        # self.ip.lo hint for ipython
        assert 'lo' in dir(self.ip.interfaces)
        assert 'lo' in self.ip.interfaces
        assert self.ip.interfaces.lo == self.ip.interfaces['lo']
        # create attribute
        self.ip.interfaces['newitem'] = True
        self.ip.interfaces.newattr = True
        self.ip.interfaces.newitem = None
        assert self.ip.interfaces.newitem == self.ip.interfaces['newitem']
        assert self.ip.interfaces.newitem is None
        # delete attribute
        del self.ip.interfaces.newitem
        del self.ip.interfaces.newattr
        assert 'newattr' not in dir(self.ip.interfaces)

    @skip_if_not_supported
    def test_vlan_slave_bridge(self):
        # https://github.com/svinota/pyroute2/issues/58
        # based on the code by Petr Horáček
        dXname = self.get_ifname()
        vXname = self.get_ifname()
        vYname = self.get_ifname()
        brname = self.get_ifname()

        require_user('root')
        dX = self.ip.create(ifname=dXname, kind='dummy').commit()
        vX = self.ip.create(ifname=vXname, kind='vlan', link=dX,
                            vlan_id=101).commit()
        vY = self.ip.create(ifname=vYname, kind='vlan', link=dX,
                            vlan_id=102).commit()
        with self.ip.create(ifname=brname, kind='bridge') as i:
            i.add_port(vX)
            i.add_port(vY['index'])

        assert vX['index'] in self.ip.interfaces[brname]['ports']
        assert vY['index'] in self.ip.interfaces[brname].ports
        assert vX['link'] == dX['index']
        assert vY['link'] == dX['index']
        assert vX['master'] == self.ip.interfaces[brname]['index']
        assert vY['master'] == self.ip.interfaces[brname].index

    def _test_commit_hook_positive(self):
        require_user('root')

        # test callback, that adds an address by itself --
        # just to check the possibility
        def cb(interface, snapshot, transaction):
            self.ip.nl.addr('add',
                            self.ip.interfaces[self.ifd].index,
                            address='172.16.22.1',
                            mask=24)

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        self.ip.interfaces[self.ifd].commit()

        # added address should be there
        assert ('172.16.21.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr
        # and the one, added by the callback, too
        assert ('172.16.22.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def _test_commit_hook_negative(self):
        require_user('root')

        # test exception to differentiate
        class CBException(Exception):
            pass

        # test callback, that always fail
        def cb(interface, snapshot, transaction):
            raise CBException()

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it; should fail
        # 'cause of the callback
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        try:
            self.ip.interfaces[self.ifd].commit()
        except CBException:
            pass

        # added address should be removed
        assert ('172.16.21.1', 24) not in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def test_review(self):
        assert len(self.ip.interfaces.lo._tids) == 0
        if self.ip.interfaces.lo._mode == 'explicit':
            self.ip.interfaces.lo.begin()
        self.ip.interfaces.lo.add_ip('172.16.21.1/24')
        r = self.ip.interfaces.lo.review()
        assert len(r['+ipaddr']) == 1
        assert len(r['-ipaddr']) == 0
        assert len(r['+ports']) == 0
        assert len(r['-ports']) == 0
        # +/-ipaddr, +/-ports
        assert len([i for i in r if r[i] is not None]) == 4
        self.ip.interfaces.lo.drop()

    def test_rename(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='dummy').commit()

        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()
        self.ip.interfaces[ifA].ifname = ifB
        self.ip.interfaces[ifA].commit()

        assert ifB in self.ip.interfaces
        assert ifA not in self.ip.interfaces

        if self.ip.interfaces[ifB]._mode == 'explicit':
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifB].ifname = ifA
        self.ip.interfaces[ifB].commit()

        assert ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces

    def test_routes_keys(self):
        assert '172.16.0.0/24' not in self.ip.routes
        # create but not commit
        self.ip.routes.add(dst='172.16.0.0/24', gateway='127.0.0.1')
        # checks
        assert '172.16.0.0/24' in self.ip.routes
        assert '172.16.0.0/24' in list(self.ip.routes.keys())

    def test_routes(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes

        # create a route
        with self.ip.routes.add({
                'dst': '172.16.0.0/24',
                'gateway': '127.0.0.1'
        }) as r:
            pass
        assert '172.16.0.0/24' in self.ip.routes.keys()
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1')

        # change the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.gateway = '127.0.0.2'
        assert self.ip.routes['172.16.0.0/24'].gateway == '127.0.0.2'
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.2')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()
        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    def test_routes_multipath_gateway(self):
        require_user('root')
        ifR = self.get_ifname()

        with self.ip.create(ifname=ifR, kind='dummy') as i:
            i.add_ip('172.16.231.1/24')
            i.up()

        r = self.ip.routes.add({
            'dst':
            '172.16.232.0/24',
            'multipath': [{
                'gateway': '172.16.231.2',
                'hops': 20
            }, {
                'gateway': '172.16.231.3',
                'hops': 30
            }, {
                'gateway': '172.16.231.4'
            }]
        })
        r.commit()
        assert grep('ip ro', pattern='172.16.232.0/24')
        assert grep('ip ro', pattern='nexthop.*172.16.231.2.*weight.*21')
        assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31')
        assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1')

        with self.ip.routes['172.16.232.0/24'] as r:
            r.add_nh({'gateway': '172.16.231.5', 'hops': 50})
            r.del_nh({'gateway': '172.16.231.2'})
        assert grep('ip ro', pattern='172.16.232.0/24')
        assert grep('ip ro', pattern='nexthop.*172.16.231.5.*weight.*51')
        assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31')
        assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1')

    def test_routes_metrics(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes.keys()

        # create a route
        self.ip.routes.add({
            'dst': '172.16.0.0/24',
            'gateway': '127.0.0.1',
            'metrics': {
                'mtu': 1360
            }
        }).commit()
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1360')

        # change metrics
        with self.ip.routes['172.16.0.0/24'] as r:
            r.metrics.mtu = 1400
        assert self.ip.routes['172.16.0.0/24']['metrics']['mtu'] == 1400
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1400')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()

        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    @skip_if_not_supported
    def _test_shadow(self, kind):
        ifA = self.get_ifname()

        a = self.ip.create(ifname=ifA, kind=kind).commit()
        if a._mode == 'explicit':
            a.begin()
        a.shadow().commit()
        assert ifA in self.ip.interfaces
        assert not grep('ip link', pattern=ifA)
        time.sleep(0.5)
        b = self.ip.create(ifname=ifA, kind=kind).commit()
        assert a == b
        assert grep('ip link', pattern=ifA)

    def test_shadow_bond(self):
        require_user('root')
        self._test_shadow('bond')

    def test_shadow_bridge(self):
        require_user('root')
        self._test_shadow('bridge')

    def test_shadow_dummy(self):
        require_user('root')
        self._test_shadow('dummy')

    def test_updown(self):
        require_user('root')

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].up()
        self.ip.interfaces[self.ifd].commit()
        assert self.ip.interfaces[self.ifd].flags & 1

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].down()
        self.ip.interfaces[self.ifd].commit()
        assert not (self.ip.interfaces[self.ifd].flags & 1)

    def test_slave_data(self):
        require_user('root')

        ifBR = self.get_ifname()
        ifP = self.get_ifname()
        self.ip.debug = True

        bridge = self.ip.create(ifname=ifBR, kind='bridge').commit()
        port = self.ip.create(ifname=ifP, kind='dummy').commit()

        if self.ip.mode == 'explicit':
            bridge.begin()
        bridge.add_port(port)
        bridge.up()
        bridge.commit()

        li = port.nlmsg.get_attr('IFLA_LINKINFO')
        skind = li.get_attr('IFLA_INFO_SLAVE_KIND')
        sdata = li.get_attr('IFLA_INFO_SLAVE_DATA')
        self.ip.debug = False
        if skind is None or sdata is None:
            raise SkipTest('slave data not provided')

        assert sdata.get_attr('IFLA_BRPORT_STATE') is not None
        assert sdata.get_attr('IFLA_BRPORT_MODE') is not None

    def test_fail_ipaddr(self):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(ifname=ifA, kind='dummy').commit()
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.add_ip('123.456.789.1024/153')
        try:
            i.commit()
        except socket.error as e:
            if not e.args[0].startswith('illegal IP'):
                raise
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.remove().commit()
        assert ifA not in self.ip.interfaces

    def test_json_dump(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        # set up the interface
        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2/24')
            i.up()

        # make a backup
        backup = self.ip.interfaces[ifA].dump()
        assert isinstance(backup, dict)

        # remove index and protinfo -- make it portable
        del backup['index']
        if 'protinfo' in backup:
            del backup['protinfo']

        # serialize
        backup = json.dumps(backup)

        # remove the interface
        with self.ip.interfaces[ifA] as i:
            i.remove()

        # create again, but with different name
        self.ip.create(kind='dummy', ifname=ifB).commit()

        # load the backup
        # 1. prepare to the restore: bring it down
        with self.ip.interfaces[ifB] as i:
            i.down()
        # 2. please notice, the interface will be renamed after the backup
        with self.ip.interfaces[ifB] as i:
            i.load(json.loads(backup))

        # check :)
        assert ifA in self.ip.interfaces
        assert ifB not in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert self.ip.interfaces[ifA].flags & 1

    def test_freeze_del(self):
        require_user('root')

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.1.1/24')
            i.up()

        # check
        assert ('172.16.0.1', 24) in interface.ipaddr
        assert ('172.16.1.1', 24) in interface.ipaddr
        assert interface.flags & 1

        interface.freeze()

        # delete interface with an external routine
        remove_link(interface.ifname)

        # wait for a second
        time.sleep(1)

        # check if it is back
        ipdb = IPDB()
        try:
            ifc = ipdb.interfaces[self.ifd]
            assert ('172.16.0.1', 24) in ifc.ipaddr
            assert ('172.16.1.1', 24) in ifc.ipaddr
            assert ifc.flags & 1
        except:
            raise
        finally:
            interface.unfreeze()
            ipdb.release()

    def test_freeze(self):
        require_user('root')

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.1.1/24')
            i.up()

        # check
        assert ('172.16.0.1', 24) in interface.ipaddr
        assert ('172.16.1.1', 24) in interface.ipaddr
        assert interface.flags & 1

        # assert routine
        def probe():
            # The freeze results are dynamic: it is not a real freeze,
            # it is a restore routine. So it takes time for results
            # to stabilize
            err = None
            for _ in range(3):
                err = None
                interface.ipaddr.set_target(
                    (('172.16.0.1', 24), ('172.16.1.1', 24)))
                interface.ipaddr.target.wait()
                try:
                    assert ('172.16.0.1', 24) in interface.ipaddr
                    assert ('172.16.1.1', 24) in interface.ipaddr
                    assert interface.flags & 1
                    break
                except AssertionError as e:
                    err = e
                    continue
                except Exception as e:
                    err = e
                    break
            if err is not None:
                interface.unfreeze()
                i2.close()
                raise err

        # freeze
        interface.freeze()

        # change the interface somehow
        i2 = IPRoute()
        i2.addr('delete', interface.index, '172.16.0.1', 24)
        i2.addr('delete', interface.index, '172.16.1.1', 24)
        probe()

        # unfreeze
        self.ip.interfaces[self.ifd].unfreeze()

        try:
            i2.addr('delete', interface.index, '172.16.0.1', 24)
            i2.addr('delete', interface.index, '172.16.1.1', 24)
        except:
            pass
        finally:
            i2.close()

        # should be up, but w/o addresses
        interface.ipaddr.set_target(set())
        interface.ipaddr.target.wait(3)
        assert ('172.16.0.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert ('172.16.1.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    def test_snapshots(self):
        require_user('root')

        ifB = self.get_ifname()

        # set up the interface
        with self.ip.interfaces[self.ifd] as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        # check it
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

        # make a snapshot
        s = self.ip.interfaces[self.ifd].snapshot()
        i = self.ip.interfaces[self.ifd]

        # check it
        assert i.last_snapshot_id() == s

        # unset the interface
        with self.ip.interfaces[self.ifd] as i:
            i.del_ip('172.16.0.1/24')
            i.down()

        # we can not rename the interface while it is up,
        # so do it in two turns
        with self.ip.interfaces[self.ifd] as i:
            i.ifname = ifB

        # check it
        assert ifB in self.ip.interfaces
        assert self.ifd not in self.ip.interfaces
        y = self.ip.interfaces[ifB]
        assert i == y
        assert ('172.16.0.1', 24) not in y.ipaddr
        assert not (y.flags & 1)

        # revert snapshot
        y.revert(s).commit()

        # check it
        assert ifB not in self.ip.interfaces
        assert self.ifd in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    @skip_if_not_supported
    def _test_ipv(self, ipv, kind):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(kind=kind, ifname=ifA).commit()
        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()

        if ipv == 4:
            addr = '172.16.0.1/24'
        elif ipv == 6:
            addr = 'fdb3:84e5:4ff4:55e4::1/64'
        else:
            raise Exception('bad IP version')

        i.add_ip(addr).commit()
        pre_target = addr.split('/')
        target = (pre_target[0], int(pre_target[1]))
        assert target in i['ipaddr']

    def test_ipv4_dummy(self):
        self._test_ipv(4, 'dummy')

    def test_ipv4_bond(self):
        self._test_ipv(4, 'bond')

    def test_ipv4_bridge(self):
        self._test_ipv(4, 'bridge')

    def test_ipv6_dummy(self):
        self._test_ipv(6, 'dummy')

    def test_ipv6_bond(self):
        self._test_ipv(6, 'bond')

    def test_ipv6_bridge(self):
        self._test_ipv(6, 'bridge')

    @skip_if_not_supported
    def test_create_tuntap_fail(self):
        try:
            self.ip.create(ifname='fAiL', kind='tuntap', mode='fail').commit()
        except:
            assert not grep('ip link', pattern='fAiL')
            return
        raise Exception('tuntap create succeded')

    @skip_if_not_supported
    def test_create_tuntap(self):
        require_user('root')

        ifA = self.get_ifname()
        self.ip.create(ifname=ifA, kind='tuntap', mode='tap', uid=1,
                       gid=1).commit()

        assert ifA in self.ip.interfaces
        assert grep('ip link', pattern=ifA)

    @skip_if_not_supported
    def test_ovs_kind_aliases(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, kind='ovs-bridge').commit()
        self.ip.create(ifname=ifB, kind='openvswitch').commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert grep('ip link', pattern=ifA)
        assert grep('ip link', pattern=ifB)

    @skip_if_not_supported
    def test_ovs_add_remove_port(self):
        require_user('root')

        ifOVS = self.get_ifname()
        self.ip.create(ifname=ifOVS, kind='ovs-bridge').commit()
        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, kind='dummy')
        self.ip.create(ifname=ifB, peer='x' + ifB, kind='veth')
        self.ip.commit()

        # add ports
        if self.ip.mode == 'explicit':
            self.ip.interfaces[ifOVS].begin()
        self.ip.interfaces[ifOVS].\
            add_port(self.ip.interfaces[ifA]).\
            add_port(self.ip.interfaces[ifB]).\
            commit()

        #
        assert self.ip.interfaces[ifA].master == \
            self.ip.interfaces[ifOVS].index
        assert self.ip.interfaces[ifB].master == \
            self.ip.interfaces[ifOVS].index
        assert self.ip.interfaces[ifA].index in \
            self.ip.interfaces[ifOVS].ports
        assert self.ip.interfaces[ifB].index in \
            self.ip.interfaces[ifOVS].ports

        # remove ports
        if self.ip.mode == 'explicit':
            self.ip.interfaces[ifOVS].begin()
        self.ip.interfaces[ifOVS].\
            del_port(self.ip.interfaces[ifA]).\
            del_port(self.ip.interfaces[ifB]).\
            commit()

        #
        assert self.ip.interfaces[ifA].get('master') is None
        assert self.ip.interfaces[ifB].get('master') is None
        assert not self.ip.interfaces[ifOVS].ports

    def test_global_create(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, kind='dummy')
        self.ip.create(ifname=ifB, kind='dummy')
        self.ip.commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert grep('ip link', pattern=ifA)
        assert grep('ip link', pattern=ifB)

    def test_global_priorities(self):
        require_user('root')
        ifA = self.get_ifname()
        ifB = self.get_ifname()
        ifC = self.get_ifname()
        a = self.ip.create(ifname=ifA, kind='dummy').commit()
        #
        if a._mode == 'explicit':
            a.begin()

        # prepare transaction: two interface creations
        # and one failure on an existing interface
        a.set_address('11:22:33:44:55:66')
        b = self.ip.create(ifname=ifB, kind='dummy')
        c = self.ip.create(ifname=ifC, kind='dummy')
        # now assign priorities
        b.ipdb_priority = 15  # will be execute first
        a.ipdb_priority = 10  # second -- and fail
        c.ipdb_priority = 5  # should not be executed
        # prepare watchdogs
        wdb = self.ip.watchdog(ifname=ifB)
        wdc = self.ip.watchdog(ifname=ifC)
        # run the transaction
        try:
            self.ip.commit()
        except NetlinkError:
            pass
        # control system state
        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert ifC in self.ip.interfaces
        assert a.ipdb_scope == 'system'
        assert b.ipdb_scope == 'create'
        assert c.ipdb_scope == 'create'
        assert a.address != '11:22:33:44:55:66'
        assert grep('ip link', pattern=ifA)
        assert not grep('ip link', pattern=ifB)
        assert not grep('ip link', pattern=ifC)
        wdb.wait(1)
        wdc.wait(1)
        assert wdb.is_set
        assert not wdc.is_set

    def test_global_veth(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, peer=ifB, kind='veth')
        self.ip.commit()

        assert self.ip.interfaces[ifA]['ipdb_scope'] == 'system'
        assert self.ip.interfaces[ifB]['ipdb_scope'] == 'system'

        if self.ip.mode == 'explicit':
            self.ip.interfaces[ifA].begin()
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifA].remove()
        self.ip.interfaces[ifB].remove()
        self.ip.commit()

        assert ifA not in self.ip.interfaces
        assert ifB not in self.ip.interfaces

    def test_global_rollback(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        a = self.ip.create(ifname=ifA, kind='dummy').commit()
        #
        if a._mode == 'explicit':
            a.begin()
        a.remove()
        b = self.ip.create(ifname=ifB, kind='dummy')
        b.set_mtu(1500).set_address('11:22:33:44:55:66')
        try:
            self.ip.commit()
        except NetlinkError:
            pass

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert b.ipdb_scope == 'create'
        assert grep('ip link', pattern=ifA)
        assert not grep('ip link', pattern=ifB)

    def test_global_netns(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        ns = str(uuid.uuid4())

        with IPDB(nl=NetNS(ns)) as nsdb:
            v1 = self.ip.create(ifname='x' + ifA, kind='veth', peer=ifA)
            v2 = self.ip.create(ifname='x' + ifB, kind='veth', peer=ifB)
            if v1._mode == 'explicit':
                v1.begin()
                v2.begin()
            v1.net_ns_fd = ns
            v2.net_ns_fd = ns
            self.ip.commit()
            nsdb.interfaces['x' + ifA].ifname = 'eth0'
            nsdb.interfaces['x' + ifB].ifname = 'eth1'
            nsdb.commit()
            if self.ip.interfaces[ifA]._mode == 'explicit':
                self.ip.interfaces[ifA].begin()
                self.ip.interfaces[ifB].begin()
            self.ip.interfaces[ifA].up()
            self.ip.interfaces[ifB].up()
            self.ip.commit()

        assert 'x' + ifA not in self.ip.interfaces
        assert 'x' + ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert self.ip.interfaces[ifA].flags & 1
        assert self.ip.interfaces[ifB].flags & 1

        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifA].remove()
        self.ip.interfaces[ifB].remove()
        self.ip.commit()
        netns.remove(ns)

    @skip_if_not_supported
    def test_create_veth(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='veth', peer=ifB).commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces

    def test_create_fail(self):
        require_user('root')

        ifA = self.get_ifname()

        # create with mac 11:22:33:44:55:66 should fail
        i = self.ip.create(kind='dummy',
                           ifname=ifA,
                           address='11:22:33:44:55:66')
        try:
            i.commit()
        except NetlinkError:
            pass

        assert i._mode == 'invalid'
        assert ifA not in self.ip.interfaces

    def test_create_dqn(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/255.255.255.0')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_double_reuse(self):
        require_user('root')

        ifA = self.get_ifname()
        # create an interface
        i1 = self.ip.create(kind='dummy', ifname=ifA).commit()
        try:
            # this call should fail on the very first step:
            # `bala` interface already exists
            self.ip.create(kind='dummy', ifname=ifA)
        except CreateException:
            pass
        # add `reuse` keyword -- now should pass
        i2 = self.ip.create(kind='dummy', ifname=ifA, reuse=True).commit()
        # assert that we have got references to the same interface
        assert i1 == i2

    @skip_if_not_supported
    def _create_double(self, kind):
        require_user('root')
        ifA = self.get_ifname()

        self.ip.create(kind=kind, ifname=ifA).commit()
        try:
            self.ip.create(kind=kind, ifname=ifA).commit()
        except CreateException:
            pass

    def test_create_double_dummy(self):
        self._create_double('dummy')

    def test_create_double_bridge(self):
        self._create_double('bridge')

    def test_create_double_bond(self):
        self._create_double('bond')

    def test_create_plain(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/24')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_and_remove(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

        with self.ip.interfaces[ifA] as i:
            i.remove()
        assert ifA not in self.ip.interfaces

    def test_dqn_mask(self):
        require_user('root')

        iface = self.ip.interfaces[self.ifd]
        with iface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2', mask=24)
            i.add_ip('172.16.0.3/255.255.255.0')
            i.add_ip('172.16.0.4', mask='255.255.255.0')

        assert ('172.16.0.1', 24) in iface.ipaddr
        assert ('172.16.0.2', 24) in iface.ipaddr
        assert ('172.16.0.3', 24) in iface.ipaddr
        assert ('172.16.0.4', 24) in iface.ipaddr

    @skip_if_not_supported
    def _create_master(self, kind, **kwarg):

        ifM = self.get_ifname()
        ifP1 = self.get_ifname()
        ifP2 = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifP1).commit()
        self.ip.create(kind='dummy', ifname=ifP2).commit()

        with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i:
            i.add_port(self.ip.interfaces[ifP1])
            i.add_ip('172.16.0.1/24')

        with self.ip.interfaces[ifM] as i:
            i.add_port(self.ip.interfaces[ifP2])
            i.add_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master == \
            self.ip.interfaces[ifM].index
        assert self.ip.interfaces[ifP2].if_master == \
            self.ip.interfaces[ifM].index

        with self.ip.interfaces[ifM] as i:
            i.del_port(self.ip.interfaces[ifP1])
            i.del_port(self.ip.interfaces[ifP2])
            i.del_ip('172.16.0.1/24')
            i.del_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master is None
        assert self.ip.interfaces[ifP2].if_master is None

    def test_create_bridge(self):
        require_user('root')
        self._create_master('bridge')

    def test_create_bond(self):
        require_user('root')
        self._create_master('bond')

    def test_create_team(self):
        require_user('root')
        self._create_master('team')

    def test_create_ovs(self):
        require_user('root')
        self._create_master('openvswitch')

    def test_create_bond2(self):
        require_user('root')
        self._create_master('bond', bond_mode=2)

    @skip_if_not_supported
    def _create_macvx_mode(self, kind, mode):
        require_user('root')
        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(**{
            'kind': kind,
            'link': ifdb[ifL],
            'ifname': ifV,
            '%s_mode' % kind: mode
        }).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].link == ifdb[ifL].index
            assert ifdb[ifV]['%s_mode' % kind] == mode
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_macvtap_vepa(self):
        return self._create_macvx_mode('macvtap', 'vepa')

    def test_create_macvtap_bridge(self):
        return self._create_macvx_mode('macvtap', 'bridge')

    def test_create_macvlan_vepa(self):
        return self._create_macvx_mode('macvlan', 'vepa')

    def test_create_macvlan_bridge(self):
        return self._create_macvx_mode('macvlan', 'bridge')

    def test_create_utf_name(self):
        require_user('root')
        ifO = 'ༀ'
        self.ip.create(kind='dummy', ifname=ifO).commit()
        assert ifO in self.ip.interfaces
        assert self.ip.nl.link_lookup(ifname=ifO)
        if self.ip.interfaces[ifO]._mode == 'explicit':
            self.ip.interfaces[ifO].begin()
        self.ip.interfaces[ifO].remove().commit()

    @skip_if_not_supported
    def test_create_gre(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        with self.ip.create(kind='dummy', ifname=ifL) as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        self.ip.create(kind='gre',
                       ifname=ifV,
                       gre_local='172.16.0.1',
                       gre_remote='172.16.0.2',
                       gre_ttl=16).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].gre_local == '172.16.0.1'
            assert ifdb[ifV].gre_remote == '172.16.0.2'
            assert ifdb[ifV].gre_ttl == 16
        except Exception:
            raise
        finally:
            ip2.release()

    @skip_if_not_supported
    def test_create_vxlan(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(kind='vxlan',
                       ifname=ifV,
                       vxlan_link=ifdb[ifL],
                       vxlan_id=101,
                       vxlan_group='239.1.1.1').commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces

        try:
            assert ifdb[ifV].vxlan_link == ifdb[ifL].index
            assert ifdb[ifV].vxlan_group == '239.1.1.1'
            assert ifdb[ifV].vxlan_id == 101
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_vlan_by_interface(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL],
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_create_vlan_by_index(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL].index,
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_remove_secondaries(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1', 24)
            i.add_ip('172.16.0.2', 24)

        assert ifA in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifA)

        if i._mode == 'explicit':
            i.begin()

        i.del_ip('172.16.0.1', 24)
        i.del_ip('172.16.0.2', 24)
        i.commit()

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifA)
Ejemplo n.º 53
0
def create_ns(br_name, ns_name, ns_ip, ns_netmask, if_description, add_if):
    """
    :param br_name:
    :param ns_name:
    :param ns_ip:
    :param ns_netmask:
    :param if_description:
    :param add_if:
    :return:
    """

    # start the main network settings database:
    ipdb = IPDB()

    # Check if the bridge exists
    if br_name not in ipdb.interfaces.keys():
        log.fatal("Could not find bridge %s!" % br_name)
        sys.exit(-1)

    # veth naming
    ifname = "%s_%s_p%%d" % (ns_name, if_description)

    if (ifname % 0) in ipdb.interfaces.keys():
        log.fatal("%s already exists as interface!" % (ifname % 0))
        return False

    log.debug("Creating veth pair %s - %s for namespace %s." %
              (ifname % 0, ifname % 1, ns_name))

    if ns_name in netns.listnetns() and not add_if:
        log.warning("Namespace %s already exists!" % ns_name)

    # Create/configure a network namespace
    ipdb_ns = IPDB(nl=NetNS(ns_name))

    # Make sure lo is up in the namespace
    ipdb_ns.interfaces["lo"].up().commit()

    # Create veth pair
    ipdb.create(kind='veth', ifname=(ifname % 0), peer=(ifname % 1)).commit()

    # Move peer veth into the netns
    with ipdb.interfaces[(ifname % 1)] as veth:
        veth.net_ns_fd = ns_name

    with ipdb.interfaces[(ifname % 0)] as veth:
        veth.up()

    # wait for iface to be moved to ns
    time.sleep(0.1)

    ns_ip = '%s/%s' % (ns_ip, ns_netmask)

    log.debug("Assigning IP %s to %s." % (ns_ip, (ifname % 1)))

    with ipdb_ns.interfaces[(ifname % 1)] as veth:
        veth.add_ip(ns_ip)
        veth.up()

    log.debug("Adding port %s to bridge %s." % ((ifname % 0), br_name))

    ipdb.interfaces[br_name].add_port((ifname % 0))

    ipdb.commit()

    return True
Ejemplo n.º 54
0
'''
Example: python ./examples/create_vlan.py [master]

Master is an interface to add VLAN to, e.g. eth0 or tap0 or
whatever else. Without parameters use tap0 as the default.
'''
from pyroute2 import IPDB

ip = IPDB()

try:

    master = ip.create(ifname='pr2test', kind='dummy').commit()

    with ip.create(kind='vlan', ifname='v101', link=master, vlan_id=101) as i:
        # Arguments for ip.create() are executed before the transaction,
        # in the IPRoute.link('add', ...) call. If create() fails, the
        # interface became invalid and is not operable, you can safely
        # drop it.
        #
        # Here goes the rest of transaction. If it fails, the interface
        # continues to work, only failed transaction gets dropped.
        i.add_ip('10.251.0.1', 24)
        i.add_ip('10.251.0.2', 24)
        i.mtu = 1400

finally:
    try:
        ip.interfaces.pr2test.remove().commit()
    except:
        pass
Ejemplo n.º 55
0
class ConfigApplier(object):
    def __init__(self):
        self.ip = IPDB()

    def _setIpConfig(self, iface):
        ipv4 = iface.ipv4
        ipv6 = iface.ipv6
        if ipv4.address or ipv6.address:
            self.removeIpConfig(iface)
        if ipv4.address:
            with self.ip.interfaces[iface.name] as i:
                i.add_ip(ipv4.address + '/' + ipv4.netmask)
            if ipv4.gateway and ipv4.defaultRoute:
                self.ip.routes.add({
                    'dst': 'default',
                    'gateway': ipv4.gateway
                }).commit()
        if ipv6.address:
            with self.ip.interfaces[iface.name] as i:
                i.add_ip(ipv6.address)
            if ipv6.gateway:
                self.ip.routes.add({
                    'dst': 'default',
                    'gateway': ipv6.gateway
                }).commit()
        if ipv6.ipv6autoconf is not None:
            with open('/proc/sys/net/ipv6/conf/%s/autoconf' % iface.name,
                      'w') as ipv6_autoconf:
                ipv6_autoconf.write('1' if ipv6.ipv6autoconf else '0')

    def removeIpConfig(self, iface):
        ipwrapper.addrFlush(iface.name)

    def setIfaceMtu(self, iface, mtu):
        with self.ip.interfaces[iface] as i:
            i['mtu'] = int(mtu)

    def setBondingMtu(self, iface, mtu):
        self.setIfaceMtu(iface, mtu)

    def ifup(self, iface):
        with self.ip.interfaces[iface.name] as i:
            i.up()
        if iface.ipv4.bootproto == 'dhcp':
            dhclient.run(iface.name, 4, iface.ipv4.defaultRoute,
                         iface.duid_source, iface.blockingdhcp)
        if iface.ipv6.dhcpv6:
            dhclient.run(iface.name, 6, iface.ipv6.defaultRoute,
                         iface.duid_source, iface.blockingdhcp)

    def ifdown(self, iface):
        with self.ip.interfaces[iface.name] as i:
            i.down()
        dhclient.stop(iface.name)

    def setIfaceConfigAndUp(self, iface):
        if iface.ipv4 or iface.ipv6:
            self._setIpConfig(iface)
        if iface.mtu:
            self.setIfaceMtu(iface.name, iface.mtu)
        self.ifup(iface)

    def addBridge(self, bridge):
        self.ip.create(kind='bridge', ifname=bridge.name).commit()

    def addBridgePort(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.add_port(self.ip.interfaces[bridge.port.name])

    def removeBridge(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.remove()

    def removeBridgePort(self, bridge):
        with self.ip.interfaces[bridge.name] as i:
            i.del_port(self.ip.interfaces[bridge.port.name])

    def addVlan(self, vlan):
        link = self.ip.interfaces[vlan.device.name].index
        self.ip.create(kind='vlan',
                       ifname=vlan.name,
                       link=link,
                       vlan_id=vlan.tag).commit()

    def removeVlan(self, vlan):
        with self.ip.interfaces[vlan.name] as i:
            i.remove()

    def addBond(self, bond):
        if bond.name not in netinfo.bondings():
            self.ip.create(kind='bond', ifname=bond.name).commit()

    def removeBond(self, bond):
        with self.ip.interfaces[bond.name] as i:
            i.remove()

    def addBondSlave(self, bond, slave):
        self.ifdown(slave)
        with self.ip.interfaces[bond.name] as i:
            i.add_port(self.ip.interfaces[slave.name])
        self.ifup(slave)

    def removeBondSlave(self, bond, slave):
        with self.ip.interfaces[bond.name] as i:
            i.del_port(self.ip.interfaces[slave.name])

    def addBondOptions(self, bond):
        logging.debug('Add bond options %s', bond.options)
        # 'custom' is not a real bond option, it just piggybacks custom values
        options = remove_custom_bond_option(bond.options)
        for option in options.split():
            key, value = option.split('=')
            with open(netinfo.BONDING_OPT % (bond.name, key), 'w') as f:
                f.write(value)

    def createLibvirtNetwork(self, network, bridged=True, iface=None):
        netXml = libvirt.createNetworkDef(network, bridged, iface)
        libvirt.createNetwork(netXml)

    def removeLibvirtNetwork(self, network):
        libvirt.removeNetwork(network)

    def releaseSocket(self):
        self.ip.release()
Ejemplo n.º 56
0
from pyroute2 import IPDB
from pyroute2.common import uifname

ip = IPDB()

try:

    # create unique interface names
    p0 = uifname()
    p1 = uifname()
    ms = uifname()

    # The same scheme works for bridge interfaces too: you
    # can create a bridge interface and enslave some ports
    # to it just as below.
    ip.create(kind='dummy', ifname=p0).commit()
    ip.create(kind='dummy', ifname=p1).commit()

    with ip.create(kind='bond', ifname=ms) as i:
        # enslave two interfaces
        i.add_port(ip.interfaces[p0])
        i.add_port(ip.interfaces[p1])
        # make an example more scary: add IPs
        i.add_ip('10.251.0.1/24')
        i.add_ip('10.251.0.2/24')

finally:
    for i in (p0, p1, ms):
        try:
            ip.interfaces[i].remove().commit()
        except:
                    i.remove()
        if 'tap'+args.ifname in ip.interfaces:
            with ip.interfaces['tap'+args.ifname] as i:
                i.remove()
        if brige_name in ip.interfaces:
            with ip.interfaces[brige_name] as i:
                i.remove()
        for ifn in range(args.ifnum):
            netns = NetNS('node'+str(ifn))
            netns.close()
            netns.remove()
    else:
        for ifn in range(args.ifnum):
            iface = args.ifname+str(ifn)
            if not iface in ip.interfaces:
                ip.create(kind='veth', ifname=iface, peer=iface+'.1').commit()

        ip.create(kind='tuntap', ifname='tap'+args.ifname, mode='tap').commit()

        with ip.create(kind='bridge', ifname=brige_name) as i:
            for ifn in range(args.ifnum):
                iface = args.ifname+str(ifn)
                i.add_port(ip.interfaces[iface])
            i.add_port(ip.interfaces['tap'+args.ifname])
            if args.ipv4:
                i.add_ip(local_addr4+'1/24')
            if args.ipv6:
                i.add_ip(local_addr6+'1/64')
            i.up()

        with ip.interfaces['tap'+args.ifname] as tap:
Ejemplo n.º 58
0
class TestExplicit(object):
    ip = None
    mode = 'explicit'

    def setup(self):
        self.ifaces = []
        self.ifd = self.get_ifname()
        create_link(self.ifd, kind='dummy')
        self.ip = IPDB(mode=self.mode)

    def get_ifname(self):
        ifname = uifname()
        self.ifaces.append(ifname)
        return ifname

    def teardown(self):
        for name in self.ifaces:
            try:
                # just a hardcore removal
                self.ip.nl.link_remove(self.ip.interfaces[name].index)
            except Exception:
                pass
        self.ip.release()
        self.ifaces = []

    def test_simple(self):
        assert len(list(self.ip.interfaces.keys())) > 0

    def test_empty_transaction(self):
        assert 'lo' in self.ip.interfaces
        with self.ip.interfaces.lo as i:
            assert isinstance(i.mtu, int)

    def test_idx_len(self):
        assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys())

    def test_idx_set(self):
        assert set(self.ip.by_name.values()) == set(self.ip.by_index.values())

    def test_idx_types(self):
        assert all(isinstance(i, int) for i in self.ip.by_index.keys())
        assert all(isinstance(i, basestring) for i in self.ip.by_name.keys())

    def test_addr_attributes(self):
        require_user('root')

        if1 = self.get_ifname()
        if2 = self.get_ifname()

        with self.ip.create(ifname=if1, kind='dummy') as i:
            # +scope host (=> broadcast == None)
            i.add_ip('172.16.102.1/24', scope=254)

        with self.ip.create(ifname=if2, kind='dummy') as i:
            # +broadcast (default scope == 0)
            i.add_ip('172.16.103.1/24', broadcast='172.16.103.128')

        index = self.ip.interfaces[if1]['index']
        addr = self.ip.nl.get_addr(index=index)[0]
        assert addr['scope'] == 254
        assert addr.get_attr('IFA_BROADCAST') is None

        index = self.ip.interfaces[if2]['index']
        addr = self.ip.nl.get_addr(index=index)[0]
        assert addr['scope'] == 0
        assert addr.get_attr('IFA_BROADCAST') == '172.16.103.128'

    def test_addr_loaded(self):
        for name in self.ip.by_name:
            assert len(self.ip.interfaces[name]['ipaddr']) == \
                len(get_ip_addr(name))

    def test_reprs(self):
        assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring)
        assert isinstance(repr(self.ip.interfaces.lo), basestring)

    def test_dotkeys(self):
        # self.ip.lo hint for ipython
        assert 'lo' in dir(self.ip.interfaces)
        assert 'lo' in self.ip.interfaces
        assert self.ip.interfaces.lo == self.ip.interfaces['lo']
        # create attribute
        self.ip.interfaces['newitem'] = True
        self.ip.interfaces.newattr = True
        self.ip.interfaces.newitem = None
        assert self.ip.interfaces.newitem == self.ip.interfaces['newitem']
        assert self.ip.interfaces.newitem is None
        # delete attribute
        del self.ip.interfaces.newitem
        del self.ip.interfaces.newattr
        assert 'newattr' not in dir(self.ip.interfaces)

    @skip_if_not_supported
    def test_vlan_slave_bridge(self):
        # https://github.com/svinota/pyroute2/issues/58
        # based on the code by Petr Horáček
        dXname = self.get_ifname()
        vXname = self.get_ifname()
        vYname = self.get_ifname()
        brname = self.get_ifname()

        require_user('root')
        dX = self.ip.create(ifname=dXname, kind='dummy').commit()
        vX = self.ip.create(ifname=vXname, kind='vlan',
                            link=dX, vlan_id=101).commit()
        vY = self.ip.create(ifname=vYname, kind='vlan',
                            link=dX, vlan_id=102).commit()
        with self.ip.create(ifname=brname, kind='bridge') as i:
            i.add_port(vX)
            i.add_port(vY['index'])

        assert vX['index'] in self.ip.interfaces[brname]['ports']
        assert vY['index'] in self.ip.interfaces[brname].ports
        assert vX['link'] == dX['index']
        assert vY['link'] == dX['index']
        assert vX['master'] == self.ip.interfaces[brname]['index']
        assert vY['master'] == self.ip.interfaces[brname].index

    def _test_commit_hook_positive(self):
        require_user('root')

        # test callback, that adds an address by itself --
        # just to check the possibility
        def cb(interface, snapshot, transaction):
            self.ip.nl.addr('add',
                            self.ip.interfaces[self.ifd].index,
                            address='172.16.22.1',
                            mask=24)

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        self.ip.interfaces[self.ifd].commit()

        # added address should be there
        assert ('172.16.21.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr
        # and the one, added by the callback, too
        assert ('172.16.22.1', 24) in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def _test_commit_hook_negative(self):
        require_user('root')

        # test exception to differentiate
        class CBException(Exception):
            pass

        # test callback, that always fail
        def cb(interface, snapshot, transaction):
            raise CBException()

        # register callback and check CB chain length
        self.ip.interfaces[self.ifd].register_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1

        # create a transaction and commit it; should fail
        # 'cause of the callback
        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24')
        try:
            self.ip.interfaces[self.ifd].commit()
        except CBException:
            pass

        # added address should be removed
        assert ('172.16.21.1', 24) not in \
            self.ip.interfaces[self.ifd].ipaddr

        # unregister callback
        self.ip.interfaces[self.ifd].unregister_commit_hook(cb)
        assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0

    def test_review(self):
        assert len(self.ip.interfaces.lo._tids) == 0
        if self.ip.interfaces.lo._mode == 'explicit':
            self.ip.interfaces.lo.begin()
        self.ip.interfaces.lo.add_ip('172.16.21.1/24')
        r = self.ip.interfaces.lo.review()
        assert len(r['+ipaddr']) == 1
        assert len(r['-ipaddr']) == 0
        assert len(r['+ports']) == 0
        assert len(r['-ports']) == 0
        # +/-ipaddr, +/-ports
        assert len([i for i in r if r[i] is not None]) == 4
        self.ip.interfaces.lo.drop()

    def test_rename(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='dummy').commit()

        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()
        self.ip.interfaces[ifA].ifname = ifB
        self.ip.interfaces[ifA].commit()

        assert ifB in self.ip.interfaces
        assert ifA not in self.ip.interfaces

        if self.ip.interfaces[ifB]._mode == 'explicit':
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifB].ifname = ifA
        self.ip.interfaces[ifB].commit()

        assert ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces

    def test_routes_keys(self):
        assert '172.16.0.0/24' not in self.ip.routes
        # create but not commit
        self.ip.routes.add(dst='172.16.0.0/24', gateway='127.0.0.1')
        # checks
        assert '172.16.0.0/24' in self.ip.routes
        assert '172.16.0.0/24' in list(self.ip.routes.keys())

    def test_routes(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes

        # create a route
        with self.ip.routes.add({'dst': '172.16.0.0/24',
                                 'gateway': '127.0.0.1'}) as r:
            pass
        assert '172.16.0.0/24' in self.ip.routes.keys()
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1')

        # change the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.gateway = '127.0.0.2'
        assert self.ip.routes['172.16.0.0/24'].gateway == '127.0.0.2'
        assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.2')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()
        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    def test_routes_multipath_gateway(self):
        require_user('root')
        ifR = self.get_ifname()

        with self.ip.create(ifname=ifR, kind='dummy') as i:
            i.add_ip('172.16.231.1/24')
            i.up()

        r = self.ip.routes.add({'dst': '172.16.232.0/24',
                                'multipath': [{'gateway': '172.16.231.2',
                                               'hops': 20},
                                              {'gateway': '172.16.231.3',
                                               'hops': 30},
                                              {'gateway': '172.16.231.4'}]})
        r.commit()
        assert grep('ip ro', pattern='172.16.232.0/24')
        assert grep('ip ro', pattern='nexthop.*172.16.231.2.*weight.*21')
        assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31')
        assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1')

        with self.ip.routes['172.16.232.0/24'] as r:
            r.add_nh({'gateway': '172.16.231.5', 'hops': 50})
            r.del_nh({'gateway': '172.16.231.2'})
        assert grep('ip ro', pattern='172.16.232.0/24')
        assert grep('ip ro', pattern='nexthop.*172.16.231.5.*weight.*51')
        assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31')
        assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1')

    def test_routes_metrics(self):
        require_user('root')
        assert '172.16.0.0/24' not in self.ip.routes.keys()

        # create a route
        self.ip.routes.add({'dst': '172.16.0.0/24',
                            'gateway': '127.0.0.1',
                            'metrics': {'mtu': 1360}}).commit()
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1360')

        # change metrics
        with self.ip.routes['172.16.0.0/24'] as r:
            r.metrics.mtu = 1400
        assert self.ip.routes['172.16.0.0/24']['metrics']['mtu'] == 1400
        assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1400')

        # delete the route
        with self.ip.routes['172.16.0.0/24'] as r:
            r.remove()

        assert '172.16.0.0/24' not in self.ip.routes.keys()
        assert not grep('ip ro', pattern='172.16.0.0/24')

    @skip_if_not_supported
    def _test_shadow(self, kind):
        ifA = self.get_ifname()

        a = self.ip.create(ifname=ifA, kind=kind).commit()
        if a._mode == 'explicit':
            a.begin()
        a.shadow().commit()
        assert ifA in self.ip.interfaces
        assert not grep('ip link', pattern=ifA)
        time.sleep(0.5)
        b = self.ip.create(ifname=ifA, kind=kind).commit()
        assert a == b
        assert grep('ip link', pattern=ifA)

    def test_shadow_bond(self):
        require_user('root')
        self._test_shadow('bond')

    def test_shadow_bridge(self):
        require_user('root')
        self._test_shadow('bridge')

    def test_shadow_dummy(self):
        require_user('root')
        self._test_shadow('dummy')

    def test_updown(self):
        require_user('root')

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].up()
        self.ip.interfaces[self.ifd].commit()
        assert self.ip.interfaces[self.ifd].flags & 1

        if self.ip.interfaces[self.ifd]._mode == 'explicit':
            self.ip.interfaces[self.ifd].begin()
        self.ip.interfaces[self.ifd].down()
        self.ip.interfaces[self.ifd].commit()
        assert not (self.ip.interfaces[self.ifd].flags & 1)

    def test_slave_data(self):
        require_user('root')

        ifBR = self.get_ifname()
        ifP = self.get_ifname()
        self.ip.debug = True

        bridge = self.ip.create(ifname=ifBR, kind='bridge').commit()
        port = self.ip.create(ifname=ifP, kind='dummy').commit()

        if self.ip.mode == 'explicit':
            bridge.begin()
        bridge.add_port(port)
        bridge.up()
        bridge.commit()

        li = port.nlmsg.get_attr('IFLA_LINKINFO')
        skind = li.get_attr('IFLA_INFO_SLAVE_KIND')
        sdata = li.get_attr('IFLA_INFO_SLAVE_DATA')
        self.ip.debug = False
        if skind is None or sdata is None:
            raise SkipTest('slave data not provided')

        assert sdata.get_attr('IFLA_BRPORT_STATE') is not None
        assert sdata.get_attr('IFLA_BRPORT_MODE') is not None

    def test_fail_ipaddr(self):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(ifname=ifA, kind='dummy').commit()
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.add_ip('123.456.789.1024/153')
        try:
            i.commit()
        except socket.error as e:
            if not e.args[0].startswith('illegal IP'):
                raise
        assert not len(i.ipaddr)
        if i._mode == 'explicit':
            i.begin()
        i.remove().commit()
        assert ifA not in self.ip.interfaces

    def test_json_dump(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        # set up the interface
        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2/24')
            i.up()

        # make a backup
        backup = self.ip.interfaces[ifA].dump()
        assert isinstance(backup, dict)

        # remove index and protinfo -- make it portable
        del backup['index']
        if 'protinfo' in backup:
            del backup['protinfo']

        # serialize
        backup = json.dumps(backup)

        # remove the interface
        with self.ip.interfaces[ifA] as i:
            i.remove()

        # create again, but with different name
        self.ip.create(kind='dummy', ifname=ifB).commit()

        # load the backup
        # 1. prepare to the restore: bring it down
        with self.ip.interfaces[ifB] as i:
            i.down()
        # 2. please notice, the interface will be renamed after the backup
        with self.ip.interfaces[ifB] as i:
            i.load(json.loads(backup))

        # check :)
        assert ifA in self.ip.interfaces
        assert ifB not in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert self.ip.interfaces[ifA].flags & 1

    def test_freeze_del(self):
        require_user('root')

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.1.1/24')
            i.up()

        # check
        assert ('172.16.0.1', 24) in interface.ipaddr
        assert ('172.16.1.1', 24) in interface.ipaddr
        assert interface.flags & 1

        interface.freeze()

        # delete interface with an external routine
        remove_link(interface.ifname)

        # wait for a second
        time.sleep(1)

        # check if it is back
        ipdb = IPDB()
        try:
            ifc = ipdb.interfaces[self.ifd]
            assert ('172.16.0.1', 24) in ifc.ipaddr
            assert ('172.16.1.1', 24) in ifc.ipaddr
            assert ifc.flags & 1
        except:
            raise
        finally:
            interface.unfreeze()
            ipdb.release()

    def test_freeze(self):
        require_user('root')

        interface = self.ip.interfaces[self.ifd]

        # set up the interface
        with interface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.1.1/24')
            i.up()

        # check
        assert ('172.16.0.1', 24) in interface.ipaddr
        assert ('172.16.1.1', 24) in interface.ipaddr
        assert interface.flags & 1

        # assert routine
        def probe():
            # The freeze results are dynamic: it is not a real freeze,
            # it is a restore routine. So it takes time for results
            # to stabilize
            err = None
            for _ in range(3):
                err = None
                interface.ipaddr.set_target((('172.16.0.1', 24),
                                             ('172.16.1.1', 24)))
                interface.ipaddr.target.wait()
                try:
                    assert ('172.16.0.1', 24) in interface.ipaddr
                    assert ('172.16.1.1', 24) in interface.ipaddr
                    assert interface.flags & 1
                    break
                except AssertionError as e:
                    err = e
                    continue
                except Exception as e:
                    err = e
                    break
            if err is not None:
                interface.unfreeze()
                i2.close()
                raise err

        # freeze
        interface.freeze()

        # change the interface somehow
        i2 = IPRoute()
        i2.addr('delete', interface.index, '172.16.0.1', 24)
        i2.addr('delete', interface.index, '172.16.1.1', 24)
        probe()

        # unfreeze
        self.ip.interfaces[self.ifd].unfreeze()

        try:
            i2.addr('delete', interface.index, '172.16.0.1', 24)
            i2.addr('delete', interface.index, '172.16.1.1', 24)
        except:
            pass
        finally:
            i2.close()

        # should be up, but w/o addresses
        interface.ipaddr.set_target(set())
        interface.ipaddr.target.wait(3)
        assert ('172.16.0.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert ('172.16.1.1', 24) not in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    def test_snapshots(self):
        require_user('root')

        ifB = self.get_ifname()

        # set up the interface
        with self.ip.interfaces[self.ifd] as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        # check it
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

        # make a snapshot
        s = self.ip.interfaces[self.ifd].snapshot()
        i = self.ip.interfaces[self.ifd]

        # check it
        assert i.last_snapshot_id() == s

        # unset the interface
        with self.ip.interfaces[self.ifd] as i:
            i.del_ip('172.16.0.1/24')
            i.down()

        # we can not rename the interface while it is up,
        # so do it in two turns
        with self.ip.interfaces[self.ifd] as i:
            i.ifname = ifB

        # check it
        assert ifB in self.ip.interfaces
        assert self.ifd not in self.ip.interfaces
        y = self.ip.interfaces[ifB]
        assert i == y
        assert ('172.16.0.1', 24) not in y.ipaddr
        assert not (y.flags & 1)

        # revert snapshot
        y.revert(s).commit()

        # check it
        assert ifB not in self.ip.interfaces
        assert self.ifd in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr
        assert self.ip.interfaces[self.ifd].flags & 1

    @skip_if_not_supported
    def _test_ipv(self, ipv, kind):
        require_user('root')

        ifA = self.get_ifname()

        i = self.ip.create(kind=kind, ifname=ifA).commit()
        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()

        if ipv == 4:
            addr = '172.16.0.1/24'
        elif ipv == 6:
            addr = 'fdb3:84e5:4ff4:55e4::1/64'
        else:
            raise Exception('bad IP version')

        i.add_ip(addr).commit()
        pre_target = addr.split('/')
        target = (pre_target[0], int(pre_target[1]))
        assert target in i['ipaddr']

    def test_ipv4_dummy(self):
        self._test_ipv(4, 'dummy')

    def test_ipv4_bond(self):
        self._test_ipv(4, 'bond')

    def test_ipv4_bridge(self):
        self._test_ipv(4, 'bridge')

    def test_ipv6_dummy(self):
        self._test_ipv(6, 'dummy')

    def test_ipv6_bond(self):
        self._test_ipv(6, 'bond')

    def test_ipv6_bridge(self):
        self._test_ipv(6, 'bridge')

    @skip_if_not_supported
    def test_create_tuntap_fail(self):
        try:
            self.ip.create(ifname='fAiL',
                           kind='tuntap',
                           mode='fail').commit()
        except:
            assert not grep('ip link', pattern='fAiL')
            return
        raise Exception('tuntap create succeded')

    @skip_if_not_supported
    def test_create_tuntap(self):
        require_user('root')

        ifA = self.get_ifname()
        self.ip.create(ifname=ifA,
                       kind='tuntap',
                       mode='tap',
                       uid=1,
                       gid=1).commit()

        assert ifA in self.ip.interfaces
        assert grep('ip link', pattern=ifA)

    @skip_if_not_supported
    def test_ovs_kind_aliases(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA,
                       kind='ovs-bridge').commit()
        self.ip.create(ifname=ifB,
                       kind='openvswitch').commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert grep('ip link', pattern=ifA)
        assert grep('ip link', pattern=ifB)

    @skip_if_not_supported
    def test_ovs_add_remove_port(self):
        require_user('root')

        ifOVS = self.get_ifname()
        self.ip.create(ifname=ifOVS,
                       kind='ovs-bridge').commit()
        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, kind='dummy')
        self.ip.create(ifname=ifB, peer='x' + ifB, kind='veth')
        self.ip.commit()

        # add ports
        if self.ip.mode == 'explicit':
            self.ip.interfaces[ifOVS].begin()
        self.ip.interfaces[ifOVS].\
            add_port(self.ip.interfaces[ifA]).\
            add_port(self.ip.interfaces[ifB]).\
            commit()

        #
        assert self.ip.interfaces[ifA].master == \
            self.ip.interfaces[ifOVS].index
        assert self.ip.interfaces[ifB].master == \
            self.ip.interfaces[ifOVS].index
        assert self.ip.interfaces[ifA].index in \
            self.ip.interfaces[ifOVS].ports
        assert self.ip.interfaces[ifB].index in \
            self.ip.interfaces[ifOVS].ports

        # remove ports
        if self.ip.mode == 'explicit':
            self.ip.interfaces[ifOVS].begin()
        self.ip.interfaces[ifOVS].\
            del_port(self.ip.interfaces[ifA]).\
            del_port(self.ip.interfaces[ifB]).\
            commit()

        #
        assert self.ip.interfaces[ifA].get('master') is None
        assert self.ip.interfaces[ifB].get('master') is None
        assert not self.ip.interfaces[ifOVS].ports

    def test_global_create(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, kind='dummy')
        self.ip.create(ifname=ifB, kind='dummy')
        self.ip.commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert grep('ip link', pattern=ifA)
        assert grep('ip link', pattern=ifB)

    def test_global_priorities(self):
        require_user('root')
        ifA = self.get_ifname()
        ifB = self.get_ifname()
        ifC = self.get_ifname()
        a = self.ip.create(ifname=ifA, kind='dummy').commit()
        #
        if a._mode == 'explicit':
            a.begin()

        # prepare transaction: two interface creations
        # and one failure on an existing interface
        a.set_address('11:22:33:44:55:66')
        b = self.ip.create(ifname=ifB, kind='dummy')
        c = self.ip.create(ifname=ifC, kind='dummy')
        # now assign priorities
        b.ipdb_priority = 15  # will be execute first
        a.ipdb_priority = 10  # second -- and fail
        c.ipdb_priority = 5   # should not be executed
        # prepare watchdogs
        wdb = self.ip.watchdog(ifname=ifB)
        wdc = self.ip.watchdog(ifname=ifC)
        # run the transaction
        try:
            self.ip.commit()
        except NetlinkError:
            pass
        # control system state
        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert ifC in self.ip.interfaces
        assert a.ipdb_scope == 'system'
        assert b.ipdb_scope == 'create'
        assert c.ipdb_scope == 'create'
        assert a.address != '11:22:33:44:55:66'
        assert grep('ip link', pattern=ifA)
        assert not grep('ip link', pattern=ifB)
        assert not grep('ip link', pattern=ifC)
        wdb.wait(1)
        wdc.wait(1)
        assert wdb.is_set
        assert not wdc.is_set

    def test_global_veth(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        self.ip.create(ifname=ifA, peer=ifB, kind='veth')
        self.ip.commit()

        assert self.ip.interfaces[ifA]['ipdb_scope'] == 'system'
        assert self.ip.interfaces[ifB]['ipdb_scope'] == 'system'

        if self.ip.mode == 'explicit':
            self.ip.interfaces[ifA].begin()
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifA].remove()
        self.ip.interfaces[ifB].remove()
        self.ip.commit()

        assert ifA not in self.ip.interfaces
        assert ifB not in self.ip.interfaces

    def test_global_rollback(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        a = self.ip.create(ifname=ifA, kind='dummy').commit()
        #
        if a._mode == 'explicit':
            a.begin()
        a.remove()
        b = self.ip.create(ifname=ifB, kind='dummy')
        b.set_mtu(1500).set_address('11:22:33:44:55:66')
        try:
            self.ip.commit()
        except NetlinkError:
            pass

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert b.ipdb_scope == 'create'
        assert grep('ip link', pattern=ifA)
        assert not grep('ip link', pattern=ifB)

    def test_global_netns(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()
        ns = str(uuid.uuid4())

        with IPDB(nl=NetNS(ns)) as nsdb:
            v1 = self.ip.create(ifname='x' + ifA, kind='veth', peer=ifA)
            v2 = self.ip.create(ifname='x' + ifB, kind='veth', peer=ifB)
            if v1._mode == 'explicit':
                v1.begin()
                v2.begin()
            v1.net_ns_fd = ns
            v2.net_ns_fd = ns
            self.ip.commit()
            nsdb.interfaces['x' + ifA].ifname = 'eth0'
            nsdb.interfaces['x' + ifB].ifname = 'eth1'
            nsdb.commit()
            if self.ip.interfaces[ifA]._mode == 'explicit':
                self.ip.interfaces[ifA].begin()
                self.ip.interfaces[ifB].begin()
            self.ip.interfaces[ifA].up()
            self.ip.interfaces[ifB].up()
            self.ip.commit()

        assert 'x' + ifA not in self.ip.interfaces
        assert 'x' + ifB not in self.ip.interfaces
        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces
        assert self.ip.interfaces[ifA].flags & 1
        assert self.ip.interfaces[ifB].flags & 1

        if self.ip.interfaces[ifA]._mode == 'explicit':
            self.ip.interfaces[ifA].begin()
            self.ip.interfaces[ifB].begin()
        self.ip.interfaces[ifA].remove()
        self.ip.interfaces[ifB].remove()
        self.ip.commit()
        netns.remove(ns)

    @skip_if_not_supported
    def test_create_veth(self):
        require_user('root')

        ifA = self.get_ifname()
        ifB = self.get_ifname()

        self.ip.create(ifname=ifA, kind='veth', peer=ifB).commit()

        assert ifA in self.ip.interfaces
        assert ifB in self.ip.interfaces

    def test_create_fail(self):
        require_user('root')

        ifA = self.get_ifname()

        # create with mac 11:22:33:44:55:66 should fail
        i = self.ip.create(kind='dummy',
                           ifname=ifA,
                           address='11:22:33:44:55:66')
        try:
            i.commit()
        except NetlinkError:
            pass

        assert i._mode == 'invalid'
        assert ifA not in self.ip.interfaces

    def test_create_dqn(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/255.255.255.0')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_double_reuse(self):
        require_user('root')

        ifA = self.get_ifname()
        # create an interface
        i1 = self.ip.create(kind='dummy', ifname=ifA).commit()
        try:
            # this call should fail on the very first step:
            # `bala` interface already exists
            self.ip.create(kind='dummy', ifname=ifA)
        except CreateException:
            pass
        # add `reuse` keyword -- now should pass
        i2 = self.ip.create(kind='dummy',
                            ifname=ifA,
                            reuse=True).commit()
        # assert that we have got references to the same interface
        assert i1 == i2

    @skip_if_not_supported
    def _create_double(self, kind):
        require_user('root')
        ifA = self.get_ifname()

        self.ip.create(kind=kind, ifname=ifA).commit()
        try:
            self.ip.create(kind=kind, ifname=ifA).commit()
        except CreateException:
            pass

    def test_create_double_dummy(self):
        self._create_double('dummy')

    def test_create_double_bridge(self):
        self._create_double('bridge')

    def test_create_double_bond(self):
        self._create_double('bond')

    def test_create_plain(self):
        require_user('root')
        ifA = self.get_ifname()

        i = self.ip.create(kind='dummy', ifname=ifA)
        i.add_ip('172.16.0.1/24')
        i.commit()
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

    def test_create_and_remove(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1/24')
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)

        with self.ip.interfaces[ifA] as i:
            i.remove()
        assert ifA not in self.ip.interfaces

    def test_dqn_mask(self):
        require_user('root')

        iface = self.ip.interfaces[self.ifd]
        with iface as i:
            i.add_ip('172.16.0.1/24')
            i.add_ip('172.16.0.2', mask=24)
            i.add_ip('172.16.0.3/255.255.255.0')
            i.add_ip('172.16.0.4', mask='255.255.255.0')

        assert ('172.16.0.1', 24) in iface.ipaddr
        assert ('172.16.0.2', 24) in iface.ipaddr
        assert ('172.16.0.3', 24) in iface.ipaddr
        assert ('172.16.0.4', 24) in iface.ipaddr

    @skip_if_not_supported
    def _create_master(self, kind, **kwarg):

        ifM = self.get_ifname()
        ifP1 = self.get_ifname()
        ifP2 = self.get_ifname()

        self.ip.create(kind='dummy', ifname=ifP1).commit()
        self.ip.create(kind='dummy', ifname=ifP2).commit()

        with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i:
            i.add_port(self.ip.interfaces[ifP1])
            i.add_ip('172.16.0.1/24')

        with self.ip.interfaces[ifM] as i:
            i.add_port(self.ip.interfaces[ifP2])
            i.add_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master == \
            self.ip.interfaces[ifM].index
        assert self.ip.interfaces[ifP2].if_master == \
            self.ip.interfaces[ifM].index

        with self.ip.interfaces[ifM] as i:
            i.del_port(self.ip.interfaces[ifP1])
            i.del_port(self.ip.interfaces[ifP2])
            i.del_ip('172.16.0.1/24')
            i.del_ip('172.16.0.2/24')

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifM].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifM].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifM)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifM)
        assert self.ip.interfaces[ifP1].if_master is None
        assert self.ip.interfaces[ifP2].if_master is None

    def test_create_bridge(self):
        require_user('root')
        self._create_master('bridge')

    def test_create_bond(self):
        require_user('root')
        self._create_master('bond')

    def test_create_team(self):
        require_user('root')
        self._create_master('team')

    def test_create_ovs(self):
        require_user('root')
        self._create_master('openvswitch')

    def test_create_bond2(self):
        require_user('root')
        self._create_master('bond', bond_mode=2)

    @skip_if_not_supported
    def _create_macvx_mode(self, kind, mode):
        require_user('root')
        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(**{'kind': kind,
                          'link': ifdb[ifL],
                          'ifname': ifV,
                          '%s_mode' % kind: mode}).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].link == ifdb[ifL].index
            assert ifdb[ifV]['%s_mode' % kind] == mode
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_macvtap_vepa(self):
        return self._create_macvx_mode('macvtap', 'vepa')

    def test_create_macvtap_bridge(self):
        return self._create_macvx_mode('macvtap', 'bridge')

    def test_create_macvlan_vepa(self):
        return self._create_macvx_mode('macvlan', 'vepa')

    def test_create_macvlan_bridge(self):
        return self._create_macvx_mode('macvlan', 'bridge')

    def test_create_utf_name(self):
        require_user('root')
        ifO = 'ༀ'
        self.ip.create(kind='dummy', ifname=ifO).commit()
        assert ifO in self.ip.interfaces
        assert self.ip.nl.link_lookup(ifname=ifO)
        if self.ip.interfaces[ifO]._mode == 'explicit':
            self.ip.interfaces[ifO].begin()
        self.ip.interfaces[ifO].remove().commit()

    @skip_if_not_supported
    def test_create_gre(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        with self.ip.create(kind='dummy', ifname=ifL) as i:
            i.add_ip('172.16.0.1/24')
            i.up()

        self.ip.create(kind='gre',
                       ifname=ifV,
                       gre_local='172.16.0.1',
                       gre_remote='172.16.0.2',
                       gre_ttl=16).commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces
        try:
            assert ifdb[ifV].gre_local == '172.16.0.1'
            assert ifdb[ifV].gre_remote == '172.16.0.2'
            assert ifdb[ifV].gre_ttl == 16
        except Exception:
            raise
        finally:
            ip2.release()

    @skip_if_not_supported
    def test_create_vxlan(self):
        require_user('root')

        ifL = self.get_ifname()
        ifV = self.get_ifname()
        ifdb = self.ip.interfaces

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(kind='vxlan',
                       ifname=ifV,
                       vxlan_link=ifdb[ifL],
                       vxlan_id=101,
                       vxlan_group='239.1.1.1').commit()

        ip2 = IPDB()
        ifdb = ip2.interfaces

        try:
            assert ifdb[ifV].vxlan_link == ifdb[ifL].index
            assert ifdb[ifV].vxlan_group == '239.1.1.1'
            assert ifdb[ifV].vxlan_id == 101
        except Exception:
            raise
        finally:
            ip2.release()

    def test_create_vlan_by_interface(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL],
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_create_vlan_by_index(self):
        require_user('root')
        require_8021q()
        ifL = self.get_ifname()
        ifV = self.get_ifname()

        self.ip.create(kind='dummy',
                       ifname=ifL).commit()
        self.ip.create(kind='vlan',
                       ifname=ifV,
                       link=self.ip.interfaces[ifL].index,
                       vlan_id=101).commit()

        assert self.ip.interfaces[ifV].link == \
            self.ip.interfaces[ifL].index

    def test_remove_secondaries(self):
        require_user('root')

        ifA = self.get_ifname()

        with self.ip.create(kind='dummy', ifname=ifA) as i:
            i.add_ip('172.16.0.1', 24)
            i.add_ip('172.16.0.2', 24)

        assert ifA in self.ip.interfaces
        assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' in get_ip_addr(interface=ifA)

        if i._mode == 'explicit':
            i.begin()

        i.del_ip('172.16.0.1', 24)
        i.del_ip('172.16.0.2', 24)
        i.commit()

        assert ('172.16.0.1', 24) not in self.ip.interfaces[ifA].ipaddr
        assert ('172.16.0.2', 24) not in self.ip.interfaces[ifA].ipaddr
        assert '172.16.0.1/24' not in get_ip_addr(interface=ifA)
        assert '172.16.0.2/24' not in get_ip_addr(interface=ifA)