示例#1
0
    def on(self, target, component):
        if not commonl.prctl_cap_get_effective() & 1 << 12:
            # If we don't have network setting privilege,
            # don't even go there
            # CAP_NET_ADMIN is 12 (from /usr/include/linux/prctl.h.
            #
            # Fail here (upon use) instead of during server startup,
            # because maybe we don't really care about it and we have
            # a default configuration with the thargets that would
            # need this.
            raise RuntimeError("daemon lacks CAP_NET_ADMIN: unable to"
                               " add networking capabilities ")
        if_name, ic_name = self._component_validate(target, component)

        if not commonl.if_present(f"b{ic_name}"):
            target.log.info(f"{ic_name}: assuming network off since netif "
                            f"b{ic_name} is not present")
            return

        commonl.if_remove_maybe(if_name)  # ensure no leftovers
        subprocess.check_call(["ip", "tuntap", "add", if_name, "mode", "tap"],
                              stderr=subprocess.STDOUT)
        subprocess.check_call(
            ["ip", "link", "set", if_name, "master", "b" + ic_name],
            stderr=subprocess.STDOUT)
        # promisc on: needed so we can wireshark in
        subprocess.check_call(
            ["ip", "link", "set", if_name, "promisc", "on", "up"],
            stderr=subprocess.STDOUT)
        # We don't assign IP addresses here -- we leave it for the
        # client; if we do, for example QEMU won't work as it is just
        # used to associate the interface
        target.fsdb.set(component, if_name)
示例#2
0
    def off(self, target, component):
        # Kill tcpdump, if it was started
        pidfile = os.path.join(target.state_dir, "tcpdump.pid")
        commonl.process_terminate(pidfile,
                                  tag="tcpdump",
                                  path="/usr/sbin/tcpdump")
        # remove the top level device
        mode = self._get_mode(target)
        if mode == 'physical':
            # bring down the lower device
            ifname = commonl.if_find_by_mac(target.tags['mac_addr'])
            subprocess.check_call(
                # flush the IP addresses, bring it down
                "/usr/sbin/ip add flush dev %s; "
                "/usr/sbin/ip link set dev %s down promisc off" %
                (ifname, ifname),
                shell=True)
        elif mode == 'vlan':
            commonl.if_remove_maybe("b%(id)s" % target.kws)
            # nothing; we killed the upper and on the lwoer, a
            # physical device we do nothing, as others might be using it
            pass
        elif mode == 'virtual':
            commonl.if_remove_maybe("b%(id)s" % target.kws)
        else:
            raise AssertionError("Unknown mode %s" % mode)

        target.fsdb.set('power_state', 'off')
示例#3
0
    def on(self, target, component):
        if_name, ic_name = self._component_validate(target, component)

        kws = dict(
            id=target.id,
            ic_name=ic_name,
            if_name=if_name,
        )
        ic_data = target.tags['interconnects'][ic_name]
        try:
            kws['ipv4_addr'] = ic_data['ipv4_addr']
            kws['ipv4_prefix_len'] = ic_data['ipv4_prefix_len']
            kws['ipv6_addr'] = ic_data['ipv6_addr']
            kws['ipv6_prefix_len'] = ic_data['ipv6_prefix_len']
            kws['mac_addr'] = ic_data['mac_addr']
        except KeyError as e:
            raise ValueError(
                "%s: can't create TAP interface:"
                " target '%s' declares connection to interconnect '%s'"
                " but is missing field '%s'" %
                (component, target.id, ic_name, str(e)))

        if not commonl.if_present("_b%(ic_name)s" % kws):
            target.log.info(
                "%(ic_name)s: assuming network off since netif "
                "_b%(ic_name)s is not present", kws)
            return

        commonl.if_remove_maybe(if_name)  # ensure no leftovers
        subprocess.check_call(
            "ip link add "
            "  link _b%(ic_name)s"  # created by the interconnect
            "  name %(if_name)s"
            "  address %(mac_addr)s"
            "  up"
            "  type macvtap mode bridge" % kws,
            shell=True,
            stderr=subprocess.STDOUT)
        subprocess.check_call(
            "ip link set %(if_name)s"
            "  promisc on "  # needed so we can wireshark in
            "  up" % kws,
            shell=True,
            stderr=subprocess.STDOUT)
        # We don't assign IP addresses here -- we leave it for the
        # client; if we do, for example QEMU won't work as it is just
        # used to associate the interface
        target.fsdb.set(component, if_name)
