Beispiel #1
0
def update_cmd(jail):
    """Runs update with the command given inside the specified jail."""
    lgr = ioc_logger.Logger('ioc_cli_update').getLogger()

    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.critical("  {} ({})".format(u, t))
        exit(1)
    else:
        lgr.critical("{} not found!".format(jail))
        exit(1)

    freebsd_version = checkoutput(["freebsd-version"])
    status, jid = IOCList.list_get_jid(uuid)
    conf = IOCJson(path).json_load()
    started = False

    if conf["type"] == "jail":
        if not status:
            IOCStart(uuid, tag, path, conf, silent=True)
            status, jid = IOCList.list_get_jid(uuid)
            started = True
    elif conf["type"] == "basejail":
        lgr.critical("Please run \"iocage migrate\" before trying"
                     " to update {} ({})".format(uuid, tag))
        exit(1)
    elif conf["type"] == "template":
        lgr.critical("Please convert back to a jail before trying"
                     " to update {} ({})".format(uuid, tag))
        exit(1)
    else:
        lgr.critical("{} is not a supported jail type.".format(conf["type"]))
        exit(1)

    if "HBSD" in freebsd_version:
        Popen(["hbsd-update", "-j", jid]).communicate()

        if started:
            IOCStop(uuid, tag, path, conf, silent=True)
    else:
        IOCFetch(conf["cloned_release"]).fetch_update(True, uuid, tag)

        if started:
            IOCStop(uuid, tag, path, conf, silent=True)
Beispiel #2
0
def test_stop():
    jails, paths = IOCList("uuid").list_datasets()

    uuid = jails["test"]
    uuid_short = jails["test_short"]

    path = paths["test"]
    path_short = paths["test_short"]

    conf = IOCJson(path).json_load()
    conf_short = IOCJson(path_short).json_load()

    IOCStop(uuid, "test", path, conf)
    IOCStop(uuid_short, "test_short", path_short, conf_short)

    assert True == True
Beispiel #3
0
    def destroy(self, jail):
        """Takes a jail and destroys it."""
        from iocage.lib.ioc_destroy import IOCDestroy

        tag, uuid, path = self.check_jail_existence(jail)
        conf = IOCJson(path).json_load()
        status, _ = IOCList().list_get_jid(uuid)

        if status:
            from iocage.lib.ioc_stop import IOCStop
            IOCStop(uuid, tag, path, conf, silent=True)

        IOCDestroy(uuid, tag, path).destroy_jail()

        return True
Beispiel #4
0
    def destroy_jail(self, path, clean=False):
        """
        A convenience wrapper to call __stop_jails__ and  __destroy_datasets__
        """
        dataset_type, uuid = path.rsplit("/")[-2:]

        if clean:
            self.__stop_jails__(path)
        else:
            from iocage.lib.ioc_stop import IOCStop
            conf = IOCJson(path).json_load()

            IOCStop(uuid, "", path, conf, silent=True)

        self.__destroy_datasets__(f"{self.pool}/iocage/{dataset_type}/{uuid}")
Beispiel #5
0
    def stop(self, jail):
        """Takes a jail and stops it."""
        from iocage.lib.ioc_stop import IOCStop

        tag, uuid, path = self.check_jail_existence(jail)
        conf = IOCJson(path).json_load()
        status, _ = IOCList().list_get_jid(uuid)

        if status:
            if conf["type"] in ("jail", "plugin"):
                IOCStop(uuid, tag, path, conf)

                return True
            else:
                raise RuntimeError(f"{jail} must be type jail or plugin to"
                                   " be stopped")
        else:
            raise RuntimeError(f"{jail} already stopped")
