summary refs log tree commit diff
path: root/nixos/modules/virtualisation/azure-agent.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/virtualisation/azure-agent.nix')
-rw-r--r--nixos/modules/virtualisation/azure-agent.nix198
1 files changed, 198 insertions, 0 deletions
diff --git a/nixos/modules/virtualisation/azure-agent.nix b/nixos/modules/virtualisation/azure-agent.nix
new file mode 100644
index 00000000000..bd8c7f8c1ee
--- /dev/null
+++ b/nixos/modules/virtualisation/azure-agent.nix
@@ -0,0 +1,198 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.virtualisation.azure.agent;
+
+  waagent = with pkgs; stdenv.mkDerivation rec {
+    name = "waagent-2.0";
+    src = pkgs.fetchFromGitHub {
+      owner = "Azure";
+      repo = "WALinuxAgent";
+      rev = "1b3a8407a95344d9d12a2a377f64140975f1e8e4";
+      sha256 = "10byzvmpgrmr4d5mdn2kq04aapqb3sgr1admk13wjmy5cd6bwd2x";
+    };
+
+    patches = [ ./azure-agent-entropy.patch ];
+
+    buildInputs = [ makeWrapper python pythonPackages.wrapPython ];
+    runtimeDeps = [ findutils gnugrep gawk coreutils openssl openssh
+                    nettools # for hostname
+                    procps # for pidof
+                    shadow # for useradd, usermod
+                    util-linux # for (u)mount, fdisk, sfdisk, mkswap
+                    parted
+                  ];
+    pythonPath = [ pythonPackages.pyasn1 ];
+
+    configurePhase = false;
+    buildPhase = false;
+
+    installPhase = ''
+      substituteInPlace config/99-azure-product-uuid.rules \
+          --replace /bin/chmod "${coreutils}/bin/chmod"
+      mkdir -p $out/lib/udev/rules.d
+      cp config/*.rules $out/lib/udev/rules.d
+
+      mkdir -p $out/bin
+      cp waagent $out/bin/
+      chmod +x $out/bin/waagent
+
+      wrapProgram "$out/bin/waagent" \
+          --prefix PYTHONPATH : $PYTHONPATH \
+          --prefix PATH : "${makeBinPath runtimeDeps}"
+    '';
+  };
+
+  provisionedHook = pkgs.writeScript "provisioned-hook" ''
+    #!${pkgs.runtimeShell}
+    /run/current-system/systemd/bin/systemctl start provisioned.target
+  '';
+
+in
+
+{
+
+  ###### interface
+
+  options.virtualisation.azure.agent = {
+    enable = mkOption {
+      default = false;
+      description = "Whether to enable the Windows Azure Linux Agent.";
+    };
+    verboseLogging = mkOption {
+      default = false;
+      description = "Whether to enable verbose logging.";
+    };
+    mountResourceDisk = mkOption {
+      default = true;
+      description = "Whether the agent should format (ext4) and mount the resource disk to /mnt/resource.";
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    assertions = [ {
+      assertion = pkgs.stdenv.hostPlatform.isx86;
+      message = "Azure not currently supported on ${pkgs.stdenv.hostPlatform.system}";
+    } {
+      assertion = config.networking.networkmanager.enable == false;
+      message = "Windows Azure Linux Agent is not compatible with NetworkManager";
+    } ];
+
+    boot.initrd.kernelModules = [ "ata_piix" ];
+    networking.firewall.allowedUDPPorts = [ 68 ];
+
+
+    environment.etc."waagent.conf".text = ''
+        #
+        # Windows Azure Linux Agent Configuration
+        #
+
+        Role.StateConsumer=${provisionedHook}
+
+        # Enable instance creation
+        Provisioning.Enabled=y
+
+        # Password authentication for root account will be unavailable.
+        Provisioning.DeleteRootPassword=n
+
+        # Generate fresh host key pair.
+        Provisioning.RegenerateSshHostKeyPair=n
+
+        # Supported values are "rsa", "dsa" and "ecdsa".
+        Provisioning.SshHostKeyPairType=ed25519
+
+        # Monitor host name changes and publish changes via DHCP requests.
+        Provisioning.MonitorHostName=y
+
+        # Decode CustomData from Base64.
+        Provisioning.DecodeCustomData=n
+
+        # Execute CustomData after provisioning.
+        Provisioning.ExecuteCustomData=n
+
+        # Format if unformatted. If 'n', resource disk will not be mounted.
+        ResourceDisk.Format=${if cfg.mountResourceDisk then "y" else "n"}
+
+        # File system on the resource disk
+        # Typically ext3 or ext4. FreeBSD images should use 'ufs2' here.
+        ResourceDisk.Filesystem=ext4
+
+        # Mount point for the resource disk
+        ResourceDisk.MountPoint=/mnt/resource
+
+        # Respond to load balancer probes if requested by Windows Azure.
+        LBProbeResponder=y
+
+        # Enable logging to serial console (y|n)
+        # When stdout is not enough...
+        # 'y' if not set
+        Logs.Console=y
+
+        # Enable verbose logging (y|n)
+        Logs.Verbose=${if cfg.verboseLogging then "y" else "n"}
+
+        # Root device timeout in seconds.
+        OS.RootDeviceScsiTimeout=300
+    '';
+
+    services.udev.packages = [ waagent ];
+
+    networking.dhcpcd.persistent = true;
+
+    services.logrotate = {
+      enable = true;
+      extraConfig = ''
+        /var/log/waagent.log {
+            compress
+            monthly
+            rotate 6
+            notifempty
+            missingok
+        }
+      '';
+    };
+
+    systemd.targets.provisioned = {
+      description = "Services Requiring Azure VM provisioning to have finished";
+    };
+
+  systemd.services.consume-hypervisor-entropy =
+    { description = "Consume entropy in ACPI table provided by Hyper-V";
+
+      wantedBy = [ "sshd.service" "waagent.service" ];
+      before = [ "sshd.service" "waagent.service" ];
+
+      path  = [ pkgs.coreutils ];
+      script =
+        ''
+          echo "Fetching entropy..."
+          cat /sys/firmware/acpi/tables/OEM0 > /dev/random
+        '';
+      serviceConfig.Type = "oneshot";
+      serviceConfig.RemainAfterExit = true;
+      serviceConfig.StandardError = "journal+console";
+      serviceConfig.StandardOutput = "journal+console";
+     };
+
+    systemd.services.waagent = {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network-online.target" "sshd.service" ];
+      wants = [ "network-online.target" ];
+
+      path = [ pkgs.e2fsprogs pkgs.bash ];
+      description = "Windows Azure Agent Service";
+      unitConfig.ConditionPathExists = "/etc/waagent.conf";
+      serviceConfig = {
+        ExecStart = "${waagent}/bin/waagent -daemon";
+        Type = "simple";
+      };
+    };
+
+  };
+
+}