aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/.github/workflows/scripts/qemu-4-build-vm.sh
blob: 2807d9e7712714216369a451f0cde97b7f2322db (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
#!/usr/bin/env bash

######################################################################
# 4) configure and build openzfs modules.  This is run on the VMs.
#
# Usage:
#
#       qemu-4-build-vm.sh OS [--enable-debug][--dkms][--patch-level NUM]
#               [--poweroff][--release][--repo][--tarball]
#
# OS:           OS name like 'fedora41'
# --enable-debug:  Build RPMs with '--enable-debug' (for testing)
# --dkms:       Build DKMS RPMs as well
# --patch-level NUM:    Use a custom patch level number for packages.
# --poweroff:   Power-off the VM after building
# --release     Build zfs-release*.rpm as well
# --repo        After building everything, copy RPMs into /tmp/repo
#               in the ZFS RPM repository file structure.  Also
#               copy tarballs if they were built.
# --tarball:    Also build a tarball of ZFS source
######################################################################

ENABLE_DEBUG=""
DKMS=""
PATCH_LEVEL=""
POWEROFF=""
RELEASE=""
REPO=""
TARBALL=""
while [[ $# -gt 0 ]]; do
  case $1 in
    --enable-debug)
      ENABLE_DEBUG=1
      shift
      ;;
    --dkms)
      DKMS=1
      shift
      ;;
    --patch-level)
      PATCH_LEVEL=$2
      shift
      shift
      ;;
    --poweroff)
      POWEROFF=1
      shift
      ;;
    --release)
      RELEASE=1
      shift
      ;;
    --repo)
      REPO=1
      shift
      ;;
    --tarball)
      TARBALL=1
      shift
      ;;
    *)
      OS=$1
      shift
      ;;
  esac
done

set -eu

function run() {
  LOG="/var/tmp/build-stderr.txt"
  echo "****************************************************"
  echo "$(date) ($*)"
  echo "****************************************************"
  ($@ || echo $? > /tmp/rv) 3>&1 1>&2 2>&3 | stdbuf -eL -oL tee -a $LOG
  if [ -f /tmp/rv ]; then
    RV=$(cat /tmp/rv)
    echo "****************************************************"
    echo "exit with value=$RV ($*)"
    echo "****************************************************"
    echo 1 > /var/tmp/build-exitcode.txt
    exit $RV
  fi
}

# Look at the RPMs in the current directory and copy/move them to
# /tmp/repo, using the directory structure we use for the ZFS RPM repos.
#
# For example:
# /tmp/repo/epel-testing/9.5
# /tmp/repo/epel-testing/9.5/SRPMS
# /tmp/repo/epel-testing/9.5/SRPMS/zfs-2.3.99-1.el9.src.rpm
# /tmp/repo/epel-testing/9.5/SRPMS/zfs-kmod-2.3.99-1.el9.src.rpm
# /tmp/repo/epel-testing/9.5/kmod
# /tmp/repo/epel-testing/9.5/kmod/x86_64
# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug
# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug/kmod-zfs-debuginfo-2.3.99-1.el9.x86_64.rpm
# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug/libnvpair3-debuginfo-2.3.99-1.el9.x86_64.rpm
# /tmp/repo/epel-testing/9.5/kmod/x86_64/debug/libuutil3-debuginfo-2.3.99-1.el9.x86_64.rpm
# ...
function copy_rpms_to_repo {
  # Pick a RPM to query. It doesn't matter which one - we just want to extract
  # the 'Build Host' value from it.
  rpm=$(ls zfs-*.rpm | head -n 1)

  # Get zfs version '2.2.99'
  zfs_ver=$(rpm -qpi $rpm | awk '/Version/{print $3}')

  # Get "2.1" or "2.2"
  zfs_major=$(echo $zfs_ver | grep -Eo [0-9]+\.[0-9]+)

  # Get 'almalinux9.5' or 'fedora41' type string
  build_host=$(rpm -qpi $rpm | awk '/Build Host/{print $4}')

  # Get '9.5' or '41' OS version
  os_ver=$(echo $build_host | grep -Eo '[0-9\.]+$')

  # Our ZFS version and OS name will determine which repo the RPMs
  # will go in (regular or testing).  Fedora always gets the newest
  # releases, and Alma gets the older releases.
  case $build_host in
  almalinux*)
    case $zfs_major in
    2.2)
      d="epel"
      ;;
    *)
      d="epel-testing"
      ;;
    esac
    ;;
  fedora*)
    d="fedora"
    ;;
  esac

  prefix=/tmp/repo
  dst="$prefix/$d/$os_ver"

  # Special case: move zfs-release*.rpm out of the way first (if we built them).
  # This will make filtering the other RPMs easier.
  mkdir -p $dst
  mv zfs-release*.rpm $dst || true

  # Copy source RPMs
  mkdir -p $dst/SRPMS
  cp $(ls *.src.rpm) $dst/SRPMS/

  if [[ "$build_host" =~ "almalinux" ]] ; then
    # Copy kmods+userspace
    mkdir -p $dst/kmod/x86_64/debug
    cp $(ls *.rpm | grep -Ev 'src.rpm|dkms|debuginfo') $dst/kmod/x86_64
    cp *debuginfo*.rpm $dst/kmod/x86_64/debug
  fi

  if [ -n "$DKMS" ] ; then
    # Copy dkms+userspace
    mkdir -p $dst/x86_64
    cp $(ls *.rpm | grep -Ev 'src.rpm|kmod|debuginfo') $dst/x86_64
  fi

  # Copy debug
  mkdir -p $dst/x86_64/debug
  cp $(ls *debuginfo*.rpm | grep -v kmod) $dst/x86_64/debug
}

