Commit 232f6bb4 authored by Michael Raskin's avatar Michael Raskin
Browse files

Merge pull request #4929 from abbradar/prl-tools

Add packages and support for Parallel Guest Tools
parents 2399edd6 32e18bc7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -389,6 +389,7 @@
  ./virtualisation/lxc.nix
  #./virtualisation/nova.nix
  ./virtualisation/openvswitch.nix
  ./virtualisation/parallels-guest.nix
  ./virtualisation/virtualbox-guest.nix
  #./virtualisation/xen-dom0.nix
]
+93 −0
Original line number Diff line number Diff line
{ config, lib, pkgs, pkgs_i686, ... }:

with lib;

let

  prl-tools = config.boot.kernelPackages.prl-tools;

in

{

  options = {
    hardware.parallels = {

      enable = mkOption {
        type = types.bool;
        default = false;
        description = ''
          This enables Parallel Tools for Linux guests, along with provided
          video, mouse and other hardware drivers.
        '';
      };

    };

  };

  config = mkIf config.hardware.parallels.enable {

    services.xserver = {
      drivers = singleton
        { name = "prlvideo"; modules = [ prl-tools ]; libPath = [ prl-tools ]; };

      screenSection = ''
        Option "NoMTRR"
      '';

      config = ''
        Section "InputClass"
          Identifier "prlmouse"
          MatchIsPointer "on"
          MatchTag "prlmouse"
          Driver "prlmouse"
        EndSection
      '';
    };

    hardware.opengl.package = prl-tools;
    hardware.opengl.package32 = pkgs_i686.linuxPackages.prl-tools.override { libsOnly = true; kernel = null; };

    services.udev.packages = [ prl-tools ];

    environment.systemPackages = [ prl-tools ];

    boot.extraModulePackages = [ prl-tools ];

    boot.kernelModules = [ "prl_tg" "prl_eth" "prl_fs" "prl_fs_freeze" "acpi_memhotplug" ];

    services.ntp.enable = false;

    systemd.services.prltoolsd = {
      description = "Parallels Tools' service";
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        ExecStart = "${prl-tools}/bin/prltoolsd -f";
        PIDFile = "/var/run/prltoolsd.pid";
      };
    };

    systemd.services.prlfsmountd = {
      description = "Parallels Shared Folders Daemon";
      wantedBy = [ "multi-user.target" ];
      serviceConfig = rec {
        ExecStart = "${prl-tools}/sbin/prlfsmountd ${PIDFile}";
        ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /media";
        ExecStopPost = "${prl-tools}/sbin/prlfsmountd -u";
        PIDFile = "/run/prlfsmountd.pid";
      };
    };

    systemd.services.prlshprint = {
      description = "Parallels Shared Printer Tool";
      wantedBy = [ "multi-user.target" ];
      bindsTo = [ "cupsd.service" ];
      serviceConfig = {
        Type = "forking";
        ExecStart = "${prl-tools}/bin/prlshprint";
      };
    };

  };
}
+8 −0
Original line number Diff line number Diff line
[Desktop Entry]
Version=@version@
Encoding=UTF-8
Name=@description@
Type=Application
Exec=@exec@
X-KDE-autostart-phase=1
GenericName[en_US]=
+197 −0
Original line number Diff line number Diff line
{ stdenv, lib, requireFile, makeWrapper, substituteAll, p7zip
, gawk, utillinux, xorg, glib, dbus_glib, zlib
, kernel ? null, libsOnly ? false
}:

assert (!libsOnly) -> kernel != null;

let xorgFullVer = (builtins.parseDrvName xorg.xorgserver.name).version;
    xorgVer = lib.concatStringsSep "." (lib.take 2 (lib.splitString "." xorgFullVer));
    x64 = if stdenv.system == "x86_64-linux" then true
          else if stdenv.system == "i686-linux" then false
          else abort "Parallels Tools for Linux only support {x86-64,i686}-linux targets";
    # We autostart user services by ourselves, because prlcc uses hardcoded paths.
    autostart = [ { exec = "prlcc";
                    description = "Parallels Control Center";
                  }
                  { exec = "prldhd";
                    description = "Parallels Control Center"; # not a mistake
                  }
                  { exec = "prl_wmouse_d";
                    description = "Parallels Walking Mouse Daemon";
                  }
                  { exec = "prlcp";
                    description = "Parallels CopyPaste Tool";
                  }
                  { exec = "prlsga";
                    description = "Parallels Shared Guest Applications Tool";
                  }
                  { exec = "prlshprof";
                    description = "Parallels Shared Profile Tool";
                  }
                ];
