Пример #1
0
def mount(source, target, fs, flags=0):
    if ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True
                   ).mount(source, target, fs, flags) < 0:
        log.error("Failed to mount {} ({}) to {} with flags {}: {}".
                  format(source, fs, target, flags,
                         os.strerror(ctypes.get_errno())))
        exit(1)
Пример #2
0
 def inject_to_vif(self, vif):
     mac = get_vif_mac(vif)
     try:
         self.inject_packet(vif, mac)
         log.info('Inject IGMP query to vif:%s, mac:%s' % (vif, mac))
     except:
         log.error('Inject IGMP query to vif:%s, mac:%s failed' % (vif, mac))
Пример #3
0
def setup_cgroup(domid, pid):
    cg_dir = get_cg_dir(domid)

    try:
        os.mkdir(cg_dir, 0o755)
    except OSError as e:
        if e.errno != errno.EEXIST:
            log.error("Failed to create cgroup: {}".format(cg_dir))
            exit(1)

    try:
        # unbuffered write to ensure each one is flushed immediately
        with open(cg_dir + "/tasks", "w", 0) as tasks, \
                open(cg_dir + "/devices.deny", "w", 0) as deny, \
                open(cg_dir + "/devices.allow", "w", 0) as allow:

            # deny all
            deny.write("a")

            # grant rw access to /dev/null by default
            allow.write(get_ctl("/dev/null", "rw"))

            tasks.write(str(pid))

    except (IOError, OSError, RuntimeError) as e:
        log.error("Failed to setup cgroup: {}".format(str(e)))
        exit(1)
Пример #4
0
def mount(source, target, fs, flags=0):
    if ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True
                   ).mount(source, target, fs, flags) < 0:
        log.error("Failed to mount {} ({}) to {} with flags {}: {}".
                  format(source, fs, target, flags,
                         os.strerror(ctypes.get_errno())))
        exit(1)
Пример #5
0
def setup_cgroup(domid, pid):
    cg_dir = get_cg_dir(domid)

    try:
        os.mkdir(cg_dir, 0755)
    except OSError as e:
        if e.errno != errno.EEXIST:
            log.error("Failed to create cgroup: {}".format(cg_dir))
            exit(1)

    try:
        # unbuffered write to ensure each one is flushed immediately
        with open(cg_dir + "/tasks", "w", 0) as tasks, \
                open(cg_dir + "/devices.deny", "w", 0) as deny, \
                open(cg_dir + "/devices.allow", "w", 0) as allow:

            # deny all
            deny.write("a")

            # grant rw access to /dev/null by default
            allow.write(get_ctl("/dev/null", "rw"))

            tasks.write(str(pid))

    except (IOError, OSError, RuntimeError) as e:
        log.error("Failed to setup cgroup: {}".format(str(e)))
        exit(1)
Пример #6
0
def remap_netdevs(remap_list):

    # # rename everything sideways to safe faffing with temp renanes
    # for x in ( x for x in os.listdir("/sys/class/net/") if x[:3] == "eth" ):
    #     util.runCmd2(['ip', 'link', 'set', x, 'name', 'side-'+x])

    for cmd in remap_list:
        parse_arg(cmd)

        # Grab the current state from biosdevname
    current_eths = all_devices_all_names()
    current_state = []

    for nic in current_eths.keys():
        eth = current_eths[nic]

        if not ("BIOS device" in eth and "Kernel name" in eth
                and "Assigned MAC" in eth and "Bus Info" in eth and "all_ethN"
                in eth["BIOS device"] and "physical" in eth["BIOS device"]):
            LOG.error("Interface information for '%s' from biosdevname is "
                      "incomplete; Discarding." %
                      (eth.get("Kernel name", "Unknown"), ))

        try:
            current_state.append(
                MACPCI(eth["Assigned MAC"],
                       eth["Bus Info"],
                       kname=eth["Kernel name"],
                       order=int(eth["BIOS device"]["all_ethN"][3:]),
                       ppn=eth["BIOS device"]["physical"],
                       label=eth.get("SMBIOS Label", "")))
        except Exception, e:
            LOG.error("Can't generate current state for interface '%s' - "
                      "%s" % (eth, e))