Beispiel #6
0
def stop_cmd(rc, jails):
    """
    Looks for the jail supplied and passes the uuid, path and configuration
    location to stop_jail.
    """
    lgr = logging.getLogger('ioc_cli_stop')

    _jails, paths = IOCList("uuid").list_datasets()
    jail_order = {}
    boot_order = {}

    for j in _jails:
        path = paths[j]
        conf = IOCJson(path).json_load()
        boot = conf["boot"]
        priority = conf["priority"]

        jail_order[j] = int(priority)

        # This removes having to grab all the JSON again later.
        if boot == "on":
            boot_order[j] = int(priority)

    jail_order = OrderedDict(
        sorted(jail_order.items(), key=itemgetter(1), reverse=True))
    boot_order = OrderedDict(
        sorted(boot_order.items(), key=itemgetter(1), reverse=True))
    if rc:
        for j in boot_order.keys():
            uuid = _jails[j]
            path = paths[j]
            conf = IOCJson(path).json_load()
            status, _ = IOCList().list_get_jid(uuid)

            if status:
                lgr.info("  Stopping {} ({})".format(uuid, j))
                IOCStop(uuid, j, path, conf, silent=True)
            else:
                lgr.info("{} ({}) is not running!".format(uuid, j))
        exit()

    if len(jails) >= 1 and jails[0] == "ALL":
        if len(_jails) < 1:
            raise RuntimeError("No jails exist to stop!")

        for j in jail_order:
            uuid = _jails[j]
            path = paths[j]

            conf = IOCJson(path).json_load()
            IOCStop(uuid, j, path, conf)
    else:
        if len(jails) < 1:
            raise RuntimeError("Please specify either one or more jails or "
                               "ALL!")

        for jail in jails:
            _jail = {
                tag: uuid
                for (tag, uuid) in _jails.items()
                if uuid.startswith(jail) or tag == jail
            }

            if len(_jail) == 1:
                tag, uuid = next(iter(_jail.items()))
                path = paths[tag]
            elif len(_jail) > 1:
                lgr.error("Multiple jails found for" " {}:".format(jail))
                for t, u in sorted(_jail.items()):
                    lgr.error("  {} ({})".format(u, t))
                raise RuntimeError()
            else:
                raise RuntimeError("{} not found!".format(jail))

            conf = IOCJson(path).json_load()
            IOCStop(uuid, tag, path, conf)
Beispiel #7
0
    def create_install_packages(self, jail_uuid, location, _tag, config):
        """
        Takes a list of pkg's to install into the target jail. The resolver
        property is required for pkg to have network access.
        """
        status, jid = IOCList().list_get_jid(jail_uuid)
        err = False
        if not status:
            IOCStart(jail_uuid, _tag, location, config, silent=True)
            resolver = config["resolver"]

            if resolver != "/etc/resolv.conf" and resolver != "none":
                with open("{}/etc/resolv.conf".format(location),
                          "w") as resolv_conf:
                    for line in resolver.split(";"):
                        resolv_conf.write(line + "\n")
            else:
                copy(resolver, "{}/root/etc/resolv.conf".format(location))

            status, jid = IOCList().list_get_jid(jail_uuid)

        if not self.plugin:
            with open(self.pkglist, "r") as j:
                self.pkglist = json.load(j)["pkgs"]

        self.lgr.info("\nInstalling pkg... ")
        # To avoid a user being prompted about pkg.
        Popen(["pkg-static", "-j", jid, "install", "-q", "-y", "pkg"],
              stderr=PIPE).communicate()

        # We will have mismatched ABI errors from earlier, this is to be safe.
        os.environ["ASSUME_ALWAYS_YES"] = "yes"
        cmd = ("pkg-static", "upgrade", "-f", "-q", "-y")
        pkg_upgrade = IOCExec(cmd,
                              jail_uuid,
                              _tag,
                              location,
                              plugin=self.plugin).exec_jail()

        if pkg_upgrade:
            self.lgr.error("ERROR: {}".format(pkg_upgrade.decode("utf-8")))
            err = True

        self.lgr.info("Installing supplied packages:")
        for pkg in self.pkglist:
            self.lgr.info("  - {}... ".format(pkg))
            cmd = ("pkg", "install", "-q", "-y", pkg)
            pkg_install = IOCExec(cmd,
                                  jail_uuid,
                                  _tag,
                                  location,
                                  plugin=self.plugin).exec_jail()

            if pkg_install:
                self.lgr.error("ERROR: {}".format(pkg_install))
                err = True

        os.remove("{}/root/etc/resolv.conf".format(location))

        if status:
            IOCStop(jail_uuid, _tag, location, config, silent=True)

        if self.plugin and err:
            return err