示例#4
0
文件: tt_qemu2.py 项目: sriiora/tcf
 def _power_off_post_nw(self):
     # Tear down network stuff
     for ic_name, _ in list(self.tags.get('interconnects', {}).items()):
         commonl.if_remove_maybe("t%s%s" % (ic_name, self.id))
示例#5
0
文件: tt_qemu2.py 项目: sriiora/tcf
    def _power_on_pre_nw(self):
        # We need the __init__ part doing it earlier because remember,
        # these might be running different processes, and the basic
        # self.qemu_cmdline array has to be initialized so we can
        # find the actual binary being used.
        kws = dict(self.kws)
        # Get fresh values for these keys
        for key in list(self.fsdb.keys()):
            if key.startswith("qemu-"):
                kws[key] = self.fsdb.get(key)

        # Setup network stuff, create virtual tap interfaces
        for ic_name, ic_kws in list(self.tags.get('interconnects', {}).items()):
            if 'ipv4_addr' in ic_kws or 'ipv6_addr' in ic_kws:
                _kws = dict(kws)
                _kws.update(ic_kws)
                _kws['ic_name'] = ic_name
                # QEMU device ident only allows a-zA-Z0-9-, starting
                # with letter
                _kws['ident'] = "id" + self._r_ident.sub("", _kws['mac_addr'])
                # CAP_NET_ADMIN is 12 (from /usr/include/linux/prctl.h
                if not commonl.prctl_cap_get_effective() & 1 << 12:
                    # If we don't have network setting privilege,
                    # don't even go there
                    self.log.warning("daemon lacks CAP_NET_ADMIN: unable to "
                                     "add networking capabilities ")
                    continue

                if not commonl.if_present("_b%s" % ic_name):
                    self.log.warning("network %s powered off? networking "
                                     "disabled" % ic_name)
                    # If the network is not powered up, skip it
                    # FIXME: replace with it calling vlan_pci.something()
                    # that brings up the basic interface (_bICNAME) so
                    # that once we power the network, it works
                    continue

                commonl.if_remove_maybe("t%s%s" % (ic_name, self.id))
                subprocess.check_call(
                    "ip link add "
                    "  link _b%(ic_name)s "
                    "  name t%(ic_name)s%(id)s"
                    "  address %(mac_addr)s"
                    "  up"
                    "  type macvtap mode bridge; "
                    "ip link set t%(ic_name)s%(id)s"
                    "  promisc on "
                    "  up" % _kws, shell = True)

                # Add to the command line
                # note model=virtio WORKS with QEMU's BIOS OVMW_CODE.fd
                self.qemu_cmdline_append += \
                    " -net nic,id=%(ident)s,model=virtio,macaddr=%(mac_addr)s" \
                    " -net tap,fd=0,name=%(ident)s" % _kws

            # Add a nat/host interface?
            if ic_name == 'nat_host':
                raise RuntimeError("NAT configuration is currently broken")
                # we hardcode the MAC address of the NAT ethernet
                # interface, which we'll also add in the configuration
                # for systemd-network in /etc/systemd/network for it
                # to do DHCP. There is only one of those interfaces
                # per virtual host, so it will never conflict with
                # anything and we don't use the form of addressing in
                # any MAC we generate.
                mac_addr = "02:01:01:01:01:01"
                self.qemu_cmdline_append += \
                    " -net nic,name=nat_host,model=virtio,macaddr=%s" \
                    " -net user,id=nat_host,net=192.168.200.0/24,dhcpstart=192.168.200.10 " \
                     % mac_addr

        # If no network interfaces we added, remove the default
        # networking QEMU does
        if "-net" not in self.qemu_cmdline \
           and "-net" not in self.qemu_cmdline_append:
            self.qemu_cmdline_append += "-net none "
