Author: eelco Date: Mon May 9 12:38:36 2011 New Revision: 27195 URL: https://svn.nixos.org/websvn/nix/?rev=27195&sc=1
Log: * Refactoring. Modified: cloud/trunk/default.nix cloud/trunk/src/nixos-deploy-network.pl Modified: cloud/trunk/default.nix ============================================================================== --- cloud/trunk/default.nix Mon May 9 09:36:53 2011 (r27194) +++ cloud/trunk/default.nix Mon May 9 12:38:36 2011 (r27195) @@ -3,7 +3,7 @@ stdenv.mkDerivation { name = "nixos-deploy-network"; - src = ./src; + src = lib.cleanSource ./src; buildInputs = [ perl makeWrapper perlPackages.XMLLibXML perlPackages.JSON ]; Modified: cloud/trunk/src/nixos-deploy-network.pl ============================================================================== --- cloud/trunk/src/nixos-deploy-network.pl Mon May 9 09:36:53 2011 (r27194) +++ cloud/trunk/src/nixos-deploy-network.pl Mon May 9 12:38:36 2011 (r27195) @@ -1,5 +1,6 @@ #! /var/run/current-system/sw/bin/perl -w +use strict; use utf8; use XML::LibXML; use Cwd; @@ -8,13 +9,24 @@ binmode(STDERR, ":utf8"); -# !!! Cleanly separate $state->{machines} (the deployment state) and -# @machines (the deployment specification). - my @networkExprs; -my @machines = (); -my $outPath; + +# The deployment specification, obtained by evaluating the Nix +# expressions specified by the user. $spec->{machines} is a mapping +# from machine names (i.e. attribute names in the input) to a hash +# containing the desired deployment characteristics of the +# corresponding machine. E.g., $spec->{machines}->{foo}->{targetEnv} +# contains the target environment type of machine ‘foo’ (e.g., ‘ec2’). +my $spec; + +# The current deployment state, containing information about +# previously created or initialised (virtual) machines. In +# particular, $state->{machines} is a mapping from machine names to a +# hash containing info about the corresponding machine, such as its IP +# address. E.g., $state->{machines}->{foo}->{ipv6} contains the IPv6 +# address of machine ‘foo’. my $state; + my $stateFile = "./state.json"; my $myDir = dirname(Cwd::abs_path($0)); @@ -35,11 +47,11 @@ startMachines(); # Evaluate and build each machine configuration locally. - buildConfigs(); + my $outPath = buildConfigs(); # Copy the closures of each machine configuration to the # corresponding target machine. - copyClosures(); + copyClosures($outPath); # Activate the new configuration on each machine, and do a # rollback if any fails. @@ -81,7 +93,7 @@ } else { die "machine ‘$name’ has an unknown target environment type ‘$targetEnv’"; } - push @machines, $info; + $spec->{machines}->{$name} = $info; } } @@ -106,9 +118,9 @@ sub startMachines { - foreach my $machine (@machines) { - - my $prevMachine = $state->{machines}->{$machine->{name}}; + foreach my $name (keys %{$spec->{machines}}) { + my $machine = $spec->{machines}->{$name}; + my $prevMachine = $state->{machines}->{$name}; if (defined $prevMachine) { # So we already created/used a machine in a previous @@ -118,13 +130,12 @@ if ($machine->{targetEnv} eq $prevMachine->{targetEnv}) { # !!! Also check that parameters like the EC2 are the # same. - $machine->{ipv6} = $prevMachine->{ipv6}; # !!! hack - print STDERR "machine ‘$machine->{name}’ already exists\n"; + print STDERR "machine ‘$name’ already exists\n"; next; } # !!! Handle killing cloud VMs, etc. When killing a VM, # make sure it's not marked as precious. - die "machine ‘$machine->{name}’ was previously created with incompatible deployment parameters\n"; + die "machine ‘$name’ was previously created with incompatible deployment parameters\n"; } if ($machine->{targetEnv} eq "none") { @@ -133,29 +144,28 @@ elsif ($machine->{targetEnv} eq "adhoc") { - print STDERR "starting missing VM ‘$machine->{name}’...\n"; + print STDERR "starting missing VM ‘$name’...\n"; my $vmId = `ssh $machine->{adhoc}->{controller} $machine->{adhoc}->{createVMCommand}`; die "unable to start VM: $?" unless $? == 0; chomp $vmId; - $machine->{vmId} = $vmId; - - $ipv6 = `ssh $machine->{adhoc}->{controller} $machine->{adhoc}->{queryVMCommand} $machine->{vmId} 2> /dev/null`; + my $ipv6 = `ssh $machine->{adhoc}->{controller} $machine->{adhoc}->{queryVMCommand} $vmId 2> /dev/null`; die "unable to query VM state: $?" unless $? == 0; - chomp $ipv6; - $machine->{ipv6} = $ipv6; print STDERR "IPv6 address is $ipv6\n"; - $state->{machines}->{$machine->{name}} = + $state->{machines}->{$name} = { targetEnv => $machine->{targetEnv} - , vmId => $machine->{vmId} - , ipv6 => $machine->{ipv6} + , vmId => $vmId + , ipv6 => $ipv6 + , # Need to remember these so that we know how to kill + # the VM later, among other things. + adhoc => $machine->{adhoc} }; writeState; - print STDERR "checking whether VM ‘$machine->{name}’ is reachable via SSH...\n"; + print STDERR "checking whether VM ‘$name’ is reachable via SSH...\n"; system "ssh -o StrictHostKeyChecking=no root\@$ipv6 true < /dev/null 2> /dev/null"; die "cannot SSH to VM: $?" unless $? == 0; @@ -168,9 +178,9 @@ writeState; # Figure out how we're gonna SSH to each machine. Prefer IPv6 - # addresses over hostnames. - foreach my $machine (@machines) { - $machine->{sshName} = $machine->{ipv6} || $machine->{targetHost} || die "don't know how to reach ‘$machine->{name}’"; + # addresses over hostnames.while + while (my ($name, $machine) = each %{$state->{machines}}) { + $machine->{sshName} = $machine->{ipv6} || $machine->{targetHost} || die "don't know how to reach ‘$name’"; } # So now that we know the hostnames / IP addresses of all @@ -178,14 +188,14 @@ # network configuration that can be stacked on top of the # user-supplied network configuration. my $hosts = ""; - foreach my $machine (@machines) { - $hosts .= "$machine->{ipv6} $machine->{name}\\n" if defined $machine->{ipv6}; + while (my ($name, $machine) = each %{$state->{machines}}) { + $hosts .= "$machine->{ipv6} $name\\n" if defined $machine->{ipv6}; } open STATE, ">physical.nix" or die; print STATE "{\n"; - foreach my $machine (@machines) { - print STATE " $machine->{name} = { config, pkgs, ... }:\n"; + while (my ($name, $machine) = each %{$state->{machines}}) { + print STATE " $name = { config, pkgs, ... }:\n"; print STATE " {\n"; if ($machine->{targetEnv} eq "adhoc") { print STATE " require = [ $myDir/adhoc-cloud-vm.nix ];\n"; @@ -200,31 +210,33 @@ sub buildConfigs { print STDERR "building all machine configurations...\n"; - $outPath = `nix-build $myDir/eval-machine-info.nix --arg networkExprs '[ @networkExprs ./physical.nix ]' -A machines`; + my $outPath = `nix-build $myDir/eval-machine-info.nix --arg networkExprs '[ @networkExprs ./physical.nix ]' -A machines`; die "unable to build all machine configurations" unless $? == 0; chomp $outPath; + return $outPath; } sub copyClosures { + my ($outPath) = @_; # !!! Should copy closures in parallel. - foreach my $machine (@machines) { - print STDERR "copying closure to machine ‘$machine->{name}’...\n"; - my $toplevel = readlink "$outPath/$machine->{name}" or die; + while (my ($name, $machine) = each %{$state->{machines}}) { + print STDERR "copying closure to machine ‘$name’...\n"; + my $toplevel = readlink "$outPath/$name" or die; $machine->{toplevel} = $toplevel; system "nix-copy-closure --gzip --to root\@$machine->{sshName} $toplevel"; - die "unable to copy closure to machine ‘$machine->{name}’" unless $? == 0; + die "unable to copy closure to machine ‘$name’" unless $? == 0; } } sub activateConfigs { - foreach my $machine (@machines) { - print STDERR "activating new configuration on machine ‘$machine->{name}’...\n"; + while (my ($name, $machine) = each %{$state->{machines}}) { + print STDERR "activating new configuration on machine ‘$name’...\n"; system "ssh -o StrictHostKeyChecking=no root\@$machine->{sshName} nix-env -p /nix/var/nix/profiles/system --set $machine->{toplevel} \\; /nix/var/nix/profiles/system/bin/switch-to-configuration switch"; if ($? != 0) { # !!! do a rollback - die "unable to activate new configuration on machine ‘$machine->{name}’"; + die "unable to activate new configuration on machine ‘$name’"; } } } _______________________________________________ nix-commits mailing list nix-comm...@cs.uu.nl http://mail.cs.uu.nl/mailman/listinfo/nix-commits