summary refs log tree commit diff
path: root/nixos/modules/virtualisation
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/virtualisation')
-rw-r--r--nixos/modules/virtualisation/container-config.nix71
-rw-r--r--nixos/modules/virtualisation/containers.nix91
-rw-r--r--nixos/modules/virtualisation/docker-image.nix67
-rw-r--r--nixos/modules/virtualisation/docker.nix1
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix35
-rw-r--r--nixos/modules/virtualisation/nixos-container.pl90
-rw-r--r--nixos/modules/virtualisation/openvswitch.nix117
7 files changed, 343 insertions, 129 deletions
diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix
index b81f97f2b4e..a7e8953827a 100644
--- a/nixos/modules/virtualisation/container-config.nix
+++ b/nixos/modules/virtualisation/container-config.nix
@@ -18,76 +18,7 @@ with lib;
     # Shut up warnings about not having a boot loader.
     system.build.installBootLoader = "${pkgs.coreutils}/bin/true";
 
-    # Provide a root login prompt on /var/lib/root-login.socket that
-    # doesn't ask for a password. This socket can only be used by root
-    # on the host.
-    systemd.sockets.root-login =
-      { description = "Root Login Socket";
-        wantedBy = [ "sockets.target" ];
-        socketConfig =
-          { ListenStream = "/var/lib/root-login.socket";
-            SocketMode = "0600";
-            Accept = true;
-          };
-      };
-
-    systemd.services."root-login@" =
-      { description = "Root Login %i";
-        environment.TERM = "linux";
-        serviceConfig =
-          { Type = "simple";
-            StandardInput = "socket";
-            ExecStart = "${pkgs.socat}/bin/socat -t0 - \"exec:${pkgs.shadow}/bin/login -f root,pty,setsid,setpgid,stderr,ctty\"";
-            TimeoutStopSec = 1; # FIXME
-          };
-        restartIfChanged = false;
-      };
-
-    # Provide a daemon on /var/lib/run-command.socket that reads a
-    # command from stdin and executes it.
-    systemd.sockets.run-command =
-      { description = "Run Command Socket";
-        wantedBy = [ "sockets.target" ];
-        socketConfig =
-          { ListenStream = "/var/lib/run-command.socket";
-            SocketMode = "0600";  # only root can connect
-            Accept = true;
-          };
-      };
-
-    systemd.services."run-command@" =
-      { description = "Run Command %i";
-        environment.TERM = "linux";
-        serviceConfig =
-          { Type = "simple";
-            StandardInput = "socket";
-            TimeoutStopSec = 1; # FIXME
-          };
-        script =
-          ''
-            #! ${pkgs.stdenv.shell} -e
-            source /etc/bashrc
-            read c
-            eval "command=($c)"
-            exec "''${command[@]}"
-          '';
-        restartIfChanged = false;
-      };
-
-    systemd.services.container-startup-done =
-      { description = "Container Startup Notification";
-        wantedBy = [ "multi-user.target" ];
-        after = [ "multi-user.target" ];
-        script =
-          ''
-            if [ -p /var/lib/startup-done ]; then
-              echo done > /var/lib/startup-done
-            fi
-          '';
-        serviceConfig.Type = "oneshot";
-        serviceConfig.RemainAfterExit = true;
-        restartIfChanged = false;
-      };
+    systemd.services.systemd-remount-fs.enable = false;
 
   };
 
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 7f545a9d303..d62340f2c79 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -10,7 +10,7 @@ let
     isExecutable = true;
     src = ./nixos-container.pl;
     perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl";
-    inherit (pkgs) socat;
+    inherit (pkgs) utillinux;
   };
 
   # The container's init script, a small wrapper around the regular
@@ -32,7 +32,10 @@ let
         fi
       fi
 
-      exec "$1"
+      # Start the regular stage 1 script, passing the bind-mounted
+      # notification socket from the host to allow the container
+      # systemd to signal readiness to the host systemd.
+      NOTIFY_SOCKET=/var/lib/private/host-notify exec "$1"
     '';
 
   system = config.nixpkgs.system;
