smbd: Fix cached dos attributes
[Samba.git] / bootstrap / config.py
blob178c9029098a5e7f2708e656a6d21a710219e307
1 #!/usr/bin/env python3
3 # Copyright (C) Catalyst.Net Ltd 2019
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 """
19 Manage dependencies and bootstrap environments for Samba.
21 Config file for packages and templates.
23 Update the lists in this file to require new packages in the
24 container images used in GitLab CI
26 Author: Joe Guo <joeg@catalyst.net.nz>
27 """
28 import os
29 from os.path import abspath, dirname, join
30 HERE = abspath(dirname(__file__))
31 # output dir for rendered files
32 OUT = join(HERE, 'generated-dists')
35 # pkgs with same name in all packaging systems
36 COMMON = [
37 'acl',
38 'attr',
39 'autoconf',
40 'binutils',
41 'bison',
42 'ccache',
43 'curl',
44 'chrpath',
45 'codespell',
46 'flex',
47 'gcc',
48 'gdb',
49 'git',
50 'gzip',
51 'hostname',
52 'htop',
53 'jq',
54 'lcov',
55 'make',
56 'patch',
57 'perl',
58 'psmisc', # for pstree in test
59 'rng-tools',
60 'rsync',
61 'sed',
62 'shfmt',
63 'sudo', # docker images has no sudo by default
64 'tar',
65 'tree',
66 'wget',
70 # define pkgs for all packaging systems in parallel
71 # make it easier to find missing ones
72 # use latest ubuntu and fedora as defaults
73 # deb, rpm, ...
74 PKGS = [
75 # NAME1-dev, NAME2-devel
76 ('lmdb-utils', 'lmdb'),
77 ('mingw-w64', 'mingw64-gcc'),
78 ('zlib1g-dev', 'zlib-devel'),
79 ('libbsd-dev', 'libbsd-devel'),
80 ('liburing-dev', 'liburing-devel'),
81 ('libarchive-dev', 'libarchive-devel'),
82 ('libblkid-dev', 'libblkid-devel'),
83 ('libcap-dev', 'libcap-devel'),
84 ('libacl1-dev', 'libacl-devel'),
85 ('libattr1-dev', 'libattr-devel'),
87 # libNAME1-dev, NAME2-devel
88 ('libpopt-dev', 'popt-devel'),
89 ('libreadline-dev', 'readline-devel'),
90 ('libjansson-dev', 'jansson-devel'),
91 ('liblmdb-dev', 'lmdb-devel'),
92 ('libncurses5-dev', 'ncurses-devel'),
93 # NOTE: Debian 7+ or Ubuntu 16.04+
94 ('libsystemd-dev', 'systemd-devel'),
95 ('libkrb5-dev', 'krb5-devel'),
96 ('libldap2-dev', 'openldap-devel'),
97 ('libcups2-dev', 'cups-devel'),
98 ('libpam0g-dev', 'pam-devel'),
99 ('libgpgme11-dev', 'gpgme-devel'),
100 # NOTE: Debian 8+ and Ubuntu 14.04+
101 ('libgnutls28-dev', 'gnutls-devel'),
102 ('gnutls-bin', 'gnutls-utils'),
103 ('libtasn1-bin', 'libtasn1-tools'),
104 ('libtasn1-dev', 'libtasn1-devel'),
105 ('', 'quota-devel'),
106 ('uuid-dev', 'libuuid-devel'),
107 ('libjs-jquery', ''),
108 ('libavahi-common-dev', 'avahi-devel'),
109 ('libdbus-1-dev', 'dbus-devel'),
110 ('libpcap-dev', 'libpcap-devel'),
111 ('libunwind-dev', 'libunwind-devel'), # for back trace
112 ('libglib2.0-dev', 'glib2-devel'),
113 ('libicu-dev', 'libicu-devel'),
114 ('heimdal-multidev', ''),
116 # NAME1, NAME2
117 # for debian, locales provide locale support with language packs
118 # ubuntu split language packs to language-pack-xx
119 # for centos, glibc-common provide locale support with language packs
120 # fedora split language packs to glibc-langpack-xx
121 ('locales', 'glibc-common'), # required for locale
122 ('language-pack-en', 'glibc-langpack-en'), # we need en_US.UTF-8
123 ('bind9utils', 'bind-utils'),
124 ('dnsutils', ''),
125 ('xsltproc', 'libxslt'),
126 ('krb5-user', 'krb5-workstation'),
127 ('krb5-config', ''),
128 ('krb5-kdc', 'krb5-server'),
129 ('apt-utils', 'yum-utils'),
130 ('pkg-config', 'pkgconfig'),
131 ('procps', 'procps-ng'), # required for the free cmd in tests
132 ('lsb-release', 'lsb-release'), # we need lsb_release to show info
133 ('', 'rpcgen'), # required for test
134 # refer: https://fedoraproject.org/wiki/Changes/SunRPCRemoval
135 ('', 'libtirpc-devel'), # for <rpc/rpc.h> header on fedora
136 ('', 'rpcsvc-proto-devel'), # for <rpcsvc/rquota.h> header
137 ('mawk', 'gawk'),
138 ('', 'mold'),
139 ('shellcheck', 'ShellCheck'),
140 ('', 'crypto-policies-scripts'),
142 ('python3', 'python3'),
143 ('python3-cryptography', 'python3-cryptography'), # for krb5 tests
144 ('python3-dev', 'python3-devel'),
145 ('python3-dbg', ''),
146 ('python3-iso8601', 'python3-iso8601'),
147 ('python3-gpg', 'python3-gpg'), # defaults to ubuntu/fedora latest
148 ('python3-markdown', 'python3-markdown'),
149 ('python3-dnspython', 'python3-dns'),
150 ('python3-pexpect', ''), # for wintest only
151 ('python3-pyasn1', 'python3-pyasn1'), # for krb5 tests
152 ('python3-setproctitle', 'python3-setproctitle'),
153 ('python3-requests', 'python3-requests'), # for cert auto enroll
155 ('', 'python3-libsemanage'),
156 ('', 'python3-policycoreutils'),
158 # perl
159 ('libparse-yapp-perl', 'perl-Parse-Yapp'),
160 ('perl-modules', ''),
161 ('', 'perl-FindBin'),
162 ('', 'perl-Archive-Tar'),
163 ('', 'perl-ExtUtils-MakeMaker'),
164 ('', 'perl-Test-Base'),
165 ('', 'perl-generators'),
166 ('', 'perl-interpreter'),
168 # fs
169 ('xfslibs-dev', 'xfsprogs-devel'), # for xfs quota support
170 ('', 'glusterfs-api-devel'),
171 ('glusterfs-common', 'glusterfs-devel'),
172 ('libcephfs-dev', 'libcephfs-devel'),
174 # spotlight
175 ('libtracker-sparql-2.0-dev', 'tracker-devel'),
177 # misc
178 # @ means group for rpm, use fedora as rpm default
179 ('build-essential', '@development-tools'),
180 ('debhelper', ''),
181 # rpm has no pkg for docbook-xml
182 ('docbook-xml', 'docbook-dtds'),
183 ('docbook-xsl', 'docbook-style-xsl'),
184 ('libkeyutils-dev', 'keyutils-libs-devel'),
185 ('', 'which'),
186 ('xz-utils', 'xz')
190 DEB_PKGS = COMMON + [pkg for pkg, _ in PKGS if pkg]
191 RPM_PKGS = COMMON + [pkg for _, pkg in PKGS if pkg]
193 GENERATED_MARKER = r"""
195 # This file is generated by 'bootstrap/template.py --render'
196 # See also bootstrap/config.py
201 APT_BOOTSTRAP = r"""
202 #!/bin/bash
203 {GENERATED_MARKER}
204 set -xueo pipefail
206 export DEBIAN_FRONTEND=noninteractive
207 apt-get -y update
209 apt-get -y install \
210 {pkgs}
212 apt-get -y autoremove
213 apt-get -y autoclean
214 apt-get -y clean
218 YUM_BOOTSTRAP = r"""
219 #!/bin/bash
220 {GENERATED_MARKER}
221 set -xueo pipefail
223 yum update -y
224 yum install -y epel-release
225 yum install -y yum-plugin-copr
226 yum copr enable -y sergiomb/SambaAD
227 yum update -y
229 yum install -y \
230 {pkgs}
232 yum clean all
234 if [ ! -f /usr/bin/python3 ]; then
235 ln -sf /usr/bin/python3.6 /usr/bin/python3
239 CENTOS8S_YUM_BOOTSTRAP = r"""
240 #!/bin/bash
241 {GENERATED_MARKER}
242 set -xueo pipefail
244 sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
245 sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
247 yum update -y
248 yum install -y dnf-plugins-core
249 yum install -y epel-release
251 yum -v repolist all
252 yum config-manager --set-enabled powertools -y
254 yum update -y
256 yum install -y \
257 --setopt=install_weak_deps=False \
258 {pkgs}
260 yum clean all
263 CENTOS9S_DNF_BOOTSTRAP = r"""
264 #!/bin/bash
265 {GENERATED_MARKER}
266 set -xueo pipefail
268 dnf update -y
269 dnf install -y dnf-plugins-core
270 dnf install -y epel-release
271 dnf install -y centos-release-gluster9
273 dnf -v repolist all
274 dnf config-manager --set-enabled crb -y
276 dnf update -y
278 dnf install -y \
279 --setopt=install_weak_deps=False \
280 {pkgs}
282 dnf clean all
285 DNF_BOOTSTRAP = r"""
286 #!/bin/bash
287 {GENERATED_MARKER}
288 set -xueo pipefail
290 dnf update -y
292 dnf install -y \
293 --setopt=install_weak_deps=False \
294 {pkgs}
296 dnf clean all
298 update-crypto-policies --set DEFAULT:AD-SUPPORT
301 DNF_BOOTSTRAP_MIT = r"""
302 #!/bin/bash
303 {GENERATED_MARKER}
304 set -xueo pipefail
306 dnf update -y
307 dnf install -y dnf-plugins-core
308 dnf copr -y enable abbra/krb5-test
309 dnf update -y
311 dnf install -y \
312 --setopt=install_weak_deps=False \
313 {pkgs}
315 dnf clean all
318 ZYPPER_BOOTSTRAP = r"""
319 #!/bin/bash
320 {GENERATED_MARKER}
321 set -xueo pipefail
323 zypper --non-interactive refresh
324 zypper --non-interactive update
325 zypper --non-interactive install \
326 --no-recommends \
327 system-user-nobody \
328 {pkgs}
330 zypper --non-interactive clean
332 if [ -f /usr/lib/mit/bin/krb5-config ]; then
333 ln -sf /usr/lib/mit/bin/krb5-config /usr/bin/krb5-config
337 # A generic shell script to setup locale
338 LOCALE_SETUP = r"""
339 #!/bin/bash
340 {GENERATED_MARKER}
341 set -xueo pipefail
343 # refer to /usr/share/i18n/locales
344 INPUTFILE=en_US
345 # refer to /usr/share/i18n/charmaps
346 CHARMAP=UTF-8
347 # locale to generate in /usr/lib/locale
348 # glibc/localedef will normalize UTF-8 to utf8, follow the naming style
349 LOCALE=$INPUTFILE.utf8
351 # if locale is already correct, exit
352 ( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0
354 # if locale not available, generate locale into /usr/lib/locale
355 if ! ( locale --all-locales | grep -i $LOCALE )
356 then
357 # no-archive means create its own dir
358 localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE
361 # update locale conf and global env file
362 # set both LC_ALL and LANG for safe
364 # update conf for Debian family
365 FILE=/etc/default/locale
366 if [ -f $FILE ]
367 then
368 echo LC_ALL="$LOCALE" > $FILE
369 echo LANG="$LOCALE" >> $FILE
372 # update conf for RedHat family
373 FILE=/etc/locale.conf
374 if [ -f $FILE ]
375 then
376 # LC_ALL is not valid in this file, set LANG only
377 echo LANG="$LOCALE" > $FILE
380 # update global env file
381 FILE=/etc/environment
382 if [ -f $FILE ]
383 then
384 # append LC_ALL if not exist
385 grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE
386 # append LANG if not exist
387 grep LANG $FILE || echo LANG="$LOCALE" >> $FILE
392 DOCKERFILE = r"""
393 {GENERATED_MARKER}
394 FROM {docker_image}
396 # pass in with --build-arg while build
397 ARG SHA1SUM
398 RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt
400 ADD *.sh /tmp/
401 # need root permission, do it before USER samba
402 RUN /tmp/bootstrap.sh && /tmp/locale.sh
404 # if ld.gold exists, force link it to ld
405 RUN set -x; ! LD_GOLD=$(which ld.gold) || {{ LD=$(which ld) && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD"; }}
406 # if ld.mold exists, force link it to ld (prefer mold over gold! ;-)
407 RUN set -x; ! LD_MOLD=$(which ld.mold) || {{ LD=$(which ld) && ln -sf $LD_MOLD $LD && test -x $LD && echo "$LD is now $LD_MOLD"; }}
409 # make test can not work with root, so we have to create a new user
410 RUN useradd -m -U -s /bin/bash samba && \
411 mkdir -p /etc/sudoers.d && \
412 echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba
414 USER samba
415 WORKDIR /home/samba
416 # samba tests rely on this
417 ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8 LANGUAGE=en_US
420 # Vagrantfile snippet for each dist
421 VAGRANTFILE_SNIPPET = r"""
422 config.vm.define "{name}" do |v|
423 v.vm.box = "{vagrant_box}"
424 v.vm.hostname = "{name}"
425 v.vm.provision :shell, path: "{name}/bootstrap.sh"
426 v.vm.provision :shell, path: "{name}/locale.sh"
430 # global Vagrantfile with snippets for all dists
431 VAGRANTFILE_GLOBAL = r"""
432 {GENERATED_MARKER}
434 Vagrant.configure("2") do |config|
435 config.ssh.insert_key = false
437 {vagrantfile_snippets}
442 DEB_DISTS = {
443 'debian11': {
444 'docker_image': 'debian:11',
445 'vagrant_box': 'debian/bullseye64',
446 'replace': {
447 'language-pack-en': '', # included in locales
448 'shfmt': '',
451 'debian11-32bit': {
452 'docker_image': 'registry-1.docker.io/i386/debian:11',
453 'vagrant_box': 'debian/bullseye32',
454 'replace': {
455 'language-pack-en': '', # included in locales
456 'shfmt': '',
459 'debian12': {
460 'docker_image': 'debian:12',
461 'vagrant_box': 'debian/bookworm64',
462 'replace': {
463 'language-pack-en': '', # included in locales
464 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
467 'debian12-32bit': {
468 'docker_image': 'registry-1.docker.io/i386/debian:12',
469 'vagrant_box': 'debian/bookworm32',
470 'replace': {
471 'language-pack-en': '', # included in locales
472 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
475 'ubuntu1804': {
476 'docker_image': 'ubuntu:18.04',
477 'vagrant_box': 'ubuntu/bionic64',
478 'replace': {
479 'liburing-dev': '', # not available
480 'shfmt': '',
483 'ubuntu1804-32bit': {
484 'docker_image': 'registry-1.docker.io/i386/ubuntu:18.04',
485 'vagrant_box': 'ubuntu/bionic32',
486 'replace': {
487 'liburing-dev': '', # not available
488 'shfmt': '',
491 'ubuntu2004': {
492 'docker_image': 'ubuntu:20.04',
493 'vagrant_box': 'ubuntu/focal64',
494 'replace': {
495 'liburing-dev': '', # not available
496 'shfmt': '',
499 'ubuntu2204': {
500 'docker_image': 'ubuntu:22.04',
501 'vagrant_box': 'ubuntu/jammy64',
502 'replace': {
503 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
509 RPM_DISTS = {
510 'centos8s': {
511 'docker_image': 'quay.io/centos/centos:stream8',
512 'vagrant_box': 'centos/stream8',
513 'bootstrap': CENTOS8S_YUM_BOOTSTRAP,
514 'replace': {
515 'lsb-release': 'redhat-lsb',
516 '@development-tools': '"@Development Tools"', # add quotes
517 'lcov': '', # does not exist
518 'perl-JSON-Parse': '', # does not exist?
519 'perl-Test-Base': 'perl-Test-Simple',
520 'perl-FindBin': '',
521 'liburing-devel': '', # not available yet, Add me back, once available!
522 'mold': '',
523 'ShellCheck': '',
524 'shfmt': '',
525 'codespell': '',
528 'centos9s': {
529 'docker_image': 'quay.io/centos/centos:stream9',
530 'vagrant_box': 'centos/stream9',
531 'bootstrap': CENTOS9S_DNF_BOOTSTRAP,
532 'replace': {
533 'lsb-release': 'lsb_release',
534 '@development-tools': '"@Development Tools"', # add quotes
535 'lcov': '', # does not exist
536 'perl-JSON-Parse': '', # does not exist?
537 'perl-Test-Base': 'perl-Test-Simple',
538 'perl-FindBin': '',
539 'mold': '',
540 'ShellCheck': '',
541 'shfmt': '',
542 'codespell': '',
543 'libcephfs-devel': '', # not available anymore
544 'curl': '', # Use installed curl-minimal
547 'fedora40': {
548 'docker_image': 'quay.io/fedora/fedora:40',
549 'vagrant_box': 'fedora/40-cloud-base',
550 'bootstrap': DNF_BOOTSTRAP,
551 'replace': {
552 'lsb-release': 'redhat-lsb',
553 'perl-FindBin': '',
554 'python3-iso8601': 'python3-dateutil',
555 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
558 'opensuse155': {
559 'docker_image': 'opensuse/leap:15.5',
560 'vagrant_box': 'opensuse/openSUSE-15.5-x86_64',
561 'bootstrap': ZYPPER_BOOTSTRAP,
562 'replace': {
563 '@development-tools': '',
564 'dbus-devel': 'dbus-1-devel',
565 'docbook-style-xsl': 'docbook-xsl-stylesheets',
566 'glibc-common': 'glibc-locale',
567 'glibc-locale-source': 'glibc-i18ndata',
568 'glibc-langpack-en': '',
569 'jansson-devel': 'libjansson-devel',
570 'keyutils-libs-devel': 'keyutils-devel',
571 'krb5-workstation': 'krb5-client',
572 'python3-libsemanage': 'python3-semanage',
573 'openldap-devel': 'openldap2-devel',
574 'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
575 'perl-JSON-Parse': 'perl-JSON-XS',
576 'perl-generators': '',
577 'perl-interpreter': '',
578 'perl-FindBin': '',
579 'procps-ng': 'procps',
580 'python3-iso8601': 'python3-python-dateutil',
581 'python3-dns': 'python3-dnspython',
582 'python3-markdown': 'python3-Markdown',
583 'quota-devel': '',
584 'glusterfs-api-devel': '',
585 'gnutls-utils': 'gnutls',
586 'libtasn1-tools': '', # asn1Parser is part of libtasn1
587 'mold': '',
588 'shfmt': '',
589 'yum-utils': '',
595 DEB_FAMILY = {
596 'name': 'deb',
597 'pkgs': DEB_PKGS,
598 'bootstrap': APT_BOOTSTRAP, # family default
599 'dists': DEB_DISTS,
603 RPM_FAMILY = {
604 'name': 'rpm',
605 'pkgs': RPM_PKGS,
606 'bootstrap': YUM_BOOTSTRAP, # family default
607 'dists': RPM_DISTS,
611 YML_HEADER = r"""
613 packages:
617 def expand_family_dists(family):
618 dists = {}
619 for name, config in family['dists'].items():
620 config = config.copy()
621 config['name'] = name
622 config['home'] = join(OUT, name)
623 config['family'] = family['name']
624 config['GENERATED_MARKER'] = GENERATED_MARKER
626 # replace dist specific pkgs
627 replace = config.get('replace', {})
628 pkgs = []
629 for pkg in family['pkgs']:
630 pkg = replace.get(pkg, pkg) # replace if exists or get self
631 if pkg:
632 pkgs.append(pkg)
633 pkgs.sort()
635 lines = [' - {}'.format(pkg) for pkg in pkgs]
636 config['packages.yml'] = YML_HEADER.lstrip() + os.linesep.join(lines)
638 sep = ' \\' + os.linesep + ' '
639 config['pkgs'] = sep.join(pkgs)
641 # get dist bootstrap template or fall back to family default
642 bootstrap_template = config.get('bootstrap', family['bootstrap'])
643 config['bootstrap.sh'] = bootstrap_template.format(**config).strip()
644 config['locale.sh'] = LOCALE_SETUP.format(**config).strip()
646 config['Dockerfile'] = DOCKERFILE.format(**config).strip()
647 # keep the indent, no strip
648 config['vagrantfile_snippet'] = VAGRANTFILE_SNIPPET.format(**config)
650 dists[name] = config
651 return dists
654 # expanded config for dists
655 DEB_DISTS_EXP = expand_family_dists(DEB_FAMILY)
656 RPM_DISTS_EXP = expand_family_dists(RPM_FAMILY)
658 # assemble all together
659 DISTS = {}
660 DISTS.update(DEB_DISTS_EXP)
661 DISTS.update(RPM_DISTS_EXP)
664 def render_vagrantfile(dists):
666 Render all snippets for each dist into global Vagrantfile.
668 Vagrant supports multiple vms in one Vagrantfile.
669 This make it easier to manage the fleet, e.g:
671 start all: vagrant up
672 start one: vagrant up ubuntu1804
674 All other commands apply to above syntax, e.g.: status, destroy, provision
676 # sort dists by name and put all vagrantfile snippets together
677 snippets = [
678 dists[dist]['vagrantfile_snippet']
679 for dist in sorted(dists.keys())]
681 return VAGRANTFILE_GLOBAL.format(
682 vagrantfile_snippets=''.join(snippets),
683 GENERATED_MARKER=GENERATED_MARKER
687 VAGRANTFILE = render_vagrantfile(DISTS)
690 # data we need to expose
691 __all__ = ['DISTS', 'VAGRANTFILE', 'OUT']