~ehmry/sigil

a5e42250148a9dc1ac72be710910ad0d1609a5aa — Emery Hemingway 4 years ago b83a8bb nixos-host
WiP! nixos-host
3 files changed, 175 insertions(+), 41 deletions(-)

M nixos-modules/nixos-host.nix
A nixos-modules/root-config.dhall
M tests/nixos-host.nix
M nixos-modules/nixos-host.nix => nixos-modules/nixos-host.nix +43 -14
@@ 6,22 6,29 @@

{
  options.genodeGuests = with lib;
    with lib.types;
    let
      genodeOpts = { ... }: {
        options = {

          name = mkOption {
            example = "webserver";
            type = types.str;
            type = str;
            description = "Name of the Genode subsystem.";
          };

          config = mkOption {
            type = types.str;
            default = "<config/>";
            type = oneOf [ str path ];
            example = ''
              let Genode = env:DHALL_GENODE

              in Genode.Init::{=}
            '';
            description = ''
              Configuration of the Genode subsystem.
              Must be rendered in the Genode XML format.
              Configuration of the Genode subsystem in Dhall.
              The type of the expression must be <literal>Genode.Init.Type<literal>,
              where the <literal>Genode<literal> is library available at
              <literal>env:DHALL_GENODE<literal>.
            '';
          };



@@ 39,15 46,24 @@
            '';
          };

          nics = mkOption {
            type = with types; listOf str;
            default = [ ];
            example = [ "tap0" "tap1" ];
            description = ''
              TAP interfaces to pass from NixOS into the Genode guest.
            '';
          };

        };
      };

    in mkOption {
      type = with lib.types; loaOf (submodule genodeOpts);
      type = loaOf (submodule genodeOpts);
      default = { };
      example = {
        foobar = {
          config = "<empty/>";
          config = "…";
          rom = pkgs: { };
        };
      };


@@ 64,25 80,38 @@
      inherit (crossPkgs.genodePackages) base-linux;
      toService = name: cfg: {
        description = "Genode subsystem";
        after = [ "network.target" ];
        wantedBy = [ "multi-user.target" ];

        preStart = let
          config' =
            self.lib.${crossSystem}.runDhallCommand "${name}.config" { } ''
              set -e
              exec ${self.apps.${crossSystem}.render-init.program} > $out << EOF
              ${./root-config.dhall}
                { guest = ${cfg.config}
                , nics = [ "${builtins.concatStringsSep ''", "'' cfg.nics}" ]
                }
              EOF
            '';
          rom' = with crossPkgs.genodePackages;
            {
              core = "${base-linux}/bin/core-linux";
              init = "${init}/bin/init";
              "ld.lib.so" = "${base-linux}/bin/ld.lib.so";
              timer = "${base-linux}/bin/linux_timer_drv";
              config = builtins.toFile "${name}.config.xml" cfg.config;
              init = "${init}/init";
              "ld.lib.so" = "${base-linux}/lib/ld.lib.so";
              timer_drv = "${base-linux}/timer_drv";
              config = config';
              linux_nic_drv = "${
                  crossPkgs.genodeSources.depot "linux_nic_drv"
                }/linux_nic_drv";
            } // (cfg.rom crossPkgs);
        in builtins.concatStringsSep "\n"
        (lib.mapAttrsToList (name: value: "ln -s ${value} ${name}") rom');
        (lib.mapAttrsToList (name: value: "ln -sv ${value} ${name}") rom');

        serviceConfig = {
          DynamicUser = true;
          RuntimeDirectory = "genode/" + name;
          WorkingDirectory = "/run/genode/" + name;
          ExecStart = "${base-linux}/bin/core-linux";
          ExecStart = "${base-linux}/core-linux";
        };
      };
    in lib.mapAttrs toService config.genodeGuests;

A nixos-modules/root-config.dhall => nixos-modules/root-config.dhall +70 -0
@@ 0,0 1,70 @@
let Genode = env:DHALL_GENODE

let Prelude = Genode.Prelude

let Init = Genode.Init

let Child = Init.Child

let nicChild
    : Text → Init.Children.Entry
    =   λ(tapDevice : Text)
      → { mapKey = tapDevice
        , mapValue =
            Child.flat
              Child.Attributes::{
              , binary = "linux_nic_drv"
              , config = Init.Config::{ attributes = toMap { tap = tapDevice } }
              , ld = False
              , resources = Init.Resources::{
                , caps = 256
                , ram = Genode.units.MiB 4
                }
              , provides = [ "Nic" ]
              }
        }

let nicChildren = Prelude.List.map Text Init.Children.Entry nicChild

let init =
        λ(params : { guest : Init.Type, nics : List Text })
      → Init::{
        , routes = [ Init.ServiceRoute.child "Timer" "timer_drv" ]
        , children =
              nicChildren params.nics
            # toMap
                { timer_drv =
                    Child.flat
                      Child.Attributes::{
                      , binary = "timer_drv"
                      , provides = [ "Timer" ]
                      }
                , init =
                    Init.toChild
                      params.guest
                      Init.Attributes::{
                      , exitPropagate = True
                      , routes =
                          Prelude.List.map
                            Text
                            Init.ServiceRoute.Type
                            (   λ(tapDevice : Text)
                              → { service =
                                    { name = "Nic"
                                    , label = Init.LabelSelector.last tapDevice
                                    }
                                , route =
                                    Init.Route.Type.Child
                                      { name = tapDevice
                                      , label = None Text
                                      , diag = None Bool
                                      }
                                }
                            )
                            params.nics
                      }
                }
        , verbose = True
        }

in  init

M tests/nixos-host.nix => tests/nixos-host.nix +62 -27
@@ 6,45 6,80 @@ import "${self.inputs.nixpkgs}/nixos/tests/make-test-python.nix"
  # meta.maintainers = [ pkgs.lib.maintainers.ehmry ];

  machine = {

    imports = [
      self.nixosModules.genodeGuests
      "${self.inputs.nixpkgs}/nixos/modules/profiles/minimal.nix"
    ];
    genodeGuests.signal-test = {

    networking.bridges.br0.interfaces = [ "eth0" "tap0" ];

    networking.interfaces.eth0.useDHCP = false;

    networking.interfaces.tap0 = {
      useDHCP = false;
      virtual = true;
      virtualType = "tap";
    };

    genodeGuests.tap-test = {
      config = ''
        <config>
        	<parent-provides>
        		<service name="ROM"/>
        		<service name="CPU"/>
        		<service name="RM"/>
        		<service name="PD"/>
        		<service name="LOG"/>
        	</parent-provides>
        	<default-route>
        		<any-service> <parent/> <any-child/> </any-service>
        	</default-route>
        	<default caps="100"/>
        	<start name="timer" caps="96">
        		<resource name="RAM" quantum="1M"/>
        		<provides><service name="Timer"/></provides>
        	</start>
        	<start name="test-signal" caps="500">
        		<resource name="RAM" quantum="10M"/>
        	</start>
        </config>
        let Genode = env:DHALL_GENODE

        let Prelude = Genode.Prelude

        let XML = Prelude.XML

        let Init = Genode.Init

        in  Init::{
            , children = toMap
                { lwip_fs =
                    Init.Child.flat
                      Init.Child.Attributes::{
                      , binary = "vfs"
                      , config = Init.Config::{
                        , content =
                          [ XML.element
                              { name = "vfs"
                              , attributes = XML.emptyAttributes
                              , content =
                                [ XML.leaf
                                    { name = "lwip"
                                    , attributes = toMap { dhcp = "yes" }
                                    }
                                ]
                              }
                          ]
                        }
                      , provides = [ "File_system" ]
                      , resources = Init.Resources::{
                        , caps = 256
                        , ram = Genode.units.MiB 8
                        }
                      , routes =
                        [ Init.ServiceRoute.parentLabel "Nic" (None Text) (Some "tap0")
                        , Init.ServiceRoute.parent "Timer"
                        ]
                      }
                }
            , verbose = True
            }
      '';
      nics = [ "tap0" ];
      rom = pkgs: {
        "test-signal" =
          "${pkgs.genodeSources.depot "test-signal"}/bin/test-signal";
        "vfs" = "${pkgs.genodeSources.depot "vfs"}/vfs";
        "libvfs.so" = "${(pkgs.genodeSources.depot "vfs").lib}/lib/libvfs.so";
        "libvfs_lwip.so" =
          "${pkgs.genodeSources.depot "vfs_lwip"}/lib/libvfs_lwip.so";
      };
    };

  };

  testScript = ''
    start_all()
    machine.wait_for_unit("genode")
    machine.wait_for_unit("tap-test")
    machine.wait_for_open_port("1965")
  '';
}) {
  system = localSystem;
}
}) { system = localSystem; }