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/>.
19 Manage dependencies and bootstrap environments for Samba.
21 Config file for packages and templates.
23 Author: Joe Guo <joeg@catalyst.net.nz>
26 from os.path import abspath, dirname, join
27 HERE = abspath(dirname(__file__))
28 # output dir for rendered files
29 OUT = join(HERE, 'generated-dists')
32 # pkgs with same name in all packaging systems
51 'psmisc', # for pstree in test
55 'sudo', # docker images has no sudo by default
61 # define pkgs for all packaging systems in parallel
62 # make it easier to find missing ones
63 # use latest ubuntu and fedora as defaults
66 # NAME1-dev, NAME2-devel
67 ('lmdb-utils', 'lmdb'),
68 ('nettle-dev', 'nettle-devel'),
69 ('zlib1g-dev', 'zlib-devel'),
70 ('libbsd-dev', 'libbsd-devel'),
71 ('libaio-dev', 'libaio-devel'),
72 ('libarchive-dev', 'libarchive-devel'),
73 ('libblkid-dev', 'libblkid-devel'),
74 ('libcap-dev', 'libcap-devel'),
75 ('libacl1-dev', 'libacl-devel'),
76 ('libattr1-dev', 'libattr-devel'),
78 # libNAME1-dev, NAME2-devel
79 ('libpopt-dev', 'popt-devel'),
80 ('libreadline-dev', 'readline-devel'),
81 ('libjansson-dev', 'jansson-devel'),
82 ('liblmdb-dev', 'lmdb-devel'),
83 ('libncurses5-dev', 'ncurses-devel'),
84 # NOTE: Debian 7+ or Ubuntu 16.04+
85 ('libsystemd-dev', 'systemd-devel'),
86 ('libkrb5-dev', 'krb5-devel'),
87 ('libldap2-dev', 'openldap-devel'),
88 ('libcups2-dev', 'cups-devel'),
89 ('libpam0g-dev', 'pam-devel'),
90 ('libgpgme11-dev', 'gpgme-devel'),
91 # NOTE: Debian 8+ and Ubuntu 14.04+
92 ('libgnutls28-dev', 'gnutls-devel'),
94 ('libtasn1-dev', 'libtasn1-devel'),
96 ('uuid-dev', 'libuuid-devel'),
98 ('libavahi-common-dev', 'avahi-devel'),
99 ('libdbus-1-dev', 'dbus-devel'),
100 ('libpcap-dev', 'libpcap-devel'),
101 ('libunwind-dev', 'libunwind-devel'), # for back trace
102 ('libglib2.0-dev', 'glib2-devel'),
103 ('libicu-dev', 'libicu-devel'),
106 # for debian, locales provide locale support with language packs
107 # ubuntu split language packs to language-pack-xx
108 # for centos, glibc-common provide locale support with language packs
109 # fedora split language packs to glibc-langpack-xx
110 ('locales', 'glibc-common'), # required for locale
111 ('language-pack-en', 'glibc-langpack-en'), # we need en_US.UTF-8
112 ('bind9utils', 'bind-utils'),
114 ('xsltproc', 'libxslt'),
117 ('krb5-kdc', 'krb5-server'),
118 ('apt-utils', 'yum-utils'),
119 ('pkg-config', 'pkgconfig'),
120 ('procps', 'procps-ng'), # required for the free cmd in tests
121 ('lsb-release', 'lsb-release'), # we need lsb_relase to show info
122 ('', 'rpcgen'), # required for test
123 # refer: https://fedoraproject.org/wiki/Changes/SunRPCRemoval
124 ('', 'libtirpc-devel'), # for <rpc/rpc.h> header on fedora
125 ('', 'libnsl2-devel'), # for <rpcsvc/yp_prot.h> header on fedora
126 ('', 'rpcsvc-proto-devel'), # for <rpcsvc/rquota.h> header
130 ('python-dev', 'python-devel'),
132 ('python-iso8601', ''),
133 ('python-gpg', 'python2-gpg'), # defaults to ubuntu/fedora latest
134 ('python-crypto', 'python-crypto'),
135 ('python-markdown', 'python-markdown'),
136 ('python-dnspython', 'python-dns'),
137 ('python-pexpect', ''), # for wintest only
139 ('python3', 'python3'),
140 ('python3-dev', 'python3-devel'),
142 ('python3-iso8601', ''),
143 ('python3-gpg', 'python3-gpg'), # defaults to ubuntu/fedora latest
144 ('python3-crypto', 'python3-crypto'),
145 ('python3-markdown', 'python3-markdown'),
146 ('python3-matplotlib', ''),
147 ('python3-dnspython', 'python3-dns'),
148 ('python3-pexpect', ''), # for wintest only
150 ('', 'libsemanage-python'),
151 ('', 'policycoreutils-python'),
154 ('libparse-yapp-perl', 'perl-Parse-Yapp'),
155 ('libjson-perl', 'perl-JSON-Parse'),
156 ('perl-modules', ''),
157 ('', 'perl-Archive-Tar'),
158 ('', 'perl-ExtUtils-MakeMaker'),
159 ('', 'perl-Test-Base'),
160 ('', 'perl-generators'),
161 ('', 'perl-interpreter'),
164 ('xfslibs-dev', 'xfsprogs-devel'), # for xfs quota support
165 ('', 'glusterfs-api-devel'),
166 ('glusterfs-common', 'glusterfs-devel'),
167 ('libcephfs-dev', 'libcephfs-devel'),
170 # @ means group for rpm, use fedora as rpm default
171 ('build-essential', '@development-tools'),
173 # rpm has no pkg for docbook-xml
174 ('docbook-xml', 'docbook-dtds'),
175 ('docbook-xsl', 'docbook-style-xsl'),
176 ('', 'keyutils-libs-devel'),
181 DEB_PKGS = COMMON + [pkg for pkg, _ in PKGS if pkg]
182 RPM_PKGS = COMMON + [pkg for _, pkg in PKGS if pkg]
184 GENERATED_MARKER = r"""
186 # This file is generated by 'bootstrap/template.py --render'
187 # See also bootstrap/config.py
197 export DEBIAN_FRONTEND=noninteractive
203 apt-get -y autoremove
215 yum install -y epel-release
223 if [ ! -f /usr/bin/python3 ]; then
224 ln -sf /usr/bin/python3.4 /usr/bin/python3
237 --setopt=install_weak_deps=False \
243 ZYPPER_BOOTSTRAP = r"""
248 zypper --non-interactive refresh
249 zypper --non-interactive update
250 zypper --non-interactive install \
255 zypper --non-interactive clean
257 if [ -f /usr/lib/mit/bin/krb5-config ]; then
258 ln -sf /usr/lib/mit/bin/krb5-config /usr/bin/krb5-config
262 # A generic shell script to setup locale
268 # refer to /usr/share/i18n/locales
270 # refer to /usr/share/i18n/charmaps
272 # locale to generate in /usr/lib/locale
273 # glibc/localedef will normalize UTF-8 to utf8, follow the naming style
274 LOCALE=$INPUTFILE.utf8
276 # if locale is already correct, exit
277 ( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0
279 # if locale not available, generate locale into /usr/lib/locale
280 if ! ( locale --all-locales | grep -i $LOCALE )
282 # no-archive means create its own dir
283 localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE
286 # update locale conf and global env file
287 # set both LC_ALL and LANG for safe
289 # update conf for Debian family
290 FILE=/etc/default/locale
293 echo LC_ALL="$LOCALE" > $FILE
294 echo LANG="$LOCALE" >> $FILE
297 # update conf for RedHat family
298 FILE=/etc/locale.conf
301 # LC_ALL is not valid in this file, set LANG only
302 echo LANG="$LOCALE" > $FILE
305 # update global env file
306 FILE=/etc/environment
309 # append LC_ALL if not exist
310 grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE
311 # append LANG if not exist
312 grep LANG $FILE || echo LANG="$LOCALE" >> $FILE
321 # pass in with --build-arg while build
323 RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt
326 # need root permission, do it before USER samba
327 RUN /tmp/bootstrap.sh && /tmp/locale.sh
329 # if ld.gold exists, force link it to ld
330 RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD"
332 # make test can not work with root, so we have to create a new user
333 RUN useradd -m -U -s /bin/bash samba && \
334 mkdir -p /etc/sudoers.d && \
335 echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba
339 # samba tests rely on this
340 ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8
343 # Vagrantfile snippet for each dist
344 VAGRANTFILE_SNIPPET = r"""
345 config.vm.define "{name}" do |v|
346 v.vm.box = "{vagrant_box}"
347 v.vm.hostname = "{name}"
348 v.vm.provision :shell, path: "{name}/bootstrap.sh"
349 v.vm.provision :shell, path: "{name}/locale.sh"
353 # global Vagrantfile with snippets for all dists
354 VAGRANTFILE_GLOBAL = r"""
357 Vagrant.configure("2") do |config|
358 config.ssh.insert_key = false
360 {vagrantfile_snippets}
368 'docker_image': 'debian:7',
369 'vagrant_box': 'debian/wheezy64',
371 'libgnutls28-dev': 'libgnutls-dev',
372 'libsystemd-dev': '', # not available, remove
373 'lmdb-utils': '', # not available, remove
374 'liblmdb-dev': '', # not available, remove
375 'python-gpg': 'python-gpgme',
376 'python3-gpg': '', # no python3 gpg pkg available, remove
377 'language-pack-en': '', # included in locales
381 'docker_image': 'debian:8',
382 'vagrant_box': 'debian/jessie64',
384 'python-gpg': 'python-gpgme',
385 'python3-gpg': 'python3-gpgme',
386 'language-pack-en': '', # included in locales
390 'docker_image': 'debian:9',
391 'vagrant_box': 'debian/stretch64',
393 'language-pack-en': '', # included in locales
397 'docker_image': 'ubuntu:14.04',
398 'vagrant_box': 'ubuntu/trusty64',
400 'libsystemd-dev': '', # remove
401 'libgnutls28-dev': 'libgnutls-dev',
402 'python-gpg': 'python-gpgme',
403 'python3-gpg': 'python3-gpgme',
404 'lmdb-utils': 'lmdb-utils/trusty-backports',
405 'liblmdb-dev': 'liblmdb-dev/trusty-backports',
406 'libunwind-dev': 'libunwind8-dev',
407 'glusterfs-common': '',
412 'docker_image': 'ubuntu:16.04',
413 'vagrant_box': 'ubuntu/xenial64',
415 'python-gpg': 'python-gpgme',
416 'python3-gpg': 'python3-gpgme',
417 'glusterfs-common': '',
422 'docker_image': 'ubuntu:18.04',
423 'vagrant_box': 'ubuntu/bionic64',
430 'docker_image': 'centos:6',
431 'vagrant_box': 'centos/6',
432 'bootstrap': YUM_BOOTSTRAP,
434 'lsb-release': 'redhat-lsb',
435 'python3': 'python34',
436 'python3-devel': 'python34-devel',
437 'python2-gpg': 'pygpgme',
438 'python3-gpg': '', # no python3-gpg yet
439 '@development-tools': '"@Development Tools"', # add quotes
440 'glibc-langpack-en': '', # included in glibc-common
441 'glibc-locale-source': '', # included in glibc-common
442 'procps-ng': 'procps', # centos6 still use old name
443 # update perl core modules on centos
444 # fix: Can't locate Archive/Tar.pm in @INC
446 'rpcsvc-proto-devel': '',
447 'glusterfs-api-devel': '',
448 'glusterfs-devel': '',
449 'libcephfs-devel': '',
453 'docker_image': 'centos:7',
454 'vagrant_box': 'centos/7',
455 'bootstrap': YUM_BOOTSTRAP,
457 'lsb-release': 'redhat-lsb',
458 'python3': 'python34',
459 'python3-devel': 'python34-devel',
460 # although python36-devel is available
461 # after epel-release installed
462 # however, all other python3 pkgs are still python34-ish
463 'python2-gpg': 'pygpgme',
464 'python3-gpg': '', # no python3-gpg yet
465 '@development-tools': '"@Development Tools"', # add quotes
466 'glibc-langpack-en': '', # included in glibc-common
467 'glibc-locale-source': '', # included in glibc-common
468 # update perl core modules on centos
469 # fix: Can't locate Archive/Tar.pm in @INC
471 'rpcsvc-proto-devel': '',
472 'glusterfs-api-devel': '',
473 'glusterfs-devel': '',
474 'libcephfs-devel': '',
478 'docker_image': 'fedora:28',
479 'vagrant_box': 'fedora/28-cloud-base',
480 'bootstrap': DNF_BOOTSTRAP,
482 'lsb-release': 'redhat-lsb',
486 'docker_image': 'fedora:29',
487 'vagrant_box': 'fedora/29-cloud-base',
488 'bootstrap': DNF_BOOTSTRAP,
490 'lsb-release': 'redhat-lsb',
494 'docker_image': 'opensuse/leap:15.0',
495 'vagrant_box': 'opensuse/openSUSE-15.0-x86_64',
496 'bootstrap': ZYPPER_BOOTSTRAP,
498 '@development-tools': '',
499 'dbus-devel': 'dbus-1-devel',
500 'docbook-style-xsl': 'docbook-xsl-stylesheets',
501 'glibc-common': 'glibc-locale',
502 'glibc-locale-source': 'glibc-i18ndata',
503 'glibc-langpack-en': '',
504 'jansson-devel': 'libjansson-devel',
505 'keyutils-libs-devel': 'keyutils-devel',
506 'krb5-workstation': 'krb5-client',
507 'libnsl2-devel': 'libnsl-devel',
508 'libsemanage-python': 'python2-semanage',
509 'nettle-devel': 'libnettle-devel',
510 'openldap-devel': 'openldap2-devel',
511 'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
512 'perl-JSON-Parse': 'perl-JSON-XS',
513 'perl-generators': '',
514 'perl-interpreter': '',
515 'procps-ng': 'procps',
516 'python-dns': 'python2-dnspython',
517 'python3-crypto': 'python3-pycrypto',
518 'python3-dns': 'python3-dnspython',
519 'python3-markdown': 'python3-Markdown',
521 'glusterfs-api-devel': '',
530 'bootstrap': APT_BOOTSTRAP, # family default
538 'bootstrap': YUM_BOOTSTRAP, # family default
549 def expand_family_dists(family):
551 for name, config in family['dists'].items():
552 config = config.copy()
553 config['name'] = name
554 config['home'] = join(OUT, name)
555 config['family'] = family['name']
556 config['GENERATED_MARKER'] = GENERATED_MARKER
558 # replace dist specific pkgs
559 replace = config.get('replace', {})
561 for pkg in family['pkgs']:
562 pkg = replace.get(pkg, pkg) # replace if exists or get self
567 lines = [' - {}'.format(pkg) for pkg in pkgs]
568 config['packages.yml'] = YML_HEADER.lstrip() + os.linesep.join(lines)
570 sep = ' \\' + os.linesep + ' '
571 config['pkgs'] = sep.join(pkgs)
573 # get dist bootstrap template or fall back to family default
574 bootstrap_template = config.get('bootstrap', family['bootstrap'])
575 config['bootstrap.sh'] = bootstrap_template.format(**config).strip()
576 config['locale.sh'] = LOCALE_SETUP.format(**config).strip()
578 config['Dockerfile'] = DOCKERFILE.format(**config).strip()
579 # keep the indent, no strip
580 config['vagrantfile_snippet'] = VAGRANTFILE_SNIPPET.format(**config)
586 # expanded config for dists
587 DEB_DISTS_EXP = expand_family_dists(DEB_FAMILY)
588 RPM_DISTS_EXP = expand_family_dists(RPM_FAMILY)
590 # assemble all together
592 DISTS.update(DEB_DISTS_EXP)
593 DISTS.update(RPM_DISTS_EXP)
596 def render_vagrantfile(dists):
598 Render all snippets for each dist into global Vagrantfile.
600 Vagrant supports multiple vms in one Vagrantfile.
601 This make it easier to manage the fleet, e.g:
603 start all: vagrant up
604 start one: vagrant up ubuntu1804
606 All other commands apply to above syntax, e.g.: status, destroy, provision
608 # sort dists by name and put all vagrantfile snippets together
610 dists[dist]['vagrantfile_snippet']
611 for dist in sorted(dists.keys())]
613 return VAGRANTFILE_GLOBAL.format(
614 vagrantfile_snippets=''.join(snippets),
615 GENERATED_MARKER=GENERATED_MARKER
619 VAGRANTFILE = render_vagrantfile(DISTS)
622 # data we need to expose
623 __all__ = ['DISTS', 'VAGRANTFILE', 'OUT']