Example #1
0
    def create_jail(self):
        """
        Create a snapshot of the user specified RELEASE dataset and clone a
        jail from that. The user can also specify properties to override the
        defaults.
        """
        jail_uuid = str(uuid.uuid4())

        if self.short:
            jail_uuid = jail_uuid[:8]

        location = "{}/jails/{}".format(self.iocroot, jail_uuid)

        if self.migrate:
            config = self.config
        else:
            if self.template:
                _type = "templates"
            else:
                _type = "releases"

            freebsd_version = "{}/{}/{}/root/bin/freebsd-version".format(
                self.iocroot, _type, self.release)

            try:
                if self.release[:4].endswith("-"):
                    # 9.3-RELEASE and under don't actually have this binary.
                    cloned_release = self.release
                else:
                    with open(freebsd_version, "r") as r:
                        for line in r:
                            if line.startswith("USERLAND_VERSION"):
                                cloned_release = line.rstrip().partition(
                                    "=")[2].strip('"')
                config = self.create_config(jail_uuid, cloned_release)
            except (IOError, OSError):
                if self.template:
                    raise RuntimeError("Template: {} not found!".format(
                        self.release))
                else:
                    raise RuntimeError("RELEASE: {} not found!".format(
                        self.release))

        jail = "{}/iocage/jails/{}/root".format(self.pool, jail_uuid)

        if self.template:
            try:
                check_call([
                    "zfs", "snapshot", "{}/iocage/templates/{}/root@{}".format(
                        self.pool, self.release, jail_uuid)
                ],
                           stderr=PIPE)
            except CalledProcessError:
                raise RuntimeError("Template: {} not found!".format(
                    self.release))

            Popen([
                "zfs", "clone", "-p", "{}/iocage/templates/{}/root@{}".format(
                    self.pool, self.release, jail_uuid), jail
            ],
                  stdout=PIPE).communicate()

            # self.release is actually the templates name
            config["release"] = IOCJson("{}/templates/{}".format(
                self.iocroot, self.release)).json_get_value("release")
            config["cloned_release"] = IOCJson("{}/templates/{}".format(
                self.iocroot, self.release)).json_get_value("cloned_release")
        else:
            try:
                check_call([
                    "zfs", "snapshot", "{}/iocage/releases/{}/root@{}".format(
                        self.pool, self.release, jail_uuid)
                ],
                           stderr=PIPE)
            except CalledProcessError:
                raise RuntimeError("RELEASE: {} not found!".format(
                    self.release))

            Popen([
                "zfs", "clone", "-p", "{}/iocage/releases/{}/root@{}".format(
                    self.pool, self.release, jail_uuid), jail
            ],
                  stdout=PIPE).communicate()

        iocjson = IOCJson(location)

        # This test is to avoid the same warnings during install_packages.
        if not self.plugin:
            for prop in self.props:
                key, _, value = prop.partition("=")

                if self.num != 0:
                    if key == "tag":
                        value = f"{value}_{self.num}"
                try:
                    iocjson.json_check_prop(key, value, config)

                    config[key] = value
                except RuntimeError as err:
                    # Instead this will stay as default.
                    self.lgr.warning(f"***\n{err}\n***\n")
            iocjson.json_write(config)

        # Just "touch" the fstab file, since it won't exist.
        open("{}/jails/{}/fstab".format(self.iocroot, jail_uuid), "wb").close()
        _tag = self.create_link(jail_uuid, config["tag"])
        config["tag"] = _tag
        self.create_rc(location, config["host_hostname"])

        if self.basejail:
            from iocage.lib.ioc_fstab import IOCFstab
            basedirs = [
                "bin", "boot", "lib", "libexec", "rescue", "sbin", "usr/bin",
                "usr/include", "usr/lib", "usr/libexec", "usr/sbin",
                "usr/share", "usr/libdata", "usr/lib32"
            ]

            for bdir in basedirs:
                source = f"{self.iocroot}/releases/{self.release}/root/{bdir}"
                destination = f"{self.iocroot}/jails/{jail_uuid}/root/{bdir}"

                IOCFstab(jail_uuid,
                         _tag,
                         "add",
                         source,
                         destination,
                         "nullfs",
                         "ro",
                         "0",
                         "0",
                         silent=True)
                config["basejail"] = "yes"

            iocjson.json_write(config)

        if not self.plugin:
            self.lgr.info("{} ({}) successfully created!".format(
                jail_uuid, _tag))

        if self.pkglist:
            if config["ip4_addr"] == "none" and config["ip6_addr"] == "none":
                self.lgr.error(" ERROR: You need an IP address for the jail"
                               " to install packages!\n")
            else:
                self.create_install_packages(jail_uuid, location, _tag, config)

        return jail_uuid
Example #2
0
    def create_jail(self):
        """
        Create a snapshot of the user specified RELEASE dataset and clone a
        jail from that. The user can also specify properties to override the
        defaults.
        """
        start = False

        if self.uuid:
            jail_uuid = self.uuid
        else:
            jail_uuid = str(uuid.uuid4())

        if self.short:
            jail_uuid = jail_uuid[:8]

        location = "{}/jails/{}".format(self.iocroot, jail_uuid)

        if os.path.isdir(location):
            raise RuntimeError("The UUID is already in use by another jail.")

        if self.migrate:
            config = self.config
        else:
            try:
                if self.template:
                    _type = "templates"
                    temp_path = f"{self.iocroot}/{_type}/{self.release}"
                    template_config = IOCJson(f"{temp_path}").json_get_value
                    cloned_release = template_config("cloned_release")
                else:
                    _type = "releases"
                    rel_path = f"{self.iocroot}/{_type}/{self.release}"

                    freebsd_version = f"{rel_path}/root/bin/freebsd-version"

                    if not self.empty:
                        if self.release[:4].endswith("-"):
                            # 9.3-RELEASE and under don't actually have this
                            # binary.
                            cloned_release = self.release
                        else:
                            with open(freebsd_version, "r") as r:
                                for line in r:
                                    if line.startswith("USERLAND_VERSION"):
                                        # Long lines ftw?
                                        cl = line.rstrip().partition("=")[2]
                                        cloned_release = cl.strip('"')
                    else:
                        cloned_release = "EMPTY"
            except (IOError, OSError, FileNotFoundError, UnboundLocalError):
                # Unintuitevly a missing template will throw a
                # UnboundLocalError as the missing file will kick the
                # migration routine for zfs props. We don't need that :)
                if self.template:
                    raise RuntimeError("Template: {} not found!".format(
                        self.release))
                else:
                    raise RuntimeError("RELEASE: {} not found!".format(
                        self.release))

            config = self.create_config(jail_uuid, cloned_release)
        jail = "{}/iocage/jails/{}/root".format(self.pool, jail_uuid)

        if self.template:
            try:
                check_call([
                    "zfs", "snapshot", "{}/iocage/templates/{}/root@{}".format(
                        self.pool, self.release, jail_uuid)
                ],
                           stderr=PIPE)
            except CalledProcessError:
                raise RuntimeError("Template: {} not found!".format(
                    self.release))

            Popen([
                "zfs", "clone", "-p", "{}/iocage/templates/{}/root@{}".format(
                    self.pool, self.release, jail_uuid), jail
            ],
                  stdout=PIPE).communicate()

            # self.release is actually the templates name
            config["release"] = IOCJson("{}/templates/{}".format(
                self.iocroot, self.release)).json_get_value("release")
            config["cloned_release"] = IOCJson("{}/templates/{}".format(
                self.iocroot, self.release)).json_get_value("cloned_release")
        else:
            if not self.empty:
                try:
                    check_call([
                        "zfs", "snapshot",
                        "{}/iocage/releases/{}/root@{}".format(
                            self.pool, self.release, jail_uuid)
                    ],
                               stderr=PIPE)
                except CalledProcessError:
                    raise RuntimeError("RELEASE: {} not found!".format(
                        self.release))

                Popen([
                    "zfs", "clone", "-p",
                    "{}/iocage/releases/{}/root@{}".format(
                        self.pool, self.release, jail_uuid), jail
                ],
                      stdout=PIPE).communicate()
            else:
                try:
                    checkoutput(["zfs", "create", "-p", jail], stderr=PIPE)
                except CalledProcessError as err:
                    raise RuntimeError(err.output.decode("utf-8").rstrip())

        iocjson = IOCJson(location)

        # This test is to avoid the same warnings during install_packages.
        if not self.plugin:
            for prop in self.props:
                key, _, value = prop.partition("=")

                if self.num != 0:
                    if key == "tag":
                        value = f"{value}_{self.num}"
                elif key == "boot" and value == "on":
                    start = True

                try:
                    iocjson.json_check_prop(key, value, config)

                    config[key] = value
                except RuntimeError as err:
                    from iocage.lib.ioc_destroy import IOCDestroy
                    iocjson.json_write(config)  # Destroy counts on this.
                    IOCDestroy().destroy_jail(location)
                    raise RuntimeError(f"***\n{err}\n***\n")

            iocjson.json_write(config)

        # Just "touch" the fstab file, since it won't exist.
        open("{}/jails/{}/fstab".format(self.iocroot, jail_uuid), "wb").close()
        _tag = self.create_link(jail_uuid, config["tag"])
        config["tag"] = _tag

        if not self.empty:
            self.create_rc(location, config["host_hostname"])

        if self.basejail:
            from iocage.lib.ioc_fstab import IOCFstab
            basedirs = [
                "bin", "boot", "lib", "libexec", "rescue", "sbin", "usr/bin",
                "usr/include", "usr/lib", "usr/libexec", "usr/sbin",
                "usr/share", "usr/libdata", "usr/lib32"
            ]

            for bdir in basedirs:
                if "-RELEASE" not in self.release:
                    _type = "templates"
                else:
                    _type = "releases"

                source = f"{self.iocroot}/{_type}/{self.release}/root/{bdir}"
                destination = f"{self.iocroot}/jails/{jail_uuid}/root/{bdir}"

                IOCFstab(jail_uuid,
                         _tag,
                         "add",
                         source,
                         destination,
                         "nullfs",
                         "ro",
                         "0",
                         "0",
                         silent=True)
                config["basejail"] = "yes"

            iocjson.json_write(config)

        if self.empty:
            config["release"] = "EMPTY"
            config["cloned_release"] = "EMPTY"

            iocjson.json_write(config)

        if not self.plugin:
            self.lgr.info("{} ({}) successfully created!".format(
                jail_uuid, _tag))

        if self.pkglist:
            if config["ip4_addr"] == "none" and config["ip6_addr"] == "none":
                self.lgr.warning(" You need an IP address for the"
                                 " jail to install packages!\n")
            else:
                self.create_install_packages(jail_uuid, location, _tag, config)

        if start:
            from iocage.lib.ioc_start import IOCStart

            IOCStart(jail_uuid, _tag, location, config)

        return jail_uuid