コード例 #1
0
def initialize_lxd():
    if is_initialized():
        return

    try:
        with open(os.path.join(config.provision_dir, "lxd-init.yaml"), "r") as f:
            init = f.read()
    except OSError as e:
        raise LXCException(f"Error reading lxd-init.yaml {e}")

    try:
        logging.info("Updating package information...")
        vm.run_cmd("sudo apt update", show_spinner=True)
        vm.run_cmd("sudo usermod yurt -a -G lxd")

        logging.info("Initializing LXD...")
        vm.run_cmd(
            "sudo lxd init --preseed",
            stdin=init,
            show_spinner=True
        )
        _setup_yurt_socat()

        logging.info("Done.")
        config.set_config(config.Key.is_lxd_initialized, True)
    except VMException as e:
        logging.error(e)
        logging.error("Restart the VM to try again: 'yurt vm restart'")
        raise LXCException("Failed to initialize LXD.")
コード例 #2
0
def get_instance(name: str):
    client = get_pylxd_client()
    try:
        return client.instances.get(name)  # pylint: disable=no-member
    except pylxd.exceptions.NotFound:
        raise LXCException(f"Instance {name} not found.")
    except pylxd.exceptions.LXDAPIException:
        raise LXCException(
            f"Could not fetch instance {name}. API Error.")
コード例 #3
0
ファイル: util.py プロジェクト: simhaonline/yurt
def get_lxc_executable():
    if config.system == config.System.windows:
        lxc_executable = os.path.join(config.bin_dir, "lxc.exe")
        if os.path.isfile(lxc_executable):
            return lxc_executable
        else:
            raise LXCException(
                f"{lxc_executable} does not exist.")
    else:
        raise LXCException(
            f"LXC executable not found for platform: {config.system}")
コード例 #4
0
def delete(names: List[str]):
    for name in names:
        instance = util.get_instance(name)
        try:
            instance.delete(wait=True)
        except LXDAPIException as e:
            raise LXCException(f"Error deleting instance: {e}")
コード例 #5
0
def list_remote_images(remote: str):
    from functools import partial
    import json

    try:
        # We'd have to implement simplestreams ourselves as this call is handled
        # entirely by the client. Let's cheat.
        output, error = vm.run_cmd(f"lxc image list {remote}: --format json",
                                   show_spinner=True)
        if error:
            logging.error(error)

        images = util.filter_remote_images(json.loads(output))

        images_info = filter(
            None, map(partial(util.get_remote_image_info, remote), images))

        if remote == "ubuntu":
            return sorted(images_info, key=lambda i: i["Alias"], reverse=True)
        else:
            return sorted(images_info, key=lambda i: i["Alias"])

    except VMException as e:
        message = f"Could not fetch remote images: {e.message}"
        logging.error("Please confirm that you're connected to the internet.")
        raise LXCException(message)
コード例 #6
0
ファイル: lxc.py プロジェクト: simhaonline/yurt
def list_():
    import json

    def get_info(instance):
        try:
            addresses = instance["state"]["network"]["eth0"]["addresses"]
            ipv4_info = find(lambda a: a["family"] == "inet", addresses, {})
            ipv4_address = ipv4_info.get("address", "")
        except KeyError as e:
            logging.debug(f"Key Error: {e}")
            ipv4_address = ""
        except TypeError:
            ipv4_address = ""

        instance_config = instance["config"]
        architecture = instance_config.get("image.architecture", "")
        os_ = instance_config.get("image.os", "")
        release = instance_config.get("image.release", "")

        return {
            "Name": instance["name"],
            "Status": instance["state"]["status"],
            "IP Address": ipv4_address,
            "Image": f"{os_}/{release} ({architecture})"
        }

    try:
        output = run_lxc(["list", "--format", "json"], show_spinner=True)
        instances = json.loads(output)
        return list(map(get_info, instances))
    except CommandException as e:
        raise LXCException(f"Failed to list networks: {e.message}")
コード例 #7
0
def get_pylxd_client():
    lxd_port = config.get_config(config.Key.lxd_port)
    try:
        return pylxd.Client(endpoint=f"http://127.0.0.1:{lxd_port}")
    except pylxd.exceptions.ClientConnectionFailed as e:
        logging.debug(e)
        raise LXCException(
            "Error connecting to LXD. Try restarting the VM: 'yurt vm restart'")
コード例 #8
0
ファイル: lxc.py プロジェクト: simhaonline/yurt
def list_cached_images():
    try:
        output = run_lxc(["image", "list", "yurt:", "--format", "json"],
                         show_spinner=True)

        images_info = filter(None,
                             map(get_cached_image_info, json.loads(output)))
        return list(images_info)
    except CommandException as e:
        raise LXCException(f"Could not fetch images - {e.message}")
コード例 #9
0
def exec_interactive(instance_name: str, cmd: List[str], environment=None):
    from . import term

    instance = get_instance(instance_name)
    response = instance.raw_interactive_execute(cmd, environment=environment)
    lxd_port = config.get_config(config.Key.lxd_port)
    try:

        ws_url = f"ws://127.0.0.1:{lxd_port}{response['ws']}"
        term.run(ws_url)
    except KeyError as e:
        raise LXCException(f"Missing ws URL {e}")