Beispiel #8
0
    def json_load(self):
        """Load the JSON at the location given. Returns a JSON object."""
        version = self.json_get_version()
        skip = False

        try:
            with open(self.location + "/config.json", "r") as conf:
                conf = json.load(conf)
        except FileNotFoundError:
            if path.isfile(self.location + "/config"):
                self.json_convert_from_ucl()

                with open(self.location + "/config.json", "r") as conf:
                    conf = json.load(conf)
            else:
                try:
                    dataset = self.location.split("/")

                    for d in dataset:
                        if len(d) == 36:
                            uuid = d
                        elif len(d) == 8:
                            # Hack88 migration to a perm short UUID.
                            pool, iocroot = _get_pool_and_iocroot()
                            from iocage.lib.ioc_list import IOCList

                            full_uuid = checkoutput([
                                "zfs", "get", "-H", "-o", "value",
                                "org.freebsd.iocage:host_hostuuid",
                                self.location
                            ]).rstrip()
                            jail_hostname = checkoutput([
                                "zfs", "get", "-H", "-o", "value",
                                "org.freebsd.iocage:host_hostname",
                                self.location
                            ]).rstrip()
                            short_uuid = full_uuid[:8]
                            full_dataset = "{}/iocage/jails/{}".format(
                                pool, full_uuid)
                            short_dataset = "{}/iocage/jails/{}".format(
                                pool, short_uuid)

                            self.json_convert_from_zfs(full_uuid)
                            with open(self.location + "/config.json",
                                      "r") as conf:
                                conf = json.load(conf)

                            self.lgr.info("hack88 is no longer supported."
                                          "\n{} is being converted to {} "
                                          "permanently.".format(
                                              full_dataset, short_dataset))

                            status, _ = IOCList().list_get_jid(full_uuid)
                            if status:
                                self.lgr.info(
                                    "Stopping jail to migrate UUIDs.")
                                from iocage.lib.ioc_stop import IOCStop
                                IOCStop(full_uuid,
                                        conf["tag"],
                                        self.location,
                                        conf,
                                        silent=True)

                            jail_zfs_prop = \
                                "org.freebsd.iocage:jail_zfs_dataset"
                            uuid_prop = "org.freebsd.iocage:host_hostuuid"
                            host_prop = "org.freebsd.iocage:host_hostname"

                            # Set jailed=off and move the jailed dataset.
                            checkoutput([
                                "zfs", "set", "jailed=off",
                                "{}/data".format(full_dataset)
                            ])

                            # We don't want to change a real hostname.
                            if jail_hostname == full_uuid:
                                checkoutput([
                                    "zfs", "set",
                                    "{}={}".format(host_prop,
                                                   short_uuid), full_dataset
                                ])

                            checkoutput([
                                "zfs", "set",
                                "{}={}".format(uuid_prop,
                                               short_uuid), full_dataset
                            ])
                            checkoutput([
                                "zfs", "set", "{}=iocage/jails/{}/data".format(
                                    jail_zfs_prop, short_uuid),
                                "{}/data".format(full_dataset)
                            ])
                            checkoutput([
                                "zfs", "rename", "-f", full_dataset,
                                short_dataset
                            ])
                            checkoutput([
                                "zfs", "set", "jailed=on",
                                "{}/data".format(short_dataset)
                            ])

                            uuid = short_uuid
                            self.location = "{}/jails/{}".format(
                                iocroot, short_uuid)
                            skip = True

                    self.json_convert_from_zfs(uuid, skip=skip)

                    with open(self.location + "/config.json", "r") as conf:
                        conf = json.load(conf)
                except CalledProcessError:
                    # At this point it should be a real misconfigured jail
                    raise RuntimeError("Configuration is missing!"
                                       f" Please destroy {uuid} and recreate"
                                       " it.")

        try:
            conf_version = conf["CONFIG_VERSION"]

            if version != conf_version:
                conf = self.json_check_config(conf, version)
        except KeyError:
            conf = self.json_check_config(conf, version)

        return conf