Пример #7
0
 def inject_to_vif(self, vif):
     mac = get_vif_mac(vif)
     try:
         self.inject_packet(vif, mac)
         log.info('Inject IGMP query to vif:%s, mac:%s' % (vif, mac))
     except:
         log.error('Inject IGMP query to vif:%s, mac:%s failed' %
                   (vif, mac))
Пример #8
0
def _device_ctl(path, domid, allow):
    cg_dir = get_cg_dir(domid)
    file_name = "/devices.allow" if allow else "/devices.deny"
    try:
        with open(cg_dir + file_name, "w") as f:
            f.write(get_ctl(path, "rw"))
    except (IOError, OSError, RuntimeError) as e:
        log.error("Failed to {} {}: {}".format("allow" if allow else "deny",
                                               path, str(e)))
        exit(1)
Пример #9
0
def _device_ctl(path, domid, allow):
    cg_dir = get_cg_dir(domid)
    file_name = "/devices.allow" if allow else "/devices.deny"
    try:
        with open(cg_dir + file_name, "w") as f:
            f.write(get_ctl(path, "rw"))
    except (IOError, OSError, RuntimeError) as e:
        log.error("Failed to {} {}: {}".format(
            "allow" if allow else "deny", path, str(e)))
        exit(1)
Пример #10
0
 def copy_ownership(src_root, src_path, dst_root, dst_path):
     st = os.lstat('%s/%s' % (src_root, src_path))
     try:
         new_uid = dst_uid_map[src_uid_map[st.st_uid]]
         new_gid = dst_gid_map[src_gid_map[st.st_gid]]
     except IndexError as e:
         logger.error('Failed to copy ownership')
         logger.logException(e)
         return
     if st.st_uid != new_uid or st.st_gid != new_gid:
         os.lchown('%s/%s' % (dst_root, dst_path), new_uid, new_gid)
Пример #11
0
def detach(device, domid):
    path = dev_path(device)
    uid, gid = load_device_ids(device)

    # restore uid, gid of the device file.
    try:
        os.chown(path, uid, gid)
    except OSError as e:
        log.error("Failed to chown device file {}: {}".format(path, str(e)))
        exit(1)

    # remove device from cgroup allow list
    deny_device(path, domid)
Пример #12
0
def detach(device, domid):
    path = dev_path(device)
    uid, gid = load_device_ids(device)

    # restore uid, gid of the device file.
    try:
        os.chown(path, uid, gid)
    except OSError as e:
        log.error("Failed to chown device file {}: {}".format(path, str(e)))
        exit(1)

    # remove device from cgroup allow list
    deny_device(path, domid)
Пример #13
0
def dev_path(device):
    # check device node pattern
    # example: "4-1", "1-2.1.2"
    pat = re.compile(r"\d+-\d+(\.\d+)*$")
    if pat.match(device) is None:
        log.error("Unexpected device node: {}".format(device))
        exit(1)
    try:
        bus = read_int("/sys/bus/usb/devices/{}/busnum".format(device))
        dev = read_int("/sys/bus/usb/devices/{}/devnum".format(device))
        return "/dev/bus/usb/{0:03d}/{1:03d}".format(bus, dev)
    except (IOError, ValueError) as e:
        log.error("Failed to get device path {}: {}".format(device, str(e)))
        exit(1)
Пример #14
0
def dev_path(device):
    # check device node pattern
    # example: "4-1", "1-2.1.2"
    pat = re.compile(r"\d+-\d+(\.\d+)*$")
    if pat.match(device) is None:
        log.error("Unexpected device node: {}".format(device))
        exit(1)
    try:
        bus = read_int("/sys/bus/usb/devices/{}/busnum".format(device))
        dev = read_int("/sys/bus/usb/devices/{}/devnum".format(device))
        return "/dev/bus/usb/{0:03d}/{1:03d}".format(bus, dev)
    except (IOError, ValueError) as e:
        log.error("Failed to get device path {}: {}".format(device, str(e)))
        exit(1)