function freebsd() {
  extra="${1:-}"

  export MAKE="gmake"
  echo "##[group]Autogen.sh"
  run ./autogen.sh
  echo "##[endgroup]"

  echo "##[group]Configure"
  run ./configure \
    --prefix=/usr/local \
    --with-libintl-prefix=/usr/local \
    --enable-pyzfs \
    --enable-debuginfo $extra
  echo "##[endgroup]"

  echo "##[group]Build"
  run gmake -j$(sysctl -n hw.ncpu)
  echo "##[endgroup]"

  echo "##[group]Install"
  run sudo gmake install
  echo "##[endgroup]"
}

function linux() {
  extra="${1:-}"

  echo "##[group]Autogen.sh"
  run ./autogen.sh
  echo "##[endgroup]"

  echo "##[group]Configure"
  run ./configure \
    --prefix=/usr \
    --enable-pyzfs \
    --enable-debuginfo $extra
  echo "##[endgroup]"

  echo "##[group]Build"
  run make -j$(nproc)
  echo "##[endgroup]"

  echo "##[group]Install"
  run sudo make install
  echo "##[endgroup]"
}

function rpm_build_and_install() {
  extra="${1:-}"

  # Build RPMs with XZ compression by default (since gzip decompression is slow)
  echo "%_binary_payload w7.xzdio" >> ~/.rpmmacros

  echo "##[group]Autogen.sh"
  run ./autogen.sh
  echo "##[endgroup]"

  if [ -n "$PATCH_LEVEL" ] ; then
    sed -i -E 's/(Release:\s+)1/\1'$PATCH_LEVEL'/g' META
  fi

  echo "##[group]Configure"
  run ./configure --enable-debuginfo $extra
  echo "##[endgroup]"

  echo "##[group]Build"
  run make pkg-kmod pkg-utils
  echo "##[endgroup]"

  if [ -n "$DKMS" ] ; then
    echo "##[group]DKMS"
    make rpm-dkms
    echo "##[endgroup]"
  fi

  if [ -n "$REPO" ] ; then
    echo "Skipping install since we're only building RPMs and nothing else"
  else
    echo "##[group]Install"
    run sudo dnf -y --nobest install $(ls *.rpm | grep -Ev 'dkms|src.rpm')
    echo "##[endgroup]"
  fi

  # Optionally build the zfs-release.*.rpm
  if [ -n "$RELEASE" ] ; then
    echo "##[group]Release"
    pushd ~
    sudo dnf -y install rpm-build || true
    # Check out a sparse copy of zfsonlinux.github.com.git so we don't get
    # all the binaries.  We just need a few kilobytes of files to build RPMs.
    git clone --depth 1 --no-checkout \
      https://github.com/zfsonlinux/zfsonlinux.github.com.git

    cd zfsonlinux.github.com
    git sparse-checkout set zfs-release
    git checkout
    cd zfs-release

    mkdir -p ~/rpmbuild/{BUILDROOT,SPECS,RPMS,SRPMS,SOURCES,BUILD}
    cp RPM-GPG-KEY-openzfs* *.repo ~/rpmbuild/SOURCES
    cp zfs-release.spec ~/rpmbuild/SPECS/
    rpmbuild -ba ~/rpmbuild/SPECS/zfs-release.spec

    # ZFS release RPMs are built.  Copy them to the ~/zfs directory just to
    # keep all the RPMs in the same place.
    cp ~/rpmbuild/RPMS/noarch/*.rpm ~/zfs
    cp ~/rpmbuild/SRPMS/*.rpm ~/zfs

    popd
    rm -fr ~/rpmbuild
    echo "##[endgroup]"
  fi

  if [ -n "$REPO" ] ; then
    echo "##[group]Repo"
    copy_rpms_to_repo
    echo "##[endgroup]"
  fi
}

function deb_build_and_install() {
  extra="${1:-}"

  echo "##[group]Autogen.sh"
  run ./autogen.sh
  echo "##[endgroup]"

  echo "##[group]Configure"
  run ./configure \
    --prefix=/usr \
    --enable-pyzfs \
    --enable-debuginfo $extra
  echo "##[endgroup]"

  echo "##[group]Build"
  run make native-deb-kmod native-deb-utils
  echo "##[endgroup]"

  echo "##[group]Install"
  # Do kmod install.  Note that when you build the native debs, the
  # packages themselves are placed in parent directory '../' rather than
  # in the source directory like the rpms are.
  run sudo apt-get -y install $(find ../ | grep -E '\.deb$' \
    | grep -Ev 'dkms|dracut')
  echo "##[endgroup]"
}

function build_tarball {
  if [ -n "$REPO" ] ; then
    ./autogen.sh
    ./configure --with-config=srpm
    make dist
    mkdir -p /tmp/repo/releases
    # The tarball name is based off of 'Version' field in the META file.
    mv *.tar.gz /tmp/repo/releases/
  fi
}

# Debug: show kernel cmdline
if [ -f /proc/cmdline ] ; then
  cat /proc/cmdline || true
fi

# Set our hostname to our OS name and version number.  Specifically, we set the
# major and minor number so that when we query the Build Host field in the RPMs
# we build, we can see what specific version of Fedora/Almalinux we were using
# to build them.  This is helpful for matching up KMOD versions.
#
# Examples:
#
# rhel8.10
# almalinux9.5
# fedora42
source /etc/os-release
 if which hostnamectl &> /dev/null ; then
  # Fedora 42+ use hostnamectl
  sudo hostnamectl set-hostname "$ID$VERSION_ID"
  sudo hostnamectl set-hostname --pretty "$ID$VERSION_ID"
else
  sudo hostname "$ID$VERSION_ID"
fi

# save some sysinfo
uname -a > /var/tmp/uname.txt

cd $HOME/zfs
export PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin"

extra=""
if [ -n "$ENABLE_DEBUG" ] ; then
  extra="--enable-debug"
fi

# build
case "$OS" in
  freebsd*)
    freebsd "$extra"
    ;;
  alma*|centos*)
    rpm_build_and_install "--with-spec=redhat $extra"
    ;;
  fedora*)
    rpm_build_and_install "$extra"

    # Historically, we've always built the release tarballs on Fedora, since
    # there was one instance long ago where we built them on CentOS 7, and they
    # didn't work correctly for everyone.
    if [ -n "$TARBALL" ] ; then
        build_tarball
    fi
    ;;
  debian*|ubuntu*)
    deb_build_and_install "$extra"
    ;;
  *)
    linux "$extra"
    ;;
esac


# building the zfs module was ok
echo 0 > /var/tmp/build-exitcode.txt

# reset cloud-init configuration and poweroff
if [ -n "$POWEROFF" ] ; then
        sudo cloud-init clean --logs
        sync && sleep 2 && sudo poweroff &
fi
exit 0