Beispiel #9
0
    def create_install_packages(self, jail_uuid, location, _tag, config):
        """
        Takes a list of pkg's to install into the target jail. The resolver
        property is required for pkg to have network access.
        """
        status, jid = IOCList().list_get_jid(jail_uuid)
        err = False
        if not status:
            IOCStart(jail_uuid, _tag, location, config, silent=True)
            resolver = config["resolver"]

            if resolver != "/etc/resolv.conf" and resolver != "none":
                with open("{}/etc/resolv.conf".format(location),
                          "w") as resolv_conf:
                    for line in resolver.split(";"):
                        resolv_conf.write(line + "\n")
            else:
                copy(resolver, "{}/root/etc/resolv.conf".format(location))

            status, jid = IOCList().list_get_jid(jail_uuid)

        # Connectivity test courtesy David Cottlehuber off Google Group
        srv_connect_cmd = ["drill", "_http._tcp.pkg.freebsd.org", "SRV"]
        dnssec_connect_cmd = ["drill", "-D", "pkg.freebsd.org"]

        self.lgr.info("Testing SRV response to FreeBSD")
        srv_connection = IOCExec(srv_connect_cmd,
                                 jail_uuid,
                                 _tag,
                                 location,
                                 plugin=self.plugin).exec_jail()

        if srv_connection:
            raise RuntimeError(f"{srv_connection}\n"
                               f"Command run: {' '.join(srv_connect_cmd)}")

        self.lgr.info("Testing DNSSEC response to FreeBSD")
        dnssec_connection = IOCExec(dnssec_connect_cmd,
                                    jail_uuid,
                                    _tag,
                                    location,
                                    plugin=self.plugin).exec_jail()

        if dnssec_connection:
            raise RuntimeError(f"{dnssec_connection}\n"
                               f"Command run: {' '.join(dnssec_connect_cmd)}")

        if not self.plugin:
            with open(self.pkglist, "r") as j:
                self.pkglist = json.load(j)["pkgs"]

        self.lgr.info("\nInstalling pkg... ")
        # To avoid a user being prompted about pkg.
        Popen(["pkg-static", "-j", jid, "install", "-q", "-y", "pkg"],
              stderr=PIPE).communicate()

        # We will have mismatched ABI errors from earlier, this is to be safe.
        os.environ["ASSUME_ALWAYS_YES"] = "yes"
        cmd = ("pkg-static", "upgrade", "-f", "-q", "-y")
        pkg_upgrade = IOCExec(cmd,
                              jail_uuid,
                              _tag,
                              location,
                              plugin=self.plugin).exec_jail()

        if pkg_upgrade:
            self.lgr.error(f"{pkg_upgrade}")
            err = True

        self.lgr.info("Installing supplied packages:")
        for pkg in self.pkglist:
            self.lgr.info("  - {}... ".format(pkg))
            cmd = ("pkg", "install", "-q", "-y", pkg)
            pkg_install = IOCExec(cmd,
                                  jail_uuid,
                                  _tag,
                                  location,
                                  plugin=self.plugin).exec_jail()

            if pkg_install:
                self.lgr.error("{}".format(pkg_install))
                err = True

        os.remove("{}/root/etc/resolv.conf".format(location))

        if status:
            IOCStop(jail_uuid, _tag, location, config, silent=True)

        if self.plugin and err:
            return err