Пример #15
0
def load_device_ids(device):
    ids_path = get_ids_path(device)
    try:
        with open(ids_path) as f:
            uid, gid = map(int, f.readline().split())
    except (IOError, ValueError) as e:
        log.error("Failed to load device ids: {}".format(str(e)))

    try:
        os.remove(ids_path)
    except OSError as e:
        # ignore and continue
        log.warning("Failed to remove device ids: {}".format(str(e)))

    return uid, gid
Пример #16
0
def load_device_ids(device):
    ids_path = get_ids_path(device)
    try:
        with open(ids_path) as f:
            uid, gid = map(int, f.readline().split())
    except (IOError, ValueError) as e:
        log.error("Failed to load device ids: {}".format(str(e)))

    try:
        os.remove(ids_path)
    except OSError as e:
        # ignore and continue
        log.warning("Failed to remove device ids: {}".format(str(e)))

    return uid, gid
Пример #17
0
def save_device_ids(device):
    path = dev_path(device)

    try:
        stat = os.stat(path)
        ids_info = "{} {}".format(stat.st_uid, stat.st_gid)
    except OSError as e:
        log.error("Failed to stat {}: {}".format(path, str(e)))
        exit(1)

    try:
        with open(get_ids_path(device), "w") as f:
            f.write(ids_info)
    except IOError as e:
        log.error("Failed to save device ids {}: {}".format(path, str(e)))
        exit(1)
Пример #18
0
def save_device_ids(device):
    path = dev_path(device)

    try:
        stat = os.stat(path)
        ids_info = "{} {}".format(stat.st_uid, stat.st_gid)
    except OSError as e:
        log.error("Failed to stat {}: {}".format(path, str(e)))
        exit(1)

    try:
        with open(get_ids_path(device), "w") as f:
            f.write(ids_info)
    except IOError as e:
        log.error("Failed to save device ids {}: {}".format(path, str(e)))
        exit(1)
Пример #19
0
def cleanup(domid):
    # remove the cgroup if one has been created.
    if os.path.isdir(get_cg_dir(domid)):
        try:
            os.rmdir(get_cg_dir(domid))
        except OSError as e:
            # log and continue
            log.error("Failed to remove cgroup qemu-{}: {}"
                      .format(domid, str(e)))

    # umount /dev, /sys from chroot directory if they are mounted.
    root_dir = get_root_dir(domid)
    dev_dir = root_dir + "/dev"
    sys_dir = root_dir + "/sys"
    if os.path.isdir(dev_dir + "/bus"):
        umount(dev_dir)
    if os.path.isdir(sys_dir + "/devices"):
        umount(sys_dir)
Пример #20
0
def cleanup(domid):
    # remove the cgroup if one has been created.
    if os.path.isdir(get_cg_dir(domid)):
        try:
            os.rmdir(get_cg_dir(domid))
        except OSError as e:
            # log and continue
            log.error("Failed to remove cgroup qemu-{}: {}".format(
                domid, str(e)))

    # umount /dev, /sys from chroot directory if they are mounted.
    root_dir = get_root_dir(domid)
    dev_dir = root_dir + "/dev"
    sys_dir = root_dir + "/sys"
    if os.path.isdir(dev_dir + "/bus"):
        umount(dev_dir)
    if os.path.isdir(sys_dir + "/devices"):
        umount(sys_dir)
Пример #21
0
def attach(device, domid, pid, reset_only):
    path = dev_path(device)

    # reset device
    try:
        with open(path, "w") as f:
            # USBDEVFS_RESET _IO('U', 20)
            USBDEVFS_RESET = (ord('U') << 8) | 20
            fcntl.ioctl(f.fileno(), USBDEVFS_RESET, 0)
    except IOError as e:
        # log and continue
        log.error("Failed to reset {}: {}".format(path, str(e)))

    if reset_only:
        return

    save_device_ids(device)

    # set device file uid/gid
    try:
        os.chown(path,
                 pwd.getpwnam("qemu_base").pw_uid + domid,
                 grp.getgrnam("qemu_base").gr_gid + domid)
    except OSError as e:
        log.error("Failed to chown device file {}: {}".format(path, str(e)))
        exit(1)

    root_dir = get_root_dir(domid)
    dev_dir = root_dir + "/dev"
    if not os.path.isdir(root_dir) or not os.path.isdir(dev_dir):
        log.error("Error: The chroot or dev directory doesn't exist")
        exit(1)

    if not os.path.isdir(dev_dir + "/bus"):
        # first USB device to pass-through
        MS_BIND = 4096  # mount flags, from fs.h
        mount("/dev", dev_dir, "", MS_BIND)
        setup_cgroup(domid, pid)

    sys_dir = root_dir + "/sys"
    # sys_dir could already be mounted because of PCI pass-through
    if not os.path.isdir(sys_dir):
        try:
            os.mkdir(sys_dir, 0o755)
        except OSError:
            log.error("Failed to create sys dir in chroot")
            exit(1)
    if not os.path.isdir(sys_dir + "/devices"):
        mount("/sys", sys_dir, "sysfs")

    # add device to cgroup allow list
    allow_device(path, domid)
