Ejemplo n.º 1
0
 def state(depl, d, m):
     if not d and (depl.definitions != None or m.obsolete):
         return "Obsolete"
     if d and m and m.obsolete: return "Revived"
     if not m: return "New"
     if deployment.is_machine(
             m) and depl.configs_path != m.cur_configs_path:
         return "Outdated"
     if deployment.is_machine(m): return "Up-to-date"
Ejemplo n.º 2
0
def op_import(args):
    sf = nixops.statefile.StateFile(args.state_file)
    existing = set(sf.query_deployments())

    dump = json.loads(sys.stdin.read())

    for uuid, attrs in dump.iteritems():
        if uuid in existing:
            raise Exception(
                "state file already contains a deployment with UUID ‘{0}’".
                format(uuid))
        with sf._db:
            depl = sf.create_deployment(uuid=uuid)
            depl.import_(attrs)
        sys.stderr.write("added deployment ‘{0}’\n".format(uuid))

        if args.include_keys:
            for m in depl.active.itervalues():
                if deployment.is_machine(m) and hasattr(m, "public_host_key"):
                    if m.public_ipv4:
                        nixops.known_hosts.add(m.public_ipv4,
                                               m.public_host_key)
                    if m.private_ipv4:
                        nixops.known_hosts.add(m.private_ipv4,
                                               m.public_host_key)
Ejemplo n.º 3
0
    def print_deployment(depl):
        definitions = depl.definitions or {}

        # Sort machines by type, then name.  Sort numbers in machine
        # names numerically (e.g. "foo10" comes after "foo9").
        def name_to_key(name):
            d = definitions.get(name)
            r = depl.resources.get(name)
            return (machine_to_key(depl.uuid, name, r.get_type())
                    if r else machine_to_key(depl.uuid, name, d.get_type))

        names = sorted(set(definitions.keys()) | set(depl.resources.keys()),
                       key=name_to_key)

        for name in names:
            d = definitions.get(name)
            r = depl.resources.get(name)
            if deployment.is_machine(r):
                resource_state = "{0} / {1}".format(
                    r.show_state() if r else "Missing", state(depl, d, r))
            else:
                resource_state = r.show_state() if r else "Missing"

            if args.plain:
                print "\t".join((
                    [depl.uuid, depl.name or "(none)"] if args.all else []) + [
                        name,
                        resource_state.lower(),
                        r.show_type() if r else d.show_type(),
                        r.resource_id or "" if r else "",
                        r.public_ipv4 or ""
                        if r and hasattr(r, "public_ipv4") else "",
                        r.private_ipv4 or ""
                        if r and deployment.is_machine(r) else "",
                    ])
            else:
                tbl.add_row(([depl.name or depl.uuid] if args.all else []) + [
                    name,
                    resource_state,
                    r.show_type() if r else d.show_type(),
                    r.resource_id or "" if r else "",
                    (hasattr(r, "public_ipv4") and r.public_ipv4) or
                    (hasattr(r, "private_ipv4") and r.private_ipv4
                     ) or "" if r else "",
                ])
Ejemplo n.º 4
0
    def emit_resource(r: nixops.resources.ResourceState) -> None:
        config = attrs_per_resource[r.name]
        if is_machine(r):
            if authorized_keys[r.name]:
                config.append({
                    ("users", "extraUsers", "root"): {
                        ("openssh", "authorizedKeys", "keys"):
                        authorized_keys[r.name]
                    },
                    ("services", "openssh"): {
                        "extraConfig": "PermitTunnel yes\n"
                    },
                })

            config.append({
                ("boot", "kernelModules"):
                list(kernel_modules[r.name]),
                ("networking", "firewall"): {
                    "trustedInterfaces": list(trusted_interfaces[r.name])
                },
            })

            # Add SSH public host keys for all machines in network.
            for m2 in active_machines.values():
                if hasattr(m2, "public_host_key") and m2.public_host_key:
                    # Using references to files in same tempdir for now, until NixOS has support
                    # for adding the keys directly as string. This way at least it is compatible
                    # with older versions of NixOS as well.
                    # TODO: after reasonable amount of time replace with string option
                    config.append({
                        ("services", "openssh", "knownHosts", m2.name): {
                            "hostNames": [
                                m2.name + "-unencrypted",
                                m2.name + "-encrypted",
                            ],
                        }
                    })
Ejemplo n.º 5
0
    def emit_resource(r: nixops.resources.ResourceState) -> None:
        config = attrs_per_resource[r.name]
        if is_machine(r):
            # NOTE: unfortunate mypy doesn't check that is_machine calls an isinstance() function
            r = cast(nixops.backends.GenericMachineState, r)

            # Skip resource emission if the machine is excluded or the associated wgKeypair is not up yet
            if (not r.defn or r.name not in wg_keypair_list or
                (wg_keypair_list[r.name].state != wg_keypair_list[r.name].UP)):
                return

            # Sort the hosts by its canonical host names.
            sorted_hosts = sorted(hosts[r.name].items(),
                                  key=lambda item: item[1][0])

            # Just to remember the format:
            #   ip_address canonical_hostname [aliases...]
            extra_hosts = {f"{ip}": names for ip, names in sorted_hosts}

            # Add the base wireguard nix config for machine m
            wg_local_ipv4 = index_to_private_ip(wg_keypair_list[r.name],
                                                r.index)

            # Substitute wireguard IPs for any wg-link resources name in the dns list
            if wg_keypair_list[r.name].dns != []:
                dns_list = cast(List[str], wg_keypair_list[r.name].dns).copy()
                for i, dns in enumerate(wg_keypair_list[r.name].dns):
                    if dns in wg_name.values():
                        del dns_list[i]
                        dns_list.insert(
                            i,
                            index_to_private_ip(
                                wg_keypair_list[re.sub("-wg$", "", dns)],
                                active_machines[re.sub("-wg$", "", dns)].index,
                            ),
                        )
            else:
                dns_list = []

            config.append({
                ("networking", "hosts"):
                extra_hosts,
                ("networking", "firewall", "allowedUDPPorts"):
                [wg_keypair_list[r.name].listen_port],
                (
                    "networking",
                    "wg-quick",
                    "interfaces",
                    wg_keypair_list[r.name].interface_name,
                ): {
                    "address": [f"{wg_local_ipv4}/24"],
                    "listenPort":
                    wg_keypair_list[r.name].listen_port,
                    "privateKeyFile":
                    "/etc/nixops-wg-links/wireguard.private",
                    "dns":
                    dns_list,
                    "mtu":
                    wg_keypair_list[r.name].mtu if
                    (wg_keypair_list[r.name].mtu or 0) >= 1 else None,
                    "preUp":
                    wg_keypair_list[r.name].pre_up,
                    "preDown":
                    wg_keypair_list[r.name].pre_down,
                    "postUp":
                    wg_keypair_list[r.name].post_up,
                    "postDown":
                    wg_keypair_list[r.name].post_down,
                    "table":
                    wg_keypair_list[r.name].table,
                },
                (
                    "networking",
                    "wg-quick",
                    "interfaces",
                    wg_keypair_list[r.name].interface_name,
                    "peers",
                ):
                total_peers[r.name],
            })