nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 lib,
3 callPackage,
4 nixosTests,
5 stdenv,
6 fetchurl,
7 autoPatchelfHook,
8 rpmextract,
9 libxcrypt-legacy,
10 zlib,
11 lvm2, # LVM image backup and restore functions (optional)
12 acl, # EXT2/EXT3/XFS ACL support (optional)
13 gnugrep,
14 procps,
15 jdk, # Java GUI (needed for `enableGui`)
16 buildEnv,
17 makeWrapper,
18 enableGui ? false, # enables Java GUI `dsmj`
19 # path to `dsm.sys` configuration files
20 dsmSysCli ? "/etc/tsm-client/cli.dsm.sys",
21 dsmSysApi ? "/etc/tsm-client/api.dsm.sys",
22}:
23
24# For an explanation of optional packages
25# (features provided by them, version limits), see
26# https://web.archive.org/web/20240118051918/https://www.ibm.com/support/pages/node/660813#Version%208.1
27
28# IBM Tivoli Storage Manager Client uses a system-wide
29# client system-options file `dsm.sys` and expects it
30# to be located in a directory within the package.
31# Note that the command line client and the API use
32# different "dms.sys" files (located in different directories).
33# Since these files contain settings to be altered by the
34# admin user (e.g. TSM server name), we create symlinks
35# in place of the files that the client attempts to open.
36# Use the arguments `dsmSysCli` and `dsmSysApi` to
37# provide the location of the configuration files for
38# the command-line interface and the API, respectively.
39#
40# While the command-line interface contains wrappers
41# that help the executables find the configuration file,
42# packages that link against the API have to
43# set the environment variable `DSMI_DIR` to
44# point to this derivations `/dsmi_dir` directory symlink.
45# Other environment variables might be necessary,
46# depending on local configuration or usage; see:
47# https://www.ibm.com/docs/en/storage-protect/8.1.27?topic=solaris-set-api-environment-variables
48
49let
50
51 meta = {
52 homepage = "https://www.ibm.com/products/storage-protect";
53 downloadPage = "https://www.ibm.com/support/fixcentral/swg/selectFixes?product=ibm/StorageSoftware/IBM+Spectrum+Protect";
54 platforms = [ "x86_64-linux" ];
55 mainProgram = "dsmc";
56 sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
57 license = lib.licenses.unfree;
58 maintainers = [ lib.maintainers.yarny ];
59 description = "IBM Storage Protect (Tivoli Storage Manager) CLI and API";
60 longDescription = ''
61 IBM Storage Protect (Tivoli Storage Manager) provides
62 a single point of control for backup and recovery.
63 This package contains the client software, that is,
64 a command line client and linkable libraries.
65
66 Note that the software requires a system-wide
67 client system-options file (commonly named "dsm.sys").
68 This package allows to use separate files for
69 the command-line interface and for the linkable API.
70 The location of those files can
71 be provided as build parameters.
72 '';
73 };
74
75 passthru.tests = {
76 test-cli = callPackage ./test-cli.nix { };
77 test-gui = nixosTests.tsm-client-gui;
78 };
79
80 mkSrcUrl =
81 version:
82 let
83 major = lib.versions.major version;
84 minor = lib.versions.minor version;
85 patch = lib.versions.patch version;
86 fixup = lib.lists.elemAt (lib.versions.splitVersion version) 3;
87 in
88 "https://public.dhe.ibm.com/storage/tivoli-storage-management/${
89 if fixup == "0" then "maintenance" else "patches"
90 }/client/v${major}r${minor}/Linux/LinuxX86/BA/v${major}${minor}${patch}/${version}-TIV-TSMBAC-LinuxX86.tar";
91
92 unwrapped = stdenv.mkDerivation (finalAttrs: {
93 name = "tsm-client-${finalAttrs.version}-unwrapped";
94 version = "8.1.27.0";
95 src = fetchurl {
96 url = mkSrcUrl finalAttrs.version;
97 hash = "sha512-nbQHoD7fUp4qBTgRJ6nHXF4PsZRTin7FGPi340jKc73O/9DCNb1JQG/gY+B2xzPM2g6agqWu/MX5J+Wt0nOEkA==";
98 };
99 inherit meta passthru;
100
101 nativeBuildInputs = [
102 autoPatchelfHook
103 rpmextract
104 ];
105 buildInputs = [
106 libxcrypt-legacy
107 stdenv.cc.cc
108 zlib
109 ];
110 runtimeDependencies = [
111 (lib.attrsets.getLib lvm2)
112 ];
113 sourceRoot = ".";
114
115 postUnpack = ''
116 rpmextract TIVsm-API64.x86_64.rpm
117 rpmextract TIVsm-APIcit.x86_64.rpm
118 rpmextract TIVsm-BA.x86_64.rpm
119 rpmextract TIVsm-BAcit.x86_64.rpm
120 rpmextract TIVsm-BAhdw.x86_64.rpm
121 rpmextract TIVsm-JBB.x86_64.rpm
122 # use globbing so that version updates don't break the build:
123 rpmextract gskcrypt64-*.linux.x86_64.rpm
124 rpmextract gskssl64-*.linux.x86_64.rpm
125 '';
126
127 installPhase = ''
128 runHook preInstall
129 mkdir --parents $out
130 mv --target-directory=$out usr/* opt
131 runHook postInstall
132 '';
133
134 # fix symlinks pointing to `..../opt/....`
135 preFixup = ''
136 for link in $(find $out -type l -lname '*../opt*')
137 do
138 ln --symbolic --force --no-target-directory "$(readlink "$link" | sed 's|../opt|opt|')" "$link"
139 done
140 '';
141 });
142
143 binPath = lib.makeBinPath (
144 [
145 acl
146 gnugrep
147 procps
148 ]
149 ++ lib.optional enableGui jdk
150 );
151
152in
153
154buildEnv {
155 name = "tsm-client-${unwrapped.version}";
156 meta =
157 meta
158 // lib.attrsets.optionalAttrs enableGui {
159 mainProgram = "dsmj";
160 };
161 passthru = passthru // {
162 inherit unwrapped;
163 };
164 paths = [ unwrapped ];
165 nativeBuildInputs = [ makeWrapper ];
166 pathsToLink = [
167 "/"
168 "/bin"
169 "/opt/tivoli/tsm/client/ba/bin"
170 "/opt/tivoli/tsm/client/api/bin64"
171 ];
172 # * Provide top-level symlinks `dsm_dir` and `dsmi_dir`
173 # to the so-called "installation directories"
174 # * Add symlinks to the "installation directories"
175 # that point to the `dsm.sys` configuration files
176 # * Drop the Java GUI executable unless `enableGui` is set
177 # * Create wrappers for the command-line interface to
178 # prepare `PATH` and `DSM_DIR` environment variables
179 postBuild = ''
180 ln --symbolic --no-target-directory opt/tivoli/tsm/client/ba/bin $out/dsm_dir
181 ln --symbolic --no-target-directory opt/tivoli/tsm/client/api/bin64 $out/dsmi_dir
182 ln --symbolic --no-target-directory "${dsmSysCli}" $out/dsm_dir/dsm.sys
183 ln --symbolic --no-target-directory "${dsmSysApi}" $out/dsmi_dir/dsm.sys
184 ${lib.optionalString (!enableGui) "rm $out/bin/dsmj"}
185 for bin in $out/bin/*
186 do
187 target=$(readlink "$bin")
188 rm "$bin"
189 makeWrapper "$target" "$bin" \
190 --prefix PATH : "$out/dsm_dir:${binPath}" \
191 --set DSM_DIR $out/dsm_dir
192 done
193 '';
194}