cleverca22
9/25/2015 - 7:54 PM

configuration.nix

{ lib, config, pkgs, ... }:

{
  imports = [ ./iscsi-boot.nix ];
  fileSystems = {
    "/" = { device = "UUID=132e7c5b-b4a9-4154-8105-4479e17f4f5b"; fsType = "ext4"; };
    "/boot/" = { device = "UUID=fdac080d-d111-455c-a890-bc3e5e08c2d5"; fsType = "ext4"; };
  };
  boot = {
    loader = {
      grub.enable = true;
    };
    initrd = {
      kernelModules = [ "e1000e" ];
      iscsi = {
        initiatorName = "iqn.2015-09.com.example:3255a7223b2";
        devices = [
          { host = "192.168.2.61"; lun = "iqn.2001-04.com.c2d-nix5"; }
        ];
        ipAddress = "192.168.2.31";
        netDev = "eth0";
        prefixLength = 24;
        defaultGateway = "192.168.2.1";
      };
    };
  };
  networking.interfaces.eth0.ipAddress = "192.168.2.31";
  networking.interfaces.eth0.prefixLength = 24;
  networking.defaultGateway = "192.168.2.1";
  networking.hostName = "iscsi-boot";
  networking.nameservers = [ "192.168.2.61" ];
  networking.dhcpcd.persistent = true;
  environment.systemPackages = [ ];
}
# find the targets available on a host
iscsi_discovery 192.168.2.61
# connect to one
iscsiadm -m node -T iqn.2001-04.com.c2d-nix4 -p 192.168.2.61 -l
# in my case, it appears as sdd, check dmesg
[root@nixos:~]# hexdump -C /dev/sdd
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
# format and mount to /mnt like a normal nixos install
mkfs.ext4 /dev/sdd
mount -v /dev/sdd /mnt/
# cheat to aid in qemu testing
mount --bind /home/clever/iscsi-boot/boot/ /mnt/boot/
# paste the following into /mnt/etc/nixos/configuration.nix
{ lib, config, pkgs, ... }:

{
  imports = [ ./iscsi-boot.nix ];
  fileSystems."/" = { device = "UUID=35d3ccb9-89d8-4f3a-a6da-1d94d4d94f8a"; fsType = "ext4"; };
  boot = {
    loader = {
      grub.enable = false;
      generic-extlinux-compatible.enable = true;
    };
    initrd = {
      kernelModules = [ "e1000" ];
      iscsi.initiatorName = "iqn.2015-09.com.example:3255a7223b2";
      iscsi.devices = [
        { host = "192.168.2.61"; lun = "iqn.2001-04.com.c2d-nix4"; }
      ];
    };
  };
}
# and then install like usual
nixos-install
# un-mount everything
umount /mnt/boot /mnt
# launch the system under qemu
/nix/store/c22c7vrjxpji16bbg24rs1rg6ngx3y38-qemu-x86-only-2.4.0/bin/qemu-system-x86_64 -enable-kvm -m 1024 -kernel boot/nixos/q50nnkhsmfbqmbn2imnflfiqhj1hp6x0-linux-3.18.21-bzImage -initrd boot/nixos/kcaqy563wwr5f7cxlscsp0j2qfhnz92z-initrd-initrd -append console=ttyS0 panic=-1 boot.shell_on_fail init=/nix/store/idpgwjsiggc5k33p2il9kr5s3np92wgp-nixos-system-nixos-16.03pre69426.2a574cb/init -no-reboot -net nic,vlan=0,model=e1000 -net user,vlan=0 -net dump,vlan=0 -serial stdio
{ config, lib, pkgs, ... }:

with lib;

let
  open-iscsi = pkgs.callPackage ./open-iscsi.nix {};
  openCommand = { host, lun, ... }: ''
    iscsistart -t ${lun} -a ${host} -i ${config.boot.initrd.iscsi.initiatorName} -g 0
  '';
in
{
  options = {
    boot.initrd.iscsi.initiatorName = mkOption {
      default = "";
      example = "iqn.2015-09.com.example:3255a7223b2";
      type = types.string;
      description = "the initiator name used when connecting";
    };
    boot.initrd.iscsi.devices = mkOption {
      default = [ ];
      type = types.listOf types.optionSet;
      options = {
        host = mkOption {
          example = "192.168.2.61";
          type = types.string;
          description = "the iscsi target";
        };
        lun = mkOption {
          example = "iqn.2015-01.com.example:san.img";
          type = types.string;
          description = "the LUN to connect";
        };
      };
    };
  };
  config = mkIf (config.boot.initrd.iscsi.devices != []) {
    boot.initrd.kernelModules = [ "iscsi_tcp" ];
    boot.initrd.availableKernelModules = [ "crc32c" ];
    boot.initrd.preLVMCommands = ''
      export PATH=$PATH:${open-iscsi.iscsistart}/bin/
      mkdir -pv /var/run/ /var/lock/
      ip link set ${cfg.netDev} up
      ip addr add ${cfg.ipAddress}/${toString cfg.prefixLength} dev ${cfg.netDev}
      ip route add via ${cfg.defaultGateway} dev ${cfg.netDev}
      sleep 20
    '' + concatMapStrings openCommand config.boot.initrd.iscsi.devices + ''
      ls -lR /dev/disk/
    '';
  };
}
{ stdenv, fetchurl }:
let
  pname = "open-iscsi-2.0-873";
in stdenv.mkDerivation {
  name = "${pname}";
  outputs = [ "out" "iscsistart" ];
  
  src = fetchurl {
    url = "http://www.open-iscsi.org/bits/${pname}.tar.gz";
    sha256 = "1nbwmj48xzy45h52917jbvyqpsfg9zm49nm8941mc5x4gpwz5nbx";
  };
  
  DESTDIR = "$(out)";
  
  preConfigure = ''
    sed -i 's|/usr/|/|' Makefile
  '';
  # TODO, its staticaly linked, but refers to glibc locale files, dependancies need a trim
  postInstall = ''
    mkdir -pv $iscsistart/bin/
    cp -v usr/iscsistart $iscsistart/bin/
  '';
  
  meta = {
    description = "A high performance, transport independent, multi-platform implementation of RFC3720";
    license = stdenv.lib.licenses.gpl2Plus;
    homepage = http://www.open-iscsi.org;
  };
}