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
52 'psmisc', # for pstree in test
56 'sudo', # docker images has no sudo by default
62 # define pkgs for all packaging systems in parallel
63 # make it easier to find missing ones
64 # use latest ubuntu and fedora as defaults
67 # NAME1-dev, NAME2-devel
68 ('lmdb-utils', 'lmdb'),
69 ('mingw-w64', 'mingw64-gcc'),
70 ('zlib1g-dev', 'zlib-devel'),
71 ('libbsd-dev', 'libbsd-devel'),
72 ('libaio-dev', 'libaio-devel'),
73 ('libarchive-dev', 'libarchive-devel'),
74 ('libblkid-dev', 'libblkid-devel'),
75 ('libcap-dev', 'libcap-devel'),
76 ('libacl1-dev', 'libacl-devel'),
77 ('libattr1-dev', 'libattr-devel'),
79 # libNAME1-dev, NAME2-devel
80 ('libpopt-dev', 'popt-devel'),
81 ('libreadline-dev', 'readline-devel'),
82 ('libjansson-dev', 'jansson-devel'),
83 ('liblmdb-dev', 'lmdb-devel'),
84 ('libncurses5-dev', 'ncurses-devel'),
85 # NOTE: Debian 7+ or Ubuntu 16.04+
86 ('libsystemd-dev', 'systemd-devel'),
87 ('libkrb5-dev', 'krb5-devel'),
88 ('libldap2-dev', 'openldap-devel'),
89 ('libcups2-dev', 'cups-devel'),
90 ('libpam0g-dev', 'pam-devel'),
91 ('libgpgme11-dev', 'gpgme-devel'),
92 # NOTE: Debian 8+ and Ubuntu 14.04+
93 ('libgnutls28-dev', 'gnutls-devel'),
94 ('libtasn1-bin', 'libtasn1-tools'),
95 ('libtasn1-dev', 'libtasn1-devel'),
97 ('uuid-dev', 'libuuid-devel'),
99 ('libavahi-common-dev', 'avahi-devel'),
100 ('libdbus-1-dev', 'dbus-devel'),
101 ('libpcap-dev', 'libpcap-devel'),
102 ('libunwind-dev', 'libunwind-devel'), # for back trace
103 ('libglib2.0-dev', 'glib2-devel'),
104 ('libicu-dev', 'libicu-devel'),
105 ('heimdal-multidev', ''),
108 # for debian, locales provide locale support with language packs
109 # ubuntu split language packs to language-pack-xx
110 # for centos, glibc-common provide locale support with language packs
111 # fedora split language packs to glibc-langpack-xx
112 ('locales', 'glibc-common'), # required for locale
113 ('language-pack-en', 'glibc-langpack-en'), # we need en_US.UTF-8
114 ('bind9utils', 'bind-utils'),
116 ('xsltproc', 'libxslt'),
119 ('krb5-kdc', 'krb5-server'),
120 ('apt-utils', 'yum-utils'),
121 ('pkg-config', 'pkgconfig'),
122 ('procps', 'procps-ng'), # required for the free cmd in tests
123 ('lsb-release', 'lsb-release'), # we need lsb_relase to show info
124 ('', 'rpcgen'), # required for test
125 # refer: https://fedoraproject.org/wiki/Changes/SunRPCRemoval
126 ('', 'libtirpc-devel'), # for <rpc/rpc.h> header on fedora
127 ('', 'libnsl2-devel'), # for <rpcsvc/yp_prot.h> header on fedora
128 ('', 'rpcsvc-proto-devel'), # for <rpcsvc/rquota.h> header
131 ('python3', 'python3'),
132 ('python3-dev', 'python3-devel'),
134 ('python3-iso8601', ''),
135 ('python3-gpg', 'python3-gpg'), # defaults to ubuntu/fedora latest
136 ('python3-crypto', 'python3-crypto'),
137 ('python3-markdown', 'python3-markdown'),
138 ('python3-matplotlib', ''),
139 ('python3-dnspython', 'python3-dns'),
140 ('python3-pexpect', ''), # for wintest only
142 ('', 'libsemanage-python'),
143 ('', 'policycoreutils-python'),
146 ('libparse-yapp-perl', 'perl-Parse-Yapp'),
147 ('libjson-perl', 'perl-JSON-Parse'),
148 ('perl-modules', ''),
149 ('', 'perl-Archive-Tar'),
150 ('', 'perl-ExtUtils-MakeMaker'),
151 ('', 'perl-Test-Base'),
152 ('', 'perl-generators'),
153 ('', 'perl-interpreter'),
156 ('xfslibs-dev', 'xfsprogs-devel'), # for xfs quota support
157 ('', 'glusterfs-api-devel'),
158 ('glusterfs-common', 'glusterfs-devel'),
159 ('libcephfs-dev', 'libcephfs-devel'),
162 # @ means group for rpm, use fedora as rpm default
163 ('build-essential', '@development-tools'),
165 # rpm has no pkg for docbook-xml
166 ('docbook-xml', 'docbook-dtds'),
167 ('docbook-xsl', 'docbook-style-xsl'),
168 ('', 'keyutils-libs-devel'),
173 DEB_PKGS
= COMMON
+ [pkg
for pkg
, _
in PKGS
if pkg
]
174 RPM_PKGS
= COMMON
+ [pkg
for _
, pkg
in PKGS
if pkg
]
176 GENERATED_MARKER
= r
"""
178 # This file is generated by 'bootstrap/template.py --render'
179 # See also bootstrap/config.py
189 export DEBIAN_FRONTEND=noninteractive
195 apt-get -y autoremove
207 yum install -y epel-release
208 yum install -y yum-plugin-copr
209 yum copr enable -y sergiomb/SambaAD
217 if [ ! -f /usr/bin/python3 ]; then
218 ln -sf /usr/bin/python3.6 /usr/bin/python3
222 CENTOS8_YUM_BOOTSTRAP
= r
"""
228 yum install -y dnf-plugins-core
229 yum install -y epel-release
230 yum config-manager --set-enabled PowerTools -y
234 --setopt=install_weak_deps=False \
248 --setopt=install_weak_deps=False \
254 ZYPPER_BOOTSTRAP
= r
"""
259 zypper --non-interactive refresh
260 zypper --non-interactive update
261 zypper --non-interactive install \
266 zypper --non-interactive clean
268 if [ -f /usr/lib/mit/bin/krb5-config ]; then
269 ln -sf /usr/lib/mit/bin/krb5-config /usr/bin/krb5-config
273 # A generic shell script to setup locale
279 # refer to /usr/share/i18n/locales
281 # refer to /usr/share/i18n/charmaps
283 # locale to generate in /usr/lib/locale
284 # glibc/localedef will normalize UTF-8 to utf8, follow the naming style
285 LOCALE=$INPUTFILE.utf8
287 # if locale is already correct, exit
288 ( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0
290 # if locale not available, generate locale into /usr/lib/locale
291 if ! ( locale --all-locales | grep -i $LOCALE )
293 # no-archive means create its own dir
294 localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE
297 # update locale conf and global env file
298 # set both LC_ALL and LANG for safe
300 # update conf for Debian family
301 FILE=/etc/default/locale
304 echo LC_ALL="$LOCALE" > $FILE
305 echo LANG="$LOCALE" >> $FILE
308 # update conf for RedHat family
309 FILE=/etc/locale.conf
312 # LC_ALL is not valid in this file, set LANG only
313 echo LANG="$LOCALE" > $FILE
316 # update global env file
317 FILE=/etc/environment
320 # append LC_ALL if not exist
321 grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE
322 # append LANG if not exist
323 grep LANG $FILE || echo LANG="$LOCALE" >> $FILE
332 # pass in with --build-arg while build
334 RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt
337 # need root permission, do it before USER samba
338 RUN /tmp/bootstrap.sh && /tmp/locale.sh
340 # if ld.gold exists, force link it to ld
341 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"
343 # make test can not work with root, so we have to create a new user
344 RUN useradd -m -U -s /bin/bash samba && \
345 mkdir -p /etc/sudoers.d && \
346 echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba
350 # samba tests rely on this
351 ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8
354 # Vagrantfile snippet for each dist
355 VAGRANTFILE_SNIPPET
= r
"""
356 config.vm.define "{name}" do |v|
357 v.vm.box = "{vagrant_box}"
358 v.vm.hostname = "{name}"
359 v.vm.provision :shell, path: "{name}/bootstrap.sh"
360 v.vm.provision :shell, path: "{name}/locale.sh"
364 # global Vagrantfile with snippets for all dists
365 VAGRANTFILE_GLOBAL
= r
"""
368 Vagrant.configure("2") do |config|
369 config.ssh.insert_key = false
371 {vagrantfile_snippets}
379 'docker_image': 'debian:7',
380 'vagrant_box': 'debian/wheezy64',
382 'libgnutls28-dev': 'libgnutls-dev',
383 'libsystemd-dev': '', # not available, remove
384 'lmdb-utils': '', # not available, remove
385 'liblmdb-dev': '', # not available, remove
386 'python-gpg': 'python-gpgme',
387 'python3-gpg': '', # no python3 gpg pkg available, remove
388 'language-pack-en': '', # included in locales
392 'docker_image': 'debian:8',
393 'vagrant_box': 'debian/jessie64',
395 'python-gpg': 'python-gpgme',
396 'python3-gpg': 'python3-gpgme',
397 'language-pack-en': '', # included in locales
401 'docker_image': 'debian:9',
402 'vagrant_box': 'debian/stretch64',
404 'language-pack-en': '', # included in locales
408 'docker_image': 'debian:10',
409 'vagrant_box': 'debian/buster64',
411 'language-pack-en': '', # included in locales
415 'docker_image': 'ubuntu:14.04',
416 'vagrant_box': 'ubuntu/trusty64',
418 'libsystemd-dev': '', # remove
419 'libgnutls28-dev': 'libgnutls-dev',
420 'python-gpg': 'python-gpgme',
421 'python3-gpg': 'python3-gpgme',
422 'lmdb-utils': 'lmdb-utils/trusty-backports',
423 'liblmdb-dev': 'liblmdb-dev/trusty-backports',
424 'libunwind-dev': 'libunwind8-dev',
425 'glusterfs-common': '',
430 'docker_image': 'ubuntu:16.04',
431 'vagrant_box': 'ubuntu/xenial64',
433 'python-gpg': 'python-gpgme',
434 'python3-gpg': 'python3-gpgme',
435 'glusterfs-common': '',
440 'docker_image': 'ubuntu:18.04',
441 'vagrant_box': 'ubuntu/bionic64',
448 'docker_image': 'centos:6',
449 'vagrant_box': 'centos/6',
450 'bootstrap': YUM_BOOTSTRAP
,
452 'lsb-release': 'redhat-lsb',
453 'python3': 'python36',
454 'python3-devel': 'python36-devel',
455 'python2-gpg': 'pygpgme',
456 'python3-gpg': '', # no python3-gpg yet
457 '@development-tools': '"@Development Tools"', # add quotes
458 'glibc-langpack-en': '', # included in glibc-common
459 'glibc-locale-source': '', # included in glibc-common
460 'procps-ng': 'procps', # centos6 still use old name
461 # update perl core modules on centos
462 # fix: Can't locate Archive/Tar.pm in @INC
464 'rpcsvc-proto-devel': '',
465 'glusterfs-api-devel': '',
466 'glusterfs-devel': '',
467 'libcephfs-devel': '',
471 'docker_image': 'centos:7',
472 'vagrant_box': 'centos/7',
473 'bootstrap': YUM_BOOTSTRAP
,
475 'lsb-release': 'redhat-lsb',
476 'python3': 'python36',
477 'python3-crypto': 'python36-crypto',
478 'python3-devel': 'python36-devel',
479 'python3-dns': 'python36-dns',
480 'python3-gpg': 'python36-gpg',
481 'python3-iso8601' : 'python36-iso8601',
482 'python3-markdown': 'python36-markdown',
483 # although python36-devel is available
484 # after epel-release installed
485 # however, all other python3 pkgs are still python36-ish
486 'python2-gpg': 'pygpgme',
487 'python3-gpg': '', # no python3-gpg yet
488 '@development-tools': '"@Development Tools"', # add quotes
489 'glibc-langpack-en': '', # included in glibc-common
490 'glibc-locale-source': '', # included in glibc-common
491 # update perl core modules on centos
492 # fix: Can't locate Archive/Tar.pm in @INC
494 'rpcsvc-proto-devel': '',
495 'glusterfs-api-devel': '',
496 'glusterfs-devel': '',
497 'libcephfs-devel': '',
498 'gnutls-devel': 'compat-gnutls34-devel',
502 'docker_image': 'centos:8',
503 'vagrant_box': 'centos/8',
504 'bootstrap': CENTOS8_YUM_BOOTSTRAP
,
506 'lsb-release': 'redhat-lsb',
507 '@development-tools': '"@Development Tools"', # add quotes
508 'libsemanage-python': 'python3-libsemanage',
509 'lcov': '', # does not exist
510 'perl-JSON-Parse': '', # does not exist?
511 'perl-Test-Base': 'perl-Test-Simple',
512 'policycoreutils-python': 'python3-policycoreutils',
513 'python3-crypto': '',
514 'quota-devel': '', # FIXME: Add me back, once available!
518 'docker_image': 'fedora:29',
519 'vagrant_box': 'fedora/29-cloud-base',
520 'bootstrap': DNF_BOOTSTRAP
,
522 'lsb-release': 'redhat-lsb',
526 'docker_image': 'fedora:30',
527 'vagrant_box': 'fedora/30-cloud-base',
528 'bootstrap': DNF_BOOTSTRAP
,
530 'lsb-release': 'redhat-lsb',
534 'docker_image': 'fedora:31',
535 'vagrant_box': 'fedora/31-cloud-base',
536 'bootstrap': DNF_BOOTSTRAP
,
538 'lsb-release': 'redhat-lsb',
539 'libsemanage-python': 'python3-libsemanage',
540 'policycoreutils-python': 'python3-policycoreutils',
544 'docker_image': 'opensuse/leap:15.0',
545 'vagrant_box': 'opensuse/openSUSE-15.0-x86_64',
546 'bootstrap': ZYPPER_BOOTSTRAP
,
548 '@development-tools': '',
549 'dbus-devel': 'dbus-1-devel',
550 'docbook-style-xsl': 'docbook-xsl-stylesheets',
551 'glibc-common': 'glibc-locale',
552 'glibc-locale-source': 'glibc-i18ndata',
553 'glibc-langpack-en': '',
554 'jansson-devel': 'libjansson-devel',
555 'keyutils-libs-devel': 'keyutils-devel',
556 'krb5-workstation': 'krb5-client',
557 'libnsl2-devel': 'libnsl-devel',
558 'libsemanage-python': 'python2-semanage',
559 'openldap-devel': 'openldap2-devel',
560 'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
561 'perl-JSON-Parse': 'perl-JSON-XS',
562 'perl-generators': '',
563 'perl-interpreter': '',
564 'procps-ng': 'procps',
565 'python-dns': 'python2-dnspython',
566 'python3-crypto': 'python3-pycrypto',
567 'python3-dns': 'python3-dnspython',
568 'python3-markdown': 'python3-Markdown',
570 'glusterfs-api-devel': '',
571 'libtasn1-tools': '', # asn1Parser is part of libtasn1
572 'mingw64-gcc': '', # doesn't exist
576 'docker_image': 'opensuse/leap:15.1',
577 'vagrant_box': 'opensuse/openSUSE-15.1-x86_64',
578 'bootstrap': ZYPPER_BOOTSTRAP
,
580 '@development-tools': '',
581 'dbus-devel': 'dbus-1-devel',
582 'docbook-style-xsl': 'docbook-xsl-stylesheets',
583 'glibc-common': 'glibc-locale',
584 'glibc-locale-source': 'glibc-i18ndata',
585 'glibc-langpack-en': '',
586 'jansson-devel': 'libjansson-devel',
587 'keyutils-libs-devel': 'keyutils-devel',
588 'krb5-workstation': 'krb5-client',
589 'libnsl2-devel': 'libnsl-devel',
590 'libsemanage-python': 'python2-semanage',
591 'openldap-devel': 'openldap2-devel',
592 'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
593 'perl-JSON-Parse': 'perl-JSON-XS',
594 'perl-generators': '',
595 'perl-interpreter': '',
596 'procps-ng': 'procps',
597 'python-dns': 'python2-dnspython',
598 'python3-crypto': 'python3-pycrypto',
599 'python3-dns': 'python3-dnspython',
600 'python3-markdown': 'python3-Markdown',
602 'glusterfs-api-devel': '',
603 'libtasn1-tools': '', # asn1Parser is part of libtasn1
604 'mingw64-gcc': '', # doesn't exist
613 'bootstrap': APT_BOOTSTRAP
, # family default
621 'bootstrap': YUM_BOOTSTRAP
, # family default
632 def expand_family_dists(family
):
634 for name
, config
in family
['dists'].items():
635 config
= config
.copy()
636 config
['name'] = name
637 config
['home'] = join(OUT
, name
)
638 config
['family'] = family
['name']
639 config
['GENERATED_MARKER'] = GENERATED_MARKER
641 # replace dist specific pkgs
642 replace
= config
.get('replace', {})
644 for pkg
in family
['pkgs']:
645 pkg
= replace
.get(pkg
, pkg
) # replace if exists or get self
650 lines
= [' - {}'.format(pkg
) for pkg
in pkgs
]
651 config
['packages.yml'] = YML_HEADER
.lstrip() + os
.linesep
.join(lines
)
653 sep
= ' \\' + os
.linesep
+ ' '
654 config
['pkgs'] = sep
.join(pkgs
)
656 # get dist bootstrap template or fall back to family default
657 bootstrap_template
= config
.get('bootstrap', family
['bootstrap'])
658 config
['bootstrap.sh'] = bootstrap_template
.format(**config
).strip()
659 config
['locale.sh'] = LOCALE_SETUP
.format(**config
).strip()
661 config
['Dockerfile'] = DOCKERFILE
.format(**config
).strip()
662 # keep the indent, no strip
663 config
['vagrantfile_snippet'] = VAGRANTFILE_SNIPPET
.format(**config
)
669 # expanded config for dists
670 DEB_DISTS_EXP
= expand_family_dists(DEB_FAMILY
)
671 RPM_DISTS_EXP
= expand_family_dists(RPM_FAMILY
)
673 # assemble all together
675 DISTS
.update(DEB_DISTS_EXP
)
676 DISTS
.update(RPM_DISTS_EXP
)
679 def render_vagrantfile(dists
):
681 Render all snippets for each dist into global Vagrantfile.
683 Vagrant supports multiple vms in one Vagrantfile.
684 This make it easier to manage the fleet, e.g:
686 start all: vagrant up
687 start one: vagrant up ubuntu1804
689 All other commands apply to above syntax, e.g.: status, destroy, provision
691 # sort dists by name and put all vagrantfile snippets together
693 dists
[dist
]['vagrantfile_snippet']
694 for dist
in sorted(dists
.keys())]
696 return VAGRANTFILE_GLOBAL
.format(
697 vagrantfile_snippets
=''.join(snippets
),
698 GENERATED_MARKER
=GENERATED_MARKER
702 VAGRANTFILE
= render_vagrantfile(DISTS
)
705 # data we need to expose
706 __all__
= ['DISTS', 'VAGRANTFILE', 'OUT']