Beispiel #1
0
 def test_function_call(self):
     self.assert_nix(Call(RawValue("fun_call"), {"a": "b"}),
                     '( fun_call { a = "b"; } )')
     self.assert_nix(
         Call(RawValue("multiline_call"), {"a": "b"}),
         '(\n  multiline_call\n  {\n    a = "b";\n  }\n)',
         maxwidth=0,
     )
Beispiel #2
0
 def test_list_compound(self):
     self.assert_nix([Call(RawValue("123 //"), 456),
                      RawValue("a b c")], '[ (( 123 // 456 )) (a b c) ]')
     self.assert_nix([
         RawValue("a b c"), {
             'cde':
             [RawValue("1,2,3"),
              RawValue("4 5 6"),
              RawValue("7\n8\n9")]
         }
     ], '[ (a b c) { cde = [ 1,2,3 (4 5 6) (7\n8\n9) ]; } ]')
Beispiel #3
0
 def get_physical_backup_spec(self, backupid):
     val = {}
     if backupid in self.backups:
         for dev, snap in self.backups[backupid].items():
             val[dev] = {
                 'snapshot': Call(RawValue("pkgs.lib.mkOverride 10"), snap)
             }
         val = {('deployment', 'gce', 'blockDeviceMapping'): val}
     else:
         val = RawValue(
             "{{}} /* No backup found for id '{0}' */".format(backupid))
     return Function("{ config, pkgs, ... }", val)
Beispiel #4
0
    def destroy_resources(self, include=[], exclude=[], wipe=False):
        """Destroy all active or obsolete resources."""

        with self._get_deployment_lock():
            for r in self.resources.itervalues():
                r._destroyed_event = threading.Event()
                r._errored = False
                for rev_dep in r.destroy_before(self.resources.itervalues()):
                    try:
                        rev_dep._wait_for.append(r)
                    except AttributeError:
                        rev_dep._wait_for = [ r ]

            def worker(m):
                try:
                    if not should_do(m, include, exclude): return
                    try:
                        for dep in m._wait_for:
                            dep._destroyed_event.wait()
                            # !!! Should we print a message here?
                            if dep._errored:
                                m._errored = True
                                return
                    except AttributeError:
                        pass
                    if m.destroy(wipe=wipe): self.delete_resource(m)
                except:
                    m._errored = True
                    raise
                finally:
                    m._destroyed_event.set()

            nixops.parallel.run_tasks(nr_workers=-1, tasks=self.resources.values(), worker_fun=worker)

        # Remove the destroyed machines from the rollback profile.
        # This way, a subsequent "nix-env --delete-generations old" or
        # "nix-collect-garbage -d" will get rid of the machine
        # configurations.
        if self.rollback_enabled: # and len(self.active) == 0:
            profile = self.create_profile()
            attrs = {m.name:
                     Call(RawValue("builtins.storePath", m.cur_toplevel))
                     for m in self.active.itervalues() if m.cur_toplevel}
            if subprocess.call(
                ["nix-env", "-p", profile, "--set", "*", "-I", "nixops=" + self.expr_path,
                 "-f", "<nixops/update-profile.nix>",
                 "--arg", "machines", py2nix(attrs, inline=True)]) != 0:
                raise Exception("cannot update profile ‘{0}’".format(profile))
Beispiel #5
0
    def get_physical_spec(self):
        block_device_mapping = {}
        for k, v in self.block_device_mapping.items():
            if (v.get('encrypt', False)
                and v.get('passphrase', "") == ""
                and v.get('generatedKey', "") != ""):
                block_device_mapping[k] = {
                    'passphrase': Call(RawValue("pkgs.lib.mkOverride 10"), v['generatedKey']),
                }

        return {
            'imports': [
                RawValue("<nixpkgs/nixos/modules/virtualisation/google-compute-config.nix>")
            ],
            ('deployment', 'gce', 'blockDeviceMapping'): block_device_mapping,
        }
