ClusterLabs/pcs

Packaging pcs with Nix

Opened this issue · 1 comments

I've been trying to package pcs for NixOS and I've been mostly successful. You can see my attempt here: https://github.com/matt1432/nixos-pcsd

However, a lot of changes to the build process were needed to get everything to work so I was looking for some help or pointers on how I could deal with this in a better way.

Here are the things I would like help with:

Modifications of build files
postUnpack = ''
      # Fix version of untagged build
      echo 'printf %s "${version}"' > $sourceRoot/make/git-version-gen


      # Fix pam path https://github.com/NixOS/nixpkgs/blob/5a072b4a9d7ccf64df63645f3ee808dc115210ba/pkgs/development/python-modules/pamela/default.nix#L20
      substituteInPlace $sourceRoot/pcs/lib/auth/pam.py --replace \
        'find_library("pam")' \
        '"${lib.getLib pam}/lib/libpam.so"'


      # Fix hardcoded paths to binaries
      substituteInPlace $sourceRoot/pcsd/bootstrap.rb --replace \
        "/bin/hostname" "${lib.getBin hostname}/bin/hostname"

      substituteInPlace $sourceRoot/pcsd/pcs.rb --replace \
        "/bin/cat" "${lib.getBin coreutils}/bin/cat"


      # Fix systemd path
      substituteInPlace $sourceRoot/configure.ac \
        --replace 'AC_SUBST([SYSTEMD_UNIT_DIR])' "SYSTEMD_UNIT_DIR=$out/lib/systemd/system
        AC_SUBST([SYSTEMD_UNIT_DIR])"


      # Fix paths to corosync and pacemaker executables
      substituteInPlace $sourceRoot/configure.ac \
        --replace 'PCS_PKG_CHECK_VAR([COROEXECPREFIX], [corosync], [exec_prefix], [/usr])' "COROEXECPREFIX=${corosync}
        AC_SUBST([COROEXECPREFIX])"

      substituteInPlace $sourceRoot/configure.ac \
        --replace 'PCS_PKG_CHECK_VAR([PCMKEXECPREFIX], [pacemaker], [exec_prefix], [/usr])' "PCMKEXECPREFIX=${pacemaker}
        AC_SUBST([PCMKEXECPREFIX])"

      substituteInPlace $sourceRoot/configure.ac \
        --replace "\$prefix/libexec/pacemaker" "${pacemaker}/libexec/pacemaker"


      # Don't create var files
      substituteInPlace $sourceRoot/pcsd/Makefile.am --replace \
        '$(MKDIR_P) -m 0700 $(DESTDIR)$(localstatedir)/log/pcsd' ""

      substituteInPlace $sourceRoot/pcsd/Makefile.am --replace \
	      '$(MKDIR_P) -m 0700 $(DESTDIR)$(localstatedir)/lib/pcsd' ""
    '';
Configure flags
configureFlags = [
  # This was the closest to what I needed, see PAM config
  "--with-distro=fedora"
  "--enable-use-local-cache-only"
  "--with-pcs-lib-dir=${placeholder "out"}/lib"
  "--with-default-config-dir=${placeholder "out"}/etc"
  "--localstatedir=/var"
];
PAM config
security.pam.services.pcsd.text = ''
  #%PAM-1.0
  auth       include      systemd-user
  account    include      systemd-user
  password   include      systemd-user
  session    include      systemd-user
'';


Some more info:

Untagged build

Since I wanted to get latest git to update to the latest gems, I tried building from source but I got this error:

> make/git-version-gen: WARNING: .gitarchivever doesn't contain valid version tag                                                            
> make/git-version-gen: ERROR: Can't find valid version. Please use valid git repository, released tarball or version tagged archive

which I fixed with this line: echo 'printf %s "${version}"' > $sourceRoot/make/git-version-gen
I could definitely use some help with git-version-gen



SystemD paths

In nix, all the built files go to $out which is a path in the nix store that only has the package's files. I found it quite hard to specify where pcs should place the systemd unit files so I had to a very ugly text replacement with a new line to get it to work.
I am also unsure which systemd environment variable I was supposed to change.