Beispiel #10
0
def __hard_restart__(uuid, jail, path, conf):
    """Stops and then starts the jail."""
    IOCStop(uuid, jail, path, conf)
    IOCStart(uuid, jail, path, conf)
Beispiel #11
0
def upgrade_cmd(jail, release):
    """Runs upgrade with the command given inside the specified jail."""
    lgr = logging.getLogger('ioc_cli_upgrade')

    jails, paths = IOCList("uuid").list_datasets()
    _jail = {
        tag: uuid
        for (tag, uuid) in jails.items()
        if uuid.startswith(jail) or tag == jail
    }

    if len(_jail) == 1:
        tag, uuid = next(iter(_jail.items()))
        path = paths[tag]
        root_path = "{}/root".format(path)
    elif len(_jail) > 1:
        lgr.error("Multiple jails found for" " {}:".format(jail))
        for t, u in sorted(_jail.items()):
            lgr.error("  {} ({})".format(u, t))
        raise RuntimeError()
    else:
        raise RuntimeError("{} not found!".format(jail))

    pool = IOCJson().json_get_value("pool")
    iocroot = IOCJson(pool).json_get_value("iocroot")
    freebsd_version = checkoutput(["freebsd-version"])
    status, jid = IOCList.list_get_jid(uuid)
    conf = IOCJson(path).json_load()
    host_release = os.uname()[2]
    jail_release = conf["release"]
    started = False

    if conf["release"] == "EMPTY":
        raise RuntimeError("Upgrading is not supported for empty jails.")

    if conf["type"] == "jail":
        if not status:
            IOCStart(uuid, tag, path, conf, silent=True)
            status, jid = IOCList.list_get_jid(uuid)
            started = True
    elif conf["type"] == "basejail":
        raise RuntimeError("Please run \"iocage migrate\" before trying"
                           " to upgrade {} ({})".format(uuid, tag))
    elif conf["type"] == "template":
        raise RuntimeError("Please convert back to a jail before trying"
                           " to upgrade {} ({})".format(uuid, tag))
    else:
        raise RuntimeError("{} is not a supported jail type.".format(
            conf["type"]))

    _freebsd_version = "{}/releases/{}/root/bin/freebsd-version".format(
        iocroot, release)

    if "HBSD" in freebsd_version:
        Popen(["hbsd-upgrade", "-j", jid]).communicate()
    else:
        if os.path.isfile("{}/etc/freebsd-update.conf".format(root_path)):
            # 10.3-RELEASE and under lack this flag
            if float(host_release.partition("-")[0][:5]) <= 10.3:
                raise RuntimeError(
                    "Host: {} is too old, please upgrade to "
                    "10.3-RELEASE or above".format(host_release))

            os.environ["PAGER"] = "/bin/cat"
            fetch = Popen([
                "freebsd-update", "-b", root_path, "-d",
                "{}/var/db/freebsd-update/".format(root_path), "-f",
                "{}/etc/freebsd-update.conf".format(root_path),
                "--currently-running {}".format(jail_release), "-r", release,
                "upgrade"
            ],
                          stdin=PIPE)
            fetch.communicate(b"y")

            while not __upgrade_install__(root_path, release):
                pass

            if release[:4].endswith("-"):
                # 9.3-RELEASE and under don't actually have this binary.
                new_release = release
            else:
                with open(_freebsd_version, "r") as r:
                    for line in r:
                        if line.startswith("USERLAND_VERSION"):
                            new_release = line.rstrip().partition(
                                "=")[2].strip('"')

            IOCJson(path, silent=True).json_set_value(
                "release={}".format(new_release))

            if started:
                IOCStop(uuid, tag, path, conf, silent=True)

            lgr.info("\n{} ({}) successfully upgraded from {} to {}!".format(
                uuid, tag, jail_release, new_release))