Beispiel #6
0
    def destroy_resources(self, include=[], exclude=[], wipe=False):
        """Destroy all active and obsolete resources."""

        with self._get_deployment_lock():
            self._destroy_resources(include, exclude, wipe)

        # Remove the destroyed machines from the rollback profile.
        # This way, a subsequent "nix-env --delete-generations old" or
        # "nix-collect-garbage -d" will get rid of the machine
        # configurations.
        if self.rollback_enabled: # and len(self.active) == 0:
            profile = self.create_profile()
            attrs = {m.name:
                     Call(RawValue("builtins.storePath"), m.cur_toplevel)
                     for m in self.active.itervalues() if m.cur_toplevel}
            if subprocess.call(
                ["nix-env", "-p", profile, "--set", "*", "-I", "nixops=" + self.expr_path,
                 "-f", "<nixops/update-profile.nix>",
                 "--arg", "machines", py2nix(attrs, inline=True)]) != 0:
                raise Exception("cannot update profile ‘{0}’".format(profile))
Beispiel #7
0
        def do_machine(m):
            defn = self.definitions[m.name]
            attrs_list = attrs_per_resource[m.name]

            # Emit configuration to realise encrypted peer-to-peer links.
            for m2 in active_resources.itervalues():
                ip = m.address_to(m2)
                if ip:
                    hosts[m.name][ip] += [m2.name, m2.name + "-unencrypted"]

            # Always use the encrypted/unencrypted suffixes for aliases rather
            # than for the canonical name!
            hosts[m.name]["127.0.0.1"].append(m.name + "-encrypted")

            for m2_name in defn.encrypted_links_to:

                if m2_name not in active_machines:
                    raise Exception("‘deployment.encryptedLinksTo’ in machine ‘{0}’ refers to an unknown machine ‘{1}’"
                                    .format(m.name, m2_name))
                m2 = active_machines[m2_name]

                # Don't create two tunnels between a pair of machines.
                if m.name in self.definitions[m2.name].encrypted_links_to and m.name >= m2.name:
                    continue
                local_ipv4 = index_to_private_ip(m.index)
                remote_ipv4 = index_to_private_ip(m2.index)
                local_tunnel = 10000 + m2.index
                remote_tunnel = 10000 + m.index
                attrs_list.append({
                    ('networking', 'p2pTunnels', 'ssh', m2.name): {
                        'target': '{0}-unencrypted'.format(m2.name),
                        'targetPort': m2.ssh_port,
                        'localTunnel': local_tunnel,
                        'remoteTunnel': remote_tunnel,
                        'localIPv4': local_ipv4,
                        'remoteIPv4': remote_ipv4,
                        'privateKey': '/root/.ssh/id_charon_vpn',
                    }
                })

                # FIXME: set up the authorized_key file such that ‘m’
                # can do nothing more than create a tunnel.
                authorized_keys[m2.name].append(m.public_vpn_key)
                kernel_modules[m.name].add('tun')
                kernel_modules[m2.name].add('tun')
                hosts[m.name][remote_ipv4] += [m2.name, m2.name + "-encrypted"]
                hosts[m2.name][local_ipv4] += [m.name, m.name + "-encrypted"]
                trusted_interfaces[m.name].add('tun' + str(local_tunnel))
                trusted_interfaces[m2.name].add('tun' + str(remote_tunnel))

            private_ipv4 = m.private_ipv4
            if private_ipv4:
                attrs_list.append({
                    ('networking', 'privateIPv4'): private_ipv4
                })
            public_ipv4 = m.public_ipv4
            if public_ipv4:
                attrs_list.append({
                    ('networking', 'publicIPv4'): public_ipv4
                })
            public_vpn_key = m.public_vpn_key
            if public_vpn_key:
                attrs_list.append({
                    ('networking', 'vpnPublicKey'): public_vpn_key
                })

            # Set system.stateVersion if the Nixpkgs version supports it.
            if nixops.util.parse_nixos_version(defn.config["nixosVersion"]) >= ["15", "09"]:
                attrs_list.append({
                    ('system', 'stateVersion'): Call(RawValue("lib.mkDefault"), m.state_version or '14.12')
                })

            if self.nixos_version_suffix:
                attrs_list.append({
                    ('system', 'nixosVersionSuffix'): self.nixos_version_suffix
                })