about summary refs log tree commit diff
path: root/nixpkgs/pkgs/tools/virtualization
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/tools/virtualization')
-rw-r--r--nixpkgs/pkgs/tools/virtualization/alpine-make-vm-image/default.nix36
-rw-r--r--nixpkgs/pkgs/tools/virtualization/amazon-ecs-cli/default.nix37
-rw-r--r--nixpkgs/pkgs/tools/virtualization/awless/default.nix23
-rw-r--r--nixpkgs/pkgs/tools/virtualization/aws/default.nix29
-rw-r--r--nixpkgs/pkgs/tools/virtualization/awsebcli/default.nix97
-rw-r--r--nixpkgs/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch139
-rw-r--r--nixpkgs/pkgs/tools/virtualization/cloud-init/default.nix111
-rw-r--r--nixpkgs/pkgs/tools/virtualization/cloudmonkey/default.nix25
-rw-r--r--nixpkgs/pkgs/tools/virtualization/cri-tools/default.nix47
-rw-r--r--nixpkgs/pkgs/tools/virtualization/distrobuilder/default.nix57
-rw-r--r--nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/default.nix44
-rw-r--r--nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/writable.patch23
-rw-r--r--nixpkgs/pkgs/tools/virtualization/ec2-api-tools/default.nix35
-rw-r--r--nixpkgs/pkgs/tools/virtualization/ec2-utils/default.nix47
-rw-r--r--nixpkgs/pkgs/tools/virtualization/ec2instanceconnectcli/default.nix25
-rw-r--r--nixpkgs/pkgs/tools/virtualization/euca2ools/default.nix23
-rw-r--r--nixpkgs/pkgs/tools/virtualization/google-compute-engine-oslogin/default.nix56
-rw-r--r--nixpkgs/pkgs/tools/virtualization/google-compute-engine/default.nix105
-rw-r--r--nixpkgs/pkgs/tools/virtualization/govc/default.nix24
-rw-r--r--nixpkgs/pkgs/tools/virtualization/linode-cli/default.nix69
-rw-r--r--nixpkgs/pkgs/tools/virtualization/marathonctl/default.nix24
-rw-r--r--nixpkgs/pkgs/tools/virtualization/marathonctl/deps.nix12
-rw-r--r--nixpkgs/pkgs/tools/virtualization/mininet/default.nix49
-rw-r--r--nixpkgs/pkgs/tools/virtualization/nixos-container/default.nix17
-rw-r--r--nixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container-completion.sh33
-rwxr-xr-xnixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container.pl476
-rw-r--r--nixpkgs/pkgs/tools/virtualization/nixos-shell/default.nix30
-rw-r--r--nixpkgs/pkgs/tools/virtualization/ovftool/default.nix230
-rw-r--r--nixpkgs/pkgs/tools/virtualization/reg/default.nix26
-rw-r--r--nixpkgs/pkgs/tools/virtualization/rootlesskit/default.nix22
-rw-r--r--nixpkgs/pkgs/tools/virtualization/shipyard/default.nix29
-rw-r--r--nixpkgs/pkgs/tools/virtualization/udocker/default.nix49
-rw-r--r--nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile5
-rw-r--r--nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile.lock75
-rw-r--r--nixpkgs/pkgs/tools/virtualization/vpsfree-client/default.nix17
-rw-r--r--nixpkgs/pkgs/tools/virtualization/vpsfree-client/gemset.nix316
-rw-r--r--nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/default.nix75
-rw-r--r--nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/ip-address.patch16
-rw-r--r--nixpkgs/pkgs/tools/virtualization/xva-img/default.nix24
39 files changed, 2577 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/tools/virtualization/alpine-make-vm-image/default.nix b/nixpkgs/pkgs/tools/virtualization/alpine-make-vm-image/default.nix
new file mode 100644
index 000000000000..239a00a665d8
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/alpine-make-vm-image/default.nix
@@ -0,0 +1,36 @@
+{ stdenv, lib, fetchFromGitHub, makeWrapper
+, apk-tools, coreutils, e2fsprogs, findutils, gnugrep, gnused, kmod, qemu-utils
+, util-linux
+}:
+
+stdenv.mkDerivation rec {
+  pname = "alpine-make-vm-image";
+  version = "0.7.0";
+
+  src = fetchFromGitHub {
+    owner = "alpinelinux";
+    repo = "alpine-make-vm-image";
+    rev = "v${version}";
+    sha256 = "0cjcwq957nsml06kdnnvgzki84agjfvqw3mpyiix4i4q5by91lcl";
+  };
+
+  nativeBuildInputs = [ makeWrapper ];
+
+  dontBuild = true;
+  makeFlags = [ "PREFIX=$(out)" ];
+
+  postInstall = ''
+    wrapProgram $out/bin/alpine-make-vm-image --set PATH ${lib.makeBinPath [
+      apk-tools coreutils e2fsprogs findutils gnugrep gnused kmod qemu-utils
+      util-linux
+    ]}
+  '';
+
+  meta = with lib; {
+    homepage = "https://github.com/alpinelinux/alpine-make-vm-image";
+    description = "Make customized Alpine Linux disk image for virtual machines";
+    maintainers = with maintainers; [ qyliss ];
+    license = licenses.mit;
+    platforms = platforms.unix;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/amazon-ecs-cli/default.nix b/nixpkgs/pkgs/tools/virtualization/amazon-ecs-cli/default.nix
new file mode 100644
index 000000000000..012546160e09
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/amazon-ecs-cli/default.nix
@@ -0,0 +1,37 @@
+{ lib, stdenv, fetchurl}:
+
+stdenv.mkDerivation rec {
+  pname = "amazon-ecs-cli";
+  version = "1.21.0";
+
+  src =
+    if stdenv.hostPlatform.system == "x86_64-linux" then
+      fetchurl {
+        url = "https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-linux-amd64-v${version}";
+        sha256 = "sEHwhirU2EYwtBRegiIvN4yr7VKtmy7e6xx5gZOkuY0=";
+      }
+    else if stdenv.hostPlatform.system == "x86_64-darwin" then
+      fetchurl {
+        url = "https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-darwin-amd64-v${version}";
+        sha256 = "1viala49sifpcmgn3jw24h5bkrlm4ffadjiqagbxj3lr0r78i9nm";
+      }
+    else throw "Architecture not supported";
+
+  dontUnpack = true;
+
+  installPhase =
+    ''
+      mkdir -p $out/bin
+      cp $src $out/bin/ecs-cli
+      chmod +x $out/bin/ecs-cli
+    '';  # */
+
+  meta = with lib; {
+    homepage = "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_CLI.html";
+    description = "The Amazon ECS command line interface";
+    longDescription = "The Amazon Elastic Container Service (Amazon ECS) command line interface (CLI) provides high-level commands to simplify creating, updating, and monitoring clusters and tasks from a local development environment.";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ Scriptkiddi ];
+    platforms = [ "x86_64-linux" "x86_64-darwin" ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/awless/default.nix b/nixpkgs/pkgs/tools/virtualization/awless/default.nix
new file mode 100644
index 000000000000..061dd486e0d8
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/awless/default.nix
@@ -0,0 +1,23 @@
+{ lib, buildGoPackage, fetchFromGitHub }:
+
+buildGoPackage rec {
+  pname = "awless";
+  version = "0.1.11";
+
+  goPackagePath = "github.com/wallix/awless";
+
+  src = fetchFromGitHub {
+    owner  = "wallix";
+    repo   = "awless";
+    rev    = "v${version}";
+    sha256 = "187i21yrm10r3f5naj3jl0rmydr5dkhmdhxs90hhf8hjp59a89kg";
+  };
+
+  meta = with lib; {
+    homepage = "https://github.com/wallix/awless/";
+    description = "A Mighty CLI for AWS";
+    platforms = with platforms; linux ++ darwin;
+    license = licenses.asl20;
+    maintainers = with maintainers; [ pradeepchhetri swdunlop ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/aws/default.nix b/nixpkgs/pkgs/tools/virtualization/aws/default.nix
new file mode 100644
index 000000000000..d09e001ec6eb
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/aws/default.nix
@@ -0,0 +1,29 @@
+{ lib, stdenv, fetchurl, perl, curl }:
+
+stdenv.mkDerivation {
+  pname = "aws";
+  version = "2019.06.18";
+
+  src = fetchurl {
+    url = "https://raw.github.com/timkay/aws/ac68eb5191c52f069b9aa0c9a99808f8a4430833/aws";
+    sha256 = "02bym9wicqpdr7mdim13zw5ssh97xfswzab9q29rsbg7058ddbil";
+  };
+
+  buildInputs = [ perl ];
+
+  dontUnpack = true;
+
+  installPhase =
+    ''
+      mkdir -p $out/bin
+      sed 's|\[curl|[${curl.bin}/bin/curl|g' $src > $out/bin/aws
+      chmod +x $out/bin/aws
+    '';
+
+  meta = {
+    homepage = "https://www.timkay.com/aws/";
+    description = "Command-line utility for working with Amazon EC2, S3, SQS, ELB, IAM and SDB";
+    license = lib.licenses.gpl3Plus;
+    platforms = lib.platforms.unix;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/awsebcli/default.nix b/nixpkgs/pkgs/tools/virtualization/awsebcli/default.nix
new file mode 100644
index 000000000000..eaaf7046fff9
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/awsebcli/default.nix
@@ -0,0 +1,97 @@
+{ lib, python3, glibcLocales }:
+let
+
+  localPython = python3.override {
+    packageOverrides = self: super: {
+      cement = super.cement.overridePythonAttrs (oldAttrs: rec {
+        version = "2.8.2";
+        src = oldAttrs.src.override {
+          inherit version;
+          sha256 = "1li2whjzfhbpg6fjb6r1r92fb3967p1xv6hqs3j787865h2ysrc7";
+        };
+      });
+
+      colorama = super.colorama.overridePythonAttrs (oldAttrs: rec {
+        version = "0.3.7";
+        src = oldAttrs.src.override {
+          inherit version;
+          sha256 = "0avqkn6362v7k2kg3afb35g4sfdvixjgy890clip4q174p9whhz0";
+        };
+      });
+
+      pathspec = super.pathspec.overridePythonAttrs (oldAttrs: rec {
+        name = "${oldAttrs.pname}-${version}";
+        version = "0.5.5";
+        src = oldAttrs.src.override {
+          inherit version;
+          sha256 = "72c495d1bbe76674219e307f6d1c6062f2e1b0b483a5e4886435127d0df3d0d3";
+        };
+      });
+
+      requests = super.requests.overridePythonAttrs (oldAttrs: rec {
+        version = "2.9.1";
+        src = oldAttrs.src.override {
+          inherit version;
+          sha256 = "0zsqrzlybf25xscgi7ja4s48y2abf9wvjkn47wh984qgs1fq2xy5";
+        };
+      });
+
+      semantic-version = super.semantic-version.overridePythonAttrs (oldAttrs: rec {
+        version = "2.5.0";
+        src = oldAttrs.src.override {
+          inherit version;
+          sha256 = "0p5n3d6blgkncxdz00yxqav0cis87fisdkirjm0ljjh7rdfx7aiv";
+        };
+      });
+
+      tabulate = super.tabulate.overridePythonAttrs (oldAttrs: rec {
+        version = "0.7.5";
+        src = oldAttrs.src.override {
+          inherit version;
+          sha256 = "03l1r7ddd1a0j2snv1yd0hlnghjad3fg1an1jr8936ksv75slwch";
+        };
+      });
+    };
+  };
+in with localPython.pkgs; buildPythonApplication rec {
+  pname = "awsebcli";
+  version = "3.12.4";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "128dgxyz2bgl3r4jdkbmjs280004bm0dwzln7p6ly3yjs2x37jl6";
+  };
+
+  buildInputs = [
+    glibcLocales
+  ];
+
+  LC_ALL = "en_US.UTF-8";
+
+  checkInputs = [
+    pytest mock nose pathspec colorama requests docutils
+  ];
+
+  doCheck = false;
+
+  propagatedBuildInputs = [
+    # FIXME: Add optional docker dependency, which requires requests >= 2.14.2.
+    # Otherwise, awsebcli will try to install it using pip when using some
+    # commands (like "eb local run").
+    blessed botocore cement colorama dockerpty docopt pathspec pyyaml
+    requests semantic-version setuptools tabulate termcolor websocket-client
+  ];
+
+  postInstall = ''
+    mkdir -p $out/share/bash-completion/completions
+    mv $out/bin/eb_completion.bash $out/share/bash-completion/completions/
+  '';
+
+  meta = with lib; {
+    homepage = "https://aws.amazon.com/elasticbeanstalk/";
+    description = "A command line interface for Elastic Beanstalk";
+    maintainers = with maintainers; [ eqyiel ];
+    license = licenses.asl20;
+    broken = true;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch b/nixpkgs/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch
new file mode 100644
index 000000000000..997d28aaecbf
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch
@@ -0,0 +1,139 @@
+From 269cc4c9558549f340ec186d9246654564b2f633 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
+Date: Tue, 18 Aug 2020 10:22:36 +0100
+Subject: [PATCH] add nixos support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
+---
+ cloudinit/distros/__init__.py |   1 +
+ cloudinit/distros/nixos.py    | 103 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 104 insertions(+)
+ create mode 100644 cloudinit/distros/nixos.py
+
+diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
+index 2537608f..c533b585 100755
+--- a/cloudinit/distros/__init__.py
++++ b/cloudinit/distros/__init__.py
+@@ -47,6 +47,7 @@ OSFAMILIES = {
+     'gentoo': ['gentoo'],
+     'redhat': ['amazon', 'centos', 'fedora', 'rhel'],
+     'suse': ['opensuse', 'sles'],
++    'nixos': ['nixos'],
+ }
+ 
+ LOG = logging.getLogger(__name__)
+diff --git a/cloudinit/distros/nixos.py b/cloudinit/distros/nixos.py
+new file mode 100644
+index 00000000..d53d2a61
+--- /dev/null
++++ b/cloudinit/distros/nixos.py
+@@ -0,0 +1,103 @@
++# vi: ts=4 expandtab
++#
++#    Copyright (C) 2012 Canonical Ltd.
++#    Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
++#    Copyright (C) 2012 Yahoo! Inc.
++#
++#    Author: Scott Moser <scott.moser@canonical.com>
++#    Author: Juerg Haefliger <juerg.haefliger@hp.com>
++#    Author: Joshua Harlow <harlowja@yahoo-inc.com>
++#
++#    This program is free software: you can redistribute it and/or modify
++#    it under the terms of the GNU General Public License version 3, as
++#    published by the Free Software Foundation.
++#
++#    This program is distributed in the hope that it will be useful,
++#    but WITHOUT ANY WARRANTY; without even the implied warranty of
++#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++#    GNU General Public License for more details.
++#
++#    You should have received a copy of the GNU General Public License
++#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++import os
++
++from cloudinit import distros
++from cloudinit import helpers
++from cloudinit import log as logging
++from cloudinit import util
++from cloudinit import atomic_helper
++
++from cloudinit.distros.parsers.hostname import HostnameConf
++
++LOG = logging.getLogger(__name__)
++
++class Distro(distros.Distro):
++
++    def __init__(self, name, cfg, paths):
++        distros.Distro.__init__(self, name, cfg, paths)
++        # This will be used to restrict certain
++        # calls from repeatly happening (when they
++        # should only happen say once per instance...)
++        self._runner = helpers.Runners(paths)
++        self.usr_lib_exec = os.path.join(os.path.dirname(__file__),
++                                         "../../../../../libexec")
++        self.osfamily = 'nixos'
++
++    def _select_hostname(self, hostname, fqdn):
++        # Prefer the short hostname over the long
++        # fully qualified domain name
++        if not hostname:
++            return fqdn
++        return hostname
++
++    def _write_hostname(self, your_hostname, out_fn):
++        conf = None
++        try:
++            # Try to update the previous one
++            # so lets see if we can read it first.
++            conf = self._read_hostname_conf(out_fn)
++        except IOError:
++            pass
++        if not conf:
++            conf = HostnameConf('')
++        conf.set_hostname(your_hostname)
++        atomic_helper.write_file(out_fn, str(conf).encode("utf-8"))
++
++    def _read_system_hostname(self):
++        sys_hostname = self._read_hostname(self.hostname_conf_fn)
++        return (self.hostname_conf_fn, sys_hostname)
++
++    def _read_hostname_conf(self, filename):
++        conf = HostnameConf(util.load_file(filename))
++        conf.parse()
++        return conf
++
++    def _read_hostname(self, filename, default=None):
++        hostname = None
++        try:
++            conf = self._read_hostname_conf(filename)
++            hostname = conf.hostname
++        except IOError:
++            pass
++        if not hostname:
++            return default
++        return hostname
++
++    def _write_network(self, settings):
++        raise NotImplementedError()
++
++    def apply_locale(self, locale, out_fn=None):
++        raise NotImplementedError()
++
++    def install_packages(self, pkglist):
++        raise NotImplementedError()
++
++    def package_command(self, command, args=None, pkgs=None):
++        raise NotImplementedError()
++
++    def set_timezone(self, tz):
++        raise NotImplementedError()
++
++    def update_package_sources(self):
++        raise NotImplementedError()
+-- 
+2.28.0
+
diff --git a/nixpkgs/pkgs/tools/virtualization/cloud-init/default.nix b/nixpkgs/pkgs/tools/virtualization/cloud-init/default.nix
new file mode 100644
index 000000000000..dd30969ed8bd
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/cloud-init/default.nix
@@ -0,0 +1,111 @@
+{ lib
+, fetchFromGitHub
+, buildPythonApplication
+, jinja2
+, oauthlib
+, configobj
+, pyyaml
+, requests
+, jsonschema
+, jsonpatch
+, httpretty
+, dmidecode
+, pytestCheckHook
+, shadow
+, cloud-utils
+, openssh
+}:
+
+buildPythonApplication rec {
+  pname = "cloud-init";
+  version = "21.2";
+  namePrefix = "";
+
+  src = fetchFromGitHub {
+    owner = "canonical";
+    repo = "cloud-init";
+    rev = version;
+    sha256 = "0vhjkgs49ixfa3kkj5s3v3gcxvypm3cdvfk6adrk2bx3wv2cbhvz";
+  };
+
+  patches = [ ./0001-add-nixos-support.patch ];
+  prePatch = ''
+    substituteInPlace setup.py --replace /lib/systemd $out/lib/systemd
+  '';
+
+  postInstall = ''
+    install -D -m755 ./tools/write-ssh-key-fingerprints $out/libexec/write-ssh-key-fingerprints
+    for i in $out/libexec/*; do
+      wrapProgram $i --prefix PATH : "${lib.makeBinPath [ openssh ]}"
+    done
+  '';
+
+  propagatedBuildInputs = [
+    jinja2
+    oauthlib
+    configobj
+    pyyaml
+    requests
+    jsonschema
+    jsonpatch
+  ];
+
+  checkInputs = [
+    pytestCheckHook
+    httpretty
+    dmidecode
+    # needed for tests; at runtime we rather want the setuid wrapper
+    shadow
+  ];
+
+  makeWrapperArgs = [
+    "--prefix PATH : ${lib.makeBinPath [ dmidecode cloud-utils.guest ]}/bin"
+  ];
+
+  disabledTests = [
+    # tries to create /var
+    "test_dhclient_run_with_tmpdir"
+    # clears path and fails because mkdir is not found
+    "test_path_env_gets_set_from_main"
+    # tries to read from /etc/ca-certificates.conf while inside the sandbox
+    "test_handler_ca_certs"
+    # Doesn't work in the sandbox
+    "TestEphemeralDhcpNoNetworkSetup"
+    "TestHasURLConnectivity"
+    "TestReadFileOrUrl"
+    "TestConsumeUserDataHttp"
+    # Chef Omnibus
+    "TestInstallChefOmnibus"
+    # https://github.com/canonical/cloud-init/pull/893
+    "TestGetPackageMirrorInfo"
+  ];
+
+  disabledTestPaths = [
+    # Oracle tests are not passing
+    "cloudinit/sources/tests/test_oracle.py"
+    # Disable the integration tests. pycloudlib would be required
+    "tests/unittests/test_datasource/test_aliyun.py"
+    "tests/unittests/test_datasource/test_azure.py"
+    "tests/unittests/test_datasource/test_ec2.py"
+    "tests/unittests/test_datasource/test_exoscale.py"
+    "tests/unittests/test_datasource/test_gce.py"
+    "tests/unittests/test_datasource/test_openstack.py"
+    "tests/unittests/test_datasource/test_scaleway.py"
+    "tests/unittests/test_ec2_util.py"
+  ];
+
+  preCheck = ''
+    # TestTempUtils.test_mkdtemp_default_non_root does not like TMPDIR=/build
+    export TMPDIR=/tmp
+  '';
+
+  pythonImportsCheck = [ "cloudinit" ];
+
+  meta = with lib; {
+    homepage = "https://cloudinit.readthedocs.org";
+    description = "Provides configuration and customization of cloud instance";
+    license = with licenses; [ asl20 gpl3Plus ];
+    maintainers = with maintainers; [ madjar phile314 ];
+    platforms = platforms.all;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/cloudmonkey/default.nix b/nixpkgs/pkgs/tools/virtualization/cloudmonkey/default.nix
new file mode 100644
index 000000000000..1945e56b96e7
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/cloudmonkey/default.nix
@@ -0,0 +1,25 @@
+{ buildGoModule, fetchFromGitHub, lib }:
+
+buildGoModule rec {
+  pname = "cloudmonkey";
+  version = "6.1.0";
+
+  src = fetchFromGitHub {
+    owner = "apache";
+    repo = "cloudstack-cloudmonkey";
+    rev = version;
+    sha256 = "sha256-OmVM6ayrtrLl+PADnkUnrssbsq1GZp2KiMBOXPgfi5Y=";
+  };
+
+  runVend = true;
+
+  vendorSha256 = null;
+
+  meta = with lib; {
+    description = "CLI for Apache CloudStack";
+    homepage = "https://github.com/apache/cloudstack-cloudmonkey";
+    license = [ licenses.asl20 ];
+    maintainers = [ maintainers.womfoo ];
+  };
+
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/cri-tools/default.nix b/nixpkgs/pkgs/tools/virtualization/cri-tools/default.nix
new file mode 100644
index 000000000000..16a7ecffa043
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/cri-tools/default.nix
@@ -0,0 +1,47 @@
+{ lib
+, buildGoModule
+, fetchFromGitHub
+, installShellFiles
+}:
+
+buildGoModule rec {
+  pname = "cri-tools";
+  version = "1.22.0";
+
+  src = fetchFromGitHub {
+    owner = "kubernetes-sigs";
+    repo = pname;
+    rev = "v${version}";
+    sha256 = "sha256-+36lGLpNnTQnwwmXoVNPt3RMcnE46AdXOpghvhP0Bq0=";
+  };
+
+  vendorSha256 = null;
+
+  doCheck = false;
+
+  nativeBuildInputs = [ installShellFiles ];
+
+  buildPhase = ''
+    runHook preBuild
+    make binaries VERSION=${version}
+    runHook postBuild
+  '';
+
+  installPhase = ''
+    runHook preInstall
+    make install BINDIR=$out/bin
+
+    for shell in bash fish zsh; do
+      $out/bin/crictl completion $shell > crictl.$shell
+      installShellCompletion crictl.$shell
+    done
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    description = "CLI and validation tools for Kubelet Container Runtime Interface (CRI)";
+    homepage = "https://github.com/kubernetes-sigs/cri-tools";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ ] ++ teams.podman.members;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/distrobuilder/default.nix b/nixpkgs/pkgs/tools/virtualization/distrobuilder/default.nix
new file mode 100644
index 000000000000..73f602cbf695
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/distrobuilder/default.nix
@@ -0,0 +1,57 @@
+{ lib
+, pkg-config
+, buildGoModule
+, fetchFromGitHub
+, makeWrapper
+, coreutils
+, gnupg
+, gnutar
+, squashfsTools
+, debootstrap
+}:
+
+let
+  bins = [
+    coreutils
+    gnupg
+    gnutar
+    squashfsTools
+    debootstrap
+  ];
+in
+buildGoModule rec {
+  pname = "distrobuilder";
+  version = "1.3";
+
+  vendorSha256 = "sha256-FKnpoLA4enZ1vGSJQFLbp/OjoEgdxagL73ucxUgIoKY=";
+
+  src = fetchFromGitHub {
+    owner = "lxc";
+    repo = "distrobuilder";
+    rev = "distrobuilder-${version}";
+    sha256 = "sha256-cvxbJbg9yTcAPWQccH+1nQivwRh8CIN3Cga2HKY8VlQ=";
+    fetchSubmodules = false;
+  };
+
+  buildInputs = bins;
+
+  # tests require a local keyserver (mkg20001/nixpkgs branch distrobuilder-with-tests) but gpg is currently broken in tests
+  doCheck = false;
+
+  nativeBuildInputs = [
+    pkg-config
+    makeWrapper
+  ] ++ bins;
+
+  postInstall = ''
+    wrapProgram $out/bin/distrobuilder --prefix PATH ":" ${lib.makeBinPath bins}
+  '';
+
+  meta = with lib; {
+    description = "System container image builder for LXC and LXD";
+    homepage = "https://github.com/lxc/distrobuilder";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ megheaiulian ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/default.nix b/nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/default.nix
new file mode 100644
index 000000000000..8e6d7b06d170
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/default.nix
@@ -0,0 +1,44 @@
+{ lib, stdenv, fetchurl, unzip, ruby, openssl, makeWrapper }:
+
+stdenv.mkDerivation rec {
+  pname = "ec2-ami-tools";
+
+  version = "1.5.7";
+
+  nativeBuildInputs = [ makeWrapper unzip ];
+
+  src = fetchurl {
+    url = "https://s3.amazonaws.com/ec2-downloads/${pname}-${version}.zip";
+    sha256 = "17xj7xmdbcwdbzalhfs6yyiwa64978mk3li39l949qfjjgrxjias";
+  };
+
+  # Amazon EC2 requires that disk images are writable.  If they're
+  # not, the VM immediately terminates with a mysterious
+  # "Server.InternalError" message.  Since disk images generated in
+  # the Nix store are read-only, they must be made writable in the
+  # tarball uploaded to Amazon S3.  So add a `--mode=0755' flag to the
+  # tar invocation.
+  patches = [ ./writable.patch ];
+
+  installPhase =
+    ''
+      mkdir -p $out
+      mv * $out
+      rm $out/*.txt
+
+      for i in $out/bin/*; do
+          wrapProgram $i \
+            --set EC2_HOME $out \
+            --prefix PATH : ${lib.makeBinPath [ ruby openssl ]}
+      done
+
+      sed -i 's|/bin/bash|${stdenv.shell}|' $out/lib/ec2/platform/base/pipeline.rb
+    '';  # */
+
+  meta = {
+    homepage = "https://aws.amazon.com/developertools/Amazon-EC2/368";
+    description = "Command-line tools to create and manage Amazon EC2 virtual machine images";
+    license = lib.licenses.amazonsl;
+  };
+
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/writable.patch b/nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/writable.patch
new file mode 100644
index 000000000000..54c2228911eb
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/ec2-ami-tools/writable.patch
@@ -0,0 +1,23 @@
+diff -ru ec2-ami-tools-1.4.0.5-orig/lib/ec2/amitools/bundle.rb ec2-ami-tools-1.4.0.5/lib/ec2/amitools/bundle.rb
+--- ec2-ami-tools-1.4.0.5-orig/lib/ec2/amitools/bundle.rb	2011-12-06 14:57:28.000000000 +0100
++++ ec2-ami-tools-1.4.0.5/lib/ec2/amitools/bundle.rb	2012-02-25 21:24:57.682427268 +0100
+@@ -80,7 +80,7 @@
+       # piped via several processes. The tee is used to allow a
+       # digest of the file to be calculated without having to re-read
+       # it from disk.
+-      tar = EC2::Platform::Current::Tar::Command.new.create.dereference.sparse
++      tar = EC2::Platform::Current::Tar::Command.new.create.dereference.sparse.writable
+       tar.owner(0).group(0)
+       tar.add(File::basename( image_file ), File::dirname( image_file ))
+       openssl = EC2::Platform::Current::Constants::Utility::OPENSSL
+diff -ru ec2-ami-tools-1.4.0.5-orig/lib/ec2/platform/linux/tar.rb ec2-ami-tools-1.4.0.5/lib/ec2/platform/linux/tar.rb
+--- ec2-ami-tools-1.4.0.5-orig/lib/ec2/platform/linux/tar.rb	2011-12-06 14:57:28.000000000 +0100
++++ ec2-ami-tools-1.4.0.5/lib/ec2/platform/linux/tar.rb	2012-02-25 21:23:36.342716403 +0100
+@@ -31,6 +31,7 @@
+           def update;         @options << '-u';          self; end
+           def sparse;         @options << '-S';          self; end
+           def dereference;    @options << '-h';          self; end
++          def writable;       @options << '--mode=0755'; self; end
+           
+           def archive(filename)
+             filename = '-' if filename.nil? 
diff --git a/nixpkgs/pkgs/tools/virtualization/ec2-api-tools/default.nix b/nixpkgs/pkgs/tools/virtualization/ec2-api-tools/default.nix
new file mode 100644
index 000000000000..babcbcfc6c33
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/ec2-api-tools/default.nix
@@ -0,0 +1,35 @@
+{ lib, stdenv, fetchurl, unzip, makeWrapper, jre }:
+
+stdenv.mkDerivation rec {
+  pname = "ec2-api-tools";
+  version = "1.7.5.1";
+
+  src = fetchurl {
+    url = "http://tarballs.nixos.org/ec2-api-tools-${version}.zip";
+    sha256 = "0figmvcm82ghmpz3018ihysz8zpxpysgbpdx7rmciq9y80qbw6l5";
+  };
+
+  nativeBuildInputs = [ makeWrapper unzip ];
+
+  installPhase =
+    ''
+      d=$out/libexec/ec2-api-tools
+      mkdir -p $d
+      mv * $d
+      rm $d/bin/*.cmd # Windows stuff
+
+      for i in $d/bin/*; do
+          b=$(basename $i)
+          if [ $b = "ec2-cmd" ]; then continue; fi
+          makeWrapper $i $out/bin/$(basename $i) \
+            --set EC2_HOME $d \
+            --set JAVA_HOME ${jre}
+      done
+    ''; # */
+
+  meta = {
+    homepage = "http://developer.amazonwebservices.com/connect/entry.jspa?externalID=351";
+    description = "Command-line tools to create and manage Amazon EC2 virtual machines";
+    license = lib.licenses.amazonsl;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/ec2-utils/default.nix b/nixpkgs/pkgs/tools/virtualization/ec2-utils/default.nix
new file mode 100644
index 000000000000..1605bcfa43b6
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/ec2-utils/default.nix
@@ -0,0 +1,47 @@
+{ stdenv, lib, rpmextract, fetchurl, python2, tree }:
+
+stdenv.mkDerivation {
+  name = "ec2-utils";
+  version = "0.5.1";
+
+  # The url can be determined by booting an "Amazon Linux 2" and running:
+  # > yumdownloader --urls ec2-utils
+  src = fetchurl {
+    url = "http://amazonlinux.ap-northeast-1.amazonaws.com/blobstore/a3b4d2c35c2300518fe10381a05b3bd7936ff5cdd3d351143a11bf84073d9e00/ec2-utils-0.5-1.amzn2.0.1.noarch.rpm";
+    sha256 = "004y7l3q9gqi78a53lykrpsnz4yp7dds1083w67m2013bk1x5d53";
+  };
+
+  nativeBuildInputs = [ rpmextract ];
+
+  buildInputs = [ python2 ];
+
+  unpackPhase = ''
+    mkdir source
+    cd source
+    rpmextract "$src"
+  '';
+
+  installPhase = ''
+    mkdir $out
+
+    mv --target-directory $out \
+      etc sbin usr/bin usr/lib
+  '';
+
+  postFixup = ''
+    for i in $out/etc/udev/rules.d/*.rules; do
+      substituteInPlace "$i" \
+        --replace '/sbin' "$out/bin"
+    done
+
+    substituteInPlace "$out/etc/udev/rules.d/70-ec2-nvme-devices.rules" \
+      --replace 'ec2nvme-nsid' "$out/lib/udev/ec2nvme-nsid"
+  '';
+
+  meta = {
+    description = "A set of tools for running in EC2";
+    homepage = "https://aws.amazon.com/amazon-linux-ami/";
+    license = lib.licenses.asl20;
+    maintainers = with lib.maintainers; [ thefloweringash ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/ec2instanceconnectcli/default.nix b/nixpkgs/pkgs/tools/virtualization/ec2instanceconnectcli/default.nix
new file mode 100644
index 000000000000..16c10b5ae7f0
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/ec2instanceconnectcli/default.nix
@@ -0,0 +1,25 @@
+{ lib, buildPythonPackage, fetchPypi, boto3, cryptography }:
+
+buildPythonPackage rec {
+  pname = "ec2instanceconnectcli";
+  version = "1.0.2";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "sha256-VaCyCnEhSx1I3bNo57p0IXf92+tO1tT7KSUXzO1IyIU=";
+  };
+
+  propagatedBuildInputs = [ boto3 cryptography ];
+
+  # has no tests
+  doCheck = false;
+
+  pythonImportsCheck = [ "ec2instanceconnectcli" ];
+
+  meta = with lib; {
+    description = "Command Line Interface for AWS EC2 Instance Connect";
+    homepage = "https://github.com/aws/aws-ec2-instance-connect-cli";
+    license = licenses.apsl20;
+    maintainers = with maintainers; [ yurrriq ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/euca2ools/default.nix b/nixpkgs/pkgs/tools/virtualization/euca2ools/default.nix
new file mode 100644
index 000000000000..88e83f42733e
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/euca2ools/default.nix
@@ -0,0 +1,23 @@
+{ lib, fetchgit, python2Packages }:
+
+let
+  inherit (python2Packages) buildPythonApplication boto m2crypto;
+in buildPythonApplication {
+  pname = "euca2ools";
+  version = "2.1.4";
+
+  src = fetchgit {
+    url = "https://github.com/eucalyptus/euca2ools.git";
+    rev = "19cb7eac34dd7efe3a56e4841b9692c03458bf3b";
+    sha256 = "0grsgn5gbvk1hlfa8qx7ppz7iyfyi2pdhxy8njr8lm60w4amfiyq";
+  };
+
+  propagatedBuildInputs = [ boto m2crypto ];
+
+  meta = {
+    homepage = "https://github.com/eucalyptus/euca2ools";
+    description = "Tools for interacting with Amazon EC2/S3-compatible cloud computing services";
+    maintainers = [ lib.maintainers.eelco ];
+    platforms = lib.platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/google-compute-engine-oslogin/default.nix b/nixpkgs/pkgs/tools/virtualization/google-compute-engine-oslogin/default.nix
new file mode 100644
index 000000000000..0718e437b06b
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/google-compute-engine-oslogin/default.nix
@@ -0,0 +1,56 @@
+{ stdenv
+, lib
+, bashInteractive
+, curl
+, fetchFromGitHub
+, json_c
+, nixosTests
+, pam
+}:
+
+stdenv.mkDerivation rec {
+  pname = "google-compute-engine-oslogin";
+  version = "20210429.00";
+
+  src = fetchFromGitHub {
+    owner = "GoogleCloudPlatform";
+    repo = "guest-oslogin";
+    rev = version;
+    sha256 = "eHAg9K5oxcygEzqaac81jSFHF+zsW6uB7q2Kfo9hSrA=";
+  };
+
+  postPatch = ''
+    # change sudoers dir from /var/google-sudoers.d to /run/google-sudoers.d (managed through systemd-tmpfiles)
+    substituteInPlace src/pam/pam_oslogin_admin.cc --replace /var/google-sudoers.d /run/google-sudoers.d
+    # fix "User foo not allowed because shell /bin/bash does not exist"
+    substituteInPlace src/include/compat.h --replace /bin/bash ${bashInteractive}/bin/bash
+  '';
+
+  buildInputs = [ curl.dev pam ];
+
+  NIX_CFLAGS_COMPILE = "-I${json_c.dev}/include/json-c";
+  NIX_CFLAGS_LINK = "-L${json_c}/lib";
+
+  makeFlags = [
+    "VERSION=${version}"
+    "DESTDIR=${placeholder "out"}"
+    "PREFIX=/"
+    "BINDIR=/bin"
+    "LIBDIR=/lib"
+    "PAMDIR=/lib"
+    "MANDIR=/share/man"
+  ];
+
+  enableParallelBuilding = true;
+
+  passthru.tests = {
+    inherit (nixosTests) google-oslogin;
+  };
+
+  meta = with lib; {
+    homepage = "https://github.com/GoogleCloudPlatform/compute-image-packages";
+    description = "OS Login Guest Environment for Google Compute Engine";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ flokli ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/google-compute-engine/default.nix b/nixpkgs/pkgs/tools/virtualization/google-compute-engine/default.nix
new file mode 100644
index 000000000000..fef461be7d74
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/google-compute-engine/default.nix
@@ -0,0 +1,105 @@
+{ lib
+, fetchFromGitHub
+, buildPythonPackage
+, bash
+, bashInteractive
+, util-linux
+, boto
+, setuptools
+, distro
+, stdenv
+, pythonOlder
+, pytestCheckHook
+}:
+
+let
+  guest-configs = stdenv.mkDerivation rec {
+    pname = "guest-configs";
+    version = "20210702.00";
+
+    src = fetchFromGitHub {
+      owner = "GoogleCloudPlatform";
+      repo = "guest-configs";
+      rev = version;
+      sha256 = "1965kdrb1ig3z4qwzvyzx1fb4282ak5vgxcvvg5k9c759pzbc5nn";
+    };
+
+    buildInputs = [ bash ];
+
+    dontConfigure = true;
+    dontBuild = true;
+
+    installPhase = ''
+      runHook preInstall
+
+      # allows to install the package in `services.udev.packages` in NixOS
+      mkdir -p $out/lib/udev $out/bin
+
+      cp -r "src/lib/udev/rules.d" $out/lib/udev
+      cp "src/lib/udev/google_nvme_id" $out/bin
+
+      for rules in $out/lib/udev/*.rules; do
+        substituteInPlace "$rules" \
+          --replace /bin/sh "${bash}/bin/sh" \
+          --replace /bin/umount "${util-linux}/bin/umount" \
+          --replace /usr/bin/logger "${util-linux}/bin/logger"
+      done
+
+      # sysctl snippets will be used by google-compute-config.nix
+      cp -r "src/etc/sysctl.d" $out
+
+      patchShebangs $out/bin/*
+
+      runHook postInstall
+    '';
+  };
+in
+buildPythonPackage rec {
+  pname = "google-compute-engine";
+  version = "20200113.0";
+
+  src = fetchFromGitHub {
+    owner = "GoogleCloudPlatform";
+    repo = "compute-image-packages";
+    rev = "506b9a0dbffec5620887660cd42c57b3cbbadba6";
+    sha256 = "0lmc426mvrajghpavhs6hwl19mgnnh08ziqx5yi15fzpnvwmb8vz";
+  };
+
+  buildInputs = [ bash guest-configs ];
+  propagatedBuildInputs = [ (if pythonOlder "3.7" then boto else distro) setuptools ];
+
+  preBuild = ''
+    cd packages/python-google-compute-engine
+  '';
+
+  disabledTests = [
+    "testExtractInterfaceMetadata"
+    "testCallDhclientIpv6"
+    "testWriteConfig"
+    "testCreateInterfaceMapNetifaces"
+    "testCreateInterfaceMapSysfs"
+    "testGetNetworkInterface"
+  ];
+
+  checkInputs = [ pytestCheckHook ];
+
+  postPatch = ''
+    for file in $(find google_compute_engine -type f); do
+      substituteInPlace "$file" \
+        --replace /bin/systemctl "/run/current-system/systemd/bin/systemctl" \
+        --replace /bin/bash "${bashInteractive}/bin/bash" \
+        --replace /sbin/hwclock "${util-linux}/bin/hwclock"
+      # SELinux tool ???  /sbin/restorecon
+    done
+  '';
+
+  pythonImportsCheck = [ "google_compute_engine" ];
+
+  meta = with lib; {
+    description = "Google Compute Engine tools and services";
+    homepage = "https://github.com/GoogleCloudPlatform/compute-image-packages";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ cpcloud zimbatm ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/govc/default.nix b/nixpkgs/pkgs/tools/virtualization/govc/default.nix
new file mode 100644
index 000000000000..00330f7d1a43
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/govc/default.nix
@@ -0,0 +1,24 @@
+{ lib, fetchFromGitHub, buildGoPackage }:
+
+buildGoPackage rec {
+  pname = "govc";
+  version = "0.25.0";
+
+  goPackagePath = "github.com/vmware/govmomi";
+
+  subPackages = [ "govc" ];
+
+  src = fetchFromGitHub {
+    rev = "v${version}";
+    owner = "vmware";
+    repo = "govmomi";
+    sha256 = "sha256-Ri8snbmgcAZmdumKzBl3P6gf/eZgwdgg7V+ijyeZjks=";
+  };
+
+  meta = {
+    description = "A vSphere CLI built on top of govmomi";
+    homepage = "https://github.com/vmware/govmomi/tree/master/govc";
+    license = lib.licenses.asl20;
+    maintainers = with lib.maintainers; [ nicknovitski ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/linode-cli/default.nix b/nixpkgs/pkgs/tools/virtualization/linode-cli/default.nix
new file mode 100644
index 000000000000..c815f6fcf6d5
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/linode-cli/default.nix
@@ -0,0 +1,69 @@
+{ lib
+, fetchFromGitHub
+, fetchurl
+, buildPythonApplication
+, colorclass
+, installShellFiles
+, pyyaml
+, requests
+, setuptools
+, terminaltables
+}:
+
+let
+  # specVersion taken from: https://www.linode.com/docs/api/openapi.yaml at `info.version`.
+  specVersion = "4.102.0";
+  spec = fetchurl {
+    url = "https://raw.githubusercontent.com/linode/linode-api-docs/v${specVersion}/openapi.yaml";
+    sha256 = "16njk21gdk8r8a9v607ndw2rs0q6za9ylkgdxmix4j0zvrbrw0qv";
+  };
+
+in
+
+buildPythonApplication rec {
+  pname = "linode-cli";
+  version = "5.8.1";
+
+  src = fetchFromGitHub {
+    owner = "linode";
+    repo = pname;
+    rev = version;
+    sha256 = "19lfnwgm09gxk0mcikwl7v4hw2ai2k9lkdjlalz8fsswf81my7h6";
+  };
+
+  # remove need for git history
+  prePatch = ''
+    substituteInPlace setup.py \
+      --replace "version=get_version()," "version='${version}',"
+  '';
+
+  propagatedBuildInputs = [
+    colorclass
+    pyyaml
+    requests
+    setuptools
+    terminaltables
+  ];
+
+  postConfigure = ''
+    python3 -m linodecli bake ${spec} --skip-config
+    cp data-3 linodecli/
+  '';
+
+  doInstallCheck = true;
+  installCheckPhase = ''
+    $out/bin/linode-cli --skip-config --version | grep ${version} > /dev/null
+  '';
+
+  nativeBuildInputs = [ installShellFiles ];
+  postInstall = ''
+    installShellCompletion --cmd linode-cli --bash <($out/bin/linode-cli --skip-config completion bash)
+  '';
+
+  meta = with lib; {
+    description = "The Linode Command Line Interface";
+    homepage = "https://github.com/linode/linode-cli";
+    license = licenses.bsd3;
+    maintainers = with maintainers; [ ryantm superherointj ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/marathonctl/default.nix b/nixpkgs/pkgs/tools/virtualization/marathonctl/default.nix
new file mode 100644
index 000000000000..fe31c64952a5
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/marathonctl/default.nix
@@ -0,0 +1,24 @@
+{ lib, buildGoPackage, fetchFromGitHub }:
+
+buildGoPackage {
+  pname = "marathonctl-unstable";
+  version = "2017-03-06";
+
+  goPackagePath = "github.com/shoenig/marathonctl";
+  subPackages = [ "." ];
+  goDeps = ./deps.nix;
+
+  src = fetchFromGitHub {
+    owner = "shoenig";
+    repo = "marathonctl";
+    rev = "0867e66551fff5d81f25959baf914a8ee11a3a8b";
+    sha256 = "1fcc54hwpa8s3kz4gn26mc6nrv6zjrw869331nvm47khi23gpmxw";
+  };
+
+  meta = with lib; {
+    homepage = "https://github.com/shoenig/marathonctl";
+    description = "CLI tool for Marathon";
+    license = licenses.mit;
+    maintainers = with maintainers; [ manveru ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/marathonctl/deps.nix b/nixpkgs/pkgs/tools/virtualization/marathonctl/deps.nix
new file mode 100644
index 000000000000..39efaab95358
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/marathonctl/deps.nix
@@ -0,0 +1,12 @@
+# This file was generated by go2nix.
+[
+  {
+    goPackagePath = "github.com/shoenig/config";
+    fetch = {
+      type = "git";
+      url = "https://github.com/shoenig/config";
+      rev = "7d793e7ad7f175ef22743b1ea38acee8267788db";
+      sha256 = "1dhcv1j5xk30kj73dfnx3xqx8mcvk9r8ywp9khgf2kq6wh9sm1qr";
+    };
+  }
+]
diff --git a/nixpkgs/pkgs/tools/virtualization/mininet/default.nix b/nixpkgs/pkgs/tools/virtualization/mininet/default.nix
new file mode 100644
index 000000000000..78ddc8e6dfd5
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/mininet/default.nix
@@ -0,0 +1,49 @@
+{ stdenv, lib, fetchFromGitHub
+, which
+, python
+, help2man
+}:
+
+let
+  pyEnv = python.withPackages(ps: [ ps.setuptools ]);
+in
+stdenv.mkDerivation rec {
+  pname = "mininet";
+  version = "2.3.0d6";
+
+  outputs = [ "out" "py" ];
+
+  src = fetchFromGitHub {
+    owner = "mininet";
+    repo = "mininet";
+    rev = version;
+    sha256 = "0wc6gni9dxj9jjnw66a28jdvcfm8bxv1i776m5dh002bn5wjcl6x";
+  };
+
+  buildFlags = [ "mnexec" ];
+  makeFlags = [ "PREFIX=$(out)" ];
+
+  pythonPath = [ python.pkgs.setuptools ];
+  buildInputs = [ python which help2man ];
+
+  installTargets = [ "install-mnexec" "install-manpages" ];
+
+  preInstall = ''
+    mkdir -p $out $py
+    # without --root, install fails
+    ${pyEnv.interpreter} setup.py install --root="/" --prefix=$py
+  '';
+
+  doCheck = false;
+
+
+  meta = with lib; {
+    description = "Emulator for rapid prototyping of Software Defined Networks";
+    license = {
+      fullName = "Mininet 2.3.0d6 License";
+    };
+    platforms = platforms.linux;
+    homepage = "https://github.com/mininet/mininet";
+    maintainers = with maintainers; [ teto ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/nixos-container/default.nix b/nixpkgs/pkgs/tools/virtualization/nixos-container/default.nix
new file mode 100644
index 000000000000..17065a2aa8b9
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/nixos-container/default.nix
@@ -0,0 +1,17 @@
+{ substituteAll, perl, shadow, util-linux }:
+
+substituteAll {
+    name = "nixos-container";
+    dir = "bin";
+    isExecutable = true;
+    src = ./nixos-container.pl;
+    perl = perl.withPackages (p: [ p.FileSlurp ]);
+    su = "${shadow.su}/bin/su";
+    utillinux = util-linux;
+
+    postInstall = ''
+      t=$out/share/bash-completion/completions
+      mkdir -p $t
+      cp ${./nixos-container-completion.sh} $t/nixos-container
+    '';
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container-completion.sh b/nixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container-completion.sh
new file mode 100644
index 000000000000..0fe8ab811a17
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container-completion.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+_nixos-container() {
+    local cur prev opts
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    prev="${COMP_WORDS[COMP_CWORD-1]}"
+    opts="list create destroy start stop status update login root-login run show-ip show-host-key"
+    startstop_opts=$(nixos-container list)
+    update_opts="--config"
+
+    if [[ "$prev" == "nixos-container" ]]
+    then
+        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+        return 0
+    fi
+
+    if [[ $(echo "$opts" | grep "$prev") ]]
+    then
+        if [[ "$prev" == "start" || "$prev" == "stop" ]]
+        then
+            COMPREPLY=( $(compgen -W "${startstop_opts}" -- ${cur}) )
+            return 0
+        elif [[ "$prev" == "update" ]]
+        then
+            COMPREPLY=( $(compgen -W "${update_opts}" -- ${cur}) )
+            return 0
+        fi
+    fi
+}
+
+complete -F _nixos-container nixos-container
+
diff --git a/nixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container.pl b/nixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container.pl
new file mode 100755
index 000000000000..d99b4cfba4a3
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/nixos-container/nixos-container.pl
@@ -0,0 +1,476 @@
+#! @perl@/bin/perl
+
+use strict;
+use POSIX;
+use File::Path;
+use File::Slurp;
+use Fcntl ':flock';
+use Getopt::Long qw(:config gnu_getopt no_bundling);
+use Cwd 'abs_path';
+use Time::HiRes;
+
+my $nsenter = "@utillinux@/bin/nsenter";
+my $su = "@su@";
+
+# Ensure a consistent umask.
+umask 0022;
+
+# Ensure $NIXOS_CONFIG is not set.
+$ENV{"NIXOS_CONFIG"} = "";
+
+# Parse the command line.
+
+sub showHelp {
+    print <<EOF;
+Usage: nixos-container list
+       nixos-container create <container-name>
+         [--nixos-path <path>]
+         [--system-path <path>]
+         [--config <string>]
+         [--config-file <path>]
+         [--flake <flakeref>]
+         [--ensure-unique-name]
+         [--auto-start]
+         [--bridge <iface>]
+         [--port <port>]
+         [--host-address <string>]
+         [--local-address <string>]
+       nixos-container destroy <container-name>
+       nixos-container start <container-name>
+       nixos-container stop <container-name>
+       nixos-container terminate <container-name>
+       nixos-container status <container-name>
+       nixos-container update <container-name>
+         [--config <string>]
+         [--config-file <path>]
+         [--flake <flakeref>]
+         [--nixos-path <path>]
+       nixos-container login <container-name>
+       nixos-container root-login <container-name>
+       nixos-container run <container-name> -- args...
+       nixos-container show-ip <container-name>
+       nixos-container show-host-key <container-name>
+EOF
+    exit 0;
+}
+
+my $systemPath;
+my $nixosPath;
+my $ensureUniqueName = 0;
+my $autoStart = 0;
+my $bridge;
+my $port;
+my $extraConfig;
+my $signal;
+my $configFile;
+my $hostAddress;
+my $localAddress;
+my $flake;
+my $flakeAttr = "container";
+
+# Nix passthru flags.
+my @nixFlags;
+my @nixFlags2;
+
+sub copyNixFlags0 { push @nixFlags, "--$_[0]"; }
+sub copyNixFlags1 { push @nixFlags, "--$_[0]", $_[1]; }
+
+# Ugly hack to handle flags that take two arguments, like --option.
+sub copyNixFlags2 {
+    if (scalar(@nixFlags2) % 3 == 0) {
+        push @nixFlags2, "--$_[0]", $_[1];
+    } else {
+        push @nixFlags2, $_[1];
+    }
+}
+
+GetOptions(
+    "help" => sub { showHelp() },
+    "ensure-unique-name" => \$ensureUniqueName,
+    "auto-start" => \$autoStart,
+    "bridge=s" => \$bridge,
+    "port=s" => \$port,
+    "system-path=s" => \$systemPath,
+    "signal=s" => \$signal,
+    "nixos-path=s" => \$nixosPath,
+    "config=s" => \$extraConfig,
+    "config-file=s" => \$configFile,
+    "host-address=s" => \$hostAddress,
+    "local-address=s" => \$localAddress,
+    "flake=s" => \$flake,
+    # Nix passthru options.
+    "log-format=s" => \&copyNixFlags1,
+    "option=s{2}" => \&copyNixFlags2,
+    "impure" => \&copyNixFlags0,
+    "update-input=s" => \&copyNixFlags1,
+    "override-input=s{2}" => \&copyNixFlags2,
+    "commit-lock-file" => \&copyNixFlags0,
+    "no-registries" => \&copyNixFlags0,
+    "no-update-lock-file" => \&copyNixFlags0,
+    "no-write-lock-file" => \&copyNixFlags0,
+    "no-allow-dirty" => \&copyNixFlags0,
+    "recreate-lock-file" => \&copyNixFlags0,
+    ) or exit 1;
+
+push @nixFlags, @nixFlags2;
+
+if (defined $hostAddress and !defined $localAddress or defined $localAddress and !defined $hostAddress) {
+    die "With --host-address set, --local-address is required as well!";
+}
+
+my $action = $ARGV[0] or die "$0: no action specified\n";
+
+if (defined $configFile and defined $extraConfig) {
+    die "--config and --config-file are mutually incompatible. " .
+        "Please define one or the other, but not both";
+}
+
+if (defined $flake && $flake =~ /^(.*)#([^#"]+)$/) {
+    $flake = $1;
+    $flakeAttr = $2;
+}
+
+# Execute the selected action.
+
+mkpath("/etc/containers", 0, 0755);
+mkpath("/var/lib/containers", 0, 0700);
+
+if ($action eq "list") {
+    foreach my $confFile (glob "/etc/containers/*.conf") {
+        $confFile =~ /\/([^\/]+).conf$/ or next;
+        print "$1\n";
+    }
+    exit 0;
+}
+
+my $containerName = $ARGV[1] or die "$0: no container name specified\n";
+$containerName =~ /^[a-zA-Z0-9_-]+$/ or die "$0: invalid container name\n";
+
+sub writeNixOSConfig {
+    my ($nixosConfigFile) = @_;
+
+    my $localExtraConfig = "";
+
+    if ($extraConfig) {
+        $localExtraConfig = $extraConfig
+    } elsif ($configFile) {
+        my $resolvedFile = abs_path($configFile);
+        $localExtraConfig = "imports = [ $resolvedFile ];"
+    }
+
+    my $nixosConfig = <<EOF;
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{ boot.isContainer = true;
+  networking.hostName = mkDefault "$containerName";
+  networking.useDHCP = false;
+  $localExtraConfig
+}
+EOF
+
+    write_file($nixosConfigFile, $nixosConfig);
+}
+
+sub buildFlake {
+    system("nix", "build", "-o", "$systemPath.tmp", @nixFlags, "--",
+           "$flake#nixosConfigurations.\"$flakeAttr\".config.system.build.toplevel") == 0
+        or die "$0: failed to build container from flake '$flake'\n";
+    $systemPath = readlink("$systemPath.tmp") or die;
+    unlink("$systemPath.tmp");
+}
+
+sub clearContainerState {
+    my ($profileDir, $gcRootsDir, $root, $configFile) = @_;
+
+    safeRemoveTree($profileDir) if -e $profileDir;
+    safeRemoveTree($gcRootsDir) if -e $gcRootsDir;
+    system("chattr", "-i", "$root/var/empty") if -e "$root/var/empty";
+    safeRemoveTree($root) if -e $root;
+    unlink($configFile) or die;
+}
+
+if ($action eq "create") {
+    # Acquire an exclusive lock to prevent races with other
+    # invocations of ‘nixos-container create’.
+    my $lockFN = "/run/lock/nixos-container";
+    open(my $lock, '>>', $lockFN) or die "$0: opening $lockFN: $!";
+    flock($lock, LOCK_EX) or die "$0: could not lock $lockFN: $!";
+
+    my $confFile = "/etc/containers/$containerName.conf";
+    my $root = "/var/lib/containers/$containerName";
+
+    # Maybe generate a unique name.
+    if ($ensureUniqueName) {
+        my $base = $containerName;
+        for (my $nr = 0; ; $nr++) {
+            $confFile = "/etc/containers/$containerName.conf";
+            $root = "/var/lib/containers/$containerName";
+            last unless -e $confFile || -e $root;
+            $containerName = "$base-$nr";
+        }
+    }
+
+    die "$0: container ‘$containerName’ already exists\n" if -e $confFile;
+
+    # Due to interface name length restrictions, container names must
+    # be restricted too.
+    die "$0: container name ‘$containerName’ is too long\n" if length $containerName > 11;
+
+    # Get an unused IP address.
+    my %usedIPs;
+    foreach my $confFile2 (glob "/etc/containers/*.conf") {
+        my $s = read_file($confFile2) or die;
+        $usedIPs{$1} = 1 if $s =~ /^HOST_ADDRESS=([0-9\.]+)$/m;
+        $usedIPs{$1} = 1 if $s =~ /^LOCAL_ADDRESS=([0-9\.]+)$/m;
+    }
+
+    unless (defined $hostAddress) {
+        my $ipPrefix;
+        for (my $nr = 1; $nr < 255; $nr++) {
+            $ipPrefix = "10.233.$nr";
+            $hostAddress = "$ipPrefix.1";
+            $localAddress = "$ipPrefix.2";
+            last unless $usedIPs{$hostAddress} || $usedIPs{$localAddress};
+            $ipPrefix = undef;
+        }
+
+        die "$0: out of IP addresses\n" unless defined $ipPrefix;
+    }
+
+    my @conf;
+    push @conf, "PRIVATE_NETWORK=1\n";
+    push @conf, "HOST_ADDRESS=$hostAddress\n";
+    push @conf, "LOCAL_ADDRESS=$localAddress\n";
+    push @conf, "HOST_BRIDGE=$bridge\n";
+    push @conf, "HOST_PORT=$port\n";
+    push @conf, "AUTO_START=$autoStart\n";
+    push @conf, "FLAKE=$flake\n" if defined $flake;
+    write_file($confFile, \@conf);
+
+    close($lock);
+
+    print STDERR "host IP is $hostAddress, container IP is $localAddress\n";
+
+    # The per-container directory is restricted to prevent users on
+    # the host from messing with guest users who happen to have the
+    # same uid.
+    my $profileDir = "/nix/var/nix/profiles/per-container";
+    mkpath($profileDir, 0, 0700);
+    $profileDir = "$profileDir/$containerName";
+    mkpath($profileDir, 0, 0755);
+
+    # Build/set the initial configuration.
+    if (defined $flake) {
+        buildFlake();
+    }
+
+    if (defined $systemPath) {
+        system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0
+            or do {
+                clearContainerState($profileDir, "$profileDir/$containerName", $root, $confFile);
+                die "$0: failed to set initial container configuration\n";
+            };
+    } else {
+        mkpath("$root/etc/nixos", 0, 0755);
+
+        my $nixenvF = $nixosPath // "<nixpkgs/nixos>";
+        my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
+        writeNixOSConfig $nixosConfigFile;
+
+        system("nix-env", "-p", "$profileDir/system",
+               "-I", "nixos-config=$nixosConfigFile", "-f", "$nixenvF",
+               "--set", "-A", "system", @nixFlags) == 0
+            or do {
+                clearContainerState($profileDir, "$profileDir/$containerName", $root, $confFile);
+                die "$0: failed to build initial container configuration\n"
+            };
+    }
+
+    print "$containerName\n" if $ensureUniqueName;
+    exit 0;
+}
+
+my $root = "/var/lib/containers/$containerName";
+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) {
+    if ($action eq "destroy") {
+        exit 0;
+    } elsif ($action eq "status") {
+        print "gone\n";
+    }
+    die "$0: container ‘$containerName’ does not exist\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);
+}
+
+sub isContainerRunning {
+    my $status = `systemctl show 'container\@$containerName'`;
+    return $status =~ /ActiveState=active/;
+}
+
+sub terminateContainer {
+    my $leader = getLeader;
+    system("machinectl", "terminate", $containerName) == 0
+        or die "$0: failed to terminate container\n";
+    # Wait for the leader process to exit
+    # TODO: As for any use of PIDs for process control where the process is
+    #       not a direct child of ours, this can go wrong when the pid gets
+    #       recycled after a PID overflow.
+    #       Relying entirely on some form of UUID provided by machinectl
+    #       instead of PIDs would remove this risk.
+    #       See https://github.com/NixOS/nixpkgs/pull/32992#discussion_r158586048
+    while ( kill 0, $leader ) { Time::HiRes::sleep(0.1) }
+}
+
+sub startContainer {
+    system("systemctl", "start", "container\@$containerName") == 0
+        or die "$0: failed to start container\n";
+}
+
+sub stopContainer {
+    system("systemctl", "stop", "container\@$containerName") == 0
+        or die "$0: failed to stop container\n";
+}
+
+sub restartContainer {
+    stopContainer;
+    startContainer;
+}
+
+# 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";
+}
+
+# Remove a directory while recursively unmounting all mounted filesystems within
+# that directory and unmounting/removing that directory afterwards as well.
+#
+# NOTE: If the specified path is a mountpoint, its contents will be removed,
+#       only mountpoints underneath that path will be unmounted properly.
+sub safeRemoveTree {
+    my ($path) = @_;
+    system("find", $path, "-mindepth", "1", "-xdev",
+           "(", "-type", "d", "-exec", "mountpoint", "-q", "{}", ";", ")",
+           "-exec", "umount", "-fR", "{}", "+");
+    system("rm", "--one-file-system", "-rf", $path);
+    if (-e $path) {
+        system("umount", "-fR", $path);
+        system("rm", "--one-file-system", "-rf", $path);
+    }
+}
+
+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);
+
+    terminateContainer if (isContainerRunning);
+
+    clearContainerState($profileDir, $gcRootsDir, $root, $confFile);
+}
+
+elsif ($action eq "restart") {
+    restartContainer;
+}
+
+elsif ($action eq "start") {
+    startContainer;
+}
+
+elsif ($action eq "stop") {
+    stopContainer;
+}
+
+elsif ($action eq "terminate") {
+    terminateContainer;
+}
+
+elsif ($action eq "status") {
+    print isContainerRunning() ? "up" : "down", "\n";
+}
+
+elsif ($action eq "update") {
+
+    # Unless overriden on the command line, rebuild the flake recorded
+    # in the container config file. FIXME: read the container config
+    # in a more sensible way.
+    if (!defined $flake && !defined $configFile && !defined $extraConfig) {
+        my $s = read_file($confFile);
+        $s =~ /^FLAKE=(.*)$/m;
+        $flake = $1;
+    }
+
+    if (defined $flake) {
+        buildFlake();
+        system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0
+            or die "$0: failed to set container configuration\n";
+    } else {
+
+        my $nixosConfigFile = "$root/etc/nixos/configuration.nix";
+
+        # FIXME: may want to be more careful about clobbering the existing
+        # configuration.nix.
+        if ((defined $extraConfig && $extraConfig ne "") ||
+            (defined $configFile && $configFile ne "")) {
+            writeNixOSConfig $nixosConfigFile;
+        }
+
+        my $nixenvF = $nixosPath // "<nixpkgs/nixos>";
+        system("nix-env", "-p", "$profileDir/system",
+               "-I", "nixos-config=$nixosConfigFile", "-f", $nixenvF,
+               "--set", "-A", "system", @nixFlags) == 0
+            or die "$0: failed to build container configuration\n";
+    }
+
+    if (isContainerRunning) {
+        print STDERR "reloading container...\n";
+        system("systemctl", "reload", "container\@$containerName") == 0
+            or die "$0: failed to reload container\n";
+    }
+}
+
+elsif ($action eq "login") {
+    exec("machinectl", "login", "--", $containerName);
+}
+
+elsif ($action eq "root-login") {
+    runInContainer("@su@", "root", "-l");
+}
+
+elsif ($action eq "run") {
+    shift @ARGV; shift @ARGV;
+    # Escape command.
+    my $s = join(' ', map { s/'/'\\''/g; "'$_'" } @ARGV);
+    runInContainer("@su@", "root", "-l", "-c", "exec " . $s);
+}
+
+elsif ($action eq "show-ip") {
+    my $s = read_file($confFile) or die;
+    $s =~ /^LOCAL_ADDRESS=([0-9\.]+)(\/[0-9]+)?$/m
+        or $s =~ /^LOCAL_ADDRESS6=([0-9a-f:]+)(\/[0-9]+)?$/m
+        or die "$0: cannot get IP address\n";
+    print "$1\n";
+}
+
+elsif ($action eq "show-host-key") {
+    my $fn = "$root/etc/ssh/ssh_host_ed25519_key.pub";
+    $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub" unless -e $fn;
+    exit 1 if ! -f $fn;
+    print read_file($fn);
+}
+
+else {
+    die "$0: unknown action ‘$action’\n";
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/nixos-shell/default.nix b/nixpkgs/pkgs/tools/virtualization/nixos-shell/default.nix
new file mode 100644
index 000000000000..9f34fb99c754
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/nixos-shell/default.nix
@@ -0,0 +1,30 @@
+{ lib, stdenv, nix, fetchFromGitHub, makeWrapper }:
+
+stdenv.mkDerivation rec {
+  pname = "nixos-shell";
+  version = "0.2.1";
+
+  src = fetchFromGitHub {
+    owner = "Mic92";
+    repo = "nixos-shell";
+    rev = version;
+    sha256 = "sha256-HoY2diusDHXwR0BjYwKR3svLz5LrviE03yxyjWG9oPQ=";
+  };
+
+  nativeBuildInputs = [ makeWrapper ];
+
+  postInstall = ''
+    wrapProgram $out/bin/nixos-shell \
+      --prefix PATH : ${lib.makeBinPath [ nix ]}
+  '';
+
+  installFlags = [ "PREFIX=${placeholder "out"}" ];
+
+  meta = with lib; {
+    description = "Spawns lightweight nixos vms in a shell";
+    inherit (src.meta) homepage;
+    license = licenses.mit;
+    maintainers = with maintainers; [ mic92 ];
+    platforms = platforms.unix;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/ovftool/default.nix b/nixpkgs/pkgs/tools/virtualization/ovftool/default.nix
new file mode 100644
index 000000000000..cc4af17b47d0
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/ovftool/default.nix
@@ -0,0 +1,230 @@
+{ lib, stdenv, system ? builtins.currentSystem, ovftoolBundles ? {}
+, requireFile, buildFHSUserEnv, patchelf, autoPatchelfHook, makeWrapper, nix, unzip
+, glibc, c-ares, openssl_1_0_2, curl, expat, icu60, xercesc, zlib
+}:
+
+let
+  version = "4.4.1-16812187";
+
+  # FHS environment required to unpack ovftool on x86.
+  ovftoolX86Unpacker = buildFHSUserEnv rec {
+    name = "ovftool-unpacker";
+    targetPkgs = pkgs: [ pkgs.bash ];
+    multiPkgs = targetPkgs;
+    runScript = "bash";
+  };
+
+  # unpackPhase for i686 and x86_64 ovftool self-extracting bundles.
+  ovftoolX86UnpackPhase = ''
+    runHook preUnpack
+
+    # This is a self-extracting shell script and needs a FHS environment to run.
+    # In reality, it could be doing anything, which is bad for reproducibility.
+    # Our postUnpack uses nix-hash to verify the hash to prevent problems.
+    #
+    # Note that the Arch PKGBUILD at
+    # https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=vmware-ovftool
+    # appears to use xvfb-run - this hasn't been proven necessary so far.
+    #
+    cp ${ovftoolSource} ./ovftool.bundle
+    chmod +x ./ovftool.bundle
+    ${ovftoolX86Unpacker}/bin/ovftool-unpacker ./ovftool.bundle -x ovftool
+    rm ovftool.bundle
+
+    local extracted=ovftool/vmware-ovftool/
+    if [ -d "$extracted" ]; then
+      # Move the directory we care about to ovftool/
+      mv "$extracted" .
+      rm -r ovftool
+      mv "$(basename -- "$extracted")" ovftool
+      echo "ovftool extracted successfully" >&2
+    else
+      echo "Could not find $extracted - are you sure this is ovftool?" >&2
+      rm -r ovftool
+      exit 1
+    fi
+
+    runHook postUnpack
+  '';
+
+  # unpackPhase for aarch64 .zip.
+  ovftoolAarch64UnpackPhase = ''
+    runHook preUnpack
+
+    unzip ${ovftoolSource}
+
+    local extracted=ovftool/
+    if [ -d "$extracted" ]; then
+      echo "ovftool extracted successfully" >&2
+    else
+      echo "Could not find $extracted - are you sure this is ovftool?" >&2
+      exit 1
+    fi
+
+    runHook postUnpack
+  '';
+
+  # When the version is bumped, postUnpackHash will change
+  # for all these supported systems. Update it from the printed error on build.
+  #
+  # This is just a sanity check, since ovftool is a self-extracting bundle
+  # that could be doing absolutely anything on 2/3 of the supported platforms.
+  ovftoolSystems = {
+    "i686-linux" = {
+      filename = "VMware-ovftool-${version}-lin.i386.bundle";
+      sha256 = "0gx78g3s77mmpir7jbiskna10i6262ihal1ywivlb6xxxxbhqzwj";
+      unpackPhase = ovftoolX86UnpackPhase;
+      postUnpackHash = "1k8rp8ywhs0cl9aad37v1p0493bdvkxrsvwg5pgv2bhvjs4hqk7n";
+    };
+    "x86_64-linux" = {
+      filename = "VMware-ovftool-${version}-lin.x86_64.bundle";
+      sha256 = "1kp2bp4d9i8y7q25yqff2bn62mh292lws7b66lyn8ka9b35kvnzc";
+      unpackPhase = ovftoolX86UnpackPhase;
+      postUnpackHash = "0zvyakwi4iishqxxisihgh91bmdsfvj5vchm2c192hia03a143py";
+    };
+    "aarch64-linux" = {
+      filename = "VMware-ovftool-${version}-lin.aarch64.zip";
+      sha256 = "0all8bwv5p5adnzqvrly6nzmxmfpywvlbfr0finr4n100yv0v1xy";
+      unpackPhase = ovftoolAarch64UnpackPhase;
+      postUnpackHash = "16vyyzrmryi8b7mrd6nxnhywvvj2pw0ban4qfiqfahw763fn6971";
+    };
+  };
+
+  ovftoolSystem = if builtins.hasAttr system ovftoolSystems then
+                    ovftoolSystems.${system}
+                  else throw "System '${system}' is unsupported by ovftool";
+
+  ovftoolSource = if builtins.hasAttr system ovftoolBundles then
+                    ovftoolBundles.${system}
+                  else
+                    requireFile {
+                      name = ovftoolSystem.filename;
+                      url = "https://my.vmware.com/group/vmware/downloads/get-download?downloadGroup=OVFTOOL441";
+                      sha256 = ovftoolSystem.sha256;
+                    };
+in
+stdenv.mkDerivation rec {
+  pname = "ovftool";
+  inherit version;
+
+  src = ovftoolSource;
+
+  buildInputs = [
+    glibc
+
+    # This is insecure, but we don't really have a way around it
+    # since ovftool depends on it. In theory we could ship their OpenSSL
+    # build... but that makes the reliance on an insecure library less obvious.
+    openssl_1_0_2
+
+    c-ares
+    (curl.override { openssl = openssl_1_0_2; })
+    expat
+    icu60
+    xercesc
+    zlib
+  ];
+
+  nativeBuildInputs = [ nix patchelf autoPatchelfHook makeWrapper unzip ];
+
+  sourceRoot = ".";
+
+  unpackPhase = ovftoolSystem.unpackPhase;
+
+  postUnpackHash = ovftoolSystem.postUnpackHash;
+
+  # Expects a directory named 'ovftool'. Validates the postUnpackHash in
+  # ovftoolSystem.
+  postUnpack = ''
+    if [ -d ovftool ]; then
+      # Ensure we're in the staging directory
+      cd ovftool
+    fi
+
+    # Verify the hash with nix-hash before proceeding to ensure reproducibility.
+    local ovftool_hash
+    ovftool_hash="$(nix-hash --type sha256 --base32 .)"
+    if [ "$ovftool_hash" != "$postUnpackHash" ]; then
+      echo "Expected hash: $postUnpackHash" >&2
+      echo "Actual hash:   $ovftool_hash" >&2
+      echo "Could not verify post-unpack hash!" >&2
+      exit 1
+    fi
+  '';
+
+  # Expects a directory named 'ovftool' containing the ovftool install.
+  # Based on https://aur.archlinux.org/packages/vmware-ovftool/
+  # with the addition of a libexec directory and a Nix-style binary wrapper.
+  installPhase = ''
+    runHook preInstall
+
+    if [ -d ovftool ]; then
+      # Ensure we're in the staging directory
+      cd ovftool
+    fi
+
+    # libraries
+    install -m 755 -d "$out/lib/$pname"
+
+    # These all appear to be VMWare proprietary except for libgoogleurl.
+    # The rest of the libraries that the installer extracts are omitted here,
+    # and provided in buildInputs.
+    #
+    # FIXME: can we replace libgoogleurl? Possibly from Chromium?
+    #
+    install -m 644 -t "$out/lib/$pname" \
+      libgoogleurl.so.59 \
+      libssoclient.so \
+      libvim-types.so libvmacore.so libvmomi.so
+
+    # ovftool specifically wants 1.0.2 but our libcrypto is named 1.0.0
+    ln -s "${openssl_1_0_2.out}/lib/libcrypto.so" \
+      "$out/lib/$pname/libcrypto.so.1.0.2"
+    ln -s "${openssl_1_0_2.out}/lib/libssl.so" \
+      "$out/lib/$pname/libssl.so.1.0.2"
+
+    # libexec
+    install -m 755 -d "$out/libexec/$pname"
+    install -m 755 -t "$out/libexec/$pname" ovftool.bin
+    install -m 644 -t "$out/libexec/$pname" icudt44l.dat
+
+    # libexec resources
+    for subdir in "certs" "env" "env/en" "schemas/DMTF" "schemas/vmware"; do
+      install -m 755 -d "$out/libexec/$pname/$subdir"
+      install -m 644 -t "$out/libexec/$pname/$subdir" "$subdir"/*.*
+    done
+
+    # EULA/OSS files
+    install -m 755 -d "$out/share/licenses/$pname"
+    install -m 644 -t "$out/share/licenses/$pname" \
+      "vmware.eula" "vmware-eula.rtf" "open_source_licenses.txt"
+
+    # documentation files
+    install -m 755 -d "$out/share/doc/$pname"
+    install -m 644 -t "$out/share/doc/$pname" "README.txt"
+
+    # binary wrapper; note that LC_CTYPE is defaulted to en_US.UTF-8 by
+    # VMWare's wrapper script. We use C.UTF-8 instead.
+    install -m 755 -d "$out/bin"
+    makeWrapper "$out/libexec/$pname/ovftool.bin" "$out/bin/ovftool" \
+      --set-default LC_CTYPE C.UTF-8 \
+      --prefix LD_LIBRARY_PATH : "$out/lib"
+
+    runHook postInstall
+  '';
+
+  preFixup = ''
+    addAutoPatchelfSearchPath "$out/lib"
+  '';
+
+  dontBuild = true;
+  dontPatch = true;
+  dontConfigure = true;
+
+  meta = with lib; {
+    description = "VMWare tools for working with OVF, OVA, and VMX images";
+    license = licenses.unfree;
+    maintainers = with maintainers; [ numinit ];
+    platforms = builtins.attrNames ovftoolSystems;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/reg/default.nix b/nixpkgs/pkgs/tools/virtualization/reg/default.nix
new file mode 100644
index 000000000000..a1b246aff0d3
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/reg/default.nix
@@ -0,0 +1,26 @@
+{ lib
+, fetchFromGitHub
+, buildGoModule
+}:
+
+buildGoModule rec {
+  pname = "reg";
+  version = "0.16.1";
+
+  src = fetchFromGitHub {
+    owner = "genuinetools";
+    repo = "reg";
+    rev = "v${version}";
+    sha256 = "1jlza1czfssssi3y9zi6kr8k9msfa7vp215ibhwbz4h97av5xw5m";
+  };
+
+  vendorSha256 = null;
+  doCheck = false;
+
+  meta = with lib; {
+    description = "Docker registry v2 command line client and repo listing generator with security checks";
+    homepage = "https://github.com/genuinetools/reg";
+    license = licenses.mit;
+    maintainers = with maintainers; [ ereslibre ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/rootlesskit/default.nix b/nixpkgs/pkgs/tools/virtualization/rootlesskit/default.nix
new file mode 100644
index 000000000000..61da0d86e33b
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/rootlesskit/default.nix
@@ -0,0 +1,22 @@
+{ lib, buildGoPackage, fetchFromGitHub }:
+
+buildGoPackage rec {
+  pname = "rootlesskit";
+  version = "0.11.1";
+  goPackagePath = "github.com/rootless-containers/rootlesskit";
+
+  src = fetchFromGitHub {
+    owner = "rootless-containers";
+    repo = "rootlesskit";
+    rev = "v${version}";
+    sha256 = "15k0503077ang9ywvmhpr1l7ax0v3wla0x8n6lqpmd71w0j2zm5r";
+  };
+
+  meta = with lib; {
+    homepage = "https://github.com/rootless-containers/rootlesskit";
+    description = ''Kind of Linux-native "fake root" utility, made for mainly running Docker and Kubernetes as an unprivileged user'';
+    license = licenses.asl20;
+    maintainers = with maintainers; [ offline ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/shipyard/default.nix b/nixpkgs/pkgs/tools/virtualization/shipyard/default.nix
new file mode 100644
index 000000000000..9c67b5462bbf
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/shipyard/default.nix
@@ -0,0 +1,29 @@
+{ lib, buildGoModule, fetchFromGitHub }:
+
+buildGoModule rec {
+  pname = "shipyard";
+  version = "0.3.2";
+
+  src = fetchFromGitHub {
+    rev = "v${version}";
+    owner = "shipyard-run";
+    repo = pname;
+    sha256 = "sha256-9eGaOSmHrJlcLOvZuLaNu8D/D/rWiyFb4ztxybUP0uM=";
+  };
+  vendorSha256 = "sha256-tTkPFftPDNXafIjAjNg6V6e/+2S/v5Do/YyAXPaGIqA=";
+
+  ldflags = [
+    "-s" "-w" "-X main.version=${version}"
+  ];
+
+  # Tests require a large variety of tools and resources to run including
+  # Kubernetes, Docker, and GCC.
+  doCheck = false;
+
+  meta = with lib; {
+    description = "Shipyard is a tool for building modern cloud native development environments";
+    homepage = "https://shipyard.run";
+    license = licenses.mpl20;
+    maintainers = with maintainers; [ cpcloud ];
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/udocker/default.nix b/nixpkgs/pkgs/tools/virtualization/udocker/default.nix
new file mode 100644
index 000000000000..6584c5bee5c6
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/udocker/default.nix
@@ -0,0 +1,49 @@
+{ lib
+, fetchFromGitHub
+, singularity
+, python3Packages
+}:
+
+python3Packages.buildPythonApplication rec {
+  pname = "udocker";
+  version = "1.3.1";
+
+  src = fetchFromGitHub {
+    owner = "indigo-dc";
+    repo = "udocker";
+    rev = "v${version}";
+    sha256 = "0dfsjgidsnah8nrclrq10yz3ja859123z81kq4zdifbrhnrn5a2x";
+  };
+
+  # crun patchelf proot runc fakechroot
+  # are download statistically linked during runtime
+  buildInputs = [
+    singularity
+  ] ++ (with python3Packages; [
+    pytest-runner
+    pycurl
+  ]);
+
+  checkInputs = with python3Packages; [
+    pytestCheckHook
+  ];
+
+  disabledTests = [
+    "test_05__get_volume_bindings"
+  ];
+
+  disabledTestPaths = [
+    # Network
+    "tests/unit/test_curl.py"
+    "tests/unit/test_dockerioapi.py"
+  ];
+
+  meta = with lib; {
+    description = "basic user tool to execute simple docker containers in user space without root privileges";
+    homepage = "https://indigo-dc.gitbooks.io/udocker";
+    license = licenses.asl20;
+    maintainers = [ maintainers.bzizou ];
+    platforms = platforms.linux;
+  };
+
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile
new file mode 100644
index 000000000000..87c9aeebb90c
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "vpsfree-client"
diff --git a/nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile.lock b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile.lock
new file mode 100644
index 000000000000..9b8fd4b918a3
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/Gemfile.lock
@@ -0,0 +1,75 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    activesupport (6.0.2.2)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (>= 0.7, < 2)
+      minitest (~> 5.1)
+      tzinfo (~> 1.1)
+      zeitwerk (~> 2.2)
+    addressable (2.7.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    concurrent-ruby (1.1.6)
+    cookiejar (0.3.3)
+    curses (1.3.2)
+    domain_name (0.5.20190701)
+      unf (>= 0.0.5, < 1.0.0)
+    em-http-request (1.1.5)
+      addressable (>= 2.3.4)
+      cookiejar (!= 0.3.1)
+      em-socksify (>= 0.3)
+      eventmachine (>= 1.0.3)
+      http_parser.rb (>= 0.6.0)
+    em-socksify (0.3.2)
+      eventmachine (>= 1.0.0.beta.4)
+    eventmachine (1.0.9.1)
+    haveapi-client (0.13.2)
+      activesupport (>= 4.0)
+      highline (~> 1.7.8)
+      json
+      require_all (~> 2.0.0)
+      rest-client (~> 2.0.2)
+      ruby-progressbar (~> 1.7.5)
+    highline (1.7.10)
+    http-cookie (1.0.3)
+      domain_name (~> 0.5)
+    http_parser.rb (0.6.0)
+    i18n (1.8.2)
+      concurrent-ruby (~> 1.0)
+    json (2.3.0)
+    mime-types (3.3.1)
+      mime-types-data (~> 3.2015)
+    mime-types-data (3.2020.0425)
+    minitest (5.14.0)
+    netrc (0.11.0)
+    public_suffix (4.0.4)
+    require_all (2.0.0)
+    rest-client (2.0.2)
+      http-cookie (>= 1.0.2, < 2.0)
+      mime-types (>= 1.16, < 4.0)
+      netrc (~> 0.8)
+    ruby-progressbar (1.7.5)
+    thread_safe (0.3.6)
+    tzinfo (1.2.7)
+      thread_safe (~> 0.1)
+    unf (0.1.4)
+      unf_ext
+    unf_ext (0.0.7.7)
+    vpsadmin-client (3.0.0.master.20190517.pre.0.3ab5ddfe)
+      curses
+      em-http-request (~> 1.1.3)
+      eventmachine (~> 1.0.3)
+      haveapi-client (~> 0.13.0)
+      json
+    vpsfree-client (0.11.0)
+      vpsadmin-client (= 3.0.0.master.20190517.pre.0.3ab5ddfe)
+    zeitwerk (2.3.0)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  vpsfree-client
+
+BUNDLED WITH
+   2.1.4
diff --git a/nixpkgs/pkgs/tools/virtualization/vpsfree-client/default.nix b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/default.nix
new file mode 100644
index 000000000000..17d570414882
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/default.nix
@@ -0,0 +1,17 @@
+{ lib, bundlerApp, bundlerUpdateScript }:
+
+bundlerApp {
+  pname = "vpsfree-client";
+  gemdir = ./.;
+  exes = [ "vpsfreectl" ];
+
+  passthru.updateScript = bundlerUpdateScript "vpsfree-client";
+
+  meta = with lib; {
+    description = "Ruby API and CLI for the vpsFree.cz API";
+    homepage = "https://github.com/vpsfreecz/vpsfree-client";
+    maintainers = with maintainers; [ zimbatm ];
+    license = licenses.gpl3;
+    platforms = platforms.unix;
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/vpsfree-client/gemset.nix b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/gemset.nix
new file mode 100644
index 000000000000..a1b4376f9484
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/vpsfree-client/gemset.nix
@@ -0,0 +1,316 @@
+{
+  activesupport = {
+    dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo" "zeitwerk"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1md98dkbirc8mq5nbz1vqq3hwqjiv7b54q7180w8wyxgd4k1awwb";
+      type = "gem";
+    };
+    version = "6.0.2.2";
+  };
+  addressable = {
+    dependencies = ["public_suffix"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1fvchp2rhp2rmigx7qglf69xvjqvzq7x0g49naliw29r2bz656sy";
+      type = "gem";
+    };
+    version = "2.7.0";
+  };
+  concurrent-ruby = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "094387x4yasb797mv07cs3g6f08y56virc2rjcpb1k79rzaj3nhl";
+      type = "gem";
+    };
+    version = "1.1.6";
+  };
+  cookiejar = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0q0kmbks9l3hl0wdq744hzy97ssq9dvlzywyqv9k9y1p3qc9va2a";
+      type = "gem";
+    };
+    version = "0.3.3";
+  };
+  curses = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0hic9kq09dhh8jqjx3k1991rnqhlj3glz82w0g7ndcri52m1hgqg";
+      type = "gem";
+    };
+    version = "1.3.2";
+  };
+  domain_name = {
+    dependencies = ["unf"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0lcqjsmixjp52bnlgzh4lg9ppsk52x9hpwdjd53k8jnbah2602h0";
+      type = "gem";
+    };
+    version = "0.5.20190701";
+  };
+  em-http-request = {
+    dependencies = ["addressable" "cookiejar" "em-socksify" "eventmachine" "http_parser.rb"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "13rxmbi0fv91n4sg300v3i9iiwd0jxv0i6xd0sp81dx3jlx7kasx";
+      type = "gem";
+    };
+    version = "1.1.5";
+  };
+  em-socksify = {
+    dependencies = ["eventmachine"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0rk43ywaanfrd8180d98287xv2pxyl7llj291cwy87g1s735d5nk";
+      type = "gem";
+    };
+    version = "0.3.2";
+  };
+  eventmachine = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "17jr1caa3ggg696dd02g2zqzdjqj9x9q2nl7va82l36f7c5v6k4z";
+      type = "gem";
+    };
+    version = "1.0.9.1";
+  };
+  haveapi-client = {
+    dependencies = ["activesupport" "highline" "json" "require_all" "rest-client" "ruby-progressbar"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1wn5zvyy3w3q74m2fsb4jwxfdbdnpyyzxdf9iklpggcdmjhb78z0";
+      type = "gem";
+    };
+    version = "0.13.2";
+  };
+  highline = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "01ib7jp85xjc4gh4jg0wyzllm46hwv8p0w1m4c75pbgi41fps50y";
+      type = "gem";
+    };
+    version = "1.7.10";
+  };
+  http-cookie = {
+    dependencies = ["domain_name"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "004cgs4xg5n6byjs7qld0xhsjq3n6ydfh897myr2mibvh6fjc49g";
+      type = "gem";
+    };
+    version = "1.0.3";
+  };
+  "http_parser.rb" = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "15nidriy0v5yqfjsgsra51wmknxci2n2grliz78sf9pga3n0l7gi";
+      type = "gem";
+    };
+    version = "0.6.0";
+  };
+  i18n = {
+    dependencies = ["concurrent-ruby"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0jwrd1l4mxz06iyx6053lr6hz2zy7ah2k3ranfzisvych5q19kwm";
+      type = "gem";
+    };
+    version = "1.8.2";
+  };
+  json = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0nrmw2r4nfxlfgprfgki3hjifgrcrs3l5zvm3ca3gb4743yr25mn";
+      type = "gem";
+    };
+    version = "2.3.0";
+  };
+  mime-types = {
+    dependencies = ["mime-types-data"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1zj12l9qk62anvk9bjvandpa6vy4xslil15wl6wlivyf51z773vh";
+      type = "gem";
+    };
+    version = "3.3.1";
+  };
+  mime-types-data = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1zin0q26wc5p7zb7glpwary7ms60s676vcq987yv22jgm6hnlwlh";
+      type = "gem";
+    };
+    version = "3.2020.0425";
+  };
+  minitest = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0g73x65hmjph8dg1h3rkzfg7ys3ffxm35hj35grw75fixmq53qyz";
+      type = "gem";
+    };
+    version = "5.14.0";
+  };
+  netrc = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0gzfmcywp1da8nzfqsql2zqi648mfnx6qwkig3cv36n9m0yy676y";
+      type = "gem";
+    };
+    version = "0.11.0";
+  };
+  public_suffix = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1l1kqw75asziwmzrig8rywxswxz8l91sc3pvns02ffsqac1a3wiz";
+      type = "gem";
+    };
+    version = "4.0.4";
+  };
+  require_all = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0sjf2vigdg4wq7z0xlw14zyhcz4992s05wgr2s58kjgin12bkmv8";
+      type = "gem";
+    };
+    version = "2.0.0";
+  };
+  rest-client = {
+    dependencies = ["http-cookie" "mime-types" "netrc"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1hzcs2r7b5bjkf2x2z3n8z6082maz0j8vqjiciwgg3hzb63f958j";
+      type = "gem";
+    };
+    version = "2.0.2";
+  };
+  ruby-progressbar = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0hynaavnqzld17qdx9r7hfw00y16ybldwq730zrqfszjwgi59ivi";
+      type = "gem";
+    };
+    version = "1.7.5";
+  };
+  thread_safe = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0nmhcgq6cgz44srylra07bmaw99f5271l0dpsvl5f75m44l0gmwy";
+      type = "gem";
+    };
+    version = "0.3.6";
+  };
+  tzinfo = {
+    dependencies = ["thread_safe"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1i3jh086w1kbdj3k5l60lc3nwbanmzdf8yjj3mlrx9b2gjjxhi9r";
+      type = "gem";
+    };
+    version = "1.2.7";
+  };
+  unf = {
+    dependencies = ["unf_ext"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0bh2cf73i2ffh4fcpdn9ir4mhq8zi50ik0zqa1braahzadx536a9";
+      type = "gem";
+    };
+    version = "0.1.4";
+  };
+  unf_ext = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0wc47r23h063l8ysws8sy24gzh74mks81cak3lkzlrw4qkqb3sg4";
+      type = "gem";
+    };
+    version = "0.0.7.7";
+  };
+  vpsadmin-client = {
+    dependencies = ["curses" "em-http-request" "eventmachine" "haveapi-client" "json"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0ki3204pkg3f9wk9plbq5n9lrnsmc364smfxyrbq32gi8ag2y2s8";
+      type = "gem";
+    };
+    version = "3.0.0.master.20190517.pre.0.3ab5ddfe";
+  };
+  vpsfree-client = {
+    dependencies = ["vpsadmin-client"];
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "0cs2ibl9kl39hnpzyhyczaqv4i58pn106vx2m6lds9p3av5mcbxs";
+      type = "gem";
+    };
+    version = "0.11.0";
+  };
+  zeitwerk = {
+    groups = ["default"];
+    platforms = [];
+    source = {
+      remotes = ["https://rubygems.org"];
+      sha256 = "1akpm3pwvyiack2zk6giv9yn3cqb8pw6g40p4394pdc3xmy3s4k0";
+      type = "gem";
+    };
+    version = "2.3.0";
+  };
+}
diff --git a/nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/default.nix b/nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/default.nix
new file mode 100644
index 000000000000..ab3c9b1e71cd
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/default.nix
@@ -0,0 +1,75 @@
+{ lib, stdenv, fetchurl, bzip2, lzo, zlib, xz, bash, python, gnutar, gnused, gnugrep, which }:
+
+stdenv.mkDerivation (rec {
+  pname = "xe-guest-utilities";
+  version = "6.2.0";
+  meta = {
+    description = "Citrix XenServer Tools";
+    homepage = "http://citrix.com/English/ps2/products/product.asp?contentID=683148&ntref=hp_nav_US";
+    maintainers = with lib.maintainers; [ benwbooth ];
+    platforms = lib.platforms.linux;
+    license = [ lib.licenses.gpl2 lib.licenses.lgpl21 ];
+  };
+  src = fetchurl {
+    url = "https://sources.archlinux.org/other/community/xe-guest-utilities/xe-guest-utilities_${version}-1120.tar.gz";
+    sha256 = "f9593cd9588188f80253e736f48d8dd94c5b517abb18316085f86acffab48794";
+  };
+  buildInputs = [ bzip2 gnutar gnused python lzo zlib xz stdenv gnugrep which ];
+  patches = [ ./ip-address.patch ];
+  postPatch = ''
+    tar xf "$NIX_BUILD_TOP/$name/xenstore-sources.tar.bz2"
+  '';
+
+  buildPhase = ''
+    export CC=gcc
+    export CFLAGS='-Wall -Wstrict-prototypes -Wno-unused-local-typedefs -Wno-sizeof-pointer-memaccess'
+    export PYTHON=python2
+    cd "$NIX_BUILD_TOP/$name/uclibc-sources"
+    for file in Config.mk tools/libxc/Makefile tools/misc/Makefile tools/misc/lomount/Makefile tools/xenstore/Makefile; do
+      substituteInPlace "$file" --replace -Werror ""
+    done
+    make -C tools/include
+    make -C tools/libxc
+    make -C tools/xenstore
+  '';
+
+  installPhase = ''
+    export CFLAGS+='-Wall -Wstrict-prototypes -Wno-unused-local-typedefs -Wno-sizeof-pointer-memaccess'
+    if [[ $CARCH == x86_64 ]]; then
+      export LIBLEAFDIR_x86_64=lib
+    fi
+    for f in include libxc xenstore; do
+      [[ ! -d $NIX_BUILD_TOP/$name/uclibc-sources/tools/$f ]] && continue
+      make -C "$NIX_BUILD_TOP/$name/uclibc-sources/tools/$f" DESTDIR="$out" BINDIR=/bin SBINDIR=/bin INCLUDEDIR=/include LIBDIR=/lib install
+    done
+    rm -r "$out"/var
+
+    cd "$NIX_BUILD_TOP/$name"
+    install -Dm755 xe-update-guest-attrs "$out/bin/xe-update-guest-attrs"
+    install -Dm755 xe-daemon "$out/bin/xe-daemon"
+    install -Dm644 xen-vcpu-hotplug.rules "$out/lib/udev/rules.d/10-xen-vcpu-hotplug.rules"
+    substituteInPlace "$out/bin/xe-daemon" --replace sbin bin
+    substituteInPlace "$out/bin/xe-daemon" --replace /usr/ "$out/"
+    substituteInPlace "$out/bin/xe-update-guest-attrs" --replace /usr/ "$out/"
+    substituteInPlace "$out/bin/xe-update-guest-attrs" --replace 'export PATH=' 'export PATH=$PATH:'
+    substituteInPlace "$out/lib/udev/rules.d/10-xen-vcpu-hotplug.rules" --replace /bin/sh '${bash}/bin/sh'
+
+    cat <<'EOS' >"$out/bin/xe-linux-distribution"
+    #!${bash}/bin/bash -eu
+    . /etc/os-release
+    if [[ $# -gt 0 ]]; then
+      mkdir -p "$(dirname "$1")"
+      exec 1>"$1"
+    fi
+    cat <<EOF
+    os_distro="$ID"
+    os_majorver="''${VERSION_ID%%.*}"
+    os_minorver="''${VERSION_ID#*.}"
+    os_uname="$(uname -r)"
+    os_name="$PRETTY_NAME"
+    EOF
+    EOS
+    chmod 0755 "$out/bin/xe-linux-distribution"
+  '';
+
+})
diff --git a/nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/ip-address.patch b/nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/ip-address.patch
new file mode 100644
index 000000000000..185f259ef708
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/xe-guest-utilities/ip-address.patch
@@ -0,0 +1,16 @@
+diff -uNr a/xe-update-guest-attrs b/xe-update-guest-attrs
+--- a/xe-update-guest-attrs	2012-09-25 12:45:14.000000000 +0200
++++ b/xe-update-guest-attrs	2012-11-21 16:46:35.000000000 +0100
+@@ -177,9 +177,9 @@
+ #           collisions:0 txqueuelen:0 
+ #           RX bytes:3604609 (3.4 MiB)  TX bytes:3604609 (3.4 MiB)
+ 
+-ifs=`/sbin/ifconfig | sed -n -e 's/^\([a-z0-9]\+\).*/name \1/p' \
+-    -e 's/.*inet addr:\('$IPADDR_RE'\) .*/ipv4 \1/p' \
+-    -e 's+.*inet6 addr: \('$IPADDR6_RE'\)/.*+ipv6 \1+p' | \
++ifs=`ip addr show | sed -n -e 's/^[[:digit:]]*: \([a-z0-9]*\): .*/name \1 /gp;' \
++    -e 's/^[[:space:]]\{4\}inet \('${IPADDR_RE}'\)\/.*/ipv4 \1 /gp;' \
++    -e 's/^[[:space:]]\{4\}inet6 \('${IPADDR6_RE}'\)\/.*/ipv6 \1 /gp;' | \
+ while read tag value; do
+     case "${tag}" in
+         name)
\ No newline at end of file
diff --git a/nixpkgs/pkgs/tools/virtualization/xva-img/default.nix b/nixpkgs/pkgs/tools/virtualization/xva-img/default.nix
new file mode 100644
index 000000000000..4fe2e5bbb40b
--- /dev/null
+++ b/nixpkgs/pkgs/tools/virtualization/xva-img/default.nix
@@ -0,0 +1,24 @@
+{ stdenv, lib, cmake, fetchFromGitHub, openssl }:
+
+stdenv.mkDerivation rec {
+  pname = "xva-img";
+  version = "1.4.2";
+
+  src = fetchFromGitHub {
+    owner = "eriklax";
+    repo = "xva-img";
+    rev = version;
+    sha256 = "sha256-QHCKGsHSMT2P64No1IUCjenm1XZMSgEvsJGJOyHFZS8=";
+  };
+
+  nativeBuildInputs = [ cmake ];
+
+  buildInputs = [ openssl ];
+
+  meta = {
+    maintainers = with lib.maintainers; [ lheckemann willibutz globin ];
+    description = "Tool for converting Xen images to raw and back";
+    license = lib.licenses.gpl2;
+    platforms = lib.platforms.unix;
+  };
+}