@@ -168,17 +171,18 @@ in
 
         preStart =
           ''
-            mkdir -p -m 0755 $root/var/lib
+            # Clean up existing machined registration and interfaces.
+            machinectl terminate "$INSTANCE" 2> /dev/null || true
 
-            # Create a named pipe to get a signal when the container
-            # has finished booting.
-            rm -f $root/var/lib/startup-done
-            mkfifo -m 0600 $root/var/lib/startup-done
+            if [ "$PRIVATE_NETWORK" = 1 ]; then
+              ip link del dev "ve-$INSTANCE" 2> /dev/null || true
+            fi
          '';
 
         script =
           ''
             mkdir -p -m 0755 "$root/etc" "$root/var/lib"
+            mkdir -p -m 0700 "$root/var/lib/private"
             if ! [ -e "$root/etc/os-release" ]; then
               touch "$root/etc/os-release"
             fi
@@ -205,12 +209,16 @@ in
               fi
             ''}
 
+            # Run systemd-nspawn without startup notification (we'll
+            # wait for the container systemd to signal readiness).
+            EXIT_ON_REBOOT=1 NOTIFY_SOCKET= \
             exec ${config.systemd.package}/bin/systemd-nspawn \
               --keep-unit \
               -M "$INSTANCE" -D "$root" $extraFlags \
               --bind-ro=/nix/store \
               --bind-ro=/nix/var/nix/db \
               --bind-ro=/nix/var/nix/daemon-socket \
+              --bind=/run/systemd/notify:/var/lib/private/host-notify \
               --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \
               --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \
               --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \
@@ -222,12 +230,6 @@ in
 
         postStart =
           ''
-            # This blocks until the container-startup-done service
-            # writes something to this pipe.  FIXME: it also hangs
-            # until the start timeout expires if systemd-nspawn exits.
-            read x < $root/var/lib/startup-done
-            rm -f $root/var/lib/startup-done
-
             if [ "$PRIVATE_NETWORK" = 1 ]; then
               ifaceHost=ve-$INSTANCE
               ip link set dev $ifaceHost up
@@ -242,23 +244,41 @@ in
 
         preStop =
           ''
-            machinectl poweroff "$INSTANCE"
+            machinectl poweroff "$INSTANCE" || true
           '';
 
         restartIfChanged = false;
         #reloadIfChanged = true; # FIXME
 
-        serviceConfig.ExecReload = pkgs.writeScript "reload-container"
-          ''
-            #! ${pkgs.stdenv.shell} -e
-            SYSTEM_PATH=/nix/var/nix/profiles/system
-            echo $SYSTEM_PATH/bin/switch-to-configuration test | \
-              ${pkgs.socat}/bin/socat unix:$root/var/lib/run-command.socket -
-          '';
+        serviceConfig = {
+          ExecReload = pkgs.writeScript "reload-container"
+            ''
+              #! ${pkgs.stdenv.shell} -e
+              ${nixos-container}/bin/nixos-container run "$INSTANCE" -- \
+                bash --login -c "/nix/var/nix/profiles/system/bin/switch-to-configuration test"
+            '';
 
-        serviceConfig.SyslogIdentifier = "container %i";
+          SyslogIdentifier = "container %i";
 
-        serviceConfig.EnvironmentFile = "-/etc/containers/%i.conf";
+          EnvironmentFile = "-/etc/containers/%i.conf";
+
+          Type = "notify";
+
+          NotifyAccess = "all";
+
+          # Note that on reboot, systemd-nspawn returns 10, so this
+          # unit will be restarted. On poweroff, it returns 0, so the
+          # unit won't be restarted.
+          Restart = "on-failure";
+
+          # Hack: we don't want to kill systemd-nspawn, since we call
+          # "machinectl poweroff" in preStop to shut down the
+          # container cleanly. But systemd requires sending a signal
+          # (at least if we want remaining processes to be killed
+          # after the timeout). So send an ignored signal.
+          KillMode = "mixed";
+          KillSignal = "WINCH";
+        };
       };
 
     # Generate a configuration file in /etc/containers for each