示例#6
0
    def on(self, target, _component):
        # Bring up the lower network interface; lower is called
        # whatever (if it is a physical device) or _bNAME; bring it
        # up, make it promiscuous
        mode = self._get_mode(target)
        if mode == 'vlan':
            # our lower is a physical device, our upper is a device
            # which till tag for eth vlan %(vlan)
            ifname = commonl.if_find_by_mac(target.tags['mac_addr'],
                                            physical=True)
            commonl.if_remove_maybe("b%(id)s" % target.kws)
            kws = dict(target.kws)
            kws['ifname'] = ifname
            subprocess.check_call(
                "/usr/sbin/ip link add"
                " link %(ifname)s name b%(id)s"
                " type vlan id %(vlan)s"
                #" protocol VLAN_PROTO"
                #" reorder_hdr on|off"
                #" gvrp on|off mvrp on|off loose_binding on|off"
                % kws,
                shell=True)
            subprocess.check_call(  # bring lower up
                "/usr/sbin/ip link set dev %s up promisc on" % ifname,
                shell=True)
        elif mode == 'physical':
            ifname = commonl.if_find_by_mac(target.tags['mac_addr'])
            subprocess.check_call(  # bring lower up
                "/usr/sbin/ip link set dev %s up promisc on" % ifname,
                shell=True)
            self._if_rename(target)
        elif mode == 'virtual':
            # We do not have a physical device, a bridge, to serve as
            # lower
            commonl.if_remove_maybe("_b%(id)s" % target.kws)
            subprocess.check_call("/usr/sbin/ip link add"
                                  "  name _b%(id)s"
                                  "  type bridge" % target.kws,
                                  shell=True)
            subprocess.check_call("/usr/sbin/ip link add"
                                  "  link _b%(id)s name b%(id)s"
                                  "  type macvlan mode bridge; " % target.kws,
                                  shell=True)
            subprocess.check_call(  # bring lower up
                "/usr/sbin/ip link set"
                "  dev _b%(id)s"
                "  up promisc on" % target.kws,
                shell=True)
        else:
            raise AssertionError("Unknown mode %s" % mode)

        # Configure the IP addresses for the top interface
        subprocess.check_call(  # clean up existing address
            "/usr/sbin/ip add flush dev b%(id)s " % target.kws,
            shell=True)
        subprocess.check_call(  # add IPv6
            # if this fails, check Network Manager hasn't disabled ipv6
            # sysctl -a | grep disable_ipv6 must show all to 0
            "/usr/sbin/ip addr add"
            "  %(ipv6_addr)s/%(ipv6_prefix_len)s dev b%(id)s " % target.kws,
            shell=True)
        subprocess.check_call(  # add IPv4
            "/usr/sbin/ip addr add"
            "  %(ipv4_addr)s/%(ipv4_prefix_len)d"
            "  dev b%(id)s" % target.kws,
            shell=True)

        # Bring up the top interface, which sets up ther outing
        subprocess.check_call(
            "/usr/sbin/ip link set dev b%(id)s up promisc on" % target.kws,
            shell=True)

        target.fsdb.set('power_state', 'on')

        # Start tcpdump on the network?
        #
        # The value of the tcpdump property, if not None, is the
        # filename we'll capture to.
        tcpdump = target.fsdb.get('tcpdump')
        if tcpdump:
            assert not os.path.sep in tcpdump \
                and tcpdump != "" \
                and tcpdump != os.path.pardir \
                and tcpdump != os.path.curdir, \
                "Bad filename for TCP dump capture '%s' specified as " \
                " value to property *tcpdump*: must not include" % tcpdump
            # per ttbd:make_ticket(), colon splits the real username
            # from the ticket
            owner = target.owner_get().split(":")[0]
            assert owner, "BUG? target not owned on power on?"
            capfile = os.path.join(target.files_path, owner, tcpdump)
            # Because it is in the user's area,
            # we assume the user knows what he is doing to overwrite it,
            # so we'll remove any first
            commonl.rm_f(capfile)
            pidfile = os.path.join(target.state_dir, "tcpdump.pid")
            logfile = os.path.join(target.state_dir, "tcpdump.log")
            cmdline = [
                "/usr/sbin/tcpdump", "-U", "-i",
                "_b%(id)s" % target.kws, "-w", capfile
            ]
            try:
                logf = open(logfile, "a")
                target.log.info("Starting tcpdump with: %s", " ".join(cmdline))
                p = subprocess.Popen(cmdline,
                                     shell=False,
                                     cwd=target.state_dir,
                                     close_fds=True,
                                     stdout=logf,
                                     stderr=subprocess.STDOUT)
            except OSError as e:
                raise RuntimeError("tcpdump failed to start: %s" % e)
            ttbl.daemon_pid_add(p.pid)  # FIXME: race condition if it died?
            with open(pidfile, "w") as pidfilef:
                pidfilef.write("%d" % p.pid)

            pid = commonl.process_started(  # Verify it started
                pidfile,
                "/usr/sbin/tcpdump",
                verification_f=os.path.exists,
                verification_f_args=(capfile, ),
                timeout=20,
                tag="tcpdump",
                log=target.log)
            if pid == None:
                raise RuntimeError("tcpdump failed to start after 5s")