Пример #22
0
def attach(device, domid, pid, reset_only):
    path = dev_path(device)

    # reset device
    try:
        with open(path, "w") as f:
            # USBDEVFS_RESET _IO('U', 20)
            USBDEVFS_RESET = (ord('U') << 8) | 20
            fcntl.ioctl(f.fileno(), USBDEVFS_RESET, 0)
    except IOError as e:
        # log and continue
        log.error("Failed to reset {}: {}".format(path, str(e)))

    if reset_only:
        return

    save_device_ids(device)

    # set device file uid/gid
    try:
        os.chown(path, pwd.getpwnam("qemu_base").pw_uid + domid,
                 grp.getgrnam("qemu_base").gr_gid + domid)
    except OSError as e:
        log.error("Failed to chown device file {}: {}".format(path, str(e)))
        exit(1)

    root_dir = get_root_dir(domid)
    dev_dir = root_dir + "/dev"
    if not os.path.isdir(root_dir) or not os.path.isdir(dev_dir):
        log.error("Error: The chroot or dev directory doesn't exist")
        exit(1)

    if not os.path.isdir(dev_dir + "/bus"):
        # first USB device to pass-through
        MS_BIND = 4096  # mount flags, from fs.h
        mount("/dev", dev_dir, "", MS_BIND)
        setup_cgroup(domid, pid)

    sys_dir = root_dir + "/sys"
    # sys_dir could already be mounted because of PCI pass-through
    if not os.path.isdir(sys_dir):
        try:
            os.mkdir(sys_dir, 0755)
        except OSError:
            log.error("Failed to create sys dir in chroot")
            exit(1)
    if not os.path.isdir(sys_dir + "/devices"):
        mount("/sys", sys_dir, "sysfs")

    # add device to cgroup allow list
    allow_device(path, domid)
Пример #23
0
def get_ctl(path, mode):
    """get the string to control device access for cgroup
    :param path: the device file path
    :param mode: either "r" or "rw"
    :return: the string to control device access
    """
    try:
        st = os.stat(path)
    except OSError as e:
        log.error("Failed to get stat of {}: {}".format(path, str(e)))
        raise

    t = ""
    if S_ISBLK(st.st_mode):
        t = "b"
    elif S_ISCHR(st.st_mode):
        t = "c"
    if t and mode in ("r", "rw"):
        return "{} {}:{} {}".format(t, os.major(st.st_rdev), os.minor(
            st.st_rdev), mode)
    raise RuntimeError("Failed to get control string of {}".format(path))
Пример #24
0
def get_ctl(path, mode):
    """get the string to control device access for cgroup
    :param path: the device file path
    :param mode: either "r" or "rw"
    :return: the string to control device access
    """
    try:
        st = os.stat(path)
    except OSError as e:
        log.error("Failed to get stat of {}: {}".format(path, str(e)))
        raise

    t = ""
    if S_ISBLK(st.st_mode):
        t = "b"
    elif S_ISCHR(st.st_mode):
        t = "c"
    if t and mode in ("r", "rw"):
        return "{} {}:{} {}".format(t, os.major(st.st_rdev),
                                    os.minor(st.st_rdev), mode)
    raise RuntimeError("Failed to get control string of {}".format(path))