@@ -292,5 +312,30 @@ in
 
     environment.systemPackages = [ nixos-container ];
 
+    # Start containers at boot time.
+    systemd.services.all-containers =
+      { description = "All Containers";
+
+        wantedBy = [ "multi-user.target" ];
+
+        unitConfig.ConditionDirectoryNotEmpty = "/etc/containers";
+
+        serviceConfig.Type = "oneshot";
+
+        script =
+          ''
+            res=0
+            shopt -s nullglob
+            for i in /etc/containers/*.conf; do
+              AUTO_START=
+              source "$i"
+              if [ "$AUTO_START" = 1 ]; then
+                systemctl start "container@$(basename "$i" .conf).service" || res=1
+              fi
+            done
+            exit $res
+          ''; # */
+      };
+
   };
 }
diff --git a/nixos/modules/virtualisation/docker-image.nix b/nixos/modules/virtualisation/docker-image.nix
new file mode 100644
index 00000000000..13b861dc988
--- /dev/null
+++ b/nixos/modules/virtualisation/docker-image.nix
@@ -0,0 +1,67 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l;
+
+in {
+  # Create the tarball
+  system.build.dockerImage = import ../../lib/make-system-tarball.nix {
+    inherit (pkgs) stdenv perl xz pathsFromGraph;
+
+    contents = [];
+    extraArgs = "--owner=0";
+    storeContents = [
+      { object = config.system.build.toplevel + "/init";
+        symlink = "/bin/init";
+      }
+    ] ++ (pkgs2storeContents [ pkgs.stdenv ]);
+  };
+
+  boot.postBootCommands =
+    ''
+      # After booting, register the contents of the Nix store in the Nix
+      # database.
+      if [ -f /nix-path-registration ]; then
+        ${config.nix.package}/bin/nix-store --load-db < /nix-path-registration &&
+        rm /nix-path-registration
+      fi
+
+      # nixos-rebuild also requires a "system" profile and an
+      # /etc/NIXOS tag.
+      touch /etc/NIXOS
+      ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+
+      # Set virtualisation to docker
+      echo "docker" > /run/systemd/container 
+    '';
+
+
+  # docker image config
+  require = [
+    ../installer/cd-dvd/channel.nix
+    ../profiles/minimal.nix
+    ../profiles/clone-config.nix
+  ];
+
+  boot.isContainer = true;
+
+  # Iptables do not work in docker
+  networking.firewall.enable = false;
+
+  services.openssh.enable = true;
+
+  # Socket activated ssh presents problem in docker
+  services.openssh.startWhenNeeded = false;
+
+  # Allow the user to login as root without password
+  security.initialRootPassword = "";
+
+  # Some more help text.
+  services.mingetty.helpLine =
+    ''
+
+      Log in as "root" with an empty password.
+    '';
+}
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index a0aa6135326..1ce066cdc73 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -59,6 +59,7 @@ in
 
   config = mkIf cfg.enable (mkMerge [
     { environment.systemPackages = [ pkgs.docker ];
+      users.extraGroups.docker.gid = config.ids.gids.docker;
     }
     (mkIf cfg.socketActivation {
 
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index d7d700d8841..318460f4c2c 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -7,6 +7,7 @@ with lib;
 let
 
   cfg = config.virtualisation.libvirtd;
+  vswitch = config.virtualisation.vswitch;
   configFile = pkgs.writeText "libvirtd.conf" ''
     unix_sock_group = "libvirtd"
     unix_sock_rw_perms = "0770"
@@ -56,6 +57,20 @@ in
           '';
       };
 
+    virtualisation.libvirtd.onShutdown =
+      mkOption {
+        type = types.enum ["shutdown" "suspend" ];
+        default = "suspend";
+        description =
+          ''
+            When shutting down / restarting the host what method should
+            be used to gracefully halt the guests. Setting to "shutdown"
+            will cause an ACPI shutdown of each guest. "suspend" will
+            attempt to save the state of the guests ready to restore on boot.
+          '';
+      };
+
+
   };
 
 
@@ -73,12 +88,17 @@ in
       { description = "Libvirt Virtual Machine Management Daemon";
 
         wantedBy = [ "multi-user.target" ];
-        after = [ "systemd-udev-settle.service" ];
+        after = [ "systemd-udev-settle.service" ]
+                ++ optional vswitch.enable "vswitchd.service";
 
-        path =
-          [ pkgs.bridge_utils pkgs.dmidecode pkgs.dnsmasq
+        path = [ 
+            pkgs.bridge_utils 
+            pkgs.dmidecode 
+            pkgs.dnsmasq
             pkgs.ebtables
-          ] ++ optional cfg.enableKVM pkgs.qemu_kvm;
+          ] 
+          ++ optional cfg.enableKVM pkgs.qemu_kvm
+          ++ optional vswitch.enable vswitch.package;
 
         preStart =
           ''
@@ -152,7 +172,12 @@ in
             ${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests start || true
           '';
 
-        postStop = "${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests stop";
+        postStop = 
+            ''
+            export PATH=${pkgs.gettext}/bin:$PATH
+            export ON_SHUTDOWN=${cfg.onShutdown}
+            ${pkgs.libvirt}/etc/rc.d/init.d/libvirt-guests stop
+            '';
 
         serviceConfig.Type = "oneshot";
         serviceConfig.RemainAfterExit = true;
diff --git a/nixos/modules/virtualisation/nixos-container.pl b/nixos/modules/virtualisation/nixos-container.pl
index c6a5ecde9e3..7403a42f0f1 100644
--- a/nixos/modules/virtualisation/nixos-container.pl
+++ b/nixos/modules/virtualisation/nixos-container.pl
@@ -7,7 +7,7 @@ use File::Slurp;
 use Fcntl ':flock';
 use Getopt::Long qw(:config gnu_getopt);
 
-my $socat = '@socat@/bin/socat';
+my $nsenter = "@utillinux@/bin/nsenter";
 
 # Ensure a consistent umask.
 umask 0022;
@@ -17,25 +17,30 @@ umask 0022;
 sub showHelp {
     print <<EOF;
 Usage: nixos-container list
-       nixos-container create <container-name> [--config <string>] [--ensure-unique-name]
+       nixos-container create <container-name> [--system-path <path>] [--config <string>] [--ensure-unique-name] [--auto-start]
        nixos-container destroy <container-name>
        nixos-container start <container-name>
        nixos-container stop <container-name>
+       nixos-container status <container-name>
        nixos-container login <container-name>
        nixos-container root-login <container-name>
        nixos-container run <container-name> -- args...
-       nixos-container set-root-password <container-name> <password>
        nixos-container show-ip <container-name>
+       nixos-container show-host-key <container-name>
 EOF
     exit 0;
 }
 
+my $systemPath;
 my $ensureUniqueName = 0;
+my $autoStart = 0;
 my $extraConfig;
 
 GetOptions(
     "help" => sub { showHelp() },
     "ensure-unique-name" => \$ensureUniqueName,
+    "auto-start" => \$autoStart,
+    "system-path=s" => \$systemPath,
     "config=s" => \$extraConfig
     ) or exit 1;
 
@@ -122,17 +127,13 @@ if ($action eq "create") {
     push @conf, "PRIVATE_NETWORK=1\n";
     push @conf, "HOST_ADDRESS=$hostAddress\n";
     push @conf, "LOCAL_ADDRESS=$localAddress\n";
+    push @conf, "AUTO_START=$autoStart\n";
     write_file($confFile, \@conf);
 
     close($lock);
 
     print STDERR "host IP is $hostAddress, container IP is $localAddress\n";
 
-    mkpath("$root/etc/nixos", 0, 0755);
-
-    my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
-    writeNixOSConfig $nixosConfigFile;
-
     # The per-container directory is restricted to prevent users on
     # the host from messing with guest users who happen to have the
     # same uid.
@@ -141,10 +142,21 @@ if ($action eq "create") {
     $profileDir = "$profileDir/$containerName";
     mkpath($profileDir, 0, 0755);
 
-    system("nix-env", "-p", "$profileDir/system",
-           "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>",
-           "--set", "-A", "system") == 0
-        or die "$0: failed to build initial container configuration\n";
+    # Build/set the initial configuration.
+    if (defined $systemPath) {
+        system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0
+            or die "$0: failed to set initial container configuration\n";
+    } else {
+        mkpath("$root/etc/nixos", 0, 0755);
+
+        my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
+        writeNixOSConfig $nixosConfigFile;
+
+        system("nix-env", "-p", "$profileDir/system",
+               "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>",
+               "--set", "-A", "system") == 0
+            or die "$0: failed to build initial container configuration\n";
+    }
 
     print "$containerName\n" if $ensureUniqueName;
     exit 0;
@@ -155,7 +167,11 @@ my $profileDir = "/nix/var/nix/profiles/per-container/$containerName";
 my $gcRootsDir = "/nix/var/nix/gcroots/per-container/$containerName";
 my $confFile = "/etc/containers/$containerName.conf";
 if (!-e $confFile) {
-    exit 0 if $action eq "destroy";
+    if ($action eq "destroy") {
+        exit 0;
+    } elsif ($action eq "status") {
+        print "gone\n";
+    }
     die "$0: container ‘$containerName’ does not exist\n" ;
 }
 
@@ -169,6 +185,22 @@ sub stopContainer {
         or die "$0: failed to stop container\n";
 }
 
+# Return the PID of the init process of the container.
+sub getLeader {
+    my $s = `machinectl show "$containerName" -p Leader`;
+    chomp $s;
+    $s =~ /^Leader=(\d+)$/ or die "unable to get container's main PID\n";
+    return int($1);
+}
+
+# Run a command in the container.
+sub runInContainer {
+    my @args = @_;
+    my $leader = getLeader;
+    exec($nsenter, "-t", $leader, "-m", "-u", "-i", "-n", "-p", "--", @args);
+    die "cannot run ‘nsenter’: $!\n";
+}
+
 if ($action eq "destroy") {
     die "$0: cannot destroy declarative container (remove it from your configuration.nix instead)\n"
         unless POSIX::access($confFile, &POSIX::W_OK);
@@ -190,6 +222,10 @@ elsif ($action eq "stop") {
     stopContainer;
 }
 
+elsif ($action eq "status") {
+    print isContainerRunning() ? "up" : "down", "\n";
+}
+
 elsif ($action eq "update") {
     my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
 
@@ -214,28 +250,14 @@ elsif ($action eq "login") {
 }
 
 elsif ($action eq "root-login") {
-    exec($socat, "unix:$root/var/lib/root-login.socket", "-,echo=0,raw");
+    runInContainer("su", "root", "-l");
 }
 
 elsif ($action eq "run") {
     shift @ARGV; shift @ARGV;
-    my $pid = open(SOCAT, "|-", $socat, "-t0", "-", "unix:$root/var/lib/run-command.socket") or die "$0: cannot start $socat: $!\n";
-    print SOCAT join(' ', map { "'$_'" } @ARGV), "\n";
-    flush SOCAT;
-    waitpid($pid, 0);
-    close(SOCAT);
-}
-
-elsif ($action eq "set-root-password") {
-    # FIXME: don't get password from the command line.
-    my $password = $ARGV[2] or die "$0: no password given\n";
-    my $pid = open(SOCAT, "|-", $socat, "-t0", "-", "unix:$root/var/lib/run-command.socket") or die "$0: cannot start $socat: $!\n";
-    print SOCAT "passwd\n";
-    print SOCAT "$password\n";
-    print SOCAT "$password\n";
-    flush SOCAT;
-    waitpid($pid, 0);
-    close(SOCAT);
+    # Escape command.
+    my $s = join(' ', map { s/'/'\\''/g; "'$_'" } @ARGV);
+    runInContainer("su", "root", "-l", "-c", "exec " . $s);
 }
 
 elsif ($action eq "show-ip") {
@@ -244,6 +266,12 @@ elsif ($action eq "show-ip") {
     print "$1\n";
 }
 
+elsif ($action eq "show-host-key") {
+    my $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub";
+    exit 1 if ! -f $fn;
+    print read_file($fn);
+}
+
 else {
     die "$0: unknown action ‘$action’\n";
 }
diff --git a/nixos/modules/virtualisation/openvswitch.nix b/nixos/modules/virtualisation/openvswitch.nix
new file mode 100644
index 00000000000..c1579d94657
--- /dev/null
+++ b/nixos/modules/virtualisation/openvswitch.nix
@@ -0,0 +1,117 @@
+# Systemd services for openvswitch
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.virtualisation.vswitch;
+
+in
+
+{
+
+  options = {
+
+    virtualisation.vswitch.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description =
+        ''
+        Enable Open vSwitch. A configuration 
+        daemon (ovs-server) will be started.
+        '';
+    };
+
+
+    virtualisation.vswitch.package = mkOption {
+      type = types.package;
+      default = pkgs.openvswitch;
+      description =
+        ''
+        Open vSwitch package to use.
+        '';
+    };
+
+  };
+
+  config = mkIf cfg.enable (let 
+
+    # Where the communication sockets live
+    runDir = "/var/run/openvswitch";
+
+    # Where the config database live (can't be in nix-store)
+    stateDir = "/var/db/openvswitch";
+
+    # The path to the an initialized version of the database 
+    db = pkgs.stdenv.mkDerivation {
+      name = "vswitch.db";
+      unpackPhase = "true";
+      buildPhase = "true";
+      buildInputs = with pkgs; [
+        cfg.package
+      ];
+      installPhase = 
+        ''
+        ensureDir $out/
+        '';
+    };
+
+  in {
+
+    environment.systemPackages = [ cfg.package ]; 
+
+    boot.kernelModules = [ "tun" "openvswitch" ];
+
+    boot.extraModulePackages = [ cfg.package ];
+
+    systemd.services.ovsdb = {
+      description = "Open_vSwitch Database Server";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "systemd-udev-settle.service" ];
+      wants = [ "vswitchd.service" ];
+      path = [ cfg.package ];
+      restartTriggers = [ db cfg.package ];
+      # Create the config database
+      preStart = 
+        ''
+        mkdir -p ${runDir}
+        mkdir -p /var/db/openvswitch
+        chmod +w /var/db/openvswitch
+        if [[ ! -e /var/db/openvswitch/conf.db ]]; then
+          ${cfg.package}/bin/ovsdb-tool create \
+            "/var/db/openvswitch/conf.db" \
+            "${cfg.package}/share/openvswitch/vswitch.ovsschema"
+        fi
+        chmod -R +w /var/db/openvswitch
+        '';
+      serviceConfig.ExecStart = 
+        ''
+        ${cfg.package}/bin/ovsdb-server \
+          --remote=punix:${runDir}/db.sock \
+          --private-key=db:Open_vSwitch,SSL,private_key \
+          --certificate=db:Open_vSwitch,SSL,certificate \
+          --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
+          --unixctl=ovsdb.ctl.sock \
+          /var/db/openvswitch/conf.db
+        '';       
+      serviceConfig.Restart = "always";
+      serviceConfig.RestartSec = 3;
+      postStart =
+        ''
+        ${cfg.package}/bin/ovs-vsctl --timeout 3 --retry --no-wait init
+        '';
+
+    };
+
+    systemd.services.vswitchd = {
+      description = "Open_vSwitch Daemon";
+      bindsTo = [ "ovsdb.service" ];
+      after = [ "ovsdb.service" ];
+      path = [ cfg.package ];
+      serviceConfig.ExecStart = ''${cfg.package}/bin/ovs-vswitchd'';
+    };
+
+  });
+
+}