in
stdenv.mkDerivation rec {
  version = "10.0.2.27712";
  name = "prl-tools-${version}";

  src = requireFile rec {
    name = "prl-tools-lin.iso";
    sha256 = "07960jvyv7gihjlg922znjm6db6l6bd23x9mg6ympwibzf2mylmx";
    message = ''
      Please, place Parallel Tools for Linux image into Nix store
      using either
        nix-store --add-fixed sha256 ${name}
      or
        nix-prefetch-url file://path/to/${name}
    '';
  };

  # also maybe python2 to generate xorg.conf
  nativeBuildInputs = [ p7zip ] ++ lib.optionals (!libsOnly) [ makeWrapper ];

  inherit libsOnly;

  unpackPhase = ''
    7z x $src
    export sourceRoot=.
    if test -z "$libsOnly"; then
      ( cd kmods; tar -xaf prl_mod.tar.gz )
    fi
    ( cd tools; tar -xaf prltools${if x64 then ".x64" else ""}.tar.gz )
  '';

  kernelVersion = if libsOnly then "" else (builtins.parseDrvName kernel.name).version;
  kernelDir = if libsOnly then "" else "${kernel.dev}/lib/modules/${kernelVersion}";
  scriptPath = lib.concatStringsSep ":" (lib.optionals (!libsOnly) [ "${utillinux}/bin" "${gawk}/bin" ]);

  buildPhase = ''
    if test -z "$libsOnly"; then
      ( # kernel modules
        cd kmods
        make -f Makefile.kmods \
          KSRC=$kernelDir/source \
          HEADERS_CHECK_DIR=$kernelDir/source \
          KERNEL_DIR=$kernelDir/build \
          SRC=$kernelDir/build \
          KVER=$kernelVersion
      )

      # Xorg config (maybe would be useful for other versions)
      #python2 installer/xserver-config.py xorg ${xorgVer} /dev/null parallels.conf
    fi
  '';

  libPath = with xorg;
            stdenv.lib.makeLibraryPath ([ stdenv.gcc.gcc libXrandr libXext libX11 libXcomposite libXinerama ]
            ++ lib.optionals (!libsOnly) [ libXi glib dbus_glib zlib ]);

  desktops = map (x: substituteAll ({
               src = ./autostart.desktop;
               name = x.exec + ".desktop";
               version = version;
             } // x)) autostart;

  installPhase = ''
    if test -z "$libsOnly"; then
      ( # kernel modules
        cd kmods
        mkdir -p $out/lib/modules/${kernelVersion}/extra
        cp prl_eth/pvmnet/prl_eth.ko $out/lib/modules/${kernelVersion}/extra
        cp prl_tg/Toolgate/Guest/Linux/prl_tg/prl_tg.ko $out/lib/modules/${kernelVersion}/extra
        cp prl_fs/SharedFolders/Guest/Linux/prl_fs/prl_fs.ko $out/lib/modules/${kernelVersion}/extra
        cp prl_fs_freeze/Snapshot/Guest/Linux/prl_freeze/prl_fs_freeze.ko $out/lib/modules/${kernelVersion}/extra
      )
    fi

    ( # tools
      cd tools
      mkdir -p $out/lib

      if test -z "$libsOnly"; then
        # install binaries
        for i in bin/* sbin/prl_nettool sbin/prl_snapshot; do
          install -Dm755 $i $out/$i
        done
        # other binaries
        for i in xorg.7.1/usr/bin/*; do
          cp $i $out/bin
        done

        for i in $out/bin/* $out/sbin/*; do
          patchelf \
            --interpreter "$(cat $NIX_GCC/nix-support/dynamic-linker)" \
            --set-rpath "$out/lib:$libPath" \
            $i
        done

        mkdir -p $out/bin
        install -Dm755 ../installer/prlfsmountd.sh $out/sbin/prlfsmountd
        wrapProgram $out/sbin/prlfsmountd \
          --prefix PATH ':' "$scriptPath"

        for i in lib/*.a; do
          cp $i $out/lib
        done

        for i in xorg.7.1/usr/lib/libprl_wmouse_watcher.*; do
          cp $i $out/lib
        done

        mkdir -p $out/lib/udev/rules.d
        for i in *.rules; do
          sed 's,/bin/bash,${stdenv.shell},g' $i > $out/lib/udev/rules.d/$i
        done

        mkdir -p $out/share/autostart
        for i in $desktops; do
          cat $i | sed "s,^Exec=,Exec=$out/bin/," > $out/share/autostart/$(basename $i)
        done

        (
          cd xorg.${xorgVer}
          # Install the X modules.
          (
            cd x-server/modules
            for i in */*; do
              install -Dm755 $i $out/lib/xorg/modules/$i
            done
          )
          (
            cd usr/lib
            libGLXname=$(echo libglx.so*)
            install -Dm755 $libGLXname $out/lib/xorg/modules/extensions/$libGLXname
            ln -s $libGLXname $out/lib/xorg/modules/extensions/libglx.so
            ln -s $libGLXname $out/lib/xorg/modules/extensions/libglx.so.1
          )
        )
      fi

      for i in xorg.7.1/usr/lib/libGL.*; do
        cp $i $out/lib
      done

      cd $out
      find -name \*.so\* -type f -exec \
        patchelf --set-rpath "$out/lib:$libPath" {} \;

      cd lib
      libGLname=$(echo libGL.so*)
      ln -s $libGLname libGL.so
      ln -s $libGLname libGL.so.1
    )
  '';

  dontStrip = true;
  dontPatchELF = true;

  meta = with stdenv.lib; {
    description = "Parallels Tools for Linux guests";
    homepage = http://parallels.com;
    platforms = platforms.linux;
    license = licenses.unfree;
    # I was making this package blindly and requesting testing from the real user,
    # so I can't even test it by myself and won't provide future updates.
    maintainers = with maintainers; [ abbradar ];
  };
}
+2 −0
Original line number Diff line number Diff line
@@ -8290,6 +8290,8 @@ let

    perf = callPackage ../os-specific/linux/kernel/perf.nix { };

    prl-tools = callPackage ../os-specific/linux/prl-tools { };

    psmouse_alps = callPackage ../os-specific/linux/psmouse-alps { };

    seturgent = callPackage ../os-specific/linux/seturgent { };