示例#7
0
文件: tt_qemu2.py 项目: intel/tcf
 def _power_off_post_nw(self):
     # Tear down network stuff
     for ic_name, _ in self.tags.get('interconnects', {}).iteritems():
         commonl.if_remove_maybe("t%s%s" % (ic_name, self.id))
示例#8
0
文件: tt_qemu2.py 项目: intel/tcf
    def _power_on_pre_nw(self):
        # We need the __init__ part doing it earlier because remember,
        # these might be running different processes, and the basic
        # self.qemu_cmdline array has to be initialized so we can
        # find the actual binary being used.
        kws = dict(self.kws)
        # Get fresh values for these keys
        for key in self.fsdb.keys():
            if key.startswith("qemu-"):
                kws[key] = self.fsdb.get(key)

        # Setup network stuff, create virtual tap interfaces
        for ic_name, ic_kws in self.tags.get('interconnects', {}).iteritems():
            if 'ipv4_addr' in ic_kws or 'ipv6_addr' in ic_kws:
                _kws = dict(kws)
                _kws.update(ic_kws)
                _kws['ic_name'] = ic_name
                # QEMU device ident only allows a-zA-Z0-9-, starting
                # with letter
                _kws['ident'] = "id" + self._r_ident.sub("", _kws['mac_addr'])
                # CAP_NET_ADMIN is 12 (from /usr/include/linux/prctl.h
                if not commonl.prctl_cap_get_effective() & 1 << 12:
                    # If we don't have network setting privilege,
                    # don't even go there
                    self.log.warning("daemon lacks CAP_NET_ADMIN: unable to "
                                     "add networking capabilities ")
                    continue

                if not commonl.if_present("_b%s" % ic_name):
                    self.log.warning("network %s powered off? networking "
                                     "disabled" % ic_name)
                    # If the network is not powered up, skip it
                    # FIXME: replace with it calling vlan_pci.something()
                    # that brings up the basic interface (_bICNAME) so
                    # that once we power the network, it works
                    continue

                commonl.if_remove_maybe("t%s%s" % (ic_name, self.id))
                subprocess.check_call(
                    "ip link add "
                    "  link _b%(ic_name)s "
                    "  name t%(ic_name)s%(id)s"
                    "  address %(mac_addr)s"
                    "  up"
                    "  type macvtap mode bridge; "
                    "ip link set t%(ic_name)s%(id)s"
                    "  promisc on "
                    "  up" % _kws, shell = True)

                # Add to the command line
                # note model=virtio WORKS with QEMU's BIOS OVMW_CODE.fd
                self.qemu_cmdline_append += \
                    " -net nic,id=%(ident)s,model=virtio,macaddr=%(mac_addr)s" \
                    " -net tap,fd=0,name=%(ident)s" % _kws

            # Add a nat/host interface?
            if ic_name == 'nat_host':
                raise RuntimeError("NAT configuration is currently broken")
                # we hardcode the MAC address of the NAT ethernet
                # interface, which we'll also add in the configuration
                # for systemd-network in /etc/systemd/network for it
                # to do DHCP. There is only one of those interfaces
                # per virtual host, so it will never conflict with
                # anything and we don't use the form of addressing in
                # any MAC we generate.
                mac_addr = "02:01:01:01:01:01"
                self.qemu_cmdline_append += \
                    " -net nic,name=nat_host,model=virtio,macaddr=%s" \
                    " -net user,id=nat_host,net=192.168.200.0/24,dhcpstart=192.168.200.10 " \
                     % mac_addr

        # If no network interfaces we added, remove the default
        # networking QEMU does
        if "-net" not in self.qemu_cmdline \
           and "-net" not in self.qemu_cmdline_append:
            self.qemu_cmdline_append += "-net none "
示例#9
0
 def off(self, target, component):
     target.fsdb.set(component, None)
     if_name, _ = self._component_validate(target, component)
     commonl.if_remove_maybe(if_name)