summary refs log tree commit diff
path: root/modules/installer/tools/nixos-deploy-network/deploy.nix
blob: 7ece202a990c01a346b14f4798f9742976999b56 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
{ nixos ? /etc/nixos/nixos
, nixpkgs ? /etc/nixos/nixpkgs
, networkExprs
, targetProperty ? "targetHost"
}:

let
  pkgs = import nixpkgs {};

  inherit (builtins) attrNames getAttr listToAttrs;
  inherit (pkgs.lib) concatMapStrings zipAttrs;

  networks = map (networkExpr: import networkExpr) networkExprs;

  network = zipAttrs networks;

  generateRollbackSucceededPhase = network: configs:
    concatMapStrings (configurationName:
      let
	config = getAttr configurationName configs;
      in
      ''
        if [ "$rollback" != "$succeeded" ]
	then
	    ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --rollback
	    ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} /nix/var/nix/profiles/system/bin/switch-to-configuration switch

	    rollback=$((rollback + 1))
	fi
      ''
    ) (attrNames network)
  ;

  generateDistributionPhase = network: configs:
    concatMapStrings (configurationName:
      let
	config = getAttr configurationName configs;
      in
      ''
        echo "=== copy system closure to ${getAttr targetProperty (config.deployment)} ==="
        nix-copy-closure --to ${getAttr targetProperty (config.deployment)} ${config.system.build.toplevel}
      ''
    ) (attrNames network)
  ;

  generateActivationPhase = network: configs:
    concatMapStrings (configurationName:
      let
	config = getAttr configurationName configs;
      in
      ''
        echo "=== activating system configuration on ${getAttr targetProperty (config.deployment)} ==="
	ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} ||
	  (ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --rollback; rollbackSucceeded)

        ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} /nix/var/nix/profiles/system/bin/switch-to-configuration switch ||
	  ( ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} nix-env -p /nix/var/nix/profiles/system --rollback
	    ssh $NIX_SSHOPTS ${getAttr targetProperty (config.deployment)} /nix/var/nix/profiles/system/bin/switch-to-configuration switch
	    rollbackSucceeded
	  )

	succeeded=$((succeeded + 1))
      ''
    ) (attrNames network)
  ;

  evaluateMachines = network:
    listToAttrs (map (configurationName:
      let
        modules = getAttr configurationName network;
      in
      { name = configurationName;
        value = (import "${nixos}/lib/eval-config.nix" {
          inherit nixpkgs;
          modules =
	    modules ++
            [ # Provide a default hostname and deployment target equal
              # to the attribute name of the machine in the model.
              { key = "set-default-hostname";
                networking.hostName = pkgs.lib.mkOverride 900 configurationName;
                deployment.targetHost = pkgs.lib.mkOverride 900 configurationName;
              }
            ];
          extraArgs = { nodes = evaluateMachines network; };
        }).config; }
    ) (attrNames (network)));

  configs = evaluateMachines network;
in
pkgs.stdenv.mkDerivation {
  name = "deploy-script";

  # This script has a zillion dependencies and is trivial to build, so
  # we don't want to build it remotely.
  preferLocalBuild = true;

  buildCommand =
  ''
    ensureDir $out/bin
    cat > $out/bin/deploy-systems << "EOF"
    #! ${pkgs.stdenv.shell} -e

    rollbackSucceeded()
    {
        rollback=0
        ${generateRollbackSucceededPhase network configs}
    }

    # Distribution phase

    ${generateDistributionPhase network configs}

    # Activation phase

    succeeded=0

    ${generateActivationPhase network configs}
    EOF
    chmod +x $out/bin/deploy-systems
  '';
}