Пример #25
0
def parseArguments(args):
    parser = argparse.ArgumentParser()
    argServ = parser.add_argument("-s", "--service", required=True)
    argMode = parser.add_argument("-m",
                                  "--mode",
                                  choices=['client', 'server'],
                                  required=True)
    argExec = parser.add_argument("-e", "--executable", required=False)
    argWait = parser.add_argument("-w",
                                  "--wait",
                                  required=False,
                                  action="store_true")
    argUniq = parser.add_argument("-u",
                                  "--uniq",
                                  required=False,
                                  action="store_true")
    argBlk = parser.add_argument("-b",
                                 "--block",
                                 required=False,
                                 action="store_true")
    args = parser.parse_args(args)

    if args.mode == 'server':
        # more check for server side, for the script parameter and whether the file exists.
        if not args.executable or args.executable == "":
            logger.error("missing parameter --executable")
            raise argparse.ArgumentError(
                argExec,
                "missing parameter --executable when mode is 'server'")
        else:
            subargs = args.executable.split(' ')
            if not os.path.isfile(subargs[0]):
                logger.error("script file not found")
                raise argparse.ArgumentError(argExec,
                                             "script to execute is not found")

    return args
Пример #26
0
        def init_id_maps(src_root, dst_root):
            """ Create mappings between (username and uid), and (group and
            gid) for the source and destination roots. """
            with open(os.path.join(src_root, 'etc/passwd'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, uid, _ = line.split(':', 3)
                        src_uid_map[int(uid)] = pwnam
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)

            with open(os.path.join(src_root, 'etc/group'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, gid, _ = line.split(':', 3)
                        src_gid_map[int(gid)] = pwnam
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)

            with open(os.path.join(dst_root, 'etc/passwd'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, uid, _ = line.split(':', 3)
                        dst_uid_map[pwnam] = int(uid)
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)

            with open(os.path.join(dst_root, 'etc/group'), 'r') as f:
                for line in f:
                    try:
                        pwnam, _, gid, _ = line.split(':', 3)
                        dst_gid_map[pwnam] = int(gid)
                    except ValueError as e:
                        logger.error('Failed to parse: ' + line)
                        logger.logException(e)
Пример #27
0
def umount(target):
    if ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True
                   ).umount(target) < 0:
        # log and continue
        log.error("Failed to umount {}: {}".
                  format(target, os.strerror(ctypes.get_errno())))
Пример #28
0
def log_exit(m):
    log.error(m)
    sys.exit(m)
Пример #29
0
def remap_netdevs(remap_list):

    # # rename everything sideways to safe faffing with temp renanes
    # for x in ( x for x in os.listdir("/sys/class/net/") if x[:3] == "eth" ):
    #     util.runCmd2(['ip', 'link', 'set', x, 'name', 'side-'+x])

    for cmd in remap_list:
        parse_arg(cmd)

        # Grab the current state from biosdevname
    current_eths = all_devices_all_names()
    current_state = []

    for nic in current_eths:
        eth = current_eths[nic]

        if not ("BIOS device" in eth and "Kernel name" in eth
                and "Assigned MAC" in eth and "Bus Info" in eth and "all_ethN"
                in eth["BIOS device"] and "physical" in eth["BIOS device"]):
            LOG.error("Interface information for '%s' from biosdevname is "
                      "incomplete; Discarding." %
                      (eth.get("Kernel name", "Unknown"), ))

        try:
            current_state.append(
                MACPCI(eth["Assigned MAC"],
                       eth["Bus Info"],
                       kname=eth["Kernel name"],
                       order=int(eth["BIOS device"]["all_ethN"][3:]),
                       ppn=eth["BIOS device"]["physical"],
                       label=eth.get("SMBIOS Label", "")))
        except Exception as e:
            LOG.error("Can't generate current state for interface '%s' - "
                      "%s" % (eth, e))
    current_state.sort()

    LOG.debug("Current state = %s" % (niceformat(current_state), ))

    static_rules.generate(current_state)
    dynamic_rules.generate(current_state)

    static_eths = [x.tname for x in static_rules.rules]
    last_boot = [x for x in dynamic_rules.rules if x.tname not in static_eths]

    LOG.debug("StaticRules Formulae = %s" %
              (niceformat(static_rules.formulae), ))
    LOG.debug("StaticRules Rules = %s" % (niceformat(static_rules.rules), ))
    LOG.debug("DynamicRules Lastboot = %s" % (niceformat(last_boot), ))

    # Invoke the renaming logic
    try:
        transactions = rename(static_rules=static_rules.rules,
                              cur_state=current_state,
                              last_state=last_boot,
                              old_state=[])
    except Exception as e:
        LOG.critical("Problem from rename logic: %s.  Giving up" % (e, ))
        return

    # Apply transactions, or explicitly state that there are none
    if len(transactions):
        for src, dst in transactions:
            ip_link_set_name(src, dst)
    else:
        LOG.info("No transactions.  No need to rename any nics")

    # Regenerate dynamic configuration
    def macpci_as_list(x):
        return [str(x.mac), str(x.pci), x.tname]

    new_lastboot = map(macpci_as_list, current_state)
    dynamic_rules.lastboot = new_lastboot

    LOG.info("All done ordering the network devices")
Пример #30
0
            os.rmdir(get_cg_dir(domid))
        except OSError as e:
            # log and continue
            log.error("Failed to remove cgroup qemu-{}: {}".format(
                domid, str(e)))

    # umount /dev, /sys from chroot directory if they are mounted.
    root_dir = get_root_dir(domid)
    dev_dir = root_dir + "/dev"
    sys_dir = root_dir + "/sys"
    if os.path.isdir(dev_dir + "/bus"):
        umount(dev_dir)
    if os.path.isdir(sys_dir + "/devices"):
        umount(sys_dir)


if __name__ == "__main__":
    log.logToSyslog(level=logging.DEBUG)

    arg = parse_arg()

    if "attach" == arg.command:
        attach(arg.device, arg.domid, arg.pid, arg.reset_only)
    elif "detach" == arg.command:
        detach(arg.device, arg.domid)
    elif "cleanup" == arg.command:
        cleanup(arg.domid)
    else:
        log.error("Unexpected command: {}".format(arg.command))
        exit(1)
Пример #31
0
            os.rmdir(get_cg_dir(domid))
        except OSError as e:
            # log and continue
            log.error("Failed to remove cgroup qemu-{}: {}"
                      .format(domid, str(e)))

    # umount /dev, /sys from chroot directory if they are mounted.
    root_dir = get_root_dir(domid)
    dev_dir = root_dir + "/dev"
    sys_dir = root_dir + "/sys"
    if os.path.isdir(dev_dir + "/bus"):
        umount(dev_dir)
    if os.path.isdir(sys_dir + "/devices"):
        umount(sys_dir)


if __name__ == "__main__":
    log.logToSyslog(level=logging.DEBUG)

    arg = parse_arg()

    if "attach" == arg.command:
        attach(arg.device, arg.domid, arg.pid, arg.reset_only)
    elif "detach" == arg.command:
        detach(arg.device, arg.domid)
    elif "cleanup" == arg.command:
        cleanup(arg.domid)
    else:
        log.error("Unexpected command: {}".format(arg.command))
        exit(1)
Пример #32
0
 def logErr(self, logtxt):
     logger.error(self.logPrefix + logtxt)
Пример #33
0
def umount(target):
    if ctypes.CDLL(ctypes.util.find_library("c"),
                   use_errno=True).umount(target) < 0:
        # log and continue
        log.error("Failed to umount {}: {}".format(
            target, os.strerror(ctypes.get_errno())))
Пример #34
0
                "missing parameter --executable when mode is 'server'")
        else:
            subargs = args.executable.split(' ')
            if not os.path.isfile(subargs[0]):
                logger.error("script file not found")
                raise argparse.ArgumentError(argExec,
                                             "script to execute is not found")

    return args


if __name__ == "__main__":
    logger.logToSyslog(level=logging.DEBUG)

    args = parseArguments(sys.argv[1:])
    service = args.service
    mode = args.mode
    executable = args.executable

    try:
        if mode == 'client':
            inst = ClientInstance(service, args.wait)
        else:  # server
            inst = ServerInstance(service, executable, args.uniq, args.block)
    except Exception as err:
        logger.error("Unable to initialize '" + service + "' service, mode:" +
                     mode + " err:" + str(err))
        rasie

    inst.work()