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";
        };
      };

  };

}
```