# This is basically a sed that replace the 2nd line with the 3rd and 4th lines in configure.ac
substituteInPlace $sourceRoot/configure.ac --replace \
'AC_SUBST([SYSTEMD_UNIT_DIR])' \
"SYSTEMD_UNIT_DIR=$out/lib/systemd/system
AC_SUBST([SYSTEMD_UNIT_DIR])"



Pacemaker and Corosync executables

To have the pacemaker and corosync executables available to pcs, I basically did the same thing as for the systemd path but for the env vars PCMKEXECPREFIX and COROEXECPREFIX
I also had to change the $prefix for $prefix/libexec/pacemaker because the prefix would be different for every package in nix



Var directories

In nix, the builds are sandbox and therefore cannot make directories. It would be nice to have a flag maybe to disable that instead of replacing the lines with nothing like I did, although there might be a better way of doing this.

In nix, the service takes care of this which I declare in my module in my git repo.



"--with-distro=*"

As far as I can tell, the major difference in the --with-distro parameters was the PAM configuration. In my module I had to make my own PAM config file based on the fedora one, but I replaced system-auth with systemd-user. I have no real knowledge of PAM so I have no idea if this is good or not but it works.



Obviously I am not expecting pcs to support nix but I would appreciate any help I can get since this was my most challenging software to package in nix and I am pretty certain there is still a lot I can improve.
Thank you

Hi @matt1432,

ad 1) untagged build

Build from an untagged commit is handled by creating a file .tarball-version
in the root of source directory. Just create a string which contains the latest
version and short commit hash like this: ${version}+${short_commit_hash}.
You can look at fedora pcs.spec
file how it is done.

ad 2) pam path

      # Fix pam path https://github.com/NixOS/nixpkgs/blob/5a072b4a9d7ccf64df63645f3ee808dc115210ba/pkgs/development/python-modules/pamela/default.nix#L20
      substituteInPlace $sourceRoot/pcs/lib/auth/pam.py --replace \
        'find_library("pam")' \
        '"${lib.getLib pam}/lib/libpam.so"'

I'm not sure how to help with this. Probably it is some issue of python package in nixos, that it cannot find the right path.

ad 3) fix other paths

     # Fix systemd path
      substituteInPlace $sourceRoot/configure.ac \
        --replace 'AC_SUBST([SYSTEMD_UNIT_DIR])' "SYSTEMD_UNIT_DIR=$out/lib/systemd/system
        AC_SUBST([SYSTEMD_UNIT_DIR])"


      # Fix paths to corosync and pacemaker executables
      substituteInPlace $sourceRoot/configure.ac \
        --replace 'PCS_PKG_CHECK_VAR([COROEXECPREFIX], [corosync], [exec_prefix], [/usr])' "COROEXECPREFIX=${corosync}
        AC_SUBST([COROEXECPREFIX])"

      substituteInPlace $sourceRoot/configure.ac \
        --replace 'PCS_PKG_CHECK_VAR([PCMKEXECPREFIX], [pacemaker], [exec_prefix], [/usr])' "PCMKEXECPREFIX=${pacemaker}
        AC_SUBST([PCMKEXECPREFIX])"

      substituteInPlace $sourceRoot/configure.ac \
        --replace "\$prefix/libexec/pacemaker" "${pacemaker}/libexec/pacemaker"

I think you do not have to modify configure.ac file. It is enough to define env variables before running configure script in order to override these settings:

SYSTEMD_UNIT_DIR_TMP="$out/lib/systemd/system"
COROEXECPREFIX="${corosync}"
PCMKEXECPREFIX="${pacemaker}"
PCMKDAEMONDIR="${pacemaker}/libexec/pacemaker"

ad 4) var files

      # Don't create var files
      substituteInPlace $sourceRoot/pcsd/Makefile.am --replace \
        '$(MKDIR_P) -m 0700 $(DESTDIR)$(localstatedir)/log/pcsd' ""

      substituteInPlace $sourceRoot/pcsd/Makefile.am --replace \
      '$(MKDIR_P) -m 0700 $(DESTDIR)$(localstatedir)/lib/pcsd' ""

Is it working without these directories? I think pcsd needs them in order to be able run.
I don't know how they should be handled in nix.

ad 5) PAM config
If your PAM config works then you can create pull request which adds a file pcsd/pam/pcsd.nixos
and also add a new distro section to configure.ac

I hope I helped a little bit.