コード例 #10
0
def launch(remote: str, image: str, name: str):
    # https://linuxcontainers.org/lxd/docs/master/instances
    # Valid instance names must:
    #   - Be between 1 and 63 characters long
    #   - Be made up exclusively of letters, numbers and dashes from the ASCII table
    #   - Not start with a digit or a dash
    #   - Not end with a dash

    client = util.get_pylxd_client()
    try:
        server_url = util.REMOTES[remote]["URL"]
    except KeyError:
        raise LXCException(f"Unsupported remote {remote}")

    try:
        logging.info(
            f"Launching container '{name}'. This might take a few minutes...")
        response = client.api.instances.post(
            json={
                "name": name,
                "profiles": [util.PROFILE_NAME],
                "source": {
                    "type": "image",
                    "alias": image,
                    "mode": "pull",
                    "server": server_url,
                    "protocol": "simplestreams"
                }
            })

        util.follow_operation(
            response.json()["operation"],
            unpack_metadata=util.unpack_download_operation_metadata)

        logging.info(f"Starting container")
        instance = util.get_instance(name)
        instance.start(wait=True)
    except LXDAPIException as e:
        logging.error(e)
        raise LXCException(f"Failed to launch instance {name}")
コード例 #11
0
ファイル: lxc.py プロジェクト: simhaonline/yurt
def list_remote_images(remote: str):
    from functools import partial

    try:
        output = run_lxc(["image", "list", f"{remote}:", "--format", "json"],
                         show_spinner=True)

        images = filter_remote_images(json.loads(output))

        images_info = filter(
            None, map(partial(get_remote_image_info, remote), images))

        if remote == "ubuntu":
            return sorted(images_info, key=lambda i: i["Alias"], reverse=True)
        else:
            return sorted(images_info, key=lambda i: i["Alias"])

    except CommandException as e:
        raise LXCException(f"Could not fetch images: {e.message}")
コード例 #12
0
ファイル: util.py プロジェクト: simhaonline/yurt
def get_cached_image_info(image: Dict):
    try:
        alias = image["update_source"]["alias"]
        server = image["update_source"]["server"]
        remote = find(lambda r: r["URL"] == server, REMOTES, None)

        if remote:
            source = f"{remote['Name']}:{alias}"
        else:
            raise LXCException("Unexpected source server: {}")

        return {
            "Alias": source,
            "Description": image["properties"]["description"]
        }

    except KeyError as e:
        logging.debug(e)
        logging.debug(f"Unexpected image schema: {image}")
コード例 #13
0
def get_ip_config():
    from ipaddress import ip_interface

    host_ip_address = config.get_config(
        config.Key.interface_ip_address)
    network_mask = config.get_config(
        config.Key.interface_netmask)
    if not (host_ip_address and network_mask):
        raise LXCException("Bad IP Configuration. ip: {0}, mask: {1}".format(
            host_ip_address, network_mask))

    full_host_address = ip_interface(
        "{0}/{1}".format(host_ip_address, network_mask))
    bridge_address = ip_interface(
        "{0}/{1}".format((full_host_address + 1).ip, network_mask)).exploded

    return {
        "bridgeAddress": bridge_address,
        "dhcpRangeLow": (full_host_address + 10).ip.exploded,
        "dhcpRangeHigh": (full_host_address + 249).ip.exploded
    }
コード例 #14
0
ファイル: util.py プロジェクト: simhaonline/yurt
def initialize_lxd():
    lxd_init = """config:
  core.https_address: '[::]:8443'
  core.trust_password: yurtsecret
networks: []
storage_pools:
- config:
    source: /dev/sdc
  description: ""
  name: yurtpool
  driver: zfs
profiles:
- config: {}
  description: ""
  devices:
    root:
      path: /
      pool: yurtpool
      type: disk
  name: default
cluster: null
    """

    try:
        logging.info("Installing LXD. This might take a few minutes...")
        run_in_vm("sudo snap install lxd", show_spinner=True)
        logging.info("LXD installed. Configuring...")

        run_in_vm("sudo lxd.migrate -yes", show_spinner=True)
        run_in_vm(
            "sudo lxd init --preseed",
            stdin=lxd_init,
            show_spinner=True
        )
        logging.info("Done.")
        config.set_config(config.Key.is_lxd_initialized, True)
    except RemoteCommandException as e:
        logging.error(e)
        logging.info("Restart the VM to try again: 'yurt shutdown; yurt boot'")
        raise LXCException("Failed to initialize LXD.")
コード例 #15
0
def follow_operation(operation_uri: str, unpack_metadata=None):
    """
    Params:
        operation_uri:      URI of the operation to follow.
        unpack_metadata:    Function to unpack the operation's metadata. Return a line of text to summarize
                            the current progress of the operation.
                            If not given, progress will not be shown.
    """
    import time
    from yurt.util import retry

    operations = get_pylxd_client().operations

    # Allow time for operation to be created.
    try:
        retry(
            lambda: operations.get(operation_uri),  # pylint: disable=no-member
            retries=10,
            wait_time=0.5
        )
        operation = operations.get(operation_uri)  # pylint: disable=no-member
    except pylxd.exceptions.NotFound:
        raise LXCException(
            f"Timed out while waiting for operation to be created.")

    logging.info(operation.description)
    while True:
        try:
            operation = operations.get(  # pylint: disable=no-member
                operation_uri
            )
            if unpack_metadata:
                print(f"\r{unpack_metadata(operation.metadata)}", end="")
            time.sleep(0.5)
        except pylxd.exceptions.NotFound:
            print("\nDone")
            break
        except KeyboardInterrupt:
            break