NixOS/nixops — pull request #194 by Phreedom (2014-06-11 11:14:20+00:00)
Title: GCE backend: initial implementation

A snapshot of the work in progress. There's support for instances, disks, static ips and basic networking. Implementation of --check and --allow-recreate is spotty and overall on
the level of the other backends :) Use nixpkgs master to build nixops and deployments or else...

I haven't tested luks and tunnels which means they probably don't work, moving resources between different zones and projects might fail too. Don't press ctrl+c, just don't.
Improvements to follow shortly.
More comments, required workarounds etc are in the following example deployment:

trivial.nix:
```
{
network.description = "Trivial test network";

machine = { config, pkgs, ... }: {
services.httpd.enable = true;
services.httpd.adminAddr = "eelco.dolstra@logicblox.com";

services.httpd.documentRoot = "${pkgs.valgrind}/share/doc/valgrind/html";
networking.firewall.allowedTCPPorts = [ 80 ];
};

machine2 = { config, pkgs, ... }: {};

}

```

trivial-gce.nix:
```
let

# change this as necessary or wipe and use ENV vars
credentials = {
project = "logicblox-dev";
serviceAccount = "572772620792-gecnc5v4ks9e6s13tociphd1p9ct6emr@developer.gserviceaccount.com";
accessKey = "/path/to/key.pem";
};

in

{
# test initializing from image
resources.gceDisks.tnxp-disk = credentials // {
region = "europe-west1-b";
image = "nixos-14-04pre-d215564-x86-64-linux";
size = 165;
};

# just a small "lab rat" disk
resources.gceDisks.tiny = credentials // {
region = "europe-west1-b";
size = 2;
};

resources.gceStaticIPs.perma-ip = credentials // {
region = "europe-west1";
};

# the most important rules are allow-ssh and allow-http

# allow-ssh rule is present in the default network
# created by GCE, but it isn't present in custom networks,
# so we have to create it by hand

# allow-http is needed to that we can curl the machine IP
# and see that the apache service is indeed up and working

# allow-test is there just to test various features

resources.gceNetworks.coolnet = credentials // {
addressRange = "192.168.3.0/24";
firewall = {
allow-http.allowed.tcp = [ 80 ];
allow-ssh.allowed.tcp = [ 22 ];

allow-test = {
sourceRanges = ["0.0.0.0/0"];
allowed.tcp = [ 88 "8080" ];

# commenting out this rule causes pings to be blackholed
allowed.icmp = null;

#sourceTags = ["blah" "hmm" ];
};
};
};

machine =
{ resources, ...}: {

# was hoping this would help troubleshoot the kernel panic
boot.initrd.postDeviceCommands = ''
ls -l /dev/sd*
ls -l /dev/disk/
ls -l /dev/disk/by-id/
ls -l /dev/disk/by-label/
'';

# for network/firewall tests
networking.firewall.allowPing = true;

deployment.targetEnv = "gce";
deployment.gce.region = "europe-west1-b";

# don't forget to change these too
deployment.gce.project = "logicblox-dev";
deployment.gce.serviceAccount = "572772620792-gecnc5v4ks9e6s13tociphd1p9ct6emr@developer.gserviceaccount.com";
deployment.gce.accessKey = "/path/to/key.pem";

# random
deployment.gce.tags = [ "seems-to" "work" ];

# meaningless despite sounding seriously
deployment.gce.metadata = { loglevel = "error"; secondmeta = "2"; };

# (un)comment mount points and see what happens!

# It's very important to ensure that disk names and devices match.
# One day device names will be generated from disk names.

fileSystems = {

# for testing what is effectively an ephemeral device, which nevertheless
# survives "GCE reboots", that is instance teardown/recreation instead of start/stop

"/data" = {
autoFormat = true; fsType = "ext4";
device = "/dev/disk/by-id/scsi-0Google_PersistentDisk_machine-data";
gce = { size = 14; disk_name = "machine-data"; };
};

# testing external/persistent disks
# toggling readOnly doesn't cause the disk to be reattached as ro
# you have to comment out, deploy, uncomment, deploy :(
"/tiny" = { gce.readOnly = false; gce.disk = resources.gceDisks.tiny; autoFormat = true; fsType = "ext4";
device = "/dev/disk/by-id/scsi-0Google_PersistentDisk_${resources.gceDisks.tiny.name}"; };

};

# This is a very important workaround.
# Currently nixos can only boot from /dev/disk/by-label/nixos,
# despite /dev/disk/by-id/* being available at the same time.
# Attempting to boot off /dev/disk/by-id/* causes a kernel panic.
# So we quietly attach the device without involving fileSystems attr.
# Don't forget to change disk_name and device name if you
# make several machines to avoid name clashes.

deployment.gce.blockDeviceMapping."/dev/disk/by-id/scsi-0Google_PersistentDisk_machine-root" = {
image = "nixos-14-04pre-d215564-x86-64-linux";
bootDisk = true;
disk_name = "machine-root";
};

# ip and network changes require a hard restart: deploy --allow-reboot

deployment.gce.ipAddress = resources.gceStaticIPs.perma-ip;
#deployment.gce.ipAddress ="nixops-2e0a724a-f030-11e3-8239-b8e8560f8b58-perma-ip"; #

deployment.gce.network = resources.gceNetworks.coolnet;
#deployment.gce.network = "nixops-2e0a724a-f030-11e3-8239-b8e8560f8b58-coolnet";

# Uncomment and see what happens!

#deployment.gce.instanceType = "n1-standard-1";
#deployment.gce.scheduling.automaticRestart = false;
#deployment.gce.scheduling.onHostMaintenance = "TERMINATE";

};

# minimal deployment
machine2 = { resources, ...}: {

deployment.targetEnv = "gce";
deployment.gce = credentials // {
region = "europe-west1-b";

blockDeviceMapping."/dev/disk/by-id/scsi-0Google_PersistentDisk_machine2-root" = {
image = "nixos-14-04pre-d215564-x86-64-linux";
bootDisk = true;
disk_name = "machine2-root";
};
};

};

}
```