Merge ~mitchdz/ubuntu/+source/open-iscsi:merge-lp2040361-noble into ubuntu/+source/open-iscsi:debian/sid

Proposed by Mitchell Dzurick
Status: Work in progress
Proposed branch: ~mitchdz/ubuntu/+source/open-iscsi:merge-lp2040361-noble
Merge into: ubuntu/+source/open-iscsi:debian/sid
Diff against target: 5606 lines (+5354/-5)
16 files modified
debian/README.Debian (+2/-2)
debian/changelog (+1415/-0)
debian/control (+2/-1)
debian/extra/startup-checks.sh (+1/-1)
debian/open-iscsi.postinst (+1/-1)
debian/patches/fix-format-overflow-warnings.patch (+29/-0)
debian/patches/series (+1/-0)
debian/tests/README-boot-test.md (+139/-0)
debian/tests/control (+4/-0)
debian/tests/get-image (+227/-0)
debian/tests/patch-image (+374/-0)
debian/tests/test-open-iscsi.py (+427/-0)
debian/tests/testlib.py (+1488/-0)
debian/tests/testsuite (+6/-0)
debian/tests/tgt-boot-test (+534/-0)
debian/tests/xkvm (+704/-0)
Reviewer Review Type Date Requested Status
git-ubuntu import Pending
Review via email: mp+455716@code.launchpad.net
To post a comment you must log in.

Unmerged commits

f8cc311... by Mitchell Dzurick

update-maintainer

718f405... by Mitchell Dzurick

reconstruct-changelog

c19e401... by Mitchell Dzurick

merge-changelogs

e472cca... by Mitchell Dzurick

      * Fix format overflow warnings seen when building with
        -O3 to avoid FTBFS on ppc64el (LP: 2036884)

5ab39bf... by Mitchell Dzurick

            - debian/tests: Add Ubuntu autopkgtest suite:
              + d/t/README-boot-test.md: document test design
              + d/t/control: register testsuite
              + d/t/get-image: helper to fetch an ubuntu cloud image
              + d/t/patch-image: helper to modify an ubuntu cloud image
              + d/test-open-iscsi.py, d/t/testlib.py: various qa regression tests
              + d/t/testsuite: helper to invoke qa regression tests
              + d/t/tgt-boot-test: test using tgt to boot from iscsi
              + d/t/xkvm: helper to spawn a VM
            - d/README.Debian, d/extra/startup-checks.sh, d/open-iscsi.postinst:
              Apply Ubuntu branding to iqn initiator name

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/README.Debian b/debian/README.Debian
2index f0c2568..43c7c81 100644
3--- a/debian/README.Debian
4+++ b/debian/README.Debian
5@@ -57,7 +57,7 @@ iSCSI Qualified Names (IQN) and initiatorname.iscsi
6 The initiatorname.iscsi file defines the iSCSI Qualified Name (IQN) of the iSCSI
7 initiator. This IQN is used by the initiator to identify itself to the target.
8
9-Example: InitiatorName=iqn.1993-08.org.debian:01:lnx-debian
10+Example: InitiatorName=iqn.2004-10.com.ubuntu:01:lnx-debian
11
12 While this name can be adjusted to suit your needs, once set, it should not be
13 changed. If you later change the InitiatorName, existing access control lists
14@@ -100,7 +100,7 @@ options in your initramfs:
15
16 Example Syntax:
17
18- ISCSI_INITIATOR="iqn.1993-08.org.debian:01:9b3e5634fdb9"
19+ ISCSI_INITIATOR="iqn.2004-10.com.ubuntu:01:9b3e5634fdb9"
20 ISCSI_TARGET_NAME=iqn.2008-01.com.example:storage.foo
21 ISCSI_TARGET_IP=192.168.1.1
22 ISCSI_TARGET_PORT=3260
23diff --git a/debian/changelog b/debian/changelog
24index b6dd1e3..36f598e 100644
25--- a/debian/changelog
26+++ b/debian/changelog
27@@ -1,3 +1,22 @@
28+open-iscsi (2.1.9-1ubuntu1) noble; urgency=medium
29+
30+ * Merge with Debian unstable (LP: #2040361). Remaining changes:
31+ - debian/tests: Add Ubuntu autopkgtest suite:
32+ + d/t/README-boot-test.md: document test design
33+ + d/t/control: register testsuite
34+ + d/t/get-image: helper to fetch an ubuntu cloud image
35+ + d/t/patch-image: helper to modify an ubuntu cloud image
36+ + d/test-open-iscsi.py, d/t/testlib.py: various qa regression tests
37+ + d/t/testsuite: helper to invoke qa regression tests
38+ + d/t/tgt-boot-test: test using tgt to boot from iscsi
39+ + d/t/xkvm: helper to spawn a VM
40+ - d/README.Debian, d/extra/startup-checks.sh, d/open-iscsi.postinst:
41+ Apply Ubuntu branding to iqn initiator name
42+ - Fix format overflow warnings seen when building with
43+ -O3 to avoid FTBFS on ppc64el (LP: 2036884)
44+
45+ -- Mitchell Dzurick <mitchell.dzurick@canonical.com> Wed, 15 Nov 2023 15:23:28 -0700
46+
47 open-iscsi (2.1.9-1) unstable; urgency=medium
48
49 * [90dd9cd] New upstream version 2.1.9
50@@ -19,6 +38,30 @@ open-iscsi (2.1.8-2) unstable; urgency=medium
51
52 -- Chris Hofstaedtler <zeha@debian.org> Sun, 27 Aug 2023 12:10:27 +0200
53
54+open-iscsi (2.1.8-1ubuntu2) mantic; urgency=medium
55+
56+ * Fix format overflow warnings seen when building with
57+ -O3 to avoid FTBFS on ppc64el (LP: #2036884)
58+
59+ -- Graham Inggs <ginggs@ubuntu.com> Fri, 22 Sep 2023 15:42:55 +0000
60+
61+open-iscsi (2.1.8-1ubuntu1) lunar; urgency=low
62+
63+ * Merge from Debian unstable. Remaining changes:
64+ - debian/tests: Add Ubuntu autopkgtest suite:
65+ + d/t/README-boot-test.md: document test design
66+ + d/t/control: register testsuite
67+ + d/t/get-image: helper to fetch an ubuntu cloud image
68+ + d/t/patch-image: helper to modify an ubuntu cloud image
69+ + d/test-open-iscsi.py, d/t/testlib.py: various qa regression tests
70+ + d/t/testsuite: helper to invoke qa regression tests
71+ + d/t/tgt-boot-test: test using tgt to boot from iscsi
72+ + d/t/xkvm: helper to spawn a VM
73+ - d/README.Debian, d/extra/startup-checks.sh, d/open-iscsi.postinst:
74+ Apply Ubuntu branding to iqn initiator name
75+
76+ -- Steve Langasek <steve.langasek@ubuntu.com> Mon, 07 Nov 2022 15:10:10 -0800
77+
78 open-iscsi (2.1.8-1) unstable; urgency=medium
79
80 [ Chris Hofstaedtler ]
81@@ -31,6 +74,33 @@ open-iscsi (2.1.8-1) unstable; urgency=medium
82
83 -- Chris Hofstaedtler <zeha@debian.org> Wed, 19 Oct 2022 15:59:32 +0000
84
85+open-iscsi (2.1.7-2ubuntu1) kinetic; urgency=low
86+
87+ * Merge from Debian unstable. Remaining changes:
88+ - debian/tests: Add Ubuntu autopkgtest suite:
89+ + d/t/README-boot-test.md: document test design
90+ + d/t/control: register testsuite
91+ + d/t/get-image: helper to fetch an ubuntu cloud image
92+ + d/t/patch-image: helper to modify an ubuntu cloud image
93+ + d/test-open-iscsi.py, d/t/testlib.py: various qa regression tests
94+ + d/t/testsuite: helper to invoke qa regression tests
95+ + d/t/tgt-boot-test: test using tgt to boot from iscsi
96+ + d/t/xkvm: helper to spawn a VM
97+ - d/README.Debian, d/extra/startup-checks.sh, d/open-iscsi.postinst:
98+ Apply Ubuntu branding to iqn initiator name
99+ * Dropped changes, no longer needed:
100+ - debian/open-iscsi-udeb.start: Apply Ubuntu branding
101+ - Stop producing udebs on i386 where we no longer have d-i or a kernel.
102+ * Dropped changes, included in Debian:
103+ - d/p/lp1979692-fix-gcc12-ftbfs-0*.patch: Fix FTBFS with GCC 12.
104+ - d/rules: remove duplicated dh_installsystemd section
105+ * Dropped changes, no longer needed:
106+ - d/control: Transition from libopeniscsiusr0.2.0 to libopeniscsiusr;
107+ not needed, the referenced version is no longer in any supported
108+ release and the transitional package is in the previous LTS.
109+
110+ -- Steve Langasek <steve.langasek@ubuntu.com> Tue, 16 Aug 2022 08:32:36 -0700
111+
112 open-iscsi (2.1.7-2) unstable; urgency=medium
113
114 * [09dfaec] Enable hardening build flags
115@@ -56,6 +126,86 @@ open-iscsi (2.1.7-1) unstable; urgency=medium
116
117 -- Chris Hofstaedtler <zeha@debian.org> Fri, 29 Jul 2022 19:59:11 +0000
118
119+open-iscsi (2.1.5-1ubuntu2) kinetic; urgency=medium
120+
121+ * d/p/lp1979692-fix-gcc12-ftbfs-0*.patch: Fix FTBFS with GCC 12.
122+ (LP: #1979692)
123+
124+ -- Sergio Durigan Junior <sergio.durigan@canonical.com> Thu, 23 Jun 2022 17:28:56 -0400
125+
126+open-iscsi (2.1.5-1ubuntu1) jammy; urgency=medium
127+
128+ * Merge with Debian unstable (LP: #1946835). Remaining changes:
129+ - debian/tests: Add Ubuntu autopkgtest suite:
130+ + d/t/README-boot-test.md: document test design
131+ + d/t/control: register testsuite
132+ + d/t/get-image: helper to fetch an ubuntu cloud image
133+ + d/t/patch-image: helper to modify an ubuntu cloud image
134+ + d/test-open-iscsi.py, d/t/testlib.py: various qa regression tests
135+ + d/t/testsuite: helper to invoke qa regression tests
136+ + d/t/tgt-boot-test: test using tgt to boot from iscsi
137+ + d/t/xkvm: helper to spawn a VM
138+ - Stop producing udebs on i386 where we no longer have d-i or a kernel.
139+ - d/README.Debian, d/extra/startup-checks.sh, d/open-iscsi-udeb.start,
140+ d/open-iscsi.postinst: Apply Ubuntu branding to iqn initiator name
141+ - d/control: Transition from libopeniscsiusr0.2.0 to libopeniscsiusr
142+ - d/t/test-open-iscsi.py: adopt to resolvectl (systemd v249 compat)
143+ * Dropped changes, included in Debian:
144+ - d/iscsid.service: Let iscsid systemd job run in privileged containers
145+ but not in unprivileged ones
146+ - debian/extra/initramfs.local-top: handle iSCSI iBFT DHCP to correctly
147+ run ipconfig to gather all DHCP config info, including DNS search
148+ domain, which iBFT can't provide.
149+ - Remove initramfs interfaces stamp in case no iscsi devs mounted
150+ If iscsi root was requested, but no iscsi devices were mounted, remove
151+ the initramfs interfaces stamp file. Meaning, that on shutdown there is
152+ no 30s delay, whilst trying to re-establish iscsi login to perform a
153+ logout.
154+ - add IPv6 support
155+ + Source /run/net6-*.conf when needed.
156+ + debian/extra/initramfs.local-top: handle IPv6 configs being shipped
157+ in DEVICE6 or /run/net6-*.conf in the initramfs, so we can fill in
158+ /run/initramfs/open-iscsi.interface
159+ - d/rules, d/open-iscsi.finalrd, d/control: ship the finalrd iscsi
160+ logout hook and recommend finalrd and busybox for the logout hook
161+ to work.
162+ - Make iscsid socket-activated to only activate it as needed:
163+ + debian/open-iscsi.service: do not start or check iscsid.service
164+ + debian/rules: install and enable iscsid.socket
165+ + debian/open-iscsi.postinst:
166+ + run restart logic only if service is running on upgrade
167+ + drop no longer reachable upgrade path that affects iscsid
168+ + disable iscsid.service on upgrade
169+ + handle iscsid.socket to be started if the service is not running yet
170+ + d/iscsi-disk.rules: Add a udev rule so that iscsid.service will be
171+ run when udev disks are attached.
172+ + d/iscsid.service: Remove ExecStop= directive.
173+ + debian/tests/install: fix tests to work with socket activation
174+ + debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch
175+ - debian/open-iscsi.service: Start open-iscsi systemd job when either
176+ /etc/iscsi/nodes or /sys/class/iscsi_session have content.
177+ - Prevent network interface that contains iscsi root from bouncing
178+ during boot or going down during shutdown if the system is using
179+ resolvconf or ifupdown:
180+ + d/iscsi-network-interface.rules
181+ + d/extra/net-interface-handler
182+ - debian/extra/initramfs.hook: add ib_iser to the list of modules
183+ included in the initramfs, so that we can in principle support
184+ iscsi root on infiniband.
185+ - debian/open-iscsi.kmod drop: (LP 1833586)
186+ no static module list is needed if we let iscsid load modules itself.
187+ - d/extra/initramfs.local-{top,bottom}: move removal of
188+ open-iscsi.interface file from local-top to local-bottom,
189+ and fix shell quoting issue that would result in /run/initramfs/
190+ open-iscsi.interface always being removed (LP 1872813)
191+ - d/rules: Don't FTBFS due to warnings new in gcc10 regarding bounds and
192+ initialization, because upstream's gcc10 support is incomplete. This
193+ change can be dropped when upstream has completed their gcc support.
194+ * Added changes
195+ - d/rules: remove duplicated dh_installsystemd section
196+
197+ -- Dave Jones <dave.jones@canonical.com> Wed, 19 Jan 2022 11:38:12 +0000
198+
199 open-iscsi (2.1.5-1) unstable; urgency=medium
200
201 * [150470c] New upstream version 2.1.5
202@@ -149,6 +299,91 @@ open-iscsi (2.1.4-1) unstable; urgency=low
203
204 -- Ritesh Raj Sarraf <rrs@debian.org> Thu, 02 Sep 2021 18:07:51 +0530
205
206+open-iscsi (2.1.4-0ubuntu3) jammy; urgency=medium
207+
208+ * No-change rebuild against openssl3
209+
210+ -- Simon Chopin <simon.chopin@canonical.com> Wed, 01 Dec 2021 16:08:23 +0000
211+
212+open-iscsi (2.1.4-0ubuntu2) jammy; urgency=medium
213+
214+ * [a0e81aa] d/t/test-open-iscsi.py: adopt to resolvectl (systemd v249 compat)
215+
216+ -- Lukas Märdian <slyon@ubuntu.com> Mon, 22 Nov 2021 11:42:18 +0100
217+
218+open-iscsi (2.1.4-0ubuntu1) impish; urgency=medium
219+
220+ * Merge with Debian unstable (LP: #1934290). Remaining changes:
221+ - debian/tests: Add Ubuntu autopkgtest suite:
222+ + d/t/README-boot-test.md: document test design
223+ + d/t/control: register testsuite
224+ + d/t/get-image: helper to fetch an ubuntu cloud image
225+ + d/t/patch-image: helper to modify an ubuntu cloud image
226+ + d/test-open-iscsi.py, d/t/testlib.py: various qa regression tests
227+ + d/t/testsuite: helper to invoke qa regression tests
228+ + d/t/tgt-boot-test: test using tgt to boot from iscsi
229+ + d/t/xkvm: helper to spawn a VM
230+ Note: this suite should be replaced by LIO that replaced TGT in main.
231+ - d/iscsid.service: Let iscsid systemd job run in privileged containers
232+ but not in unprivileged ones
233+ - debian/extra/initramfs.local-top: handle iSCSI iBFT DHCP to correctly
234+ run ipconfig to gather all DHCP config info, including DNS search
235+ domain, which iBFT can't provide.
236+ - Remove initramfs interfaces stamp in case no iscsi devs mounted
237+ If iscsi root was requested, but no iscsi devices were mounted, remove
238+ the initramfs interfaces stamp file. Meaning, that on shutdown there is
239+ no 30s delay, whilst trying to re-establish iscsi login to perform a
240+ logout.
241+ - add IPv6 support
242+ + Source /run/net6-*.conf when needed.
243+ + debian/extra/initramfs.local-top: handle IPv6 configs being shipped
244+ in DEVICE6 or /run/net6-*.conf in the initramfs, so we can fill in
245+ /run/initramfs/open-iscsi.interface
246+ - d/rules, d/open-iscsi.finalrd, d/control: ship the finalrd iscsi
247+ logout hook and recommend finalrd and busybox for the logout hook
248+ to work.
249+ - Make iscsid socket-activated to only activate it as needed:
250+ + debian/open-iscsi.service: do not start or check iscsid.service
251+ + debian/rules: install and enable iscsid.socket
252+ + debian/open-iscsi.postinst:
253+ + run restart logic only if service is running on upgrade
254+ + drop no longer reachable upgrade path that affects iscsid
255+ + disable iscsid.service on upgrade
256+ + handle iscsid.socket to be started if the service is not running yet
257+ + d/iscsi-disk.rules: Add a udev rule so that iscsid.service will be
258+ run when udev disks are attached.
259+ + d/iscsid.service: Remove ExecStop= directive.
260+ + debian/tests/install: fix tests to work with socket activation
261+ + debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch
262+ - debian/open-iscsi.service: Start open-iscsi systemd job when either
263+ /etc/iscsi/nodes or /sys/class/iscsi_session have content.
264+ - Prevent network interface that contains iscsi root from bouncing
265+ during boot or going down during shutdown if the system is using
266+ resolvconf or ifupdown:
267+ + d/iscsi-network-interface.rules
268+ + d/extra/net-interface-handler
269+ - debian/extra/initramfs.hook: add ib_iser to the list of modules
270+ included in the initramfs, so that we can in principle support
271+ iscsi root on infiniband.
272+ - debian/open-iscsi.kmod drop: (LP 1833586)
273+ no static module list is needed if we let iscsid load modules itself.
274+ - Stop producing udebs on i386 where we no longer have d-i or a kernel.
275+ - d/extra/initramfs.local-{top,bottom}: move removal of
276+ open-iscsi.interface file from local-top to local-bottom,
277+ and fix shell quoting issue that would result in /run/initramfs/
278+ open-iscsi.interface always being removed (LP 1872813)
279+ - d/rules: Don't FTBFS due to warnings new in gcc10 regarding bounds and
280+ initialization, because upstream's gcc10 support is incomplete. This
281+ change can be dropped when upstream has completed their gcc support.
282+ - d/README.Debian, d/extra/startup-checks.sh, d/open-iscsi-udeb.start,
283+ d/open-iscsi.postinst: Apply Ubuntu branding to iqn initiator name
284+ * Added changes
285+ - merge bug fix release 2.1.4 from upstream
286+ - Revert "Add patches from upstream" [upstream in 2.1.4]
287+ - d/control: Transition from libopeniscsiusr0.2.0 to libopeniscsiusr
288+
289+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Thu, 01 Jul 2021 14:13:08 +0200
290+
291 open-iscsi (2.1.3-5) unstable; urgency=medium
292
293 [ Cyril Brulebois ]
294@@ -184,6 +419,119 @@ open-iscsi (2.1.3-2) unstable; urgency=medium
295
296 -- Chris Hofstaedtler <zeha@debian.org> Sun, 07 Feb 2021 19:23:13 +0000
297
298+open-iscsi (2.1.3-1ubuntu6) hirsute; urgency=medium
299+
300+ * d/open-iscsi.finalrd: fix UID resolution issues in logout (LP: #1922976)
301+ Thanks to Michael Brown
302+
303+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Thu, 18 Mar 2021 09:44:07 +0100
304+
305+open-iscsi (2.1.3-1ubuntu5) hirsute; urgency=medium
306+
307+ * make d/t/testuite python3 compatible (LP: #1919461)
308+ - backport changes from qa-regression-testing since we diverged
309+ - various tests: make py3 compliant, fix formatting a bit
310+ - tests: convert deprecated assertEquals() to assertEqual()
311+ - Remove all references to python-utils
312+ - d/t/testlib.py: update to last state from
313+ git+ssh://git.launchpad.net/qa-regression-testing
314+ - d/t/{control,testsuite}: bump to use python3
315+ - d/t/test-open-iscsi.py: switch shebang to python3
316+ - d/t/test-open-iscsi.py: adapt to updated testlib
317+ * Add patches from upstream [this is from Debian upload 2.1.3-2]:
318+ - Fix memory leak in iscsiadm, Fix iscsiadm segfault when exiting, and
319+ - Fix iscsistart login issue when target is delayed. The last one should
320+ - fix iscsi-root with delayed network (Closes: #980085)
321+
322+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Thu, 18 Mar 2021 09:44:07 +0100
323+
324+open-iscsi (2.1.3-1ubuntu4) hirsute; urgency=medium
325+
326+ * Rebuild again so s390x pick up the right debhelper
327+
328+ -- Sebastien Bacher <seb128@ubuntu.com> Wed, 24 Feb 2021 16:29:41 +0100
329+
330+open-iscsi (2.1.3-1ubuntu3) hirsute; urgency=medium
331+
332+ * No-change rebuild to drop the udeb package.
333+
334+ -- Matthias Klose <doko@ubuntu.com> Mon, 22 Feb 2021 10:35:42 +0100
335+
336+open-iscsi (2.1.3-1ubuntu2) hirsute; urgency=medium
337+
338+ * Apply Ubuntu branding to iqn initiator name.
339+
340+ -- Dimitri John Ledkov <xnox@ubuntu.com> Wed, 17 Feb 2021 00:05:22 +0000
341+
342+open-iscsi (2.1.3-1ubuntu1) hirsute; urgency=medium
343+
344+ * Merge with Debian unstable. Remaining changes:
345+ - debian/tests: Add Ubuntu autopkgtest suite:
346+ - README-boot-test.md
347+ - tgt-boot-test: tests
348+ - test-open-iscsi.py
349+ - testlib.py
350+ - get-image
351+ - patch-image
352+ - testsuite
353+ - xkvm
354+ - d/iscsid.service: Let iscsid systemd job run in privileged containers
355+ but not in unprivileged ones
356+ - d/extra/initramfs.local-top: handle iSCSI iBFT DHCP to correctly
357+ run ipconfig to gather all DHCP config info, including DNS search
358+ domain, which iBFT can't provide.
359+ - Remove initramfs interfaces stamp in case no iscsi devs mounted.
360+ If iscsi root was requested, but no iscsi devices were mounted, remove
361+ the initramfs interfaces stamp file. Meaning, that on shutdown there is
362+ no 30s delay, whilst trying to re-establish iscsi login to perform a
363+ logout.
364+ - add IPv6 support
365+ - Source /run/net6-*.conf when needed.
366+ - d/extra/initramfs.local-top: handle IPv6 configs being shipped in
367+ DEVICE6 or /run/net6-*.conf in the initramfs, so we can fill in
368+ .interface
369+ - d/rules, d/open-iscsi.finalrd, d/control: ship the finalrd iscsi logout
370+ hook and recommend finalrd and busybox for the logout hook to work.
371+ - Make iscsid socket-activated to only activate it as needed:
372+ - debian/open-iscsi.service: do not start or check iscsid.service
373+ - debian/rules: install and enable iscsid.socket
374+ - debian/open-iscsi.postinst:
375+ - run restart logic only if service is running on upgrade
376+ - drop no longer reachable upgrade path that affects iscsid
377+ - disable iscsid.service on upgrade
378+ - handle iscsid.socket to be started if the service is not running yet
379+ - d/iscsi-disk.rules: Add a udev rule so that iscsid.service will be
380+ run when udev disks are attached.
381+ - d/iscsid.service: Remove ExecStop= directive.
382+ - debian/tests/install: fix tests to work with socket activation
383+ - debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch
384+ [updated to match 2.1.2]
385+ - debian/open-iscsi.service: Start open-iscsi systemd job when either
386+ /etc/iscsi/nodes or /sys/class/iscsi_session have content.
387+ - Prevent network interface that contains iscsi root from bouncing
388+ during boot or going down during shutdown if the system is using
389+ resolvconf or ifupdown:
390+ - d/iscsi-network-interface.rules
391+ - d/extra/net-interface-handler
392+ - d/extra/initramfs.hook: add ib_iser to the list of modules included in
393+ the initramfs, so that we can in principle support iscsi root on
394+ infiniband.
395+ - d/open-iscsi.kmod drop: (LP #1833586)
396+ no static module list is needed if we let iscsid load modules itself.
397+ - Stop producing udebs on i386 where we no longer have d-i or a kernel.
398+ - d/extra/initramfs.local-{top,bottom}: move removal of
399+ open-iscsi.interface file from local-top to local-bottom, and fix shell
400+ quoting issue that would result in /run/initramfs/ open-iscsi.interface
401+ always being removed (LP #1872813)
402+ - debian/control, debian/rules: Fix libopeniscsiusr binary package
403+ name (LP 1892228).
404+ - d/rules: Don't FTBFS due to warnings new in gcc10 regarding bounds
405+ and initialization, because upstream's gcc10 support is incomplete.
406+ This change can be dropped when upstream has completed their gcc
407+ support.
408+
409+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Tue, 19 Jan 2021 13:29:46 +0100
410+
411 open-iscsi (2.1.3-1) unstable; urgency=medium
412
413 * [afee47d] New upstream version 2.1.3
414@@ -202,6 +550,75 @@ open-iscsi (2.1.2-2) unstable; urgency=medium
415
416 -- Chris Hofstaedtler <zeha@debian.org> Sun, 06 Dec 2020 23:25:11 +0000
417
418+open-iscsi (2.1.2-1ubuntu1) hirsute; urgency=medium
419+
420+ * Merge with Debian unstable. Remaining changes:
421+ - debian/tests: Add Ubuntu autopkgtest suite:
422+ - README-boot-test.md
423+ - tgt-boot-test: tests
424+ - test-open-iscsi.py
425+ - testlib.py
426+ - get-image
427+ - patch-image
428+ - testsuite
429+ - xkvm
430+ - d/iscsid.service: Let iscsid systemd job run in privileged containers
431+ but not in unprivileged ones
432+ - d/extra/initramfs.local-top: handle iSCSI iBFT DHCP to correctly
433+ run ipconfig to gather all DHCP config info, including DNS search
434+ domain, which iBFT can't provide.
435+ - Remove initramfs interfaces stamp in case no iscsi devs mounted.
436+ If iscsi root was requested, but no iscsi devices were mounted, remove
437+ the initramfs interfaces stamp file. Meaning, that on shutdown there is
438+ no 30s delay, whilst trying to re-establish iscsi login to perform a
439+ logout.
440+ - add IPv6 support
441+ - Source /run/net6-*.conf when needed.
442+ - d/extra/initramfs.local-top: handle IPv6 configs being shipped in
443+ DEVICE6 or /run/net6-*.conf in the initramfs, so we can fill in
444+ .interface
445+ - d/rules, d/open-iscsi.finalrd, d/control: ship the finalrd iscsi logout
446+ hook and recommend finalrd and busybox for the logout hook to work.
447+ - Make iscsid socket-activated to only activate it as needed:
448+ - debian/open-iscsi.service: do not start or check iscsid.service
449+ - debian/rules: install and enable iscsid.socket
450+ - debian/open-iscsi.postinst:
451+ - run restart logic only if service is running on upgrade
452+ - drop no longer reachable upgrade path that affects iscsid
453+ - disable iscsid.service on upgrade
454+ - handle iscsid.socket to be started if the service is not running yet
455+ - d/iscsi-disk.rules: Add a udev rule so that iscsid.service will be
456+ run when udev disks are attached.
457+ - d/iscsid.service: Remove ExecStop= directive.
458+ - debian/tests/install: fix tests to work with socket activation
459+ - debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch
460+ [updated to match 2.1.2]
461+ - debian/open-iscsi.service: Start open-iscsi systemd job when either
462+ /etc/iscsi/nodes or /sys/class/iscsi_session have content.
463+ - Prevent network interface that contains iscsi root from bouncing
464+ during boot or going down during shutdown if the system is using
465+ resolvconf or ifupdown:
466+ - d/iscsi-network-interface.rules
467+ - d/extra/net-interface-handler
468+ - d/extra/initramfs.hook: add ib_iser to the list of modules included in
469+ the initramfs, so that we can in principle support iscsi root on
470+ infiniband.
471+ - d/open-iscsi.kmod drop: (LP #1833586)
472+ no static module list is needed if we let iscsid load modules itself.
473+ - Stop producing udebs on i386 where we no longer have d-i or a kernel.
474+ - d/extra/initramfs.local-{top,bottom}: move removal of
475+ open-iscsi.interface file from local-top to local-bottom, and fix shell
476+ quoting issue that would result in /run/initramfs/ open-iscsi.interface
477+ always being removed (LP #1872813)
478+ - debian/control, debian/rules: Fix libopeniscsiusr binary package
479+ name (LP 1892228).
480+ - d/rules: Don't FTBFS due to warnings new in gcc10 regarding bounds
481+ and initialization, because upstream's gcc10 support is incomplete.
482+ This change can be dropped when upstream has completed their gcc
483+ support.
484+
485+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Thu, 03 Dec 2020 14:44:39 +0100
486+
487 open-iscsi (2.1.2-1) unstable; urgency=medium
488
489 * [7f10701] New upstream version 2.1.2
490@@ -223,6 +640,86 @@ open-iscsi (2.1.1-2) unstable; urgency=medium
491
492 -- Ritesh Raj Sarraf <rrs@debian.org> Fri, 14 Aug 2020 12:32:16 +0530
493
494+open-iscsi (2.1.1-1ubuntu2) groovy; urgency=medium
495+
496+ * debian/control, debian/rules: Fix libopeniscsiusr binary package
497+ name (LP: #1892228).
498+ * debian/rules: Fix deprecated warning for dh_installinit that
499+ --no-restart-on-upgrade has been replaced by --no-stop-on-upgrade,
500+ which is equivalent in functionality (ref deb #837528).
501+
502+ -- Rafael David Tinoco <rafaeldtinoco@ubuntu.com> Wed, 19 Aug 2020 19:08:47 +0000
503+
504+open-iscsi (2.1.1-1ubuntu1) groovy; urgency=medium
505+
506+ * New upstream version 2.1.1
507+ * d/rules: Don't FTBFS due to warnings new in gcc10 regarding bounds
508+ and initialization, because upstream's gcc10 support is incomplete.
509+ This change can be dropped when upstream has completed their gcc
510+ support.
511+ * Merge with Debian unstable (LP: #1891374). Remaining changes:
512+ - debian/tests: Add Ubuntu autopkgtest suite:
513+ - README-boot-test.md
514+ - tgt-boot-test: tests
515+ - test-open-iscsi.py
516+ - testlib.py
517+ - get-image
518+ - patch-image
519+ - testsuite
520+ - xkvm
521+ - d/iscsid.service: Let iscsid systemd job run in privileged containers
522+ but not in unprivileged ones
523+ - d/extra/initramfs.local-top: handle iSCSI iBFT DHCP to correctly
524+ run ipconfig to gather all DHCP config info, including DNS search
525+ domain, which iBFT can't provide.
526+ - Remove initramfs interfaces stamp in case no iscsi devs mounted.
527+ If iscsi root was requested, but no iscsi devices were mounted, remove
528+ the initramfs interfaces stamp file. Meaning, that on shutdown there is
529+ no 30s delay, whilst trying to re-establish iscsi login to perform a
530+ logout.
531+ - add IPv6 support
532+ - Source /run/net6-*.conf when needed.
533+ - d/extra/initramfs.local-top: handle IPv6 configs being shipped in
534+ DEVICE6 or /run/net6-*.conf in the initramfs, so we can fill in
535+ .interface
536+ - d/rules, d/open-iscsi.finalrd, d/control: ship the finalrd iscsi logout
537+ hook and recommend finalrd and busybox for the logout hook to work.
538+ - Make iscsid socket-activated to only activate it as needed:
539+ - debian/open-iscsi.service: do not start or check iscsid.service
540+ - debian/rules: install and enable iscsid.socket
541+ - debian/open-iscsi.postinst:
542+ - run restart logic only if service is running on upgrade
543+ - drop no longer reachable upgrade path that affects iscsid
544+ - disable iscsid.service on upgrade
545+ - handle iscsid.socket to be started if the service is not running yet
546+ - d/iscsi-disk.rules: Add a udev rule so that iscsid.service will be
547+ run when udev disks are attached.
548+ - d/iscsid.service: Remove ExecStop= directive.
549+ - debian/tests/install: fix tests to work with socket activation
550+ - debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch
551+ - debian/open-iscsi.service: Start open-iscsi systemd job when either
552+ /etc/iscsi/nodes or /sys/class/iscsi_session have content.
553+ - Prevent network interface that contains iscsi root from bouncing
554+ during boot or going down during shutdown if the system is using
555+ resolvconf or ifupdown:
556+ - d/iscsi-network-interface.rules
557+ - d/extra/net-interface-handler
558+ - d/extra/initramfs.hook: add ib_iser to the list of modules included in
559+ the initramfs, so that we can in principle support iscsi root on
560+ infiniband.
561+ - d/open-iscsi.kmod drop: (LP #1833586)
562+ no static module list is needed if we let iscsid load modules itself.
563+ - Stop producing udebs on i386 where we no longer have d-i or a kernel.
564+ - Use python2 instead of python in the autopkg tests: Next step for
565+ open-iscsi is to revist all iscsi-root feature and autopkgtests, so
566+ keep python2 to avoid re-work later.
567+ - d/extra/initramfs.local-{top,bottom}: move removal of
568+ open-iscsi.interface file from local-top to local-bottom, and fix shell
569+ quoting issue that would result in /run/initramfs/ open-iscsi.interface
570+ always being removed (LP #1872813)
571+
572+ -- Rafael David Tinoco <rafaeldtinoco@ubuntu.com> Thu, 13 Aug 2020 04:29:43 +0000
573+
574 open-iscsi (2.1.1-1) experimental; urgency=medium
575
576 [ Rafael David Tinoco ]
577@@ -267,6 +764,98 @@ open-iscsi (2.1.1-1) experimental; urgency=medium
578
579 -- Ritesh Raj Sarraf <rrs@debian.org> Tue, 23 Jun 2020 20:38:47 +0530
580
581+open-iscsi (2.0.874-7.1ubuntu6.1) focal; urgency=medium
582+
583+ [ Ben Swartzlander ]
584+ * allow open-iscsi to disable auto-scan feature (LP: #1877617)
585+ - d/p/lp1877617-Allow-disabling-auto-LUN-scans.patch
586+ - d/p/lp1877617-Fix-manual-LUN-scans-feature.patch
587+
588+ -- Rafael David Tinoco <rafaeldtinoco@ubuntu.com> Mon, 11 May 2020 02:03:33 +0000
589+
590+open-iscsi (2.0.874-7.1ubuntu6) focal; urgency=medium
591+
592+ * d/extra/initramfs.local-{top,bottom}: move removal of open-iscsi.interface
593+ file from local-top to local-bottom, and fix shell quoting issue that
594+ would result in /run/initramfs/open-iscsi.interface always being removed
595+ (LP: #1872813)
596+
597+ -- Daniel Watkins <oddbloke@ubuntu.com> Tue, 14 Apr 2020 16:54:37 -0400
598+
599+open-iscsi (2.0.874-7.1ubuntu5) focal; urgency=medium
600+
601+ * Use python2 instead of python in the autopkg tests.
602+
603+ -- Matthias Klose <doko@ubuntu.com> Thu, 30 Jan 2020 10:14:16 +0100
604+
605+open-iscsi (2.0.874-7.1ubuntu3) eoan; urgency=medium
606+
607+ * Stop producing udebs on i386 where we no longer have d-i or a kernel.
608+
609+ -- Adam Conrad <adconrad@ubuntu.com> Wed, 09 Oct 2019 14:10:37 -0600
610+
611+open-iscsi (2.0.874-7.1ubuntu2) eoan; urgency=medium
612+
613+ * debian/open-iscsi.kmod: drop; no static module list is needed if we let
614+ iscsid load modules itself. LP: #1833586.
615+ * debian/extra/initramfs.hook: add ib_iser to the list of modules
616+ included in the initramfs, so that we can in principle support iscsi
617+ root on infiniband.
618+
619+ -- Steve Langasek <steve.langasek@ubuntu.com> Thu, 20 Jun 2019 13:48:46 -0700
620+
621+open-iscsi (2.0.874-7.1ubuntu1) eoan; urgency=low
622+
623+ * Merge from Debian unstable. Remaining changes:
624+ - debian/tests: Add Ubuntu autopkgtest.
625+ - debian/iscsi-network-interface.rules, debian/net-interface-handler,
626+ debian/open-iscsi.install:
627+ Prevent network interface that contains iscsi root from bouncing
628+ during boot or going down during shutdown if the system is using
629+ resolvconf or ifupdown.
630+ - Let iscsid systemd job run in privileged containers but not in
631+ unprivileged ones
632+ - Start open-iscsi systemd job when either /etc/iscsi/nodes or
633+ /sys/class/iscsi_session have content
634+ - add IPv6 support
635+ + Source /run/net6-*.conf when needed.
636+ + debian/extra/initramfs.local-top: handle IPv6 configs being
637+ shipped in DEVICE6 or /run/net6-*.conf in the initramfs, so we
638+ can fill in /run/initramfs/open-iscsi.interface
639+ - make iscsid socket-activated to only activate it as needed
640+ + debian/iscsid.socket: systemd socket file for iscsid
641+ + debian/open-iscsi.service: do not start or check iscsid.service
642+ + debian/rules: install and enable iscsid.socket
643+ + debian/patches/iscid-conf-use-systemd.socket-patch: default to the
644+ socket
645+ + debian/open-iscsi.postinst:
646+ * run restart logic only if service is running on upgrade
647+ * drop no longer reachable upgrade path that affects iscsid
648+ * disable iscsid.service on upgrade
649+ * handle iscsid.socket to be started if the service is not running
650+ yet
651+ + d/iscsi-disk.rules: Add a udev rule so that iscsid.service will be
652+ run when udev disks are attached.
653+ + d/iscsid.service: Remove ExecStop= directive.
654+ + debian/tests/install: fix tests to work with socket activation
655+ - Ship finalrd logout hook.
656+ - debian/extra/initramfs.local-top: handle iSCSI iBFT DHCP to correctly
657+ run ipconfig to gather all DHCP config info, including DNS search
658+ domain, which iBFT can't provide.
659+ - If iscsi root was requested, but no iscsi devices were mounted, remove
660+ the initramfs interfaces stamp file. Meaning, that on shutdown there
661+ is no 30s delay, whilst trying to re-establish iscsi login to perform
662+ a logout.
663+ * Dropped changes, included in Debian:
664+ - Fix fail to build from source due to undefined reference to
665+ minor
666+ * Drop breaks on never-released version of finalrd.
667+ * debian/net-interface-handler: drop upstart support, unused since bionic.
668+ * Drop cleanup of upstart jobs, no longer needed post bionic.
669+ * debian/tests/daemon: drop, unused.
670+
671+ -- Steve Langasek <steve.langasek@ubuntu.com> Mon, 29 Apr 2019 16:13:37 -0700
672+
673 open-iscsi (2.0.874-7) unstable; urgency=medium
674
675 * [eeda27c] Enable back pristine-tar as we have now committed it
676@@ -282,6 +871,158 @@ open-iscsi (2.0.874-6) unstable; urgency=medium
677
678 -- Ritesh Raj Sarraf <rrs@debian.org> Fri, 05 Oct 2018 11:31:19 +0530
679
680+open-iscsi (2.0.874-5ubuntu15) disco; urgency=medium
681+
682+ * d/iscsid.service: Remove ExecStop= directive. Letting systemd
683+ handle termination prevents restart failures. (LP: #1821255)
684+
685+ -- Heitor R. Alves de Siqueira <halves@canonical.com> Thu, 28 Mar 2019 10:21:24 -0300
686+
687+open-iscsi (2.0.874-5ubuntu14) disco; urgency=medium
688+
689+ * debian/iscsi-disk.rules: Fix bug with LVM on top of iscsi devices.
690+ (LP: #1807978)
691+
692+ -- Scott Moser <smoser@ubuntu.com> Tue, 11 Dec 2018 19:01:14 -0500
693+
694+open-iscsi (2.0.874-5ubuntu13) disco; urgency=medium
695+
696+ [ Robert C Jennings & Dimitri John Ledkov ]
697+ * If iscsi root was requested, but no iscsi devices were mounted, remove
698+ the initramfs interfaces stamp file. Meaning, that on shutdown there
699+ is no 30s delay, whilst trying to re-establish iscsi login to perform
700+ a logout. LP: #1800681
701+
702+ -- Dimitri John Ledkov <xnox@ubuntu.com> Sun, 09 Dec 2018 22:29:20 +0000
703+
704+open-iscsi (2.0.874-5ubuntu12) disco; urgency=medium
705+
706+ [Scott Moser]
707+ * debian/extra/initramfs.local-top: handle iSCSI iBFT DHCP to correctly
708+ run ipconfig to gather all DHCP config info, including DNS search
709+ domain, which iBFT can't provide. (LP: #1806777)
710+
711+ -- Dan Streetman <ddstreet@canonical.com> Wed, 05 Dec 2018 11:28:12 -0500
712+
713+open-iscsi (2.0.874-5ubuntu11) disco; urgency=medium
714+
715+ * debian/tests/test-open-iscsi.py: Fix called process error.
716+ If no image was available for a release, a NameError exception would be
717+ raised.
718+
719+ -- Scott Moser <smoser@ubuntu.com> Wed, 14 Nov 2018 16:50:29 -0500
720+
721+open-iscsi (2.0.874-5ubuntu10) disco; urgency=medium
722+
723+ * d/iscsi-disk.rules, d/tests: Add a udev rule so that iscsid.service
724+ will be run when udev disks are attached. (LP: #1802354)
725+ * debian/tests: improve tgt boot test
726+ - disable snapd and snap.seeded services to avoid unnecessary
727+ resource consumption during tests.
728+ - save artifacts from the test run.
729+
730+ -- Scott Moser <smoser@ubuntu.com> Wed, 14 Nov 2018 16:05:46 -0500
731+
732+open-iscsi (2.0.874-5ubuntu9) cosmic; urgency=medium
733+
734+ * d/net-interface-handler: replace 'domainsearch' with the correct
735+ configuration option 'search' in net-interface-handler (LP: #1791108)
736+
737+ -- Victor Tapia <victor.tapia@canonical.com> Mon, 17 Sep 2018 15:58:34 +0200
738+
739+open-iscsi (2.0.874-5ubuntu8) cosmic; urgency=medium
740+
741+ * d/tests: insert some debug units in an attempt to diagnose any
742+ occurences of bug 1788188.
743+ * Fix fail to build from source due to undefined reference to
744+ minor (LP: #1791154)
745+
746+ -- Scott Moser <smoser@ubuntu.com> Tue, 21 Aug 2018 13:33:06 -0400
747+
748+open-iscsi (2.0.874-5ubuntu7) cosmic; urgency=medium
749+
750+ * d/tests: make interactive use of tgt-boot-test more usable by
751+ only using 'timeout' from the test harness.
752+ * debian/tests/README-boot-test.md: minor doc fixes and whitespace.
753+ * d/net-interface-handler: Apply changes only for the iscsi-root interface.
754+ (LP: #1785108)
755+
756+ -- Scott Moser <smoser@ubuntu.com> Tue, 07 Aug 2018 16:37:13 -0400
757+
758+open-iscsi (2.0.874-5ubuntu6) cosmic; urgency=medium
759+
760+ * Ship finalrd logout hook.
761+
762+ -- Dimitri John Ledkov <xnox@ubuntu.com> Fri, 03 Aug 2018 15:03:51 +0100
763+
764+open-iscsi (2.0.874-5ubuntu5) cosmic; urgency=medium
765+
766+ * Harden dep8 tests against effects due to slow execution on Launchpad
767+ infrastructure (LP: #1732028).
768+ - debian/tests/patch-image: remove problematic fstab entries
769+ - debian/tests/tgt-boot-test: ran xkvm in verbose mode
770+
771+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Thu, 19 Jul 2018 18:22:39 +0200
772+
773+open-iscsi (2.0.874-5ubuntu4) cosmic; urgency=medium
774+
775+ * debian/tests/install: ignore the potential stderr of the probing command
776+ that is meant to activate iscsid indirectly via the socket.
777+
778+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Wed, 30 May 2018 15:42:12 +0200
779+
780+open-iscsi (2.0.874-5ubuntu3) cosmic; urgency=medium
781+
782+ * make iscsid socket activated to only activate it as-needed (LP: #1755858)
783+ - debian/iscsid.socket: systemd socket file for iscsid
784+ - debian/open-iscsi.service: do not start or check iscsid.service
785+ - debian/rules: install and enable iscsid.socket
786+ - debian/patches/iscid-conf-use-systemd.socket-patch: default to the socket
787+ - debian/open-iscsi.postinst:
788+ + run restart logic only if service is running on upgrade
789+ + drop no more reachable upgrade path that affects iscsid
790+ + disable iscsid.service on upgrade
791+ + handle iscsid.socket to be started if the service is not running yet
792+ - debian/tests/install: fix tests to work with socket activation
793+
794+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Wed, 23 May 2018 15:50:01 +0200
795+
796+open-iscsi (2.0.874-5ubuntu2) bionic; urgency=medium
797+
798+ * debian/tests:
799+ - tgt-boot-test: Use 'timeout' to force a 60m timeout of the boot test.
800+ - README-boot-test.md: document environment variables BOOT_TIMEOUT
801+ and _USE_KVM.
802+
803+ -- Scott Moser <smoser@ubuntu.com> Wed, 21 Feb 2018 13:19:17 -0500
804+
805+open-iscsi (2.0.874-5ubuntu1) bionic; urgency=low
806+
807+ * Merge with Debian unstable. Remaining changes:
808+ - debian/tests: Add Ubuntu autopkgtests.
809+ - debian/iscsi-network-interface.rules, debian/net-interface-handler,
810+ debian/open-iscsi.install:
811+ Prevent network interface that contains iscsi root from bouncing
812+ during boot or going down during shutdown.
813+ Integrates with resolvconf and initramfs code that writes
814+ /run/initramfs/open-iscsi.interface
815+ - debian/open-iscsi.maintscript: clean up the obsolete
816+ iscsi-network-interface upstart job, file on upgrade.
817+ - Let iscsid systemd job run in privileged containers but not in
818+ unprivileged ones
819+ - Start open-iscsi systemd job when either /etc/iscsi/nodes or
820+ /sys/class/iscsi_session have content
821+ Based on patch by Nish Aravamudan, thanks! (LP #1576341)
822+ - add IPv6 support
823+ + add support for IPV6{DOMAINSEARCH,DNS0,DNS1} to net-interface-handler
824+ LP #1621507
825+ + Source /run/net6-*.conf when needed.
826+ + debian/extra/initramfs.local-top: handle IPv6 configs being
827+ shipped in DEVICE6 or /run/net6-*.conf in the initramfs, so we
828+ can fill in /run/initramfs/open-iscsi.interface (LP #1621507)
829+
830+ -- Dimitri John Ledkov <xnox@ubuntu.com> Fri, 12 Jan 2018 14:00:59 +0000
831+
832 open-iscsi (2.0.874-5) unstable; urgency=high
833
834 * [aeb86f7] Fix multiple security issues in iscsiuio. (CVE-2017-17840)
835@@ -289,6 +1030,74 @@ open-iscsi (2.0.874-5) unstable; urgency=high
836
837 -- Christian Seiler <christian@iwakd.de> Sat, 23 Dec 2017 11:30:44 +0100
838
839+open-iscsi (2.0.874-4ubuntu5) bionic; urgency=medium
840+
841+ * debian/tests/patch-image: mount auxilary filesystems before upgrading
842+ packages. Fixes ADT tests, when triggered by packages, that need
843+ /proc, /dev, etc mounted to complete the upgrade.
844+
845+ -- Dimitri John Ledkov <xnox@ubuntu.com> Wed, 03 Jan 2018 12:21:05 +0000
846+
847+open-iscsi (2.0.874-4ubuntu4) bionic; urgency=medium
848+
849+ * debian/tests/test-open-iscsi.py: skip test if cloud image is unavailable.
850+ This solves flaky tests in restricted network environments as well as in
851+ the short period after opening a new release (LP: #1731907).
852+
853+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Thu, 16 Nov 2017 12:06:34 +0100
854+
855+open-iscsi (2.0.874-4ubuntu3) artful; urgency=medium
856+
857+ * debian/tests/xkvm: do not use kvm (-enable-kvm) by default if
858+ operating inside a vm. nested kvm is finicky.
859+
860+ -- Scott Moser <smoser@ubuntu.com> Wed, 11 Oct 2017 18:14:08 -0400
861+
862+open-iscsi (2.0.874-4ubuntu2) artful; urgency=medium
863+
864+ * debian/tests/test-open-iscsi.py: query systemd-resolved if present.
865+ Ubuntu images now have systemd-resolved managing /etc/resolv.conf
866+ so support test if that is the case (LP: #1715468).
867+
868+ -- Scott Moser <smoser@ubuntu.com> Wed, 06 Sep 2017 16:20:16 -0400
869+
870+open-iscsi (2.0.874-4ubuntu1) artful; urgency=medium
871+
872+ * Merge with Debian unstable. Remaining changes:
873+ - debian/tests: Add Ubuntu autopkgtests.
874+ - debian/iscsi-network-interface.rules, debian/net-interface-handler,
875+ debian/open-iscsi.install:
876+ Prevent network interface that contains iscsi root from bouncing
877+ during boot or going down during shutdown.
878+ Integrates with resolvconf and initramfs code that writes
879+ /run/initramfs/open-iscsi.interface
880+ - debian/open-iscsi.maintscript: clean up the obsolete
881+ iscsi-network-interface upstart job, file on upgrade.
882+ - Let iscsid systemd job run in privileged containers but not in
883+ unprivileged ones
884+ - Start open-iscsi systemd job when either /etc/iscsi/nodes or
885+ /sys/class/iscsi_session have content
886+ Based on patch by Nish Aravamudan, thanks! (LP #1576341)
887+ - add IPv6 support
888+ + add support for IPV6{DOMAINSEARCH,DNS0,DNS1} to net-interface-handler
889+ LP #1621507
890+ + Source /run/net6-*.conf when needed.
891+ + debian/extra/initramfs.local-top: handle IPv6 configs being
892+ shipped in DEVICE6 or /run/net6-*.conf in the initramfs, so we
893+ can fill in /run/initramfs/open-iscsi.interface (LP #1621507)
894+ * Drop:
895+ - d/extra/initramfs.local-top: When booting from iBFT,
896+ set the PROTO= entry in /run/net-*.conf accordingly,
897+ so that other tools, such as cloud-init, can use that
898+ information. (cloud-init fails if the current PROTO=none
899+ is used.) (LP: #1684039) (Closes: #866213)
900+ [ Fixed in Debian 2.0.874-4 ]
901+ * d/t/test-open-iscsi.py: drop test_daemon test
902+ - With the updates to the systemd units, the services do not run
903+ unless iSCSI is configured.
904+
905+ -- Nishanth Aravamudan <nish.aravamudan@canonical.com> Tue, 08 Aug 2017 16:16:27 -0700
906+
907 open-iscsi (2.0.874-4) unstable; urgency=medium
908
909 * [0347300] initramfs: populate PROTO= entry in /run/net-*.conf from iBFT
910@@ -303,6 +1112,64 @@ open-iscsi (2.0.874-3) unstable; urgency=medium
911
912 -- Christian Seiler <christian@iwakd.de> Sun, 18 Jun 2017 22:01:22 +0200
913
914+open-iscsi (2.0.874-2ubuntu3) artful; urgency=medium
915+
916+ * d/t/test-open-iscsi.py: drop test_daemon test
917+ - With the updates to the systemd units, the services do not run
918+ unless iSCSI is configured.
919+
920+ -- Nishanth Aravamudan <nish.aravamudan@canonical.com> Tue, 08 Aug 2017 16:05:29 -0700
921+
922+open-iscsi (2.0.874-2ubuntu2) artful; urgency=medium
923+
924+ * d/extra/initramfs.local-top: When booting from iBFT,
925+ set the PROTO= entry in /run/net-*.conf accordingly,
926+ so that other tools, such as cloud-init, can use that
927+ information. (cloud-init fails if the current PROTO=none
928+ is used.) (LP: #1684039) (Closes: #866213)
929+
930+ -- Eric Desrochers <eric.desrochers@canonical.com> Wed, 05 Jul 2017 09:02:12 -0400
931+
932+open-iscsi (2.0.874-2ubuntu1) artful; urgency=medium
933+
934+ [ Nishanth Aravamudan ]
935+ * Merge with Debian unstable. Remaining changes:
936+ - debian/tests: Add Ubuntu autopkgtests.
937+ - debian/iscsi-network-interface.rules, debian/net-interface-handler,
938+ debian/open-iscsi.install:
939+ Prevent network interface that contains iscsi root from bouncing
940+ during boot or going down during shutdown.
941+ Integrates with resolvconf and initramfs code that writes
942+ /run/initramfs/open-iscsi.interface
943+ - debian/open-iscsi.maintscript: clean up the obsolete
944+ iscsi-network-interface upstart job, file on upgrade.
945+ - add IPv6 support
946+ + add support for IPV6{DOMAINSEARCH,DNS0,DNS1} to net-interface-handler
947+ LP #1621507
948+ + Source /run/net6-*.conf when needed.
949+ + debian/extra/initramfs.local-top: handle IPv6 configs being
950+ shipped in DEVICE6 or /run/net6-*.conf in the initramfs, so we
951+ can fill in /run/initramfs/open-iscsi.interface (LP #1621507)
952+ * Drop:
953+ - Make systemd job not run in containers (LP #1576341)
954+ [ This prevents running iscsi in privileged containers.
955+ Fixed differently in this upload. ]
956+ - Cherry-pick from Debian git repository (Christian Seiler):
957+ + open-iscsi-udeb: drop Depends: libnss-files-udeb
958+ (Closes #819685)
959+ [ Fixed in Debian ]
960+ - d/extra/initramfs.local-top whitespace change
961+ [ previously undocumented ]
962+
963+ [ Balint Reczey ]
964+ * Let iscsid systemd job run in privileged containers but not in
965+ unprivileged ones
966+ * Start open-iscsi systemd job when either /etc/iscsi/nodes or
967+ /sys/class/iscsi_session have content
968+ Based on patch by Nish Aravamudan, thanks! (LP #1576341)
969+
970+ -- Nishanth Aravamudan <nish.aravamudan@canonical.com> Tue, 09 May 2017 09:24:23 -0700
971+
972 open-iscsi (2.0.874-2) unstable; urgency=medium
973
974 [ Christian Seiler ]
975@@ -442,6 +1309,155 @@ open-iscsi (2.0.873+git0.3b4b4500-15) unstable; urgency=medium
976
977 -- Christian Seiler <christian@iwakd.de> Fri, 20 May 2016 09:52:46 +0200
978
979+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu17) zesty; urgency=medium
980+
981+ * debian/tests:
982+ - README-boot-test.md: mention limited space caveat.
983+ - patch-image: fix handling of ADT_TEST_TRIGGERS if source package
984+ built more than one binary package.
985+ - test-open-iscsi.py: change to rely on patch-image
986+ adding package 'open-iscsi' rather than passing it in itself.
987+
988+ -- Scott Moser <smoser@ubuntu.com> Thu, 16 Feb 2017 15:47:58 -0500
989+
990+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu16) zesty; urgency=medium
991+
992+ * debian/tests: many improvements to the open-iscsi and tgt boot test.
993+ - only run test on amd64. just avoid timeout errors or other unrelated
994+ issues causing failure.
995+ - debian/tests/README-boot-test.md: add doc describing the tgt-boot-test
996+ - rename get-maas-eph to get-image
997+ - use a cloud image instead of a maas image for booting. The value in
998+ this is that we can then install open-iscsi inside the image and get an
999+ updated initramfs.
1000+ - use subprocess.check_call rather than subprocess.call so that we
1001+ actually catch errors.
1002+ - update xkvm to what is in curtin/tools/xkvm
1003+ - improve updating of images to consider ADT_TEST_TRIGGERS if set.
1004+
1005+ -- Scott Moser <smoser@ubuntu.com> Tue, 14 Feb 2017 17:07:00 -0500
1006+
1007+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu15) zesty; urgency=medium
1008+
1009+ * debian/tests/tgt-boot-test: set HOST_IP harder for the testsuite test.
1010+
1011+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Sun, 29 Jan 2017 13:05:47 -0500
1012+
1013+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu14) zesty; urgency=medium
1014+
1015+ * Make systemd job not run in containers (LP: #1576341)
1016+
1017+ -- Serge Hallyn <serge.hallyn@ubuntu.com> Sun, 15 Jan 2017 23:08:29 -0600
1018+
1019+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu13) zesty; urgency=medium
1020+
1021+ * Fix syntax error in previous changes. LP: #1621507
1022+
1023+ -- LaMont Jones <lamont@ubuntu.com> Fri, 09 Dec 2016 12:35:45 +0100
1024+
1025+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu12) zesty; urgency=medium
1026+
1027+ * debian/tests/tgt-boot-test: set HOST_IP to 10.0.2.2; it's suboptimal but
1028+ given the test setup this will allow the right IPs to be used to bring up
1029+ the iscsi target in the xkvm.
1030+
1031+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Thu, 08 Dec 2016 11:00:12 +0100
1032+
1033+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu11) zesty; urgency=medium
1034+
1035+ * debian/tests/tgt-boot-test: drop -serial stdio altogether since running
1036+ the VM in -nographics mode will already output to stdout.
1037+
1038+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Tue, 22 Nov 2016 11:27:55 -0500
1039+
1040+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu10) zesty; urgency=medium
1041+
1042+ * debian/tests/tgt-boot-test: always log qemu serial to stdio so we can
1043+ actually see what is going on during the tests.
1044+
1045+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Thu, 17 Nov 2016 11:01:27 -0500
1046+
1047+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu9) zesty; urgency=medium
1048+
1049+ [ LaMont Jones ]
1050+ * Clean up net-interface-handler
1051+ * Source /run/net6-*.conf when needed.
1052+
1053+ [ Mathieu Trudel-Lapierre ]
1054+ * debian/extra/initramfs.local-top: handle IPv6 configs being shipped in
1055+ DEVICE6 or /run/net6-*.conf in the initramfs, so we can fill in
1056+ /run/initramfs/open-iscsi.interface (LP: #1621507)
1057+
1058+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Thu, 03 Nov 2016 16:30:37 -0600
1059+
1060+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu8) yakkety; urgency=medium
1061+
1062+ * debian/tests/xkvm: don't --enable-kvm.
1063+
1064+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Wed, 05 Oct 2016 12:58:21 -0400
1065+
1066+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu7) yakkety; urgency=medium
1067+
1068+ * debian/tests/test-open-iscsi.py: glob to pick up open-iscsi.deb, which may
1069+ be named differently depending on how autopkgtests are run.
1070+
1071+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Wed, 05 Oct 2016 09:56:25 -0400
1072+
1073+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu6) yakkety; urgency=medium
1074+
1075+ * debian/tests/test-open-iscsi.py: install the open-iscsi binary into a test
1076+ MAAS image, so we can check bootability. Download the open-iscsi explicitly
1077+ to /tmp before trying to copy it; so that we don't need to depend on ugly
1078+ internal autopkgtest paths.
1079+
1080+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Tue, 04 Oct 2016 09:05:56 -0400
1081+
1082+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu5) yakkety; urgency=medium
1083+
1084+ * debian/tests/control: add build-needed since some of the new tests
1085+ appear to require that (so they can reach open-iscsi.deb which is a build
1086+ artifact from building in autopkgtest).
1087+
1088+ -- Mathieu Trudel-Lapierre <cyphermox@ubuntu.com> Mon, 03 Oct 2016 16:10:54 -0400
1089+
1090+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu4) yakkety; urgency=medium
1091+
1092+ * add support for IPV6{DOMAINSEARCH,DNS0,DNS1} to net-interface-handler
1093+ LP: #1621507
1094+
1095+ -- LaMont Jones <lamont@canonical.com> Tue, 20 Sep 2016 08:05:41 -0600
1096+
1097+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu3) xenial; urgency=medium
1098+
1099+ * Cherry-pick from Debian git repository (Christian Seiler):
1100+ - open-iscsi-udeb: drop Depends: libnss-files-udeb (Closes: #819685)
1101+
1102+ -- Colin Watson <cjwatson@ubuntu.com> Fri, 15 Apr 2016 16:54:26 +0100
1103+
1104+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu2) xenial; urgency=medium
1105+
1106+ * debian/tests: add two new tests. One to verify net-interface-handler is
1107+ installed executable, and one to actually test that /etc/resolv.conf is
1108+ updated with dhcp dns responses.
1109+
1110+ -- Diogo Matsubara <diogo.matsubara@gmail.com> Wed, 09 Mar 2016 12:56:42 -0300
1111+
1112+open-iscsi (2.0.873+git0.3b4b4500-14ubuntu1) xenial; urgency=medium
1113+
1114+ * Merge from debian. Remaining changes:
1115+ - debian/tests: Add Ubuntu autopkgtest.
1116+ - debian/iscsi-network-interface.rules, debian/net-interface-handler,
1117+ debian/open-iscsi.install:
1118+ Prevent network interface that contains iscsi root from bouncing
1119+ during boot or going down during shutdown.
1120+ Integrates with resolvconf and initramfs code that writes
1121+ /run/initramfs/open-iscsi.interface
1122+ - debian/open-iscsi.maintscript: clean up the obsolete
1123+ iscsi-network-interface upstart job, file on upgrade.
1124+ * make debian/net-interface-handler executable (LP: #1553017)
1125+
1126+ -- Scott Moser <smoser@ubuntu.com> Fri, 04 Mar 2016 13:17:45 -0500
1127+
1128 open-iscsi (2.0.873+git0.3b4b4500-14) unstable; urgency=medium
1129
1130 [ Christian Seiler ]
1131@@ -454,6 +1470,21 @@ open-iscsi (2.0.873+git0.3b4b4500-14) unstable; urgency=medium
1132
1133 -- Christian Seiler <christian@iwakd.de> Thu, 03 Mar 2016 18:47:46 +0100
1134
1135+open-iscsi (2.0.873+git0.3b4b4500-13ubuntu1) xenial; urgency=medium
1136+
1137+ * Merge from Debian (LP: #1546877). Remaining changes:
1138+ - debian/tests: Add Ubuntu autopkgtest.
1139+ - debian/iscsi-network-interface.rules, debian/net-interface-handler,
1140+ debian/open-iscsi.install:
1141+ Prevent network interface that contains iscsi root from bouncing
1142+ during boot or going down during shutdown.
1143+ Integrates with resolvconf and initramfs code that writes
1144+ /run/initramfs/open-iscsi.interface
1145+ - debian/open-iscsi.maintscript: clean up the obsolete
1146+ iscsi-network-interface upstart job, file on upgrade.
1147+
1148+ -- Scott Moser <smoser@ubuntu.com> Thu, 18 Feb 2016 00:53:37 -0500
1149+
1150 open-iscsi (2.0.873+git0.3b4b4500-13) unstable; urgency=medium
1151
1152 [ Christian Seiler ]
1153@@ -675,6 +1706,115 @@ open-iscsi (2.0.873+git0.3b4b4500-1) unstable; urgency=low
1154
1155 -- Ritesh Raj Sarraf <rrs@debian.org> Tue, 05 Nov 2013 21:45:47 +0530
1156
1157+open-iscsi (2.0.873-3ubuntu13) wily; urgency=medium
1158+
1159+ * debian/net-interface-handler: Create the resolvconf dir, to avoid failure
1160+ when resolvconf did not start yet; the udev rules run in parallel with
1161+ it. (LP: #1501033)
1162+
1163+ -- Martin Pitt <martin.pitt@ubuntu.com> Tue, 06 Oct 2015 07:05:48 +0200
1164+
1165+open-iscsi (2.0.873-3ubuntu12) wily; urgency=medium
1166+
1167+ * Drop debian/ifup@.service.conf again, it ceased to work with net.agent in
1168+ wily and the whole idea of net-interface-handler is to *stop* ifupdown
1169+ from fiddling with the iscsi interface. Replace with udev rules
1170+ (debian/iscsi-network-interface.rules) which achieves this without relying
1171+ on ifupdown or a particular init system. (LP: #1463461)
1172+ * Drop debian/open-iscsi.iscsi-network-interface.upstart as well, obsolete
1173+ now. Also clean it up on upgrades.
1174+
1175+ -- Martin Pitt <martin.pitt@ubuntu.com> Thu, 11 Jun 2015 11:58:29 +0200
1176+
1177+open-iscsi (2.0.873-3ubuntu11) vivid; urgency=medium
1178+
1179+ * Factor out logic from debian/open-iscsi.iscsi-network-interface.upstart
1180+ into debian/net-interface-handler, and install the latter in debian/rules.
1181+ * Add debian/ifup@.service.conf: Drop-in for ifup@.service to run
1182+ net-interface-handler under systemd. (LP: #1432829)
1183+
1184+ -- Martin Pitt <martin.pitt@ubuntu.com> Fri, 27 Mar 2015 09:51:05 +0100
1185+
1186+open-iscsi (2.0.873-3ubuntu10) vivid; urgency=medium
1187+
1188+ * Start open-iscsi after installation and make sure initiatorname is
1189+ generated. (Patch backported from Debian)
1190+ * debian/tests/daemon: Stop calling the init.d script as we expect the
1191+ daemon to start automatically now.
1192+
1193+ -- Martin Pitt <martin.pitt@ubuntu.com> Fri, 06 Mar 2015 13:17:26 +0100
1194+
1195+open-iscsi (2.0.873-3ubuntu9) trusty; urgency=medium
1196+
1197+ * Add missing python test dependency.
1198+
1199+ -- Martin Pitt <martin.pitt@ubuntu.com> Wed, 26 Feb 2014 16:07:37 +0100
1200+
1201+open-iscsi (2.0.873-3ubuntu8) trusty; urgency=medium
1202+
1203+ * open-iscsi-udeb: Enable builds on armhf, arm64, ppc64el, x32 (LP: #1274203)
1204+
1205+ -- dann frazier <dann.frazier@canonical.com> Wed, 29 Jan 2014 12:34:45 -0700
1206+
1207+open-iscsi (2.0.873-3ubuntu7) saucy; urgency=low
1208+
1209+ * Use dh_autotools-dev to update config.sub|guess.
1210+
1211+ -- Dmitrijs Ledkovs <dmitrij.ledkov@ubuntu.com> Fri, 11 Oct 2013 17:03:37 +0100
1212+
1213+open-iscsi (2.0.873-3ubuntu6) saucy; urgency=low
1214+
1215+ * debian/tests: Add autopkgtest.
1216+
1217+ -- Yolanda <yolanda.robla@canonical.com> Mon, 27 May 2013 10:39:35 +0200
1218+
1219+open-iscsi (2.0.873-3ubuntu5) quantal-proposed; urgency=low
1220+
1221+ * Ensure all udev events have been processed before trying to configure
1222+ iscsi networking in the initramfs (LP: #1066945):
1223+ - debian/extra/initramfs.local-top: Restore wait_for_udev call before
1224+ configure_networking to ensure network devices are present.
1225+
1226+ -- James Page <james.page@ubuntu.com> Wed, 17 Oct 2012 12:37:43 +0100
1227+
1228+open-iscsi (2.0.873-3ubuntu4) quantal-proposed; urgency=low
1229+
1230+ * Generate initiator name on install, not first boot, ensuring that the
1231+ initramfs built during install contains a valid iSCSI initiator name
1232+ resulting in a iSCSI based root volume that will actually boot
1233+ (LP: #1057635):
1234+ - debian/{rules,initiatorname.iscsi}: Don't install a default
1235+ initiatorname.iscsi.
1236+ - debian/open-iscsi.postinst: Generate initiatorname.iscsi on install.
1237+
1238+ -- James Page <james.page@ubuntu.com> Mon, 15 Oct 2012 12:42:53 +0100
1239+
1240+open-iscsi (2.0.873-3ubuntu3) quantal; urgency=low
1241+
1242+ * debian/open-iscsi.iscsi-network-interface.upstart: fix bad syntax
1243+ in 'post-stop'
1244+
1245+ -- Scott Moser <smoser@ubuntu.com> Mon, 17 Sep 2012 16:50:22 -0400
1246+
1247+open-iscsi (2.0.873-3ubuntu2) quantal; urgency=low
1248+
1249+ * debian/extra/initramfs.local-top: start writing
1250+ /run/initramfs/open-iscsi.interface file again (LP: #1050480)
1251+ * debian/open-iscsi.iscsi-network-interface.upstart: integrate with
1252+ resolvconf (LP: #1050487)
1253+
1254+ -- Scott Moser <smoser@ubuntu.com> Mon, 17 Sep 2012 15:46:26 -0400
1255+
1256+open-iscsi (2.0.873-3ubuntu1) quantal; urgency=low
1257+
1258+ * Merge from Debian. Remaining changes: (LP: #961114, LP: #677333)
1259+ - Add upstart job iscsi-network-interface
1260+ - Migrate from /var/run and /lib/init/rw to /run, from /var/lock to
1261+ /run/lock.
1262+ * Turn open-iscsi-utils into a transitional package
1263+
1264+ -- Stéphane Graber <stgraber@ubuntu.com> Tue, 10 Jul 2012 13:53:52 -0400
1265+
1266 open-iscsi (2.0.873-3) unstable; urgency=low
1267
1268 * [4939401] Fix build to install udeb stuff only on supported architectures
1269@@ -849,6 +1989,239 @@ open-iscsi (2.0.871-1) unstable; urgency=low
1270
1271 -- Ritesh Raj Sarraf <rrs@researchut.com> Sat, 06 Feb 2010 20:28:23 +0530
1272
1273+open-iscsi (2.0.871-0ubuntu9) oneiric-proposed; urgency=low
1274+
1275+ * Make sure the upstart job triggers ifupdown's upstart script to avoid
1276+ waiting 2 minutes at boot time for network to come up. (LP: #870214)
1277+
1278+ -- Stéphane Graber <stgraber@ubuntu.com> Tue, 11 Oct 2011 22:31:39 +0100
1279+
1280+open-iscsi (2.0.871-0ubuntu8) oneiric; urgency=low
1281+
1282+ * Disable open-iscsi init script when root is on iscsi (LP: #838809)
1283+
1284+ -- Stéphane Graber <stgraber@ubuntu.com> Thu, 15 Sep 2011 10:01:12 -0400
1285+
1286+open-iscsi (2.0.871-0ubuntu7) oneiric; urgency=low
1287+
1288+ * Migrate from /var/run and /lib/init/rw to /run, from /var/lock to
1289+ /run/lock, and from /dev/.initramfs to /run/initramfs.
1290+
1291+ -- Colin Watson <cjwatson@ubuntu.com> Thu, 14 Jul 2011 17:01:42 +0100
1292+
1293+open-iscsi (2.0.871-0ubuntu6) oneiric; urgency=low
1294+
1295+ * Fix initramfs iSCSI login (many thanks to Amos Hayes for lending me a
1296+ test system; LP: #728088):
1297+ - Write out /dev/.initramfs/open-iscsi.interface in the same subshell as
1298+ configure_networking, so that we can get at the value of DEVICE.
1299+ - Wait for udev to settle before attempting to configure networking.
1300+
1301+ -- Colin Watson <cjwatson@ubuntu.com> Fri, 27 May 2011 23:27:31 +0100
1302+
1303+open-iscsi (2.0.871-0ubuntu5) maverick; urgency=low
1304+
1305+ * Include <sys/types.h> and <sys/stat.h> in usr/iscsi_sysfs.c for S_*
1306+ macros (LP: #600953).
1307+
1308+ -- Colin Watson <cjwatson@ubuntu.com> Fri, 02 Jul 2010 17:08:14 +0100
1309+
1310+open-iscsi (2.0.871-0ubuntu4) lucid; urgency=low
1311+
1312+ * Revert ISCSI_NETDEVICE change; it's normally better to select the
1313+ interface by MAC address (LP: #473036).
1314+
1315+ -- Colin Watson <cjwatson@ubuntu.com> Fri, 05 Feb 2010 12:06:06 -0800
1316+
1317+open-iscsi (2.0.871-0ubuntu3) lucid; urgency=low
1318+
1319+ * If ISCSI_NETDEVICE is set, configure that interface in the initramfs
1320+ (LP: #473036).
1321+
1322+ -- Colin Watson <cjwatson@ubuntu.com> Fri, 22 Jan 2010 17:01:17 +0000
1323+
1324+open-iscsi (2.0.871-0ubuntu2) lucid; urgency=low
1325+
1326+ * Fix handling of ISCSI_USERNAME, ISCSI_PASSWORD, ISCSI_IN_USERNAME, and
1327+ ISCSI_IN_PASSWORD in iscsi.initramfs (closes: #525053).
1328+
1329+ -- Colin Watson <cjwatson@ubuntu.com> Mon, 14 Dec 2009 12:24:42 +0000
1330+
1331+open-iscsi (2.0.871-0ubuntu1) lucid; urgency=low
1332+
1333+ * New upstream release.
1334+ * If the root filesystem is on iSCSI, prevent the network interface used
1335+ for it from being brought up or down automatically (LP: #457767).
1336+ * Backport from upstream:
1337+ - Allow updating of discovery records (Hannes Reinecke).
1338+ - Fix discovery record use, rather than always using iscsid.conf
1339+ settings (Mike Christie).
1340+
1341+ -- Colin Watson <cjwatson@ubuntu.com> Thu, 10 Dec 2009 18:19:20 +0000
1342+
1343+open-iscsi (2.0.870.1-0ubuntu12) karmic; urgency=low
1344+
1345+ * debian/open-iscsi-udeb.finish-install: Stop checking
1346+ disk-detect/iscsi/enable, as that template doesn't exist any more.
1347+
1348+ -- Colin Watson <cjwatson@ubuntu.com> Fri, 02 Oct 2009 18:49:18 +0100
1349+
1350+open-iscsi (2.0.870.1-0ubuntu11) karmic; urgency=low
1351+
1352+ * open-iscsi-utils Replaces: old versions of open-iscsi.
1353+ * SECURITY UPDATE: temporary file vulnerability (LP: #408915)
1354+ - utils/iscsi_discovery: store iscsiadm -m discovery result in a
1355+ variable rather than writing it to an insecurely-created temporary
1356+ file
1357+ - CVE-2009-1297
1358+
1359+ -- Colin Watson <cjwatson@ubuntu.com> Mon, 24 Aug 2009 23:42:10 +0100
1360+
1361+open-iscsi (2.0.870.1-0ubuntu10) karmic; urgency=low
1362+
1363+ * debian/control, debian/open-iscsi-utils.install,
1364+ open-iscsi-utils.manpages : create a new binary package which
1365+ contains /sbin/iscsiadm, needed for some packages to build against
1366+ (eg, libvirt), but not containing the init script, LP: #414986
1367+
1368+ -- Dustin Kirkland <kirkland@ubuntu.com> Tue, 18 Aug 2009 08:11:34 -0500
1369+
1370+open-iscsi (2.0.870.1-0ubuntu9) karmic; urgency=low
1371+
1372+ * debian/open-iscsi.init: don't exit with error if
1373+ /lib/init/rw/sendsigs.omit.d/ doesn't exist (LP: #414986)
1374+
1375+ -- Jamie Strandboge <jamie@ubuntu.com> Mon, 17 Aug 2009 14:12:01 -0500
1376+
1377+open-iscsi (2.0.870.1-0ubuntu8) karmic; urgency=low
1378+
1379+ * Make sure network devices are always included in the initramfs if
1380+ booting with / on iSCSI.
1381+ * Retry initramfs network configuration for a while until it works (LP:
1382+ #237460).
1383+
1384+ -- Colin Watson <cjwatson@ubuntu.com> Tue, 11 Aug 2009 13:05:43 +0100
1385+
1386+open-iscsi (2.0.870.1-0ubuntu7) karmic; urgency=low
1387+
1388+ [ Colin Watson ]
1389+ * debian/open-iscsi-udeb.postinst, debian/open-iscsi-udeb.templates:
1390+ Remove; this is being taken over by disk-detect and partman-iscsi.
1391+ * debian/control: Remove XB-Installer-Menu-Item.
1392+
1393+ [ Mathias Gug ]
1394+ * debian/open-iscsi.postinst: Fix backwards use of update-rc.d (LP:
1395+ #306678).
1396+ * debian/open-iscsi.init: Overwrite existing pid file symlinks in
1397+ /lib/init/rw/sendsigs.omit.d/.
1398+
1399+ -- Colin Watson <cjwatson@ubuntu.com> Mon, 10 Aug 2009 13:28:41 +0100
1400+
1401+open-iscsi (2.0.870.1-0ubuntu6) karmic; urgency=low
1402+
1403+ * utils/iscsi_discovery: Fix several bashisms (test ==, &> redirection,
1404+ trap with numeric signals).
1405+
1406+ -- Colin Watson <cjwatson@ubuntu.com> Tue, 04 Aug 2009 12:30:44 +0100
1407+
1408+open-iscsi (2.0.870.1-0ubuntu5) karmic; urgency=low
1409+
1410+ * utils/iscsi_discovery: replace uses of awk with other shell voodoo, so
1411+ that this works in the installer. LP: #236640.
1412+ * debian/rules, debian/open-iscsi-udeb.dirs: install the open-isci-udeb
1413+ finish script to /usr/lib/finish-install.d, not to /lib/finish-install.d.
1414+ * debian/open-iscsi-udeb.finish-install: copy the config from the root
1415+ to the correct directory in the target.
1416+
1417+ -- Steve Langasek <steve.langasek@ubuntu.com> Tue, 07 Jul 2009 22:10:17 -0700
1418+
1419+open-iscsi (2.0.870.1-0ubuntu4) karmic; urgency=low
1420+
1421+ * debian/extra/initramfs.hook: iscsistart is in /sbin, not /usr/sbin (LP:
1422+ #364616).
1423+
1424+ -- Colin Watson <cjwatson@ubuntu.com> Thu, 02 Jul 2009 14:12:25 +0100
1425+
1426+open-iscsi (2.0.870.1-0ubuntu3) jaunty; urgency=low
1427+
1428+ * Invoke iscsi-iname using normal $PATH lookup rather than using an
1429+ incorrect explicit path (see LP #236640).
1430+
1431+ -- Colin Watson <cjwatson@ubuntu.com> Thu, 09 Apr 2009 16:49:08 +0100
1432+
1433+open-iscsi (2.0.870.1-0ubuntu2) jaunty; urgency=low
1434+
1435+ * debian/control: Drop udeb dependency on crypto-modules; as best as I can
1436+ tell, this is required for crc32c support, which is now built-in to the
1437+ Ubuntu kernels.
1438+
1439+ -- Dustin Kirkland <kirkland@ubuntu.com> Tue, 03 Feb 2009 11:20:35 +0100
1440+
1441+open-iscsi (2.0.870.1-0ubuntu1) jaunty; urgency=low
1442+
1443+ * New upstream release:
1444+ - Support 2.6.26/27 kernels (LP: #289470).
1445+ - Fix iscsid shutdown (LP: #181188).
1446+ * Merge from Debian. Remaining Ubuntu changes:
1447+ - Note: Debian version isn't 870~rc3 but 869.2 which leads to a big
1448+ .diff.gz file. Only files in debian/ have been considered for this merge
1449+ since debian hasn't patched the source.
1450+ - debian/control, debian/rules, debian/open-iscsi-udeb*:
1451+ + Add open-iscsi-udeb.
1452+ - debian/open-iscsi.dirs:
1453+ + rename dirs to open-iscsi.dirs because of open-iscsi-udeb addition.
1454+ + drop network/if-up.d/ directory since we're using symlinks instead.
1455+ + utilities installed in /bin,/sbin rather than /usr/bin,/usr/sbin.
1456+ - debian/open-iscsi.init:
1457+ + utilities installed in /bin,/sbin rather than /usr/bin,/usr/sbin.
1458+ + lsb log messages.
1459+ + Don't generate initiatorname name (moved to postinst).
1460+ + Support for being called from ifup/ifdown scripts.
1461+ + Refactor start functions:
1462+ - move daemon start to startdaemon function.
1463+ - call udevadm settle rather then udevsettle (which doesn't do anything
1464+ useful).
1465+ - don't exit if the daemon is already running during sanitychecks.
1466+ Instead check in startdaemon if the daemon needs to be started.
1467+ - only start automatic targets if necessary.
1468+ - add waitfordevices function: called during rcS, waits for all
1469+ automatic targets to be ready. Iscsi targets are considered as
1470+ local block devices - they don't need to be marked with _netdev in
1471+ fstab. (LP: #227848)
1472+ - start targets if not run from rcS.
1473+ + Check status of iscsid daemon in addition to listing the iscsi sessions
1474+ when status action is called.
1475+ + Add iscsid to the list of processes that should not be killed by
1476+ sendsigs during shutdown (LP: #192080).
1477+ + Add starttargets, stoptargets and restarttargets to usage message.
1478+ - debian/rules:
1479+ + Install utilities /bin,/sbin rather than /usr/bin,/usr/sbin.
1480+ + Start open-iscsi at S25 (waiting for devices created by ifupdown
1481+ calls and before local filesystems are checked and mounted)
1482+ + stop at S41 (after local filesystems are unmounted). Don't use
1483+ umountiscsi.sh script from debian. (LP: #192080).
1484+ - debian/initiatorname.iscsi, debian/open-iscsi.postinst:
1485+ + Generate the random initiatorname during postinstall rather than in the
1486+ init script.
1487+ + Don't ship a default initiatorname.iscsi file.
1488+ - debian/open-iscsi.postinst:
1489+ + fix init script ordering on upgrades.
1490+ - debian/open-iscsi.links:
1491+ + symlink open-iscsi init script in if-up.d and if-down.d directory so
1492+ that the iscsi subsystem is started/stopped when network interfaces
1493+ are configured.
1494+ - debian/open-iscsi.postrm:
1495+ + delete iscsi configuration when the package is purged.
1496+ - utils/iscsi_discovery: De-bashify iscsi_discovery.
1497+ - usr/idbm.c: Fix build failure with new glibc. LP: #299843.
1498+ * Dropped:
1499+ - Exit without error if /sys is not available. Otherwise, it's not possible
1500+ to use this package as a build-dependency (in Debian).
1501+ - Drop upstream url in long description now that it's in the Homepage
1502+ field (in Debian).
1503+
1504+ -- Mathias Gug <mathiaz@ubuntu.com> Mon, 01 Dec 2008 10:45:03 -0500
1505+
1506 open-iscsi (2.0.870~rc3-0.6) unstable; urgency=low
1507
1508 * Non-maintainer upload.
1509@@ -948,6 +2321,47 @@ open-iscsi (2.0.869~rc4-1) experimental; urgency=low
1510
1511 -- Philipp Hug <debian@hug.cx> Sat, 12 Apr 2008 15:53:12 +0200
1512
1513+open-iscsi (2.0.865-1ubuntu5) jaunty; urgency=low
1514+
1515+ * Fix build failure with new glibc. LP: #299843.
1516+
1517+ -- Matthias Klose <doko@ubuntu.com> Thu, 27 Nov 2008 15:58:15 +0100
1518+
1519+open-iscsi (2.0.865-1ubuntu4) intrepid; urgency=low
1520+
1521+ * Exit without error if /sys is not available. Otherwise, it's not possible
1522+ to use this package as a build-dependency.
1523+
1524+ -- Soren Hansen <soren@ubuntu.com> Fri, 02 May 2008 00:57:02 +0200
1525+
1526+open-iscsi (2.0.865-1ubuntu3) hardy; urgency=low
1527+
1528+ * Migration of /usr/{bin,sbin,lib} -> to /{bin,sbin,lib}.
1529+ (LP: #208441)
1530+ * Push the shutdown scripts back. (LP: #196748)
1531+ * Update control to 3.7.3.
1532+ * Updated the maintainer according to spec.
1533+
1534+ -- Chuck Short <zulcss@ubuntu.com> Wed, 09 Apr 2008 18:09:28 -0400
1535+
1536+open-iscsi (2.0.865-1ubuntu2) hardy; urgency=low
1537+
1538+ * Fixed init script to point to the right iscsiadm. (LP: #206520)
1539+
1540+ -- Chuck Short <zulcss@ubuntu.com> Tue, 25 Mar 2008 09:53:08 -0400
1541+
1542+open-iscsi (2.0.865-1ubuntu1) hardy; urgency=low
1543+
1544+ * Add open-iscsi-udeb.
1545+ * Include iscsi_discovery.
1546+ * De-bashify iscsi_discovery.
1547+ * Start open-iscsi in single user mode.
1548+ * Properly lsb-ify init script.
1549+ * Modify Maintainer value to match the DebianMaintainerField
1550+ specification.
1551+
1552+ -- Soren Hansen <soren@ubuntu.com> Fri, 08 Feb 2008 11:56:11 +0100
1553+
1554 open-iscsi (2.0.865-1) unstable; urgency=low
1555
1556 * New upstream release
1557@@ -1010,3 +2424,4 @@ open-iscsi (1.0.485-0unreleased) dapper; urgency=low
1558 * Put database into /var/lib/open-iscsi
1559
1560 -- Philipp Hug <debian@hug.cx> Mon, 6 Mar 2006 19:20:17 +0000
1561+
1562diff --git a/debian/control b/debian/control
1563index 0c95ac3..839fd03 100644
1564--- a/debian/control
1565+++ b/debian/control
1566@@ -1,7 +1,8 @@
1567 Source: open-iscsi
1568 Section: net
1569 Priority: optional
1570-Maintainer: Debian iSCSI Maintainers <open-iscsi@packages.debian.org>
1571+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
1572+XSBC-Original-Maintainer: Debian iSCSI Maintainers <open-iscsi@packages.debian.org>
1573 Uploaders: Ritesh Raj Sarraf <rrs@debian.org>,
1574 Christian Seiler <christian@iwakd.de>,
1575 Chris Hofstaedtler <zeha@debian.org>
1576diff --git a/debian/extra/startup-checks.sh b/debian/extra/startup-checks.sh
1577index a369785..a7c3ecd 100755
1578--- a/debian/extra/startup-checks.sh
1579+++ b/debian/extra/startup-checks.sh
1580@@ -33,7 +33,7 @@ if grep -q "^GenerateName=yes" $NAMEFILE ; then
1581 exit 1
1582 fi
1583 # Generate a unique InitiatorName and save it
1584- INAME=`/sbin/iscsi-iname -p iqn.1993-08.org.debian:01`
1585+ INAME=`/sbin/iscsi-iname -p iqn.2004-10.com.ubuntu:01`
1586 if [ "$INAME" != "" ] ; then
1587 echo "## DO NOT EDIT OR REMOVE THIS FILE!" > $NAMEFILE
1588 echo "## If you remove this file, the iSCSI daemon will not start." >> $NAMEFILE
1589diff --git a/debian/open-iscsi.postinst b/debian/open-iscsi.postinst
1590index 505f7c1..ccc8ed7 100644
1591--- a/debian/open-iscsi.postinst
1592+++ b/debian/open-iscsi.postinst
1593@@ -27,7 +27,7 @@ case "$1" in
1594 # Generate a unique iSCSI InitiatorName
1595 NAMEFILE=/etc/iscsi/initiatorname.iscsi
1596 if [ ! -e $NAMEFILE ] && [ -z "$2" ] ; then
1597- INAME=$(iscsi-iname -p iqn.1993-08.org.debian:01)
1598+ INAME=$(iscsi-iname -p iqn.2004-10.com.ubuntu:01)
1599 if [ -n "$INAME" ] ; then
1600 echo "## DO NOT EDIT OR REMOVE THIS FILE!" > $NAMEFILE
1601 echo "## If you remove this file, the iSCSI daemon will not start." >> $NAMEFILE
1602diff --git a/debian/patches/fix-format-overflow-warnings.patch b/debian/patches/fix-format-overflow-warnings.patch
1603new file mode 100644
1604index 0000000..ae1704d
1605--- /dev/null
1606+++ b/debian/patches/fix-format-overflow-warnings.patch
1607@@ -0,0 +1,29 @@
1608+Description: fix format overflow warnings
1609+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/open-iscsi/+bug/2036884
1610+Forwarded: https://github.com/open-iscsi/open-iscsi/pull/413
1611+Forwarded: https://github.com/open-iscsi/open-iscsi/pull/425
1612+Author: Chris Leech <cleech@redhat.com>
1613+Author: Graham Inggs <ginggs@debian.org>
1614+Last-Update: 2023-11-15
1615+--- a/usr/discoveryd.c
1616++++ b/usr/discoveryd.c
1617+@@ -153,8 +153,8 @@
1618+ */
1619+ list_for_each_entry_safe(rec, tmp_rec, &iscsi_targets, list) {
1620+ log_debug(7, "Trying to match %s %s to %s %s %s",
1621+- targetname, iname, rec->name, rec->conn[0].address,
1622+- rec->iface.name);
1623++ targetname ? targetname : "(null)", iname ? iname : "(null)",
1624++ rec->name, rec->conn[0].address, rec->iface.name);
1625+ if (targetname && strcmp(rec->name, targetname))
1626+ continue;
1627+
1628+@@ -169,7 +169,7 @@
1629+ }
1630+
1631+ log_debug(5, "Matched %s %s, checking if in new targets.",
1632+- targetname, iname);
1633++ targetname ? targetname : "(null)", iname ? iname : "(null)");
1634+ if (!idbm_find_rec_in_list(new_rec_list, rec->name,
1635+ rec->conn[0].address,
1636+ rec->conn[0].port, &rec->iface)) {
1637diff --git a/debian/patches/series b/debian/patches/series
1638index 405317d..deb0473 100644
1639--- a/debian/patches/series
1640+++ b/debian/patches/series
1641@@ -1,2 +1,3 @@
1642 debian/lp1755858-default-iscsid_conf-to-iscsid_socket.patch
1643 debian/multiarch-path.patch
1644+fix-format-overflow-warnings.patch
1645diff --git a/debian/tests/README-boot-test.md b/debian/tests/README-boot-test.md
1646new file mode 100644
1647index 0000000..e45bbf0
1648--- /dev/null
1649+++ b/debian/tests/README-boot-test.md
1650@@ -0,0 +1,139 @@
1651+## open-iscsi boot test
1652+The purpose of this test (`CloudImageTest`) is to test the boot of a system
1653+using an iscsi root target. In order to accomplish that, the tests does
1654+
1655+ 1. Download Ubuntu cloud image
1656+ 2. installs the open-iscsi deb inside
1657+ 3. collect kernel and initramfs from inside
1658+ 4. register the image as a read-only iscsi target served by tgt
1659+ 5. boot kernel and initramfs with a command line to use the image as root.
1660+ And additionally attach a local disk for collecting output.
1661+ 6. provide user-data that executes commands, colects files and writes them
1662+ to the output disk and then shuts the system down.
1663+ 7. extract the collected files from the output disk and inspect them.
1664+
1665+The `CloudImageTest` uses qemu user networking.
1666+
1667+
1668+## Caveats
1669+
1670+ 1. It depends on a cloud-image being present.
1671+
1672+ Cloud-images are often not available for the first few weeks of a cycle.
1673+ If no cloud-image of 'REL' is available, then boot-test will skip.
1674+ If 'REL' is not known in distro-info-data, then test will fail.
1675+
1676+ This means that uploads of open-iscsi (or its dependencies) will not
1677+ be properly tested until a cloud-image is available, and will fail
1678+ until distro-info-data is uploaded.
1679+
1680+ 2. Installation of large packages via patch-image may fail.
1681+ An ubuntu image downloaded has only a small amount of extra space.
1682+ Installation of a new kernel into the target would probably fail.
1683+
1684+ If this becomes a problem, we could grow the disk like done at
1685+ https://gist.github.com/smoser/6a048a0e2795b48221fc44962202fa14
1686+
1687+
1688+### testing manually ###
1689+The test case in `debian/tests/test-open-iscsi.py` uses some helper tools.
1690+
1691+ * **patch-image**: this is used to install packages into the pristine image
1692+ and collect the kernel and initramfs out of the image. This allows us to
1693+ test the portions of open-iscsi that update the initramfs. Without
1694+ using the updated initramfs we wouldn't really be testing the new
1695+ open-iscsi.
1696+
1697+ It will upgrade any packages inside that are mentioned in
1698+ ADT_TEST_TRIGGERS environment. It will also install open-iscsi if
1699+ it is not in that list.
1700+
1701+ It installs packages into the target by copying the host system's
1702+ /etc/apt content in, and also includes copying local (file://) apt
1703+ repos into the target. This is necessary for the autopackage test
1704+ environment that adds local package repositories to sources.list.d.
1705+
1706+ It may also make other changes to the image to workaround bugs.
1707+ See --help output for list of bugs.
1708+
1709+ * **get-image**: This downloads an image from cloud-images.ubuntu.com. See
1710+ its Usage for more information. it downloads via stream data and verifies
1711+ download. One thing to note is that it does not overwrite existing files.
1712+
1713+ * **tgt-boot-test**: this registers an image in tgt locally, and then boots
1714+ kernel and initramfs to mount that. It knows how to build iscsi kernel
1715+ command lines.
1716+
1717+ By default, the xkvm process that is started will be allowed `60m` to
1718+ complete. This can be adjusted by setting `BOOT_TIMEOUT` in the
1719+ environment.
1720+
1721+ * **xkvm**: this is a helper/wrapper around qemu. It is taken from the curtin
1722+ projects tools/ directory. It allows some simplified command lines, and
1723+ most usefully, the '--netdev=<bridge>' argument will create a tun/tap
1724+ device and attach it to the bridge.
1725+
1726+ If the host system is not bare metal, kvm will not be
1727+ enabled in the guest that is lauched. To force use of kvm, set
1728+ _USE_KVM=1 in the environment. See 'should_try_kvm' in xkvm for details.
1729+
1730+Testing manually looks like this:
1731+
1732+ ## set up path to include debian/tests directory.
1733+ $ PATH=$PWD/debian/tests:$PATH
1734+
1735+ ## Get the image you want. This creates out.d/disk.img and disk.img.dist
1736+ $ get-image xenial.d xenial
1737+
1738+ ## patch the image with an open-iscsi, which creates xenial.d/kernel
1739+ ## and xenial.d/initrd from the kernel and initramfs inside the image.
1740+ $ apt-get download open-iscsi
1741+ $ deb=$(ls open-iscsi_*.deb | tail -n 1)
1742+ $ sudo ./debian/tests/patch-image \
1743+ --kernel=xenial.d/kernel --initrd=xenial.d/initrd
1744+ xenial.d/disk.img "$deb"
1745+
1746+ ## Boot the system, log in, look around.
1747+ $ tgt-boot-test -v xenial.d/disk.img xenial.d/kernel xenial.d/initrd
1748+
1749+
1750+### Features of tgt-boot-test ###
1751+
1752+tgt-boot-test does a number of useful things.
1753+
1754+ * determines the host address that the guest will use.
1755+ This should support ipv6 and ipv4 addresses on bridges, and
1756+ knows values that qemu's user networking uses. Flags passed to `--netdev`
1757+ are read intelligently. This can be overriden with `--host-addr`, but
1758+ it does a good job of determining what the right values are.
1759+
1760+ * provides a nocloud metadata service with a python web server that
1761+ supports ipv4 and ipv6.
1762+
1763+ * provides the ability to provide additional kernel command line options
1764+ or to provide a 'template' that references variables it knows such as
1765+ {iserver} (iscsi server) or {seed_url}.
1766+
1767+ * Sets ubuntu (passw0rd) and root password (root) and imports users
1768+ ssh keys to the ubuntu user.
1769+
1770+One thing to note is that yakkety's version of qemu does not run an ipv6
1771+dhcp server on its user-network, so a stateful dhclient request will not
1772+work.
1773+
1774+In order to create a bridge easily with a ipv6 dhcp server, you can use
1775+lxd at sufficent version (https://github.com/lxc/lxd/issues/2481).
1776+Assuming that bug is fixed, to create an ipv6 only bridge:
1777+
1778+ $ netname="ipv6-only"
1779+ $ lxc network create $netname
1780+ $ lxc network unset $netname ipv4.address
1781+ $ lxc network unset $netname ipv4.nat
1782+ $ lxc network set $netname ipv6.dhcp.stateful true
1783+
1784+Then, you can use tgt-boot-test with that:
1785+
1786+ $ PATH=$PWD/debian/tests:$PATH
1787+ $ ./debian/tests/tgt-boot-test -vv --netdev=ipv6-only \
1788+ --cmdline-ip="ip=off ip6=dhcp" \
1789+ disk.img kernel initramfs
1790diff --git a/debian/tests/control b/debian/tests/control
1791index 7b3c9e2..0fcfd11 100644
1792--- a/debian/tests/control
1793+++ b/debian/tests/control
1794@@ -1,6 +1,10 @@
1795 Tests: install
1796 Restrictions: needs-root, isolation-machine, breaks-testbed
1797
1798+Tests: testsuite
1799+Restrictions: needs-root isolation-machine breaks-testbed
1800+Depends: open-iscsi, python3, tgt, qemu-system, ubuntu-cloudimage-keyring, simplestreams, python3-netifaces, distro-info, cloud-image-utils, dctrl-tools, rsync
1801+
1802 Tests: nested
1803 Restrictions: needs-root, isolation-machine, breaks-testbed, allow-stderr
1804 Depends: targetcli-fb, qemu-system, qemu-utils, python3, python3-netifaces
1805diff --git a/debian/tests/get-image b/debian/tests/get-image
1806new file mode 100755
1807index 0000000..41b903c
1808--- /dev/null
1809+++ b/debian/tests/get-image
1810@@ -0,0 +1,227 @@
1811+#!/bin/bash
1812+Usage() {
1813+ cat <<EOF
1814+${0##*/} out-directory release
1815+
1816+By default, the cloud image for 'release' is downloaded from the
1817+daily cloud image stream.
1818+
1819+Additional arguments can change behavior of what is downloaded.
1820+Some supported arguments:
1821+ * cloud-daily: use daily stream [default]
1822+ * cloud-release: use release stream rather than daily stream.
1823+ * maas-release, maas-daily: download maas images instead of cloud-image
1824+ * hwe-N: download the hwe kernel from release 'N' instead of default
1825+ this is only respected if maas stream is used.
1826+ * YYYYMMDD[.X] : download the specific build version
1827+
1828+example:
1829+ ${0##*/} xenial_dir xenial cloud-daily
1830+EOF
1831+}
1832+TEMP_D=""
1833+
1834+NO_IMAGE_AVAILABLE_RC=3
1835+
1836+cleanup() {
1837+ [ ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
1838+}
1839+VERBOSITY=1
1840+inargs() {
1841+ local n=$1 x="";
1842+ shift;
1843+ for x in "$@"; do [ "$n" = "$x" ] && return 0; done;
1844+ return 1
1845+}
1846+debug() { [ $1 -ge $VERBOSITY ] || return 0; shift; echo "$@" 1>&2; }
1847+error() { echo "$@" 1>&2; }
1848+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
1849+
1850+VERBOSITY=0
1851+TEMP_D=$(mktemp -d ${TMPDIR:-/tmp}/${0##*/}.XXXXXX) || exit 1
1852+trap cleanup EXIT
1853+
1854+arches=( ppc64el i386 amd64 )
1855+releases=( $(ubuntu-distro-info --all) )
1856+mbase="http://maas.ubuntu.com/images/ephemeral-v2"
1857+cbase="http://cloud-images.ubuntu.com"
1858+def_stream_type="cloud"
1859+stream_src=""
1860+curbase="$mbase"
1861+def_rel="xenial"
1862+vername=""
1863+
1864+[ "$1" = "-h" -o "$1" = "--help" ] && { Usage; exit 0; }
1865+[ $# -lt 2 ] && { Usage 1>&2; exit 1; }
1866+out_d="$1"
1867+shift
1868+
1869+myarch=$(uname -m)
1870+case "$myarch" in
1871+ ppc64*) def_arch="ppc64el";;
1872+ i?86) def_arch="i386";;
1873+ x86_64) def_arch="amd64";;
1874+ arm*) def_arch="armel";;
1875+esac
1876+
1877+pt=( )
1878+for x in "$@"; do
1879+ inargs "$x" "${arches[@]}" && pt[${#pt[@]}]=arch=$x && arch="$x" && continue
1880+ inargs "$x" "${releases[@]}" && pt[${#pt[@]}]="release=$x" && release=$x && continue
1881+ [ "$x" = "released" -o "$x" = "release" ] && x="releases"
1882+ case "$x" in
1883+ cloud-released|cloud-release) x="cloud-releases";;
1884+ maas-released|maas-release) x="maas-releases";;
1885+ esac
1886+
1887+ case "$x" in
1888+ maas|cloud) stream_type="$x";;
1889+ cloud-daily|maas-daily|cloud-releases|maas-releases)
1890+ stream_type="${x%-*}"
1891+ stream_sub=${x#*-};;
1892+ http://*) stream=$x;;
1893+ hwe-*) subarch="$x";;
1894+ subarch=*) subarch=${x#*=};;
1895+ *=*) pt[${#pt[@]}]="$x";;
1896+ *~*) pt[${#pt[@]}]="$x";;
1897+ [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]|[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].[0-9])
1898+ pt[${#pt[@]}]="version_name=$x"
1899+ vername="$x";;
1900+ *) fail "Confused by input token '$x'";;
1901+ esac
1902+done
1903+
1904+[ -n "$stream_type" ] || stream_type="${def_stream_type}"
1905+if [ -z "$stream" ]; then
1906+ stream_sub=${stream_sub:-daily}
1907+ case "$stream_type" in
1908+ maas) stream="$mbase/$stream_sub";;
1909+ cloud) stream="$cbase/$stream_sub";;
1910+ *) fail "unknown stream_type '$stream_type'";;
1911+ esac
1912+fi
1913+
1914+[ -n "$arch" ] || pt[${#pt[@]}]="arch=$def_arch"
1915+
1916+if [ "$stream_type" = "maas" ]; then
1917+ if [ -z "$subarch" ]; then
1918+ t=${release#?}
1919+ first_letter=${release%${t}}
1920+ subarch="hwe-${first_letter}"
1921+ error "selected subarch=${subarch} for $release"
1922+ fi
1923+ pt[${#pt[@]}]="subarch=$subarch"
1924+ ofmt="%(sha256)s %(ftype)s %(subarch)s %(item_url)s"
1925+else
1926+ ofmt="%(sha256)s %(ftype)s %(item_url)s"
1927+fi
1928+
1929+OIFS="$IFS"
1930+mkdir -p "$out_d"
1931+case "$stream" in
1932+ *.json) :;;
1933+ *) keyring="/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg";;
1934+esac
1935+
1936+needs=""
1937+[ -n "$keyring" -a ! -f "$keyring" ] &&
1938+ needs="${needs} ubuntu-cloudimage-keyring"
1939+
1940+for pair in sstream-query:simplestreams tgt-admin:tgt; do
1941+ cmd=${pair%:*}
1942+ pkg=${pair#*:}
1943+ command -v "$cmd" >/dev/null 2>&1 || needs="$needs $pkg"
1944+done
1945+
1946+if [ -n "${needs# }" ]; then
1947+ error "missing dependencies"
1948+ fail "sudo apt-get install -qy ${needs# }"
1949+fi
1950+
1951+qcmd=( sstream-query ${keyring:+"--keyring=$keyring"} ${vername:---max=1}
1952+ --output-format="$ofmt" "${stream}" datatype="image-downloads"
1953+ "${pt[@]}" )
1954+echo "${qcmd[@]}"
1955+"${qcmd[@]}" > "${TEMP_D}/qout"
1956+roots=$(awk '$2 == "root-image.gz" || $2 == "disk1.img" { print $2 }' \
1957+ "${TEMP_D}/qout" | sort -u | wc -l)
1958+if [ "$roots" = "0" ]; then
1959+ error "No image available for $release in $stream${pt:+ (${pt[*]})}"
1960+ exit ${NO_IMAGE_AVAILABLE_RC}
1961+elif [ "$roots" != "1" ]; then
1962+ error "query resulted in '$roots' root images. expect 1 and only 1"
1963+ error "cmd was ${qcmd[*]}"
1964+ cat "${TEMP_D}/qout"
1965+ fail
1966+fi
1967+
1968+set -f
1969+while read line; do
1970+ set -- $line
1971+ if [ "$stream_type" = "maas" ]; then
1972+ sha256="$1"; ftype="$2"; subarch="$3"; url="$4"
1973+ else
1974+ sha256="$1"; ftype="$2"; url="$3"
1975+ fi
1976+ case "$ftype" in
1977+ boot-kernel|boot-initrd|root-image.gz|disk1.img) :;;
1978+ *) continue
1979+ esac
1980+ if [ "$ftype" = "root-image.gz" ]; then
1981+ fname="$ftype"
1982+ image_src="$out_d/$fname"
1983+ image="$out_d/root-image"
1984+ elif [ "$ftype" = "disk1.img" ]; then
1985+ fname="disk.img.dist"
1986+ image_src="$out_d/$fname"
1987+ image="$out_d/disk.img"
1988+ else
1989+ fname="$subarch/$ftype"
1990+ fi
1991+ out_f="${out_d}/$fname"
1992+ if [ -f "$out_f" ]; then
1993+ debug 1 "reusing existing '$out_f' rather than downloading $url."
1994+ continue
1995+ fi
1996+ [ -d "${out_f%/*}" ] || mkdir -p "${out_f%/*}"
1997+ tmp="${out_f}.tmp"
1998+ wget --progress=dot:mega -O "$tmp" "$url" || {
1999+ error "Failed to download $url to $tmp."
2000+ rm -f "$tmp"
2001+ exit 3
2002+ }
2003+ debug 1 "checksumming $tmp from $url"
2004+ out=$(sha256sum "$tmp") || {
2005+ error "Failed to checksum $tmp"
2006+ rm -f "$tmp"
2007+ exit 3;
2008+ }
2009+ found=${out% *}
2010+ if [ "$found" != "$sha256" ]; then
2011+ error "$tmp from $url found sha256 of $found. expected $sha256."
2012+ ls -l "$tmp" 1>&2
2013+ rm -f "$tmp"
2014+ exit 3
2015+ fi
2016+ mv "$tmp" "$out_f" || fail "failed renaming $tmp to $out_f"
2017+ echo "$fname" "$url" >> "$out_d/contents"
2018+done < "${TEMP_D}/qout"
2019+
2020+if [ ! -f "$image" ]; then
2021+ case "$image_src" in
2022+ */root-image.gz)
2023+ debug 1 "decompressing $image_src"
2024+ zcat "$image_src" > "$image.tmp" &&
2025+ mv "$image.tmp" "$image" ||
2026+ { rm -f "$image.tmp"; exit 1; }
2027+ ;;
2028+ */disk.img.dist)
2029+ debug 1 "converting qcow2 in $image_src -> raw in $image"
2030+ qemu-img convert -O raw "$image_src" "$image.tmp" &&
2031+ mv "$image.tmp" "$image" ||
2032+ { rm -f "$image.tmp"; exit 1; }
2033+ ;;
2034+ esac
2035+fi
2036+
2037+# vi: ts=4 expandtab
2038diff --git a/debian/tests/patch-image b/debian/tests/patch-image
2039new file mode 100755
2040index 0000000..0688912
2041--- /dev/null
2042+++ b/debian/tests/patch-image
2043@@ -0,0 +1,374 @@
2044+#!/bin/bash
2045+
2046+VERBOSITY=1
2047+TEMP_D=""
2048+
2049+error() { echo "$@" 1>&2; }
2050+fail() { local r=$?; [ $r -eq 0 ] && r=1; failrc "$r" "$@"; }
2051+failrc() { local r=$1; shift; [ $# -eq 0 ] || error "$@"; exit $r; }
2052+
2053+Usage() {
2054+ cat <<EOF
2055+Usage: ${0##*/} [options] image [packages]
2056+ Patch image, upgrading [packages].
2057+ --kernel FILE copy kernel out to FILE
2058+ --initrd FILE copy initrd out to FILE
2059+
2060+ --krd-only only copy out kernel/initrd do not change image.
2061+ this is incompatible with 'packages'
2062+ it is a short-cut to specifying all the '--no-*'
2063+ options below.
2064+
2065+ --no-copy-apt do not copy host's apt repos in.
2066+
2067+ image modifications:
2068+ --no-update-fstab do not modify fstab (LP: #1732028)
2069+
2070+ if no packages are provided, and ADT_TEST_TRIGGERS is set
2071+ in environment, then it will be read for the list of packages.
2072+ to override that behavior pass package 'none'.
2073+EOF
2074+
2075+}
2076+
2077+bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; }
2078+cleanup() {
2079+ [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
2080+}
2081+
2082+debug() {
2083+ local level=${1}; shift;
2084+ [ "${level}" -gt "${VERBOSITY}" ] && return
2085+ error "${@}"
2086+}
2087+
2088+adt_test_triggers_to_bin_pkgs() {
2089+ # ADT_TEST_TRIGGERS is space delimited <src>/version
2090+ # returns a scalar '_RET', caller has to expand
2091+ local tok src="" ver="" binpkgs=""
2092+ for tok in "$@"; do
2093+ src=${tok%/*}
2094+ ver=${tok#*/}
2095+ bin_packages_from_source_pkg "$src" "$ver" || return
2096+ if [ -z "${_RET}" ]; then
2097+ error "$tok: (source=$src ver=$ver) No packages available!"
2098+ return 1
2099+ fi
2100+ binpkgs="${binpkgs} ${_RET}"
2101+ done
2102+ _RET=${binpkgs# }
2103+}
2104+
2105+bin_packages_from_source_pkg() {
2106+ local pkg=$1 ver=${2} cmd="" out="" p="" ret=""
2107+ if ! command -v grep-aptavail >/dev/null; then
2108+ error "No command grep-aptavail: apt-get install dctrl-tools"
2109+ return 1
2110+ fi
2111+ cmd=( grep-aptavail --show-field=Package
2112+ --exact-match --field=Source:Package "$pkg" )
2113+ if [ -n "$ver" ]; then
2114+ cmd=( "${cmd[@]}" --and --field=Version "$ver" )
2115+ fi
2116+ out=$("${cmd[@]}" | sed 's,Package: ,,')
2117+ ret=""
2118+ for p in $out; do
2119+ ret="$ret ${p#Package: }${ver:+=${ver}}"
2120+ done
2121+ # if no version was provided, we could have multiple results
2122+ _RET=$(set -f; for i in ${ret}; do echo "$i"; done | sort -u)
2123+}
2124+
2125+update_fstab() {
2126+ # update_fstab(path) modify the fstab at path
2127+ # to remove problematic entries (LP: #1732028)
2128+ local fstab="$1"
2129+ if [ ! -e "$fstab.patch-image-dist" ]; then
2130+ cp "$fstab" "$fstab.patch-image-dist" ||
2131+ { error "failed backing up $fstab to $fstab.dist"; return 1; }
2132+ fi
2133+ sed -i '/^LABEL=UEFI/s/^/#/' "$fstab"
2134+}
2135+
2136+cat_debug_script() {
2137+ cat <<"EOF"
2138+#!/bin/sh
2139+set -f
2140+NAME=${1:-debug-pid-$$}
2141+[ "$(id -u)" = "0" ] && log="/run/${NAME}.log" || log="/tmp/${NAME}.log"
2142+
2143+msg() {
2144+ echo "===" "$@" "===" 1>&2
2145+}
2146+showcmd() {
2147+ msg "showcmd$" "$@"
2148+ "$@"
2149+}
2150+
2151+main() {
2152+ issues=$(journalctl | egrep "[.]mount: ")
2153+ if [ -z "$issues" ]; then
2154+ msg "$NAME:" "MOUNT ISSUES FOUND: NO"
2155+ else
2156+ msg "$NAME:" "MOUNT ISSUES FOUND: YES"
2157+ fi
2158+ showcmd systemctl list-units --no-pager --all --full "*.mount"
2159+ showcmd systemctl cat --no-pager --all --full "*.mount"
2160+ showcmd systemctl status --no-pager --all --full "*.mount"
2161+ showcmd cat /etc/fstab
2162+ showcmd cat /proc/1/mountinfo
2163+}
2164+
2165+main > "$log" 2>&1
2166+echo "============ $NAME ============="
2167+cat "$log"
2168+EOF
2169+}
2170+
2171+add_systemd_job() {
2172+ local target="$1" name="$2" after="$3" start="$4"
2173+ local spath="lib/systemd/system/xdebug-$name.service"
2174+ debug 1 "writing $name to $target/$spath"
2175+ cat > "$target/$spath" <<EOF
2176+[Unit]
2177+Description=Execute xdebug ${name}
2178+After=${after}
2179+
2180+[Service]
2181+Type=oneshot
2182+ExecStart=${start} ${name}
2183+RemainAfterExit=yes
2184+StandardOutput=journal+console
2185+
2186+[Install]
2187+WantedBy=multi-user.target
2188+EOF
2189+ [ $? -eq 0 ] || { error "failed writing $target/$spath"; return 1; }
2190+ local wantsdir="$target/etc/systemd/system/multi-user.target.wants"
2191+ ln -s "/$spath" "$wantsdir/" ||
2192+ { error "failed ln -s '/$spath' '$wantsdir/'"; return 1; }
2193+}
2194+
2195+insert_debug_1788188() {
2196+ # This is an attempt to collect more debug information in the
2197+ # event that the tests trigger LP: #1788188.
2198+ local target="$1"
2199+ [ "$target" = "/" -o -z "$target" ] &&
2200+ { error "target was / in insert_debug"; return 1; }
2201+ local script="usr/local/bin/debug-mounts"
2202+ cat_debug_script > "$target/$script" &&
2203+ chmod 755 "$target/$script" ||
2204+ { error "failed writing $target/script"; return 1; }
2205+ local name=""
2206+ ( set +f;
2207+ rm -f "$target/lib/systemd/system/xdebug"-*.service \
2208+ "$target/etc/systemd/system/"*.wants/xdebug*.service )
2209+ add_systemd_job "$target" network network-online.target "/$script" &&
2210+ add_systemd_job "$target" local-fs local-fs.target "/$script" ||
2211+ { error "failed adding systemd jobs"; return 1; }
2212+}
2213+
2214+main() {
2215+ local short_opts="hv"
2216+ local long_opts="help,no-copy-apt,initrd:,kernel:,verbose"
2217+ local getopt_out="" orig_args=""
2218+ orig_args=( "$@" )
2219+ getopt_out=$(getopt --name "${0##*/}" \
2220+ --options "${short_opts}" --long "${long_opts}" -- "$@") &&
2221+ eval set -- "${getopt_out}" ||
2222+ { bad_Usage; return; }
2223+
2224+ local cur="" next=""
2225+ local kernel="" initrd="" copy_apt=true krd_only=false
2226+ local update_fstab=true
2227+
2228+ while [ $# -ne 0 ]; do
2229+ cur="$1"; next="$2";
2230+ case "$cur" in
2231+ -h|--help) Usage ; exit 0;;
2232+ --krd-only) krd_only=true; shift;;
2233+ --no-copy-apt) copy_apt=false; shift;;
2234+ --no-update-fstab) update_fstab=false; shift;;
2235+ --kernel) kernel=$next; shift;;
2236+ --initrd) initrd=$next; shift;;
2237+ -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
2238+ --) shift; break;;
2239+ esac
2240+ shift;
2241+ done
2242+
2243+ [ $# -ne 0 ] || { bad_Usage "must provide at least image"; return; }
2244+
2245+ [ "$(id -u)" = "0" ] || fail "not root"
2246+ target="$1"
2247+ shift
2248+ if [ -f "$target" ]; then
2249+ local nargs=""
2250+ nargs=( "${orig_args[@]}" )
2251+ # replace the first occurance of target in orig args with _MOUNTPOINT_
2252+ for((i=0;i<${#nargs[@]};i++)); do
2253+ [ "${nargs[$i]}" = "$target" ] && nargs[$i]=_MOUNTPOINT_ && break
2254+ done
2255+ debug 1 "mic $target -- $0 ${nargs[*]}"
2256+ IMAGE="$target" exec mount-image-callback \
2257+ --system-resolvconf "$target" -- "$0" "${nargs[@]}"
2258+ fi
2259+
2260+ if [ ! -d "$target" ]; then
2261+ fail "$target: not a directory or file"
2262+ fi
2263+
2264+ local tsrc=${IMAGE:-${target}}
2265+ local packages=( )
2266+ packages=( "$@" )
2267+
2268+ if $krd_only; then
2269+ if [ "${#packages[@]}" != 0 -a "${packages[*]}" != "none" ]; then
2270+ error "--krd-only is incompatible with packages."
2271+ return 1
2272+ fi
2273+ debug 1 "--krd-only provided no changes will be done."
2274+ copy_apt=false
2275+ update_fstab=false
2276+ packages=( "none" )
2277+ fi
2278+
2279+ if [ "${#packages[@]}" = "1" -a "${packages[0]}" = "none" ]; then
2280+ packages=( )
2281+ elif [ "${#packages[@]}" -eq 0 -a -n "${ADT_TEST_TRIGGERS}" ]; then
2282+ adt_test_triggers_to_bin_pkgs ${ADT_TEST_TRIGGERS} ||
2283+ fail "failed to find binary packages " \
2284+ "from ADT_TEST_TRIGGERS=$ADT_TEST_TRIGGERS"
2285+ packages=( $_RET )
2286+ debug 1 "read ADT_TEST_TRIGGERS=$ADT_TEST_TRIGGERS to set" \
2287+ "packages=${packages[*]}"
2288+ else
2289+ local opackages="" debs="" pkg=""
2290+ opackages=( "${packages[@]}" )
2291+ packages=( )
2292+ debs=( )
2293+ for pkg in "${opackages[@]}"; do
2294+ [ -f "${pkg}" ] && debs[${#debs[@]}]="$pkg" ||
2295+ packages[${packages[@]}]="$pkg"
2296+ done
2297+ if [ "${#packages[@]}" -eq 0 -a "${#debs[@]}" -eq 0 ]; then
2298+ packages=( open-iscsi )
2299+ debug 1 "no packages or debs given, using packages=${packages[*]}"
2300+ fi
2301+ fi
2302+
2303+ # if open-iscsi is not in the packages list above, we handle it specifically
2304+ # so that even if the image did not have open-iscsi, it will get it.
2305+ local pkg="" mypkg="open-iscsi"
2306+ for pkg in "${packages[@]}"; do
2307+ case "$pkg" in
2308+ open-iscsi|open-iscsi/*) mypkg="none";;
2309+ esac
2310+ done
2311+
2312+ TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
2313+ fail "failed to make tempdir"
2314+ trap cleanup EXIT
2315+
2316+ if $copy_apt; then
2317+ local distdir="${target}/etc/apt.dist.${0##*/}"
2318+ if [ ! -d "$distdir" ]; then
2319+ mv "$target/etc/apt" "$distdir" ||
2320+ fail "failed to backup /etc/apt in $tsrc"
2321+ fi
2322+ cp -a /etc/apt "$target/etc/" ||
2323+ fail "failed to replace /etc/apt in $tsrc"
2324+
2325+ # find file:// repos in apt sources and copy them in
2326+ local file_repos=""
2327+ file_repos=$(
2328+ fm='s,.*[[:space:]]file:///*\([^[[:space:]]*\).*,/\1,p'
2329+ shopt -s nullglob
2330+ for f in /etc/apt/sources.list /etc/apt/sources.list.d/*.list; do
2331+ sed -n -e 's/#.*//' -e "$fm" "$f"
2332+ done
2333+ )
2334+ local dir="" bdir="" tdir=""
2335+ for dir in ${file_repos}; do
2336+ tdir="${target}$(dirname $dir)/$(basename ${dir})"
2337+ if [ -d "$dir" ]; then
2338+ debug 1 "copying $dir -> $tdir"
2339+ mkdir -p "$tdir" ||
2340+ fail "failed to create $tdir"
2341+ rsync --delete -a "$dir/" "$tdir" ||
2342+ fail "failed copy from $dir/ to $tdir"
2343+ fi
2344+ done
2345+ fi
2346+
2347+ if $update_fstab; then
2348+ update_fstab "$target/etc/fstab" ||
2349+ { error "failed updating /etc/fstab in target"; return 1; }
2350+ fi
2351+
2352+ insert_debug_1788188 "$target" || return 1
2353+
2354+ mount -o bind /sys "$target"/sys || :
2355+ mount -o bind /proc "$target"/proc || :
2356+ mount -o bind /dev "$target"/dev || :
2357+ mount -o bind /dev/pts "$target"/dev/pts || :
2358+
2359+ debug 1 "${#packages[@]} packages: ${packages[*]}"
2360+ if [ "${#packages[@]}" != "0" ]; then
2361+ DEBIAN_FRONTEND=noninteractive chroot "$target" sh -exc '
2362+ mypkg=$1
2363+ shift
2364+ apt-get update -q
2365+ if [ "$mypkg" != "none" ]; then
2366+ apt-get install -qy "$mypkg"
2367+ fi
2368+ apt-get install -qy --only-upgrade "$@"' \
2369+ chroot-inst "$mypkg" "${packages[@]}" ||
2370+ fail "failed to install ${packages[*]} in $target"
2371+ fi
2372+
2373+ debug 1 "${#debs[@]} debs: ${debs[*]}"
2374+ if [ "${#debs[@]}" != "0" ]; then
2375+ local tmpd=""
2376+ tmpd=$(mktemp -d "${target}/tmp/${0##*/}.XXXXXX")
2377+ cp "${debs[@]}" "$tmpd"
2378+ DEBIAN_FRONTEND=noninteractive chroot "$target" sh -exc \
2379+ 'cd "$1"; shift; dpkg -i *.deb' debinstalls "${tmpd#${target}}"
2380+ rm -Rf "${tmpd}"
2381+ fi
2382+
2383+ umount "$target"/dev/pts || :
2384+ umount "$target"/dev || :
2385+ umount "$target"/proc || :
2386+ umount "$target"/sys || :
2387+
2388+ local kpath="" ipath=""
2389+ for f in "$target/boot/"*; do
2390+ case "${f##*/}" in
2391+ *.signed) continue;;
2392+ vmlinu?-*) kpath="$f";;
2393+ initrd.img-*) ipath="$f";;
2394+ esac
2395+ done
2396+
2397+ if [ -n "$kernel" ]; then
2398+ [ -n "$kpath" ] || fail "unable to find kernel in $tsrc"
2399+ debug 1 "using kernel ${kpath#${target}}"
2400+ cp "$kpath" "$kernel" ||
2401+ fail "failed copy $kpath to $kernel"
2402+ [ -z "$IMAGE" ] || chown "--reference=$IMAGE" "$kernel"
2403+ fi
2404+
2405+ if [ -n "$initrd" ]; then
2406+ [ -n "$ipath" ] || fail "unable to find initrd in $tsrc"
2407+ debug 1 "using initrd ${ipath#${target}}"
2408+ cp "$ipath" "$initrd" ||
2409+ fail "failed copy $ipath to $initrd"
2410+ [ -z "$IMAGE" ] || chown "--reference=$IMAGE" "$initrd"
2411+ fi
2412+
2413+}
2414+
2415+main "$@"
2416+
2417+# vi: ts=4 expandtab
2418diff --git a/debian/tests/test-open-iscsi.py b/debian/tests/test-open-iscsi.py
2419new file mode 100644
2420index 0000000..e241be9
2421--- /dev/null
2422+++ b/debian/tests/test-open-iscsi.py
2423@@ -0,0 +1,427 @@
2424+#!/usr/bin/python3
2425+#
2426+# test-open-iscsi.py quality assurance test script for open-iscsi
2427+# Copyright (C) 2011 Canonical Ltd.
2428+# Author: Jamie Strandboge <jamie@canonical.com>
2429+#
2430+# This program is free software: you can redistribute it and/or modify
2431+# it under the terms of the GNU General Public License version 3,
2432+# as published by the Free Software Foundation.
2433+#
2434+# This program is distributed in the hope that it will be useful,
2435+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2436+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2437+# GNU General Public License for more details.
2438+#
2439+# You should have received a copy of the GNU General Public License
2440+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2441+#
2442+# packages required for test to run:
2443+# QRT-Packages: open-iscsi
2444+# packages where more than one package can satisfy a runtime requirement:
2445+# QRT-Alternates:
2446+# files and directories required for the test to run:
2447+# QRT-Depends:
2448+# privilege required for the test to run (remove line if running as user is okay):
2449+# QRT-Privilege: root
2450+
2451+'''
2452+ In general, this test should be run in a virtual machine (VM) or possibly
2453+ a chroot and not on a production machine. While efforts are made to make
2454+ these tests non-destructive, there is no guarantee this script will not
2455+ alter the machine. You have been warned.
2456+
2457+ How to run in a clean VM:
2458+ $ sudo apt-get -y install <QRT-Packages> && sudo ./test-PKG.py -v'
2459+
2460+ How to run in a clean schroot named 'lucid':
2461+ $ schroot -c lucid -u root -- sh -c 'apt-get -y install <QRT-Packages> && ./test-PKG.py -v'
2462+
2463+
2464+ NOTES:
2465+ - currently only tested on Ubuntu 8.04
2466+'''
2467+
2468+from __future__ import print_function
2469+
2470+from netifaces import gateways, AF_INET
2471+import unittest, subprocess, sys, os, glob
2472+import shutil
2473+import testlib
2474+import textwrap
2475+from tempfile import mkdtemp
2476+import time
2477+
2478+# There are setup based on README.multipurpose-vm. Feel free to override.
2479+remote_server = ''
2480+username = 'ubuntu'
2481+password = 'passwd'
2482+username_in = 'ubuntu'
2483+password_in = 'ubuntupasswd'
2484+initiatorname = 'iqn.2009-10.com.example.hardy-multi:iscsi-01'
2485+
2486+COLLECT_USER_DATA = """\
2487+#cloud-config
2488+bukket:
2489+ - &get_resolved_status |
2490+ if [ "${1:--}" != "-" ]; then
2491+ exec >"$1" 2>&1
2492+ fi
2493+ if ! command -v resolvectl >/dev/null 2>&1; then
2494+ echo "resolvectl: not available."
2495+ exit
2496+ fi
2497+ if ! ( resolvectl --help | grep -q -- status ); then
2498+ echo "resolvectl: no status."
2499+ exit
2500+ fi
2501+ resolvectl status --no-pager
2502+
2503+ - &get_iscsid_status |
2504+ [ "${1:--}" != "-" ] && exec >"$1" 2>&1
2505+ udevadm settle
2506+ systemctl is-active iscsid.service
2507+ systemctl status --no-pager --full iscsid.service
2508+
2509+ - &add_and_remove_tuntap |
2510+ #!/bin/sh
2511+ # LP: #1785108 would break dns when any device was removed.
2512+ tapdev="mytap0"
2513+ echo ==== Adding $tapdev ====
2514+ ip tuntap add mode tap user root $tapdev
2515+ udevadm settle
2516+ echo ==== Removing $tapdev ====
2517+ ip tuntap del mode tap $tapdev
2518+ udevadm settle
2519+
2520+ - &collect_debug_mounts |
2521+ [ "${1:--}" != "-" ] && exec >"$1" 2>&1
2522+ [ -x /usr/local/bin/debug-mounts ] || exit 0
2523+ /usr/local/bin/debug-mounts
2524+
2525+runcmd:
2526+ - [ sh, -c, *add_and_remove_tuntap ]
2527+ - [ mkdir, -p, /output ]
2528+ - [ cp, /etc/resolv.conf, /output ]
2529+ - [ sh, -c, *get_resolved_status, --, /output/systemd-resolve-status.txt ]
2530+ - [ sh, -c, *get_iscsid_status, --, /output/iscsid-status.txt ]
2531+ - [ sh, -c, *collect_debug_mounts, --, /output/debug-mounts.txt ]
2532+ - [ sh, -c, 'journalctl --boot=0 --output=short-monotonic > /output/journal.txt' ]
2533+ - [ sh, -c, 'dpkg-query --show > /output/manifest.txt' ]
2534+ - [ tar, -C, /output, -cf, /dev/disk/by-id/virtio-output-disk, . ]
2535+
2536+power_state:
2537+ mode: poweroff
2538+ message: cloud-init finished. Shutting down.
2539+ timeout: 60
2540+"""
2541+
2542+try:
2543+ from private.qrt.OpenIscsi import PrivateOpenIscsiTest
2544+except ImportError:
2545+ class PrivateOpenIscsiTest(object):
2546+ '''Empty class'''
2547+ print("Skipping private tests", file=sys.stdout)
2548+
2549+class OpenIscsiTest(testlib.TestlibCase, PrivateOpenIscsiTest):
2550+ '''Test my thing.'''
2551+
2552+ def setUp(self):
2553+ '''Set up prior to each test_* function'''
2554+ self.pidfile = "/var/run/iscsid.pid"
2555+ self.exe = "/sbin/iscsid"
2556+ self.daemon = testlib.TestDaemon("open-iscsi")
2557+ self.initiatorname_iscsi = '/etc/iscsi/initiatorname.iscsi'
2558+ self.iscsid_conf = '/etc/iscsi/iscsid.conf'
2559+
2560+ def tearDown(self):
2561+ '''Clean up after each test_* function'''
2562+ global remote_server
2563+ global initiatorname
2564+
2565+ # If remote server is setup, convert back to manual, logout, remove
2566+ # testlib configs and restart (in that order)
2567+ if remote_server != '':
2568+ testlib.cmd(['iscsiadm', '-m', 'node', '--targetname', initiatorname, '-p', '%s:3260' % remote_server, '--op=update', '--name', 'node.startup', '--value=manual'])
2569+ testlib.cmd(['iscsiadm', '-m', 'node', '--targetname', initiatorname, '-p', '%s:3260' % remote_server, '--op=update', '--name', 'node.conn[0].startup', '--value=manual'])
2570+ testlib.cmd(['iscsiadm', '-m', 'node', '--targetname', initiatorname, '-p', '%s:3260' % remote_server, '--logout'])
2571+
2572+ testlib.config_restore(self.initiatorname_iscsi)
2573+ testlib.config_restore(self.iscsid_conf)
2574+ self.daemon.restart()
2575+
2576+ def test_discovery_with_server(self):
2577+ '''Test iscsi_discovery to remote server'''
2578+ global remote_server
2579+ global username
2580+ global password
2581+ global username_in
2582+ global password_in
2583+ global initiatorname
2584+
2585+ if remote_server == '':
2586+ return self._skipped("--remote-server not specified")
2587+
2588+ contents = '''
2589+InitiatorName=%s
2590+InitiatorAlias=ubuntu
2591+''' % (initiatorname)
2592+ testlib.config_replace(self.initiatorname_iscsi, contents, True)
2593+
2594+ contents = '''
2595+node.session.auth.authmethod = CHAP
2596+node.session.auth.username = %s
2597+node.session.auth.password = %s
2598+node.session.auth.username_in = %s
2599+node.session.auth.password_in = %s
2600+
2601+discovery.sendtargets.auth.authmethod = CHAP
2602+discovery.sendtargets.auth.username = %s
2603+discovery.sendtargets.auth.password = %s
2604+discovery.sendtargets.auth.username_in = %s
2605+discovery.sendtargets.auth.password_in = %s
2606+''' % (username, password, username_in, password_in, username, password, username_in, password_in)
2607+ testlib.config_replace(self.iscsid_conf, contents, True)
2608+
2609+ self.assertTrue(self.daemon.restart())
2610+ time.sleep(2)
2611+ self.assertTrue(self.daemon.status()[0])
2612+
2613+ rc, report = testlib.cmd(["/sbin/iscsi_discovery", remote_server])
2614+ expected = 0
2615+ result = 'Got exit code %d, expected %d\n' % (rc, expected)
2616+ self.assertEqual(expected, rc, result + report)
2617+ for i in ['starting discovery to %s' % remote_server,
2618+ 'Testing iser-login to target %s portal %s' % (initiatorname, remote_server),
2619+ 'starting to test tcp-login to target %s portal %s' % (initiatorname, remote_server),
2620+ 'discovered 1 targets at %s, connected to 1' % remote_server]:
2621+ result = "Could not find '%s' in report:\n" % i
2622+ self.assertTrue(i in report, result + report)
2623+
2624+ def test_net_interface_handler_execute_bit(self):
2625+ '''Test /lib/open-iscsi/net-interface-handler is executable.'''
2626+ nih_path = '/lib/open-iscsi/net-interface-handler'
2627+ self.assertTrue(os.access(nih_path, os.X_OK))
2628+
2629+class CloudImageTest(testlib.TestlibCase, PrivateOpenIscsiTest):
2630+ '''Test the cloud image can boot on iscsi root.
2631+
2632+ See README-boot-test.md for more information.
2633+ '''
2634+
2635+ @classmethod
2636+ def setUpClass(cls):
2637+ reason = (
2638+ "Skipped Cloud Image test on {arch}. whitelisted are: {whitelist}")
2639+ whitelisted = os.environ.get('WHITELIST_ARCHES', 'amd64').split(",")
2640+ curarch = testlib.manager.dpkg_arch
2641+ if testlib.manager.dpkg_arch not in whitelisted:
2642+ raise unittest.SkipTest(
2643+ reason.format(arch=curarch, whitelist=whitelisted))
2644+
2645+ here = os.path.dirname(os.path.abspath(__file__))
2646+ os.environ['PATH'] = "%s:%s" % (here, os.environ['PATH'])
2647+ release = os.environ.get(
2648+ "ISCSI_TEST_RELEASE", testlib.ubuntu_release())
2649+ image_d = os.path.join(here, '{}.d'.format(release))
2650+ # Download MAAS ephemeral image.
2651+ info = {'release': release,
2652+ 'image_d': image_d,
2653+ 'root_image': os.path.join(image_d, 'disk.img'),
2654+ 'kernel': os.path.join(image_d, 'kernel'),
2655+ 'initrd': os.path.join(image_d, 'initrd')}
2656+ try:
2657+ get_image(info['image_d'], release)
2658+ except subprocess.CalledProcessError as e:
2659+ if e.return_code != 3:
2660+ raise e
2661+ raise unittest.SkipTest(
2662+ "Cloud Image not available for release '%s'." % release)
2663+ if os.environ.get("NO_PATCH_IMAGE", "0") == "0":
2664+ patch_image(info['root_image'],
2665+ kernel=info['kernel'], initrd=info['initrd'])
2666+ cls.info = info
2667+ cls.here = here
2668+
2669+ def tearDown(self):
2670+ super(CloudImageTest, self).tearDown()
2671+ if os.path.exists(self.tmpdir):
2672+ shutil.rmtree(self.tmpdir)
2673+
2674+ def setUp(self):
2675+ super(CloudImageTest, self).setUp()
2676+ self.tmpdir = mkdtemp()
2677+ udp = os.path.join(self.tmpdir, 'user-data')
2678+ with open(udp, "w") as fp:
2679+ fp.write(COLLECT_USER_DATA)
2680+ self.info['user-data'] = udp
2681+
2682+ def create_output_disk(self):
2683+ path = os.path.join(self.tmpdir, 'output-disk.img')
2684+ subprocess.check_call([
2685+ 'qemu-img', 'create', '-f', 'raw', path, '10M'])
2686+ return path
2687+
2688+ def extract_files(self, path):
2689+ # get contents in a dictionary of tarball at 'path'
2690+ tmpdir = mkdtemp()
2691+ try:
2692+ subprocess.check_call(['tar', '-C', tmpdir, '-xf', path])
2693+ flist = {}
2694+ prefix = len(tmpdir) + 1
2695+ for root, dirs, files in os.walk(tmpdir):
2696+ for fname in files:
2697+ fpath = os.path.join(root, fname)
2698+ key = fpath[prefix:]
2699+ with open(fpath, "r") as fp:
2700+ flist[key] = fp.read()
2701+ return flist
2702+ finally:
2703+ shutil.rmtree(tmpdir)
2704+
2705+ def test_tgt_boot(self):
2706+ tgt_boot_cmd = os.path.join(self.here, 'tgt-boot-test')
2707+ # Add self.here to PATH so xkvm will be available to tgt-boot-test
2708+ dns_addr = '10.1.1.4'
2709+ rel_dir = '{}.d'.format(self.info['release'])
2710+ dns_search = 'example.com'
2711+ info = {'host': '10.1.1.2', 'dns': dns_addr,
2712+ 'dnssearch': dns_search, 'network': '10.1.1.0/24'}
2713+ netdev = ("--netdev=user,net={network},host={host},dns={dns},"
2714+ "dnssearch={dnssearch}").format(**info)
2715+
2716+ artifacts_dir = os.environ.get('AUTOPKGTEST_ARTIFACTS')
2717+ if artifacts_dir and not os.path.isdir(artifacts_dir):
2718+ os.makedirs(artifacts_dir)
2719+
2720+ output_disk = self.create_output_disk()
2721+ cmd = [
2722+ tgt_boot_cmd, '-v', netdev,
2723+ '--disk=%s,serial=output-disk' % output_disk,
2724+ '--user-data-add=%s' % self.info['user-data'],
2725+ self.info['root_image'], self.info['kernel'],
2726+ self.info['initrd']]
2727+ sys.stderr.write(' '.join(cmd) + "\n")
2728+
2729+ env = os.environ.copy()
2730+ env['BOOT_TIMEOUT'] = env.get('BOOT_TIMEOUT', '60m')
2731+ subprocess.check_call(cmd, env=env)
2732+
2733+ if artifacts_dir:
2734+ tgz = os.path.join(artifacts_dir, "tgt-collected.tar.gz")
2735+ shutil.copy(output_disk, tgz)
2736+ print("Copied output_disk '%s' to artifacts dir '%s'" %
2737+ (output_disk, tgz))
2738+
2739+ files = self.extract_files(output_disk)
2740+ print("collected files: %s" % files.keys())
2741+ resolvconf = files.get('resolv.conf', "NO_RESOLVCONF_FOUND")
2742+ resolve_status = files.get('systemd-resolve-status.txt')
2743+
2744+ resolvconf_id = 'generated by resolvconf'
2745+ resolved_addr = "127.0.0.53"
2746+ if resolvconf_id in resolvconf:
2747+ print("resolvconf manages resolvconf.\n")
2748+ self.assertIn(
2749+ dns_addr, resolvconf,
2750+ msg = ("%s not in resolvconf contents: \n%s" %
2751+ (dns_addr, resolvconf)))
2752+ if dns_search in resolvconf:
2753+ print("%s was found in resolv.conf." % dns_search)
2754+ elif resolved_addr in resolvconf and dns_search in resolve_status:
2755+ # zesty has resolvconf and systemd-resolved.
2756+ print("%s was in resolve_status and %s in resolv.conf" %
2757+ (resolved_addr, dns_search))
2758+ else:
2759+ raise AssertionError(
2760+ "%s domain is not being searched." % dns_search)
2761+
2762+ else:
2763+ print("systemd-resolved managing resolve.conf\n")
2764+ self.assertIn(
2765+ resolved_addr, resolvconf,
2766+ msg="%s not in resolved resolv.conf: %s" % (resolved_addr,
2767+ resolvconf))
2768+ self.assertIn(dns_addr, resolve_status,
2769+ msg=("%s not in resolvectl status: %s" %
2770+ (dns_addr, resolve_status)))
2771+ self.assertIn(dns_search, resolve_status,
2772+ msg=("search addr '%s' not in resolvectl status: %s" %
2773+ (dns_search, resolve_status)))
2774+
2775+ # iscsid-status.txt has first line output from
2776+ # 'systemctl is-active iscsid.service' and then 'systemcl status'
2777+ iscsid_status = files.get('iscsid-status.txt')
2778+ is_active = iscsid_status.splitlines()[0]
2779+ self.assertEqual(
2780+ "active", is_active,
2781+ msg=("Expected iscsid.service active, found '%s'.\n%s\n" %
2782+ (is_active, iscsid_status)))
2783+
2784+
2785+def get_image(top_d, release):
2786+ cmd = ['get-image', top_d, 'cloud-daily', release]
2787+ subprocess.check_call(cmd)
2788+
2789+
2790+def patch_image(image, packages=None, kernel=None, initrd=None):
2791+ '''Patch root-image with dep8 built open-iscsi package.'''
2792+
2793+ if packages is None:
2794+ # an empty 'packages' to patch-image still installs open-iscsi
2795+ packages = []
2796+
2797+ cmd = ['patch-image', image]
2798+ if kernel:
2799+ cmd.append('--kernel=%s' % kernel)
2800+ if initrd:
2801+ cmd.append('--initrd=%s' % initrd)
2802+ cmd.extend(packages)
2803+
2804+ subprocess.check_call(cmd)
2805+
2806+
2807+if __name__ == '__main__':
2808+ import optparse
2809+ parser = optparse.OptionParser()
2810+ parser.add_option("-v", "--verbose", dest="verbose", help="Verbose", action="store_true")
2811+ parser.add_option("-s", "--remote-server", dest="remote_server", help="Specify host with available iSCSI volumes", metavar="HOST")
2812+
2813+ parser.add_option("-n", "--initiatorname", dest="initiatorname", help="Specify initiatorname for use with --remote-server", metavar="NAME")
2814+
2815+ parser.add_option("--password", dest="password", help="Specify password for use with --remote-server", metavar="PASS")
2816+ parser.add_option("--password-in", dest="password_in", help="Specify password_in for use with --remote-server", metavar="PASS")
2817+
2818+ parser.add_option("--username", dest="username", help="Specify username for use with --remote-server", metavar="USER")
2819+ parser.add_option("--username-in", dest="username_in", help="Specify username_in for use with --remote-server", metavar="USER")
2820+
2821+ (options, args) = parser.parse_args()
2822+
2823+ if options.remote_server:
2824+ remote_server = options.remote_server
2825+
2826+ if options.username:
2827+ username = options.username
2828+ if options.password:
2829+ password = options.password
2830+ if options.username_in:
2831+ username_in = options.username_in
2832+ if options.password_in:
2833+ password_in = options.password_in
2834+ if options.initiatorname:
2835+ initiatorname = options.initiatorname
2836+ print("Connecting to remote server with:")
2837+ print(" host = %s " % remote_server)
2838+ print(' initiatorname = %s' % initiatorname)
2839+ print(' username = %s' % username)
2840+ print(' password = %s' % password)
2841+ print(' username_in = %s' % username_in)
2842+ print(' password_in = %s' % password_in)
2843+
2844+ suite = unittest.TestSuite()
2845+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(OpenIscsiTest))
2846+ suite.addTest(unittest.TestLoader().loadTestsFromTestCase(
2847+ CloudImageTest))
2848+ rc = unittest.TextTestRunner(verbosity=2).run(suite)
2849+ if not rc.wasSuccessful():
2850+ sys.exit(1)
2851diff --git a/debian/tests/testlib.py b/debian/tests/testlib.py
2852new file mode 100644
2853index 0000000..dce4252
2854--- /dev/null
2855+++ b/debian/tests/testlib.py
2856@@ -0,0 +1,1488 @@
2857+from __future__ import print_function
2858+#
2859+# testlib.py quality assurance test script
2860+# Copyright (C) 2008-2016 Canonical Ltd.
2861+#
2862+# This library is free software; you can redistribute it and/or
2863+# modify it under the terms of the GNU Library General Public
2864+# License as published by the Free Software Foundation; either
2865+# version 2 of the License.
2866+#
2867+# This library is distributed in the hope that it will be useful,
2868+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2869+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2870+# Library General Public License for more details.
2871+#
2872+# You should have received a copy of the GNU Library General Public
2873+# License along with this program. If not, see
2874+# <http://www.gnu.org/licenses/>.
2875+#
2876+
2877+'''Common classes and functions for package tests.'''
2878+
2879+import crypt
2880+import glob
2881+import grp
2882+import gzip
2883+import os
2884+import os.path
2885+import platform
2886+import pwd
2887+import random
2888+import re
2889+import shutil
2890+import socket
2891+import string
2892+import subprocess
2893+import sys
2894+import tempfile
2895+import time
2896+import unittest
2897+
2898+from stat import ST_SIZE
2899+
2900+# Don't make python-pexpect mandatory
2901+try:
2902+ import pexpect
2903+except ImportError:
2904+ pass
2905+
2906+import warnings
2907+warnings.filterwarnings('ignore', message=r'.*apt_pkg\.TagFile.*', category=DeprecationWarning)
2908+try:
2909+ import apt_pkg
2910+ # cope with apt_pkg api changes.
2911+ if 'init_system' in dir(apt_pkg):
2912+ apt_pkg.init_system()
2913+ else:
2914+ apt_pkg.InitSystem()
2915+except:
2916+ # On non-Debian system, fall back to simple comparison without debianisms
2917+ class apt_pkg(object):
2918+ @staticmethod
2919+ def version_compare(one, two):
2920+ list_one = one.split('.')
2921+ list_two = two.split('.')
2922+ while len(list_one) > 0 and len(list_two) > 0:
2923+ try:
2924+ if int(list_one[0]) > int(list_two[0]):
2925+ return 1
2926+ if int(list_one[0]) < int(list_two[0]):
2927+ return -1
2928+ except:
2929+ # ugh, non-numerics in the version, fall back to
2930+ # string comparison, which will be wrong for e.g.
2931+ # 3.2 vs 3.16rc1
2932+ if list_one[0] > list_two[0]:
2933+ return 1
2934+ if list_one[0] < list_two[0]:
2935+ return -1
2936+ list_one.pop(0)
2937+ list_two.pop(0)
2938+ return 0
2939+
2940+ @staticmethod
2941+ def VersionCompare(one, two):
2942+ return apt_pkg.version_compare(one, two)
2943+
2944+bogus_nxdomain = "208.69.32.132"
2945+
2946+# http://www.chiark.greenend.org.uk/ucgi/~cjwatson/blosxom/2009-07-02-python-sigpipe.html
2947+# This is needed so that the subprocesses that produce endless output
2948+# actually quit when the reader goes away.
2949+import signal
2950+def subprocess_setup():
2951+ # Python installs a SIGPIPE handler by default. This is usually not what
2952+ # non-Python subprocesses expect.
2953+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
2954+
2955+
2956+class TimedOutException(Exception):
2957+ def __init__(self, value="Timed Out"):
2958+ self.value = value
2959+
2960+ def __str__(self):
2961+ return repr(self.value)
2962+
2963+
2964+def _restore_backup(path):
2965+ pathbackup = path + '.autotest'
2966+ if os.path.exists(pathbackup):
2967+ shutil.move(pathbackup, path)
2968+
2969+
2970+def _save_backup(path):
2971+ pathbackup = path + '.autotest'
2972+ if os.path.exists(path) and not os.path.exists(pathbackup):
2973+ shutil.copy2(path, pathbackup)
2974+ # copy2 does not copy ownership, so do it here.
2975+ # Reference: http://docs.python.org/library/shutil.html
2976+ a = os.stat(path)
2977+ os.chown(pathbackup, a[4], a[5])
2978+
2979+
2980+def config_copydir(path):
2981+ if os.path.exists(path) and not os.path.isdir(path):
2982+ raise OSError("'%s' is not a directory" % (path))
2983+ _restore_backup(path)
2984+
2985+ pathbackup = path + '.autotest'
2986+ if os.path.exists(path):
2987+ shutil.copytree(path, pathbackup, symlinks=True)
2988+
2989+
2990+def config_replace(path, contents, append=False):
2991+ '''Replace (or append) to a config file'''
2992+ _restore_backup(path)
2993+ if os.path.exists(path):
2994+ _save_backup(path)
2995+ if append:
2996+ with open(path) as fh:
2997+ contents = fh.read() + contents
2998+ with open(path, 'w') as fh:
2999+ fh.write(contents)
3000+
3001+
3002+def config_comment(path, field):
3003+ _save_backup(path)
3004+ contents = ""
3005+ with open(path) as fh:
3006+ for line in fh:
3007+ if re.search("^\s*%s\s*=" % (field), line):
3008+ line = "#" + line
3009+ contents += line
3010+
3011+ with open(path + '.new', 'w') as new_fh:
3012+ new_fh.write(contents)
3013+ os.rename(path + '.new', path)
3014+
3015+
3016+def config_set(path, field, value, spaces=True):
3017+ _save_backup(path)
3018+ contents = ""
3019+ if spaces:
3020+ setting = '%s = %s\n' % (field, value)
3021+ else:
3022+ setting = '%s=%s\n' % (field, value)
3023+ found = False
3024+ with open(path) as fh:
3025+ for line in fh:
3026+ if re.search("^\s*%s\s*=" % (field), line):
3027+ found = True
3028+ line = setting
3029+ contents += line
3030+ if not found:
3031+ contents += setting
3032+
3033+ with open(path + '.new', 'w') as new_config:
3034+ new_config.write(contents)
3035+ os.rename(path + '.new', path)
3036+
3037+
3038+def config_patch(path, patch, depth=1):
3039+ '''Patch a config file'''
3040+ _restore_backup(path)
3041+ _save_backup(path)
3042+
3043+ handle, name = mkstemp_fill(patch)
3044+ rc = subprocess.call(['/usr/bin/patch', '-p%s' % depth, path], stdin=handle, stdout=subprocess.PIPE)
3045+ os.unlink(name)
3046+ if rc != 0:
3047+ raise Exception("Patch failed")
3048+
3049+
3050+def config_restore(path):
3051+ '''Rename a replaced config file back to its initial state'''
3052+ _restore_backup(path)
3053+
3054+
3055+def timeout(secs, f, *args):
3056+ def handler(signum, frame):
3057+ raise TimedOutException()
3058+
3059+ old = signal.signal(signal.SIGALRM, handler)
3060+ result = None
3061+ signal.alarm(secs)
3062+ try:
3063+ result = f(*args)
3064+ finally:
3065+ signal.alarm(0)
3066+ signal.signal(signal.SIGALRM, old)
3067+
3068+ return result
3069+
3070+
3071+def require_nonroot():
3072+ if os.geteuid() == 0:
3073+ print("This series of tests should be run as a regular user with sudo access, not as root.", file=sys.stderr)
3074+ sys.exit(1)
3075+
3076+
3077+def require_root():
3078+ if os.geteuid() != 0:
3079+ print("This series of tests should be run with root privileges (e.g. via sudo).", file=sys.stderr)
3080+ sys.exit(1)
3081+
3082+
3083+def require_sudo():
3084+ if os.geteuid() != 0 or os.environ.get('SUDO_USER', None) is None:
3085+ print("This series of tests must be run under sudo.", file=sys.stderr)
3086+ sys.exit(1)
3087+ if os.environ['SUDO_USER'] == 'root':
3088+ print('Please run this test using sudo from a regular user. (You ran sudo from root.)', file=sys.stderr)
3089+ sys.exit(1)
3090+
3091+
3092+def random_string(length, lower=False):
3093+ '''Return a random string, consisting of ASCII letters, with given
3094+ length.'''
3095+
3096+ s = ''
3097+ selection = string.ascii_letters
3098+ if lower:
3099+ selection = string.ascii_lowercase
3100+ maxind = len(selection) - 1
3101+ for l in range(length):
3102+ s += selection[random.randint(0, maxind)]
3103+ return s
3104+
3105+
3106+def mkstemp_fill(contents, suffix='', prefix='testlib-', dir=None):
3107+ '''As tempfile.mkstemp does, return a (file, name) pair, but with
3108+ prefilled contents.'''
3109+
3110+ handle, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
3111+ os.close(handle)
3112+ handle = open(name, "w+")
3113+ handle.write(contents)
3114+ handle.flush()
3115+ handle.seek(0)
3116+
3117+ return handle, name
3118+
3119+
3120+def create_fill(path, contents, mode=0o644):
3121+ '''Safely create a page'''
3122+ # make the temp file in the same dir as the destination file so we
3123+ # don't get invalid cross-device link errors when we rename
3124+ handle, name = mkstemp_fill(contents, dir=os.path.dirname(path))
3125+ handle.close()
3126+ os.rename(name, path)
3127+ os.chmod(path, mode)
3128+
3129+
3130+def login_exists(login):
3131+ '''Checks whether the given login exists on the system.'''
3132+
3133+ try:
3134+ pwd.getpwnam(login)
3135+ return True
3136+ except KeyError:
3137+ return False
3138+
3139+
3140+def group_exists(group):
3141+ '''Checks whether the given login exists on the system.'''
3142+
3143+ try:
3144+ grp.getgrnam(group)
3145+ return True
3146+ except KeyError:
3147+ return False
3148+
3149+
3150+def is_empty_file(path):
3151+ '''test if file is empty, returns True if so'''
3152+ with open(path) as fh:
3153+ return (len(fh.read()) == 0)
3154+
3155+
3156+def recursive_rm(dirPath, contents_only=False):
3157+ '''recursively remove directory'''
3158+ names = os.listdir(dirPath)
3159+ for name in names:
3160+ path = os.path.join(dirPath, name)
3161+ if os.path.islink(path) or not os.path.isdir(path):
3162+ os.unlink(path)
3163+ else:
3164+ recursive_rm(path)
3165+ if not contents_only:
3166+ os.rmdir(dirPath)
3167+
3168+
3169+def check_pidfile(exe, pidfile):
3170+ '''Checks if pid in pidfile is running'''
3171+ if not os.path.exists(pidfile):
3172+ return False
3173+
3174+ # get the pid
3175+ try:
3176+ with open(pidfile, 'r') as fd:
3177+ pid = fd.readline().rstrip('\n')
3178+ except:
3179+ return False
3180+
3181+ return check_pid(exe, pid)
3182+
3183+
3184+def check_pid(exe, pid):
3185+ '''Checks if pid is running'''
3186+ cmdline = "/proc/%s/cmdline" % (str(pid))
3187+ if not os.path.exists(cmdline):
3188+ return False
3189+
3190+ # get the command line
3191+ try:
3192+ with open(cmdline, 'r') as fd:
3193+ tmp = fd.readline().split('\0')
3194+ except:
3195+ return False
3196+
3197+ # this allows us to match absolute paths or just the executable name
3198+ if re.match('^' + exe + '$', tmp[0]) or \
3199+ re.match('.*/' + exe + '$', tmp[0]) or \
3200+ re.match('^' + exe + ': ', tmp[0]) or \
3201+ re.match('^\(' + exe + '\)', tmp[0]):
3202+ return True
3203+
3204+ return False
3205+
3206+
3207+def check_port(port, proto, ver=4):
3208+ '''Check if something is listening on the specified port.
3209+ WARNING: for some reason this does not work with a bind mounted /proc
3210+ '''
3211+ assert (port >= 1)
3212+ assert (port <= 65535)
3213+ assert (proto.lower() == "tcp" or proto.lower() == "udp")
3214+ assert (ver == 4 or ver == 6)
3215+
3216+ fn = "/proc/net/%s" % (proto)
3217+ if ver == 6:
3218+ fn += str(ver)
3219+
3220+ rc, report = cmd(['cat', fn])
3221+ assert (rc == 0)
3222+
3223+ hport = "%0.4x" % port
3224+
3225+ if re.search(': [0-9a-f]{8}:%s [0-9a-f]' % str(hport).lower(), report.lower()):
3226+ return True
3227+ return False
3228+
3229+
3230+def get_arch():
3231+ '''Get the current architecture'''
3232+ rc, report = cmd(['uname', '-m'])
3233+ assert (rc == 0)
3234+ return report.strip()
3235+
3236+
3237+def get_multiarch_tuple():
3238+ '''Get the current debian multiarch tuple'''
3239+
3240+ # XXX dpkg-architecture on Ubuntu 12.04 requires -q be adjacent to
3241+ # the variable name
3242+ rc, report = cmd(['dpkg-architecture', '-qDEB_HOST_MULTIARCH'])
3243+ assert (rc == 0)
3244+ return report.strip()
3245+
3246+
3247+def get_bits():
3248+ '''return the default architecture number of bits (32 or 64, usually)'''
3249+ return platform.architecture()[0][0:2]
3250+
3251+
3252+def get_memory():
3253+ '''Gets total ram and swap'''
3254+ meminfo = "/proc/meminfo"
3255+ memtotal = 0
3256+ swaptotal = 0
3257+ if not os.path.exists(meminfo):
3258+ return (False, False)
3259+
3260+ try:
3261+ fd = open(meminfo, 'r')
3262+ for line in fd.readlines():
3263+ splitline = line.split()
3264+ if splitline[0] == 'MemTotal:':
3265+ memtotal = int(splitline[1])
3266+ elif splitline[0] == 'SwapTotal:':
3267+ swaptotal = int(splitline[1])
3268+ fd.close()
3269+ except:
3270+ return (False, False)
3271+
3272+ return (memtotal, swaptotal)
3273+
3274+
3275+def is_running_in_vm():
3276+ '''Check if running under a VM'''
3277+ # add other virtualization environments here
3278+ for search in ['QEMU Virtual CPU']:
3279+ rc, report = cmd_pipe(['dmesg'], ['grep', search])
3280+ if rc == 0:
3281+ return True
3282+ return False
3283+
3284+
3285+def ubuntu_release():
3286+ '''Get the Ubuntu release'''
3287+ f = "/etc/lsb-release"
3288+ try:
3289+ size = os.stat(f)[ST_SIZE]
3290+ except:
3291+ return "UNKNOWN"
3292+
3293+ if size > 1024 * 1024:
3294+ raise IOError('Could not open "%s" (too big)' % f)
3295+
3296+ with open("/etc/lsb-release", 'r') as fh:
3297+ lines = fh.readlines()
3298+
3299+ pat = re.compile(r'DISTRIB_CODENAME')
3300+ for line in lines:
3301+ if pat.search(line):
3302+ return line.split('=')[1].rstrip('\n').rstrip('\r')
3303+
3304+ return "UNKNOWN"
3305+
3306+
3307+def cmd(command, input=None, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, stdin=None, timeout=None, env=None, shell=False, text=True):
3308+ '''Try to execute given command (array) and return its stdout, or return
3309+ a textual error if it failed.'''
3310+
3311+ try:
3312+ sp = subprocess.Popen(command, stdin=stdin, stdout=stdout, stderr=stderr, close_fds=True, preexec_fn=subprocess_setup, env=env, universal_newlines=text, shell=shell)
3313+ if sys.version_info[0] >= 3 and sys.version_info[1] > 3:
3314+ out, outerr = sp.communicate(input, timeout=timeout)
3315+ else:
3316+ out, outerr = sp.communicate(input)
3317+ except OSError as e:
3318+ return [127, str(e)]
3319+
3320+ # Handle redirection of stdout
3321+ if out is None:
3322+ out = ''
3323+ # Handle redirection of stderr
3324+ if outerr is None:
3325+ outerr = ''
3326+ if text == False:
3327+ out = str(out)
3328+ return [sp.returncode, out + outerr]
3329+
3330+
3331+def cmd_pipe(command1, command2, input=None, stderr=subprocess.STDOUT, stdin=None):
3332+ '''Try to pipe command1 into command2.'''
3333+ try:
3334+ sp1 = subprocess.Popen(command1, stdin=stdin, stdout=subprocess.PIPE, stderr=stderr, close_fds=True)
3335+ sp2 = subprocess.Popen(command2, stdin=sp1.stdout, stdout=subprocess.PIPE, stderr=stderr, close_fds=True, universal_newlines=True)
3336+ except OSError as e:
3337+ return [127, str(e)]
3338+
3339+ out = sp2.communicate(input)[0]
3340+ # ensure we don't leak open files and that sp1 is stopped
3341+ sp1.stdout.close()
3342+ sp1.wait()
3343+ return [sp2.returncode, out]
3344+
3345+
3346+def cwd_has_enough_space(cdir, total_bytes):
3347+ '''Determine if the partition of the current working directory has 'bytes'
3348+ free.'''
3349+ rc, df_output = cmd(['df'])
3350+ if rc != 0:
3351+ result = 'df failed, got exit code %d, expected %d\n' % (rc, 0)
3352+ raise OSError(result)
3353+ if rc != 0:
3354+ return False
3355+
3356+ kb = total_bytes / 1024
3357+
3358+ mounts = dict()
3359+ for line in df_output.splitlines():
3360+ if '/' not in line:
3361+ continue
3362+ tmp = line.split()
3363+ mounts[tmp[5]] = int(tmp[3])
3364+
3365+ cdir = os.getcwd()
3366+ while cdir != '/':
3367+ if cdir not in mounts:
3368+ cdir = os.path.dirname(cdir)
3369+ continue
3370+ return kb < mounts[cdir]
3371+
3372+ return kb < mounts['/']
3373+
3374+
3375+def get_md5(filename):
3376+ '''Gets the md5sum of the file specified'''
3377+
3378+ (rc, report) = cmd(["/usr/bin/md5sum", "-b", filename])
3379+ expected = 0
3380+ assert (expected == rc)
3381+
3382+ return report.split(' ')[0]
3383+
3384+
3385+def dpkg_compare_installed_version(pkg, check, version):
3386+ '''Gets the version for the installed package, and compares it to the
3387+ specified version.
3388+ '''
3389+ (rc, report) = cmd(["/usr/bin/dpkg", "-s", pkg])
3390+ assert (rc == 0)
3391+ assert ("Status: install ok installed" in report)
3392+ installed_version = ""
3393+ for line in report.splitlines():
3394+ if line.startswith("Version: "):
3395+ installed_version = line.split()[1]
3396+
3397+ assert (installed_version != "")
3398+
3399+ (rc, report) = cmd(["/usr/bin/dpkg", "--compare-versions", installed_version, check, version])
3400+ assert (rc == 0 or rc == 1)
3401+ if rc == 0:
3402+ return True
3403+ return False
3404+
3405+
3406+def _run_apt_command(pkg_list, apt_cmd='install'):
3407+ env = os.environ.copy()
3408+ env['DEBIAN_FRONTEND'] = 'noninteractive'
3409+ # debugging version, but on precise doesn't actually run dpkg
3410+ # command = ['apt-get', '-y', '--force-yes', '-o', 'Dpkg::Options::=--force-confold', '-o', 'Debug::pkgDPkgPM=true', apt_cmd]
3411+ command = ['apt-get', '-y', '--force-yes', '-o', 'Dpkg::Options::=--force-confold', apt_cmd]
3412+ command.extend(pkg_list)
3413+ rc, report = cmd(command)
3414+ return rc, report
3415+
3416+
3417+# note: for the following install_* functions, you probably want the
3418+# versions in the TestlibCase class (see below)
3419+def install_builddeps(src_pkg):
3420+ rc, report = _run_apt_command([src_pkg], 'build-dep')
3421+ assert(rc == 0)
3422+
3423+
3424+def install_package(package):
3425+ rc, report = _run_apt_command([package], 'install')
3426+ assert(rc == 0)
3427+
3428+
3429+def install_packages(pkg_list):
3430+ rc, report = _run_apt_command(pkg_list, 'install')
3431+ assert(rc == 0)
3432+
3433+
3434+def prepare_source(source, builder, cached_src, build_src, patch_system):
3435+ '''Download and unpack source package, installing necessary build depends,
3436+ adjusting the permissions for the 'builder' user, and returning the
3437+ directory of the unpacked source. Patch system can be one of:
3438+ - cdbs
3439+ - dpatch
3440+ - quilt
3441+ - quiltv3
3442+ - None (not the string)
3443+
3444+ This is normally used like this:
3445+
3446+ def setUp(self):
3447+ ...
3448+ self.topdir = os.getcwd()
3449+ self.cached_src = os.path.join(os.getcwd(), "source")
3450+ self.tmpdir = tempfile.mkdtemp(prefix='testlib', dir='/tmp')
3451+ self.builder = testlib.TestUser()
3452+ testlib.cmd(['chgrp', self.builder.login, self.tmpdir])
3453+ os.chmod(self.tmpdir, 0o775)
3454+
3455+ def tearDown(self):
3456+ ...
3457+ self.builder = None
3458+ self.topdir = os.getcwd()
3459+ if os.path.exists(self.tmpdir):
3460+ testlib.recursive_rm(self.tmpdir)
3461+
3462+ def test_suite_build(self):
3463+ ...
3464+ build_dir = testlib.prepare_source('foo', \
3465+ self.builder, \
3466+ self.cached_src, \
3467+ os.path.join(self.tmpdir, \
3468+ os.path.basename(self.cached_src)),
3469+ "quilt")
3470+ os.chdir(build_dir)
3471+
3472+ # Example for typical build, adjust as necessary
3473+ print("")
3474+ print(" make clean")
3475+ rc, report = testlib.cmd(['sudo', '-u', self.builder.login, 'make', 'clean'])
3476+
3477+ print(" configure")
3478+ rc, report = testlib.cmd(['sudo', '-u', self.builder.login, './configure', '--prefix=%s' % self.tmpdir, '--enable-debug'])
3479+
3480+ print(" make (will take a while)")
3481+ rc, report = testlib.cmd(['sudo', '-u', self.builder.login, 'make'])
3482+
3483+ print(" make check (will take a while)",)
3484+ rc, report = testlib.cmd(['sudo', '-u', self.builder.login, 'make', 'check'])
3485+ expected = 0
3486+ result = 'Got exit code %d, expected %d\n' % (rc, expected)
3487+ self.assertEqual(expected, rc, result + report)
3488+
3489+ def test_suite_cleanup(self):
3490+ ...
3491+ if os.path.exists(self.cached_src):
3492+ testlib.recursive_rm(self.cached_src)
3493+
3494+ It is up to the caller to clean up cached_src and build_src (as in the
3495+ above example, often the build_src is in a tmpdir that is cleaned in
3496+ tearDown() and the cached_src is cleaned in a one time clean-up
3497+ operation (eg 'test_suite_cleanup()) which must be run after the build
3498+ suite test (obviously).
3499+ '''
3500+
3501+ # Make sure we have a clean slate
3502+ assert (os.path.exists(os.path.dirname(build_src)))
3503+ assert (not os.path.exists(build_src))
3504+
3505+ cdir = os.getcwd()
3506+ if os.path.exists(cached_src):
3507+ shutil.copytree(cached_src, build_src)
3508+ os.chdir(build_src)
3509+ else:
3510+ # Only install the build dependencies on the initial setup
3511+ install_builddeps(source)
3512+ os.makedirs(build_src)
3513+ os.chdir(build_src)
3514+
3515+ # These are always needed
3516+ pkgs = ['build-essential', 'dpkg-dev', 'fakeroot']
3517+ install_packages(pkgs)
3518+
3519+ rc, report = cmd(['apt-get', 'source', source])
3520+ assert (rc == 0)
3521+ shutil.copytree(build_src, cached_src)
3522+ print("(unpacked %s)" % os.path.basename(glob.glob('%s_*.dsc' % source)[0]), end=' ')
3523+
3524+ unpacked_dir = os.path.join(build_src, glob.glob('%s-*' % source)[0])
3525+
3526+ # Now apply the patches. Do it here so that we don't mess up our cached
3527+ # sources.
3528+ os.chdir(unpacked_dir)
3529+ assert (patch_system in ['cdbs', 'dpatch', 'quilt', 'quiltv3', None])
3530+ if patch_system is not None and patch_system != "quiltv3":
3531+ if patch_system == "quilt":
3532+ os.environ.setdefault('QUILT_PATCHES', 'debian/patches')
3533+ rc, report = cmd(['quilt', 'push', '-a'])
3534+ assert (rc == 0)
3535+ elif patch_system == "cdbs":
3536+ rc, report = cmd(['./debian/rules', 'apply-patches'])
3537+ assert (rc == 0)
3538+ elif patch_system == "dpatch":
3539+ rc, report = cmd(['dpatch', 'apply-all'])
3540+ assert (rc == 0)
3541+
3542+ cmd(['chown', '-R', '%s:%s' % (builder.uid, builder.gid), build_src])
3543+ os.chdir(cdir)
3544+
3545+ return unpacked_dir
3546+
3547+
3548+def get_changelog_version(source_dir):
3549+ '''Extract a package version from a changelog'''
3550+ package_version = ""
3551+
3552+ changelog_file = os.path.join(source_dir, "debian/changelog")
3553+
3554+ if os.path.exists(changelog_file):
3555+ changelog = open(changelog_file, 'r')
3556+ header = changelog.readline().split()
3557+ package_version = header[1].strip('()')
3558+
3559+ return package_version
3560+
3561+
3562+def _aa_status():
3563+ '''Get aa-status output'''
3564+ exe = "/usr/sbin/aa-status"
3565+ assert (os.path.exists(exe))
3566+ if os.geteuid() == 0:
3567+ return cmd([exe])
3568+ return cmd(['sudo', exe])
3569+
3570+
3571+def is_apparmor_loaded(path):
3572+ '''Check if profile is loaded'''
3573+ rc, report = _aa_status()
3574+ if rc != 0:
3575+ return False
3576+
3577+ for line in report.splitlines():
3578+ if line.endswith(path):
3579+ return True
3580+ return False
3581+
3582+
3583+def is_apparmor_confined(path):
3584+ '''Check if application is confined'''
3585+ rc, report = _aa_status()
3586+ if rc != 0:
3587+ return False
3588+
3589+ for line in report.splitlines():
3590+ if re.search('%s \(' % path, line):
3591+ return True
3592+ return False
3593+
3594+
3595+def check_apparmor(path, first_ubuntu_release, is_running=True):
3596+ '''Check if path is loaded and confined for everything higher than the
3597+ first Ubuntu release specified.
3598+
3599+ Usage:
3600+ rc, report = testlib.check_apparmor('/usr/sbin/foo', 8.04, is_running=True)
3601+ if rc < 0:
3602+ return self._skipped(report)
3603+
3604+ expected = 0
3605+ result = 'Got exit code %d, expected %d\n' % (rc, expected)
3606+ self.assertEqual(expected, rc, result + report)
3607+ '''
3608+ global manager
3609+ rc = -1
3610+
3611+ if manager.lsb_release["Release"] < first_ubuntu_release:
3612+ return (rc, "Skipped apparmor check")
3613+
3614+ if not os.path.exists('/sbin/apparmor_parser'):
3615+ return (rc, "Skipped (couldn't find apparmor_parser)")
3616+
3617+ rc = 0
3618+ msg = ""
3619+ if not is_apparmor_loaded(path):
3620+ rc = 1
3621+ msg = "Profile not loaded for '%s'" % path
3622+
3623+ # this check only makes sense it the 'path' is currently executing
3624+ if is_running and rc == 0 and not is_apparmor_confined(path):
3625+ rc = 1
3626+ msg = "'%s' is not running in enforce mode" % path
3627+
3628+ return (rc, msg)
3629+
3630+
3631+def get_gcc_version(gcc, full=True):
3632+ gcc_version = 'none'
3633+ if not gcc.startswith('/'):
3634+ gcc = '/usr/bin/%s' % (gcc)
3635+ if os.path.exists(gcc):
3636+ gcc_version = 'unknown'
3637+ lines = cmd([gcc, '-v'])[1].strip().splitlines()
3638+ version_lines = [x for x in lines if x.startswith('gcc version')]
3639+ if len(version_lines) == 1:
3640+ gcc_version = " ".join(version_lines[0].split()[2:])
3641+ if not full:
3642+ return gcc_version.split()[0]
3643+ return gcc_version
3644+
3645+
3646+def is_kdeinit_running():
3647+ '''Test if kdeinit is running'''
3648+ # applications that use kdeinit will spawn it if it isn't running in the
3649+ # test. This is a problem because it does not exit. This is a helper to
3650+ # check for it.
3651+ rc, report = cmd(['ps', 'x'])
3652+ if 'kdeinit4 Running' not in report:
3653+ print("kdeinit not running (you may start/stop any KDE application then run this script again)", file=sys.stderr)
3654+ return False
3655+ return True
3656+
3657+
3658+def get_pkgconfig_flags(libs=[]):
3659+ '''Find pkg-config flags for libraries'''
3660+ assert (len(libs) > 0)
3661+ rc, pkg_config = cmd(['pkg-config', '--cflags', '--libs'] + libs)
3662+ expected = 0
3663+ if rc != expected:
3664+ print('Got exit code %d, expected %d\n' % (rc, expected), file=sys.stderr)
3665+ assert(rc == expected)
3666+ return pkg_config.split()
3667+
3668+
3669+def cap_to_name(cap_num):
3670+ '''given an integer, return the capability name'''
3671+ rc, output = cmd(['capsh', '--decode=%x' % cap_num])
3672+ expected = 0
3673+ if rc != expected:
3674+ print('capsh: got exit code %d, expected %d\n' % (rc, expected), file=sys.stderr)
3675+ cap_name = output.strip().split('=')[1]
3676+ return cap_name
3677+
3678+
3679+def enumerate_capabilities():
3680+ i = 0
3681+ cap_list = []
3682+ done = False
3683+ while not done:
3684+ cap_name = cap_to_name(pow(2, i))
3685+ if cap_name == str(i):
3686+ done = True
3687+ else:
3688+ cap_list.append(cap_name)
3689+ i += 1
3690+ if i > 64:
3691+ done = True
3692+ return cap_list
3693+
3694+
3695+def _run_snap_install(snapname, track="latest/stable", classic=False):
3696+ # crude, but effective
3697+ if os.path.exists(os.path.join("/snap", snapname)):
3698+ return 0, ""
3699+
3700+ command = ["snap", "install", "--channel=%s" % track, snapname]
3701+ if classic:
3702+ command.append("--classic")
3703+ rc, report = cmd(command)
3704+ return rc, report
3705+
3706+
3707+def _run_snap_remove(snapname):
3708+ # crude, but effective
3709+ if not os.path.exists(os.path.join("/snap", snapname)):
3710+ return 0, ""
3711+
3712+ command = ["snap", "remove", "--purge", snapname]
3713+ rc, report = cmd(command)
3714+ return rc, report
3715+
3716+
3717+def install_snap(self, snapname, track="latest/stable", classic=False):
3718+ rc, report = _run_snap_install(snapname, track, classic)
3719+ self.assertEqual(0, rc, "Failed to install snap %s\nOutput:\n%s" %
3720+ (snapname, report))
3721+
3722+
3723+def remove_snap(self, snapname):
3724+ rc, report = _run_snap_remove(snapname)
3725+ self.assertEqual(0, rc, "Failed to install snap %s\nOutput:\n%s" %
3726+ (snapname, report))
3727+
3728+
3729+class TestDaemon:
3730+ '''Helper class to manage daemons consistently'''
3731+ def __init__(self, service_name):
3732+ '''Setup daemon attributes'''
3733+ if os.path.isfile('/usr/sbin/service') or os.path.islink('/usr/sbin/service'):
3734+ self.test_daemon_commands = ['service', service_name]
3735+ else:
3736+ self.test_daemon_commands = ['/etc/init.d/' + service_name]
3737+
3738+ def _run_command(self, action, seconds_to_wait=2):
3739+ command = list(self.test_daemon_commands)
3740+ command.append(action)
3741+ rc, report = cmd(command)
3742+ expected = 0
3743+ result = 'Got exit code %d, expected %d\n' % (rc, expected)
3744+ time.sleep(seconds_to_wait)
3745+ if expected != rc:
3746+ return False, result + report
3747+
3748+ if "fail" in report:
3749+ return False, "Found 'fail' in report\n" + report
3750+
3751+ return True, ""
3752+
3753+ def start(self):
3754+ '''Start daemon'''
3755+ return self._run_command('start')
3756+
3757+ def stop(self):
3758+ '''Stop daemon'''
3759+ return self._run_command('stop')
3760+
3761+ def reload(self):
3762+ '''Reload daemon'''
3763+ return self._run_command('force-reload')
3764+
3765+ def restart(self):
3766+ if self.test_daemon_commands[0] == 'service':
3767+ return self._run_command('restart')
3768+ else:
3769+ '''Restart daemon'''
3770+ (res, str) = self.stop()
3771+ if not res:
3772+ return res, str
3773+
3774+ (res, str) = self.start()
3775+ if not res:
3776+ return res, str
3777+
3778+ return True, ""
3779+
3780+ def force_restart(self):
3781+ '''Restart daemon even if already stopped'''
3782+ self.stop()
3783+
3784+ (res, str) = self.start()
3785+ if not res:
3786+ return res, str
3787+
3788+ return True, ""
3789+
3790+ def status(self):
3791+ '''Check daemon status'''
3792+ return self._run_command('status')
3793+
3794+
3795+class TestlibManager(object):
3796+ '''Singleton class used to set up per-test-run information'''
3797+ def __init__(self):
3798+ # Set glibc aborts to dump to stderr instead of the tty so test output
3799+ # is more sane.
3800+ os.environ.setdefault('LIBC_FATAL_STDERR_', '1')
3801+
3802+ # check verbosity
3803+ self.verbosity = False
3804+ if (len(sys.argv) > 1 and '-v' in sys.argv[1:]):
3805+ self.verbosity = True
3806+
3807+ # Load LSB release file
3808+ self.lsb_release = dict()
3809+ if not os.path.exists('/usr/bin/lsb_release') and not os.path.exists('/bin/lsb_release'):
3810+ raise OSError("Please install 'lsb-release'")
3811+ for line in subprocess.Popen(['lsb_release', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True).communicate()[0].splitlines():
3812+ field, value = line.split(':', 1)
3813+ value = value.strip()
3814+ field = field.strip()
3815+ # Convert numerics
3816+ try:
3817+ value = float(value)
3818+ except:
3819+ pass
3820+ self.lsb_release.setdefault(field, value)
3821+
3822+ # FIXME: hack OEM releases into known-Ubuntu versions
3823+ if self.lsb_release['Distributor ID'] == "HP MIE (Mobile Internet Experience)":
3824+ if self.lsb_release['Release'] == 1.0:
3825+ self.lsb_release['Distributor ID'] = "Ubuntu"
3826+ self.lsb_release['Release'] = 8.04
3827+ else:
3828+ raise OSError("Unknown version of HP MIE")
3829+
3830+ # FIXME: hack to assume a most-recent release if we're not
3831+ # running under Ubuntu.
3832+ if self.lsb_release['Distributor ID'] not in ["Ubuntu", "Linaro"]:
3833+ self.lsb_release['Release'] = 10000
3834+ # Adjust Linaro release to pretend to be Ubuntu
3835+ if self.lsb_release['Distributor ID'] in ["Linaro"]:
3836+ self.lsb_release['Distributor ID'] = "Ubuntu"
3837+ self.lsb_release['Release'] -= 0.01
3838+
3839+ # Load arch
3840+ if not os.path.exists('/usr/bin/dpkg'):
3841+ machine = cmd(['uname', '-m'])[1].strip()
3842+ if machine.endswith('86'):
3843+ self.dpkg_arch = 'i386'
3844+ elif machine.endswith('_64'):
3845+ self.dpkg_arch = 'amd64'
3846+ elif machine.startswith('arm'):
3847+ self.dpkg_arch = 'armel'
3848+ else:
3849+ raise ValueError("Unknown machine type '%s'" % (machine))
3850+ else:
3851+ self.dpkg_arch = cmd(['dpkg', '--print-architecture'])[1].strip()
3852+
3853+ # Find kernel version
3854+ self.kernel_is_ubuntu = False
3855+ self.kernel_version_signature = None
3856+ self.kernel_version = cmd(["uname", "-r"])[1].strip()
3857+ versig = '/proc/version_signature'
3858+ if os.path.exists(versig):
3859+ self.kernel_is_ubuntu = True
3860+ self.kernel_version_signature = open(versig).read().strip()
3861+ self.kernel_version_ubuntu = self.kernel_version
3862+ elif os.path.exists('/usr/bin/dpkg'):
3863+ # this can easily be inaccurate but is only an issue for Dapper
3864+ rc, out = cmd(['dpkg', '-l', 'linux-image-%s' % (self.kernel_version)])
3865+ if rc == 0:
3866+ self.kernel_version_signature = out.strip().split('\n').pop().split()[2]
3867+ self.kernel_version_ubuntu = self.kernel_version_signature
3868+ if self.kernel_version_signature is None:
3869+ # Attempt to fall back to something for non-Debian-based
3870+ self.kernel_version_signature = self.kernel_version
3871+ self.kernel_version_ubuntu = self.kernel_version
3872+ # Build ubuntu version without hardware suffix
3873+ try:
3874+ self.kernel_version_ubuntu = "-".join([x for x in self.kernel_version_signature.split(' ')[1].split('-') if re.search('^[0-9]', x)])
3875+ except:
3876+ pass
3877+
3878+ # Find gcc version
3879+ self.gcc_version = get_gcc_version('gcc')
3880+
3881+ # Find libc
3882+ self.path_libc = [x.split()[2] for x in cmd(['ldd', '/bin/ls'])[1].splitlines() if x.startswith('\tlibc.so.')][0]
3883+
3884+ # Report self
3885+ if self.verbosity:
3886+ kernel = self.kernel_version_ubuntu
3887+ if kernel != self.kernel_version_signature:
3888+ kernel += " (%s)" % (self.kernel_version_signature)
3889+ print("Running test: '%s' distro: '%s %.2f' kernel: '%s' arch: '%s' uid: %d/%d SUDO_USER: '%s')" % (
3890+ sys.argv[0],
3891+ self.lsb_release['Distributor ID'],
3892+ self.lsb_release['Release'],
3893+ kernel,
3894+ self.dpkg_arch,
3895+ os.geteuid(), os.getuid(),
3896+ os.environ.get('SUDO_USER', '')), file=sys.stdout)
3897+ sys.stdout.flush()
3898+
3899+ # Additional heuristics
3900+ # if os.environ.get('SUDO_USER', os.environ.get('USER', '')) in ['mdeslaur']:
3901+ # sys.stdout.write("Replying to Marc Deslauriers in http://launchpad.net/bugs/%d: " % random.randint(600000, 980000))
3902+ # sys.stdout.flush()
3903+ # time.sleep(0.5)
3904+ # sys.stdout.write("destroyed\n")
3905+ # time.sleep(0.5)
3906+
3907+ def hello(self, msg):
3908+ print("Hello from %s" % (msg), file=sys.stderr)
3909+# The central instance
3910+manager = TestlibManager()
3911+
3912+
3913+class TestlibCase(unittest.TestCase):
3914+ def __init__(self, *args):
3915+ '''This is called for each TestCase test instance, which isn't much better
3916+ than SetUp.'''
3917+
3918+ unittest.TestCase.__init__(self, *args)
3919+
3920+ # Attach to and duplicate dicts from manager singleton
3921+ self.manager = manager
3922+ # self.manager.hello(repr(self) + repr(*args))
3923+ self.my_verbosity = self.manager.verbosity
3924+ self.lsb_release = self.manager.lsb_release
3925+ self.dpkg_arch = self.manager.dpkg_arch
3926+ self.kernel_version = self.manager.kernel_version
3927+ self.kernel_version_signature = self.manager.kernel_version_signature
3928+ self.kernel_version_ubuntu = self.manager.kernel_version_ubuntu
3929+ self.kernel_is_ubuntu = self.manager.kernel_is_ubuntu
3930+ self.gcc_version = self.manager.gcc_version
3931+ self.path_libc = self.manager.path_libc
3932+
3933+ def version_compare(self, one, two):
3934+ if 'version_compare' in dir(apt_pkg):
3935+ return apt_pkg.version_compare(one, two)
3936+ else:
3937+ return apt_pkg.VersionCompare(one, two)
3938+
3939+ def assertFileType(self, filename, filetype, strict=True):
3940+ '''Checks the file type of the file specified'''
3941+
3942+ (rc, report, out) = self._testlib_shell_cmd(["/usr/bin/file", "-b", filename])
3943+ out = out.strip()
3944+ expected = 0
3945+ # Absolutely no idea why this happens on Hardy
3946+ if self.lsb_release['Release'] == 8.04 and rc == 255 and len(out) > 0:
3947+ rc = 0
3948+ result = 'Got exit code %d, expected %d:\n%s\n' % (rc, expected, report)
3949+ self.assertEqual(expected, rc, result)
3950+
3951+ if strict:
3952+ filetype = '^%s$' % (filetype)
3953+ else:
3954+ # accept if the beginning of the line matches
3955+ filetype = '^%s' % (filetype)
3956+ result = 'File type reported by file: [%s], expected regex: [%s]\n' % (out, filetype)
3957+ self.assertNotEqual(None, re.search(filetype, out), result)
3958+
3959+ def yank_commonname_from_cert(self, certfile):
3960+ '''Extract the commonName from a given PEM'''
3961+ rc, out = cmd(['openssl', 'asn1parse', '-in', certfile])
3962+ if rc == 0:
3963+ ready = False
3964+ for line in out.splitlines():
3965+ if ready:
3966+ return line.split(':')[-1]
3967+ if ':commonName' in line:
3968+ ready = True
3969+ return socket.getfqdn()
3970+
3971+ def announce(self, text):
3972+ if self.my_verbosity:
3973+ print("(%s) " % (text), file=sys.stderr, end='')
3974+ sys.stdout.flush()
3975+
3976+ def make_clean(self):
3977+ rc, output = self.shell_cmd(['make', 'clean'])
3978+ self.assertEqual(rc, 0, output)
3979+
3980+ def get_makefile_compiler(self):
3981+ # Find potential compiler name
3982+ compiler = 'gcc'
3983+ if os.path.exists('Makefile'):
3984+ for line in open('Makefile'):
3985+ if line.startswith('CC') and '=' in line:
3986+ items = [x.strip() for x in line.split('=')]
3987+ if items[0] == 'CC':
3988+ compiler = items[1]
3989+ break
3990+ return compiler
3991+
3992+ def make_target(self, target, expected=0):
3993+ '''Compile a target and report output'''
3994+
3995+ compiler = self.get_makefile_compiler()
3996+ rc, output = self.shell_cmd(['make', target])
3997+ self.assertEqual(rc, expected, 'rc(%d)!=%d:\n' % (rc, expected) + output)
3998+ self.assertTrue('%s ' % (compiler) in output, 'Expected "%s":' % (compiler) + output)
3999+ return output
4000+
4001+ # call as return testlib.skipped()
4002+ def _skipped(self, reason=""):
4003+ '''Provide a visible way to indicate that a test was skipped'''
4004+ if reason != "":
4005+ reason = ': %s' % (reason)
4006+ self.announce("skipped%s" % (reason))
4007+ return False
4008+
4009+ def _testlib_shell_cmd(self, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=None):
4010+ argstr = "'" + "', '".join(args).strip() + "'"
4011+ rc, out = cmd(args, stdin=stdin, stdout=stdout, stderr=stderr, env=env)
4012+ report = 'Command: ' + argstr + '\nOutput:\n' + out
4013+ return rc, report, out
4014+
4015+ def shell_cmd(self, args, stdin=None):
4016+ return cmd(args, stdin=stdin)
4017+
4018+ def assertShellExitEquals(self, expected, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=None, msg="", bare_report=False):
4019+ '''Test a shell command matches a specific exit code'''
4020+ rc, report, out = self._testlib_shell_cmd(args, stdin=stdin, stdout=stdout, stderr=stderr, env=env)
4021+ result = 'Got exit code %d, expected %d\n' % (rc, expected)
4022+ self.assertEqual(expected, rc, msg + result + report)
4023+ if bare_report:
4024+ return out
4025+ else:
4026+ return report
4027+
4028+ def assertShellExitSuccess(self, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=None, msg="", bare_report=False):
4029+ '''Same as assertShellEquals but with an expected exit status of 0 (success).'''
4030+ return self.assertShellExitEquals(0, args, stdin, stdout, stderr, env, msg, bare_report)
4031+
4032+ # make sure exit value is in a list of expected values
4033+ def assertShellExitIn(self, expected, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, msg=""):
4034+ '''Test a shell command matches a specific exit code'''
4035+ rc, report, out = self._testlib_shell_cmd(args, stdin=stdin, stdout=stdout, stderr=stderr)
4036+ result = 'Got exit code %d, expected one of %s\n' % (rc, ', '.join(map(str, expected)))
4037+ self.assertIn(rc, expected, msg + result + report)
4038+
4039+ def assertShellExitNotEquals(self, unwanted, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, msg=""):
4040+ '''Test a shell command doesn't match a specific exit code'''
4041+ rc, report, out = self._testlib_shell_cmd(args, stdin=stdin, stdout=stdout, stderr=stderr)
4042+ result = 'Got (unwanted) exit code %d\n' % rc
4043+ self.assertNotEqual(unwanted, rc, msg + result + report)
4044+
4045+ def assertShellOutputContains(self, text, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, msg="", invert=False, expected=None):
4046+ '''Test a shell command contains a specific output'''
4047+ rc, report, out = self._testlib_shell_cmd(args, stdin=stdin, stdout=stdout, stderr=stderr)
4048+ result = 'Got exit code %d. Looking for text "%s"\n' % (rc, text)
4049+ if not invert:
4050+ self.assertTrue(text in out, msg + result + report)
4051+ else:
4052+ self.assertFalse(text in out, msg + result + report)
4053+ if expected is not None:
4054+ result = 'Got exit code %d. Expected %d (%s)\n' % (rc, expected, " ".join(args))
4055+ self.assertEqual(rc, expected, msg + result + report)
4056+
4057+ def assertShellOutputEquals(self, text, args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, msg="", invert=False, expected=None):
4058+ '''Test a shell command matches a specific output'''
4059+ rc, report, out = self._testlib_shell_cmd(args, stdin=stdin, stdout=stdout, stderr=stderr)
4060+ result = 'Got exit code %d. Looking for exact text "%s" (%s)\n' % (rc, text, " ".join(args))
4061+ if not invert:
4062+ self.assertEqual(text, out, msg + result + report)
4063+ else:
4064+ self.assertNotEqual(text, out, msg + result + report)
4065+ if expected is not None:
4066+ result = 'Got exit code %d. Expected %d (%s)\n' % (rc, expected, " ".join(args))
4067+ self.assertEqual(rc, expected, msg + result + report)
4068+
4069+ def _word_find(self, report, content, invert=False):
4070+ '''Check for a specific string'''
4071+ if invert:
4072+ warning = 'Found "%s"\n' % content
4073+ self.assertTrue(content not in report, warning + report)
4074+ else:
4075+ warning = 'Could not find "%s"\n' % content
4076+ self.assertTrue(content in report, warning + report)
4077+
4078+ def _test_sysctl_value(self, path, expected, msg=None, exists=True):
4079+ sysctl = '/proc/sys/%s' % (path)
4080+ self.assertEqual(exists, os.path.exists(sysctl), sysctl)
4081+ value = None
4082+ if exists:
4083+ with open(sysctl) as sysctl_fd:
4084+ value = int(sysctl_fd.read())
4085+ report = "%s is not %d: %d" % (sysctl, expected, value)
4086+ if msg:
4087+ report += " (%s)" % (msg)
4088+ self.assertEqual(value, expected, report)
4089+ return value
4090+
4091+ def set_sysctl_value(self, path, desired):
4092+ sysctl = '/proc/sys/%s' % (path)
4093+ self.assertTrue(os.path.exists(sysctl), "%s does not exist" % (sysctl))
4094+ with open(sysctl, 'w') as sysctl_fh:
4095+ sysctl_fh.write(str(desired))
4096+ self._test_sysctl_value(path, desired)
4097+
4098+ def kernel_at_least(self, introduced):
4099+ return self.version_compare(self.kernel_version_ubuntu,
4100+ introduced) >= 0
4101+
4102+ def kernel_claims_cve_fixed(self, cve):
4103+ changelog = "/usr/share/doc/linux-image-%s/changelog.Debian.gz" % (self.kernel_version)
4104+ if os.path.exists(changelog):
4105+ for line in gzip.open(changelog):
4106+ if cve in line and "revert" not in line and "Revert" not in line:
4107+ return True
4108+ return False
4109+
4110+ def install_builddeps(self, src_pkg):
4111+ rc, report = _run_apt_command([src_pkg], 'build-dep')
4112+ self.assertEqual(0, rc, 'Failed to install build-deps for %s\nOutput:\n%s' % (src_pkg, report))
4113+
4114+ def install_package(self, package):
4115+ rc, report = _run_apt_command([package], 'install')
4116+ self.assertEqual(0, rc, 'Failed to install package %s\nOutput:\n%s' % (package, report))
4117+
4118+ def install_packages(self, pkg_list):
4119+ rc, report = _run_apt_command(pkg_list, 'install')
4120+ self.assertEqual(0, rc, 'Failed to install packages %s\nOutput:\n%s' % (','.join(pkg_list), report))
4121+
4122+ def install_snap(self, snapname, track="latest/stable", classic=False):
4123+ rc, report = _run_snap_install(snapname, track, classic)
4124+ self.assertEqual(0, rc, "Failed to install snap %s\nOutput:\n%s" %
4125+ (snapname, report))
4126+
4127+ def remove_snap(self, snapname):
4128+ rc, report = _run_snap_remove(snapname)
4129+ self.assertEqual(0, rc, "Failed to install snap %s\nOutput:\n%s" %
4130+ (snapname, report))
4131+
4132+
4133+class TestGroup:
4134+ '''Create a temporary test group and remove it again in the dtor.'''
4135+
4136+ def __init__(self, group=None, lower=False):
4137+ '''Create a new group'''
4138+
4139+ self.group = None
4140+ if group:
4141+ if group_exists(group):
4142+ raise ValueError('group name already exists')
4143+ else:
4144+ while(True):
4145+ group = random_string(7, lower=lower)
4146+ if not group_exists(group):
4147+ break
4148+
4149+ assert subprocess.call(['groupadd', group]) == 0
4150+ self.group = group
4151+ g = grp.getgrnam(self.group)
4152+ self.gid = g[2]
4153+
4154+ def __del__(self):
4155+ '''Remove the created group.'''
4156+
4157+ if self.group:
4158+ rc, report = cmd(['groupdel', self.group])
4159+ assert rc == 0
4160+
4161+
4162+class TestUser:
4163+ '''Create a temporary test user and remove it again in the dtor.'''
4164+
4165+ def __init__(self, login=None, home=True, group=None, uidmin=None, lower=False, shell=None):
4166+ '''Create a new user account with a random password.
4167+
4168+ By default, the login name is random, too, but can be explicitly
4169+ specified with 'login'. By default, a home directory is created, this
4170+ can be suppressed with 'home=False'.'''
4171+
4172+ self.login = None
4173+
4174+ if os.geteuid() != 0:
4175+ raise ValueError("You must be root to run this test")
4176+
4177+ if login:
4178+ if login_exists(login):
4179+ raise ValueError('login name already exists')
4180+ else:
4181+ while(True):
4182+ login = 't' + random_string(7, lower=lower)
4183+ if not login_exists(login):
4184+ break
4185+
4186+ # when fips is enabled, python2.7 crypt.crypt() returns None
4187+ # for DES salts for being too weak. Force sha256 with "$5$" for
4188+ # the salt. XXX in python3, the salt is optional and will
4189+ # generate strong passwords automatically.
4190+ self.salt = "$5$%s" % random_string(2)
4191+ self.password = random_string(8, lower=lower)
4192+ self.crypted = crypt.crypt(self.password, self.salt)
4193+
4194+ creation = ['useradd', '-p', self.crypted]
4195+ if home:
4196+ creation += ['-m']
4197+ if group:
4198+ creation += ['-G', group]
4199+ if uidmin:
4200+ creation += ['-K', 'UID_MIN=%d' % uidmin]
4201+ if shell:
4202+ creation += ['-s', shell]
4203+ creation += [login]
4204+ assert subprocess.call(creation) == 0
4205+ # Set GECOS
4206+ assert subprocess.call(['usermod', '-c', 'Buddy %s' % (login), login]) == 0
4207+
4208+ self.login = login
4209+ p = pwd.getpwnam(self.login)
4210+ self.uid = p[2]
4211+ self.gid = p[3]
4212+ self.gecos = p[4]
4213+ self.home = p[5]
4214+ self.shell = p[6]
4215+
4216+ def __del__(self):
4217+ '''Remove the created user account.'''
4218+
4219+ if self.login:
4220+ # sanity check the login name so we don't accidentally wipe too much
4221+ if len(self.login) > 3 and '/' not in self.login:
4222+ subprocess.call(['rm', '-rf', '/home/' + self.login, '/var/mail/' + self.login])
4223+ rc, report = cmd(['userdel', '-f', self.login])
4224+ assert rc == 0
4225+
4226+ def add_to_group(self, group):
4227+ '''Add user to the specified group name'''
4228+ rc, report = cmd(['usermod', '-G', group, self.login])
4229+ if rc != 0:
4230+ print(report)
4231+ assert rc == 0
4232+
4233+
4234+class AddUser:
4235+ '''Create a temporary test user and remove it again in the dtor.'''
4236+
4237+ def __init__(self, login=None, home=True, encrypt_home=False, group=None, lower=False, shell=None):
4238+ '''Create a new user account with a random password.
4239+
4240+ By default, the login name is random, too, but can be explicitly
4241+ specified with 'login'. By default, a home directory is created, this
4242+ can be suppressed with 'home=False'.
4243+
4244+ This class differs from the TestUser class in that the adduser/deluser
4245+ tools are used rather than the useradd/user/del tools. The adduser
4246+ program is the only commandline program that can be used to add a new
4247+ user with an encrypted home directory. It is possible that the AddUser
4248+ class may replace the TestUser class in the future.'''
4249+
4250+ self.login = None
4251+
4252+ if os.geteuid() != 0:
4253+ raise ValueError("You must be root to run this test")
4254+
4255+ if login:
4256+ if login_exists(login):
4257+ raise ValueError('login name already exists')
4258+ else:
4259+ while(True):
4260+ login = 't' + random_string(7, lower=True)
4261+ if not login_exists(login):
4262+ break
4263+
4264+ self.password = random_string(8, lower=lower)
4265+
4266+ creation = ['adduser', '--quiet']
4267+
4268+ if not home:
4269+ creation += ['--no-create-home']
4270+ elif encrypt_home:
4271+ creation += ['--encrypt-home']
4272+
4273+ if shell:
4274+ creation += ['--shell', shell]
4275+
4276+ creation += ['--gecos', 'Buddy %s' % (login), login]
4277+
4278+ child = pexpect.spawn(creation.pop(0), creation, timeout=5)
4279+ assert child.expect(b'(Enter new UNIX|New) password:') == 0
4280+ child.sendline(self.password)
4281+ assert child.expect(b'Retype new (UNIX )?password:') == 0
4282+ child.sendline(self.password)
4283+
4284+ child.wait()
4285+ child.close()
4286+ assert child.exitstatus == 0
4287+ assert child.signalstatus is None
4288+
4289+ self.login = login
4290+
4291+ if group:
4292+ assert self.add_to_group(group) == 0
4293+
4294+ p = pwd.getpwnam(self.login)
4295+ self.uid = p[2]
4296+ self.gid = p[3]
4297+ self.gecos = p[4]
4298+ self.home = p[5]
4299+ self.shell = p[6]
4300+
4301+ def __del__(self):
4302+ '''Remove the created user account.'''
4303+
4304+ if self.login:
4305+ # sanity check the login name so we don't accidentally wipe too much
4306+ rc, report = cmd(['deluser', '--remove-home', self.login])
4307+ assert rc == 0
4308+
4309+ def add_to_group(self, group):
4310+ '''Add user to the specified group name'''
4311+ rc, report = cmd(['adduser', self.login, group])
4312+ if rc != 0:
4313+ print(report)
4314+ assert rc == 0
4315+
4316+
4317+# Timeout handler using alarm() from John P. Speno's Pythonic Avocado
4318+class TimeoutFunctionException(Exception):
4319+ """Exception to raise on a timeout"""
4320+ pass
4321+
4322+
4323+class TimeoutFunction:
4324+ def __init__(self, function, timeout):
4325+ self.timeout = timeout
4326+ self.function = function
4327+
4328+ def handle_timeout(self, signum, frame):
4329+ raise TimeoutFunctionException()
4330+
4331+ def __call__(self, *args, **kwargs):
4332+ old = signal.signal(signal.SIGALRM, self.handle_timeout)
4333+ signal.alarm(self.timeout)
4334+ try:
4335+ result = self.function(*args, **kwargs)
4336+ finally:
4337+ signal.signal(signal.SIGALRM, old)
4338+ signal.alarm(0)
4339+ return result
4340+
4341+
4342+def main():
4343+ print("hi")
4344+ unittest.main()
4345diff --git a/debian/tests/testsuite b/debian/tests/testsuite
4346new file mode 100644
4347index 0000000..29cf597
4348--- /dev/null
4349+++ b/debian/tests/testsuite
4350@@ -0,0 +1,6 @@
4351+#!/bin/bash
4352+#-------------------
4353+# Testing open-iscsi
4354+#-------------------
4355+set -e
4356+python3 `dirname $0`/test-open-iscsi.py 2>&1
4357diff --git a/debian/tests/tgt-boot-test b/debian/tests/tgt-boot-test
4358new file mode 100755
4359index 0000000..af5ec50
4360--- /dev/null
4361+++ b/debian/tests/tgt-boot-test
4362@@ -0,0 +1,534 @@
4363+#!/bin/bash
4364+
4365+VERBOSITY=0
4366+TEMP_D=""
4367+DEF_WPORT=32600
4368+IPV4_NET="10.0.12"
4369+DEF_NETDEV="user,net=${IPV4_NET}.0/24,host=${IPV4_NET}.2"
4370+
4371+ISCSI_PORT=3260
4372+TGT_CONF=""
4373+HTTP_PID=""
4374+TGT_NAME=""
4375+
4376+_DEF_CMDLINE_TMPL=(
4377+ nomodeset {icmdline_parms} {cmdline_ip} ro
4378+ net.ifnames=0 BOOTIF_DEFAULT=eth0
4379+ root={root} {overlay_drive}
4380+ console=ttyS0 {cmdline_ds}
4381+ # LP: #1796137
4382+ systemd.mask=snapd.seeded.service systemd.mask=snapd.service
4383+)
4384+DEF_CMDLINE_TMPL="${_DEF_CMDLINE_TMPL[*]}"
4385+
4386+error() { echo "$@" 1>&2; }
4387+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
4388+
4389+cleanup() {
4390+ [ ! -d "$TEMP_D" ] || rm -Rf "$TEMP_D"
4391+ if [ -f "$TGT_CONF" ]; then
4392+ error "cleaning up tgt mount ${TGT_NAME}"
4393+ sudo tgt-admin --force --delete="$TGT_NAME"
4394+ sudo rm -f "$TGT_CONF"
4395+ fi
4396+ if [ -n "$HTTP_PID" ]; then
4397+ kill $HTTP_PID
4398+ fi
4399+}
4400+
4401+Usage() {
4402+ cat <<EOF
4403+Usage: ${0##*/} [ options ] image kernel initrd
4404+
4405+ put 'image' into tgt, boot 'kernel' and 'initrd' in a kvm
4406+ guest pointing to that iscsi target.
4407+
4408+ options:
4409+ -p | --webserv-port PORT serve cloud-init seed on port PORT
4410+ default: ${DEF_WPORT}
4411+ -O | --overlay-disk DISK attach DISK to guest and use it for the overlayroot
4412+ target. Use 'temp' to use a temp file.
4413+ use an existing file to use that. Use a
4414+ non-existing file to create.
4415+ -n | --netdev DEV passed through to xkvm.
4416+ if none passed, default is:
4417+ $DEF_NETDEV
4418+ -a | --host-addr ADDR will be used for iscsi host address and
4419+ cloud-init seed address. Default is read
4420+ from 'host=' in --netdev arg.
4421+ -l | --serial-log FILE write serial log to FILE default is to let output
4422+ go to console.
4423+ --cmdline TMPL template for kernel command line.
4424+ default: ${DEF_CMDLINE_TMPL}
4425+ --cmdline-add ARGS add the args to the kernel command line. default: ""
4426+ --user-data FILE user-data to provide to instance.
4427+ default: builtin
4428+ --user-data-add FILE append FILE to default user-data.
4429+EOF
4430+}
4431+
4432+bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; }
4433+
4434+debug() {
4435+ local level=${1}; shift;
4436+ [ "${level}" -gt "${VERBOSITY}" ] && return
4437+ error "${@}"
4438+}
4439+
4440+write_userdata() {
4441+ ## set up a user-data and meta-data for cloud-init
4442+ ## and we'll seed that through the kernel command line
4443+ ##
4444+ ## The user data we provide will allow us to log in
4445+ ## as the 'ubuntu' user with 'passw0rd'.
4446+ local out="$1" keys="${2:-[]}"
4447+ cat > "$out" <<"EOF"
4448+#cloud-config
4449+chpasswd:
4450+ expire: False
4451+ list: |
4452+ ubuntu:passw0rd
4453+ root:root
4454+ssh_pwauth: True
4455+EOF
4456+}
4457+
4458+get_ssh_pubkeys() {
4459+ # get users ssh pubkeys in a yaml list format
4460+ local keys="" d=""
4461+ keys=$( (ssh-add -L 2>/dev/null ;
4462+ [ -f ~/.ssh/id_rsa.pub ] && cat ~/.ssh/id_rsa.pub ) | sort -u )
4463+ if [ -n "$keys" ]; then
4464+ d=$(IFS=$'\n'; for i in ${keys}; do echo "'$i',"; done)
4465+ keys="[${d%,}]"
4466+ else
4467+ keys="[]"
4468+ fi
4469+ _RET="$keys"
4470+}
4471+
4472+write_metadata() {
4473+ local iid="" out="$1" pubkeys="$2"
4474+ iid=$(uuidgen 2>/dev/null || echo i-abcdefg)
4475+ {
4476+ echo "instance-id: $iid"
4477+ if [ -n "$pubkeys" ]; then
4478+ echo "public-keys: $pubkeys"
4479+ fi
4480+ } > "$out"
4481+}
4482+
4483+register_image() {
4484+ local conf="$1" name="$2" image="$3"
4485+ sudo tee "$conf" >/dev/null <<EOF
4486+<target ${name}>
4487+ readonly 1
4488+ backing-store "$image"
4489+ allow-in-use yes
4490+</target>
4491+EOF
4492+ [ $? -eq 0 ] || { error "failed to write '$conf'"; return 1; }
4493+
4494+ sudo tgt-admin "--update=$name" ||
4495+ { error "failed tgt-admin update=$name"; return 1; }
4496+}
4497+
4498+address_on_dev() {
4499+ local dev="$1" atype="${2:-inet}" out="" addr=""
4500+ out=$(ip address show dev "$dev" 2>/dev/null) ||
4501+ { error "could not get address on $1"; return 1; }
4502+ addr=$(echo "$out" |
4503+ awk '$1 == atype && $4 == "global" {
4504+ sub(/\/.*/, "", $2); print $2; exit(0); }' "atype=$atype" )
4505+ [ -n "$addr" ] || return
4506+ _RET="$addr"
4507+}
4508+
4509+find_host_addr() {
4510+ # run through --netdev args and fine 'host=' or make one up base
4511+ # on there being a net= and assume .2 for host.
4512+ # example: type=user,id=net00,net=10.0.12.0/24,host=10.0.12.2
4513+ # ipv6-net=fec0::/64,ipv6-host=fec0::2
4514+ # lxcbr0
4515+ local nd="" atype="" bridge=""
4516+ local oifs="$IFS"
4517+ for nd in "$@"; do
4518+ local host="" netaddr="" cur="" ipv4="x" ipv6="x" ntype=""
4519+ bridge=${nd%%,*}
4520+ if [ "$bridge" != "user" -a -e "/sys/class/net/$bridge" ]; then
4521+ for atype in inet inet6; do
4522+ address_on_dev "$bridge" "$atype" || continue
4523+ debug 2 "took $atype address on bridge '$bridge': $_RET";
4524+ return 0;
4525+ done
4526+ fi
4527+ cur=${nd}
4528+ while :; do
4529+ first=${cur%%,*}
4530+ rest=${cur#*,}
4531+ case "$first" in
4532+ user) ntype=user;;
4533+ ipv4=on|ipv4) ipv4=on;;
4534+ ipv4=off) ipv4=off;;
4535+ ipv6=on|ipv6) ipv6=on;;
4536+ ipv6=off) ipv6=off;;
4537+ ipv6-net=*) tmp=${first#*=};
4538+ tmp=${tmp%/*}
4539+ netaddr="${tmp%.*}:2"
4540+ ;;
4541+ net=*) tmp=${first#*=};
4542+ tmp=${tmp%/*}
4543+ netaddr="${tmp%.*}.2"
4544+ ;;
4545+ host=*|ipv6-host=) host=${first#*=};;
4546+ esac
4547+ if [ "$first" = "$rest" ]; then
4548+ # there was no ','
4549+ break
4550+ fi
4551+ cur=$rest
4552+ done
4553+ local found="" msg=""
4554+ if [ -n "$host" ]; then
4555+ found="$host"
4556+ msg="host= in '$nd'"
4557+ elif [ -n "$netaddr" ]; then
4558+ found="$netaddr"
4559+ msg="second address on net= in '$nd'";
4560+ elif [ "$ntype" = "user" ]; then
4561+ case "$ipv4/$ipv6" in
4562+ */on)
4563+ msg="known user net default host in ipv6 in '$nd'"
4564+ found="fec0::2";;
4565+ x/x|on/*)
4566+ msg="known user net default host in ipv4 in '$nd'"
4567+ found="10.0.2.2";;
4568+ esac
4569+ fi
4570+ if [ -n "$found" ]; then
4571+ debug 2 "found host address '$found' via $msg"
4572+ _RET="$found"
4573+ return 0
4574+ fi
4575+ done
4576+ return 1
4577+}
4578+
4579+
4580+get_rfc4173() {
4581+ # protocol would normally be '6' (tcp but empty is fine)
4582+ # https://tools.ietf.org/html/rfc4173
4583+ # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=804162
4584+ local server="$1" name="$2" port="$3" lun="$4" user="$5" pass="$6" proto="$7"
4585+ local rfc="" auth="${user:+${user}${pass:+:${pass}}}"
4586+ rfc="iscsi:"
4587+ if [ -n "${user}" ]; then
4588+ rfc="$rfc:${user}${pass:+:${pass}}"
4589+ fi
4590+ case "$server" in
4591+ \[*\]) :;;
4592+ *:*) server="[$server]";;
4593+ esac
4594+ rfc="${server}:$proto:${port}:${lun}:${name}"
4595+ _RET="$rfc"
4596+}
4597+
4598+get_root_parm() {
4599+ local server="$1" name="$2" port="${3:-$ISCSI_PORT}"
4600+ local lun="$4" user="$5" pass="$6" proto="$7" part="$8"
4601+ local ret=""
4602+ # for ipv6 addresses, path just contains : for the server
4603+ _RET="/dev/disk/by-path/ip-$server:$port-iscsi-${name}-lun-${lun}${part:+-part$part}"
4604+}
4605+
4606+get_cmdline_params() {
4607+ local server="$1" name="$2" port="$3" lun="$4" user="$5" pass="$6"
4608+ local proto="$7" initiator="$8" ret=""
4609+ ret="${initiator:+iscsi_initiator=${initiator} }"
4610+ ret="${ret}iscsi_target_name=$name "
4611+ ret="${ret}iscsi_target_ip=$server "
4612+ ret="${ret}${port:+iscsi_target_port=$port }"
4613+ ret="${ret}${initiator:+iscsi_initiator=$initiator }"
4614+ _RET=${ret% }
4615+}
4616+
4617+get_iscsi_cmd() {
4618+ local server="$1" name="$2" port="$3" lun="$4" user="$5" pass="$6"
4619+ local proto="$7" initiator="$8" ret="" group=${9:-1}
4620+ _RET=( iscsistart -i "$initiator"
4621+ -t "$name" -g "$group" -a "$server" -p "$port"
4622+ ${user:+-u "$user"} ${pass:+-w "${pass}"} )
4623+}
4624+
4625+serv_http() {
4626+ local dir="$1" port="$2" check="$3"
4627+ local python="" kid=""
4628+ command -v python3 >/dev/null 2>&1 && python=python3 || python=python2
4629+ cat > "$TEMP_D/webserv" <<EOF
4630+import os, socket, sys
4631+try:
4632+ from BaseHTTPServer import HTTPServer
4633+ from SimpleHTTPServer import SimpleHTTPRequestHandler
4634+except ImportError:
4635+ from http.server import HTTPServer, SimpleHTTPRequestHandler
4636+
4637+class HTTPServerV6(HTTPServer):
4638+ address_family = socket.AF_INET6
4639+
4640+if __name__ == "__main__":
4641+ dir = sys.argv[1]
4642+ port = int(sys.argv[2])
4643+ os.chdir(dir)
4644+ server = HTTPServerV6(("::", port), SimpleHTTPRequestHandler)
4645+ server.serve_forever()
4646+EOF
4647+ $python "$TEMP_D/webserv" "$dir" "$port" &
4648+ HTTP_PID=$!
4649+ local i=0 site="127.0.0.1"
4650+ local url="http://$site:$port/$check"
4651+ while [ -d /proc/$HTTP_PID -a "$i" -lt 10 ] && i=$(($i+1)); do
4652+ no_proxy=$site wget -q -O /dev/null "$url" && return 0
4653+ sleep .5
4654+ done
4655+ return 1
4656+}
4657+
4658+render_templ() {
4659+ local tmpl="$1"
4660+ shift
4661+ local key val i="" cur="$tmpl"
4662+ for i in "$@"; do
4663+ key=${i%%=*}
4664+ val=${i#*=}
4665+ cur=${cur//\{${key}\}/${val}}
4666+ done
4667+ _RET="$cur"
4668+}
4669+
4670+get_partition() {
4671+ # return in _RET the 'auto' partition for a image.
4672+ # return partition number for a partitioned image
4673+ # return 0 for unpartitioned
4674+ # return 0 if image is partitioned, 1 if not
4675+ local img="$1"
4676+ out=$(LANG=C sfdisk --list -uS "$img" 2>&1) || {
4677+ error "failed determining if partitioned: $out";
4678+ return 1;
4679+ }
4680+ if echo "$out" | grep -q 'Device.*Start.*End'; then
4681+ _RET=1
4682+ else
4683+ _RET=0
4684+ fi
4685+}
4686+
4687+main() {
4688+ local short_opts="a:hn:O:p:l:v"
4689+ local long_opts="help,cmdline:,cmdline-add:,cmdline-ip:,disk:,host-addr:,overlay-disk:,netdev:,serial-log:,user-data:,user-data-add:,verbose,webserv-port:"
4690+ local getopt_out=""
4691+
4692+ getopt_out=$(getopt --name "${0##*/}" \
4693+ --options "${short_opts}" --long "${long_opts}" -- "$@") &&
4694+ eval set -- "${getopt_out}" ||
4695+ { bad_Usage; return; }
4696+
4697+ local cur="" next=""
4698+ local overlay_disk="" webserv_port="${DEF_WPORT}" netdevs="" host_addr=""
4699+ local serial_log="" cmdline_tmpl="${DEF_CMDLINE_TMPL}" user_data_file=""
4700+ local cmdline_add="" user_data_add="" pt=""
4701+ # The string 'BOOTIF' is replaced at runtime with the interface
4702+ # name by cloud-initramfs-dyn-netconf.
4703+ local cmdline_ip="ip=::::{iinitiator}:BOOTIF"
4704+ netdevs=( )
4705+ pt=( )
4706+
4707+ while [ $# -ne 0 ]; do
4708+ cur="$1"; next="$2";
4709+ case "$cur" in
4710+ -h|--help) Usage ; exit 0;;
4711+ --cmdline) cmdline_tmpl=$next; shift;;
4712+ --cmdline-add) cmdline_add=$next; shift;;
4713+ --cmdline-ip) cmdline_ip=$next; shift;;
4714+ --disk) pt[${#pt[@]}]="$1=$2"; shift;;
4715+ -a|--host-addr) host_addr=$next; shift;;
4716+ -O|--overlay-disk) overlay_disk=$next; shift;;
4717+ -n|--netdev) netdevs[${#netdevs[@]}]="$next"; shift;;
4718+ -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
4719+ -l|--serial-log) serial_log="$next"; shift;;
4720+ --user-data-file) user_data_file="$next"; shift;;
4721+ --user-data-add) user_data_add="$next"; shift;;
4722+ -p|--webserv-port) webserv_port=$port; shift;;
4723+ --) shift; break;;
4724+ esac
4725+ shift;
4726+ done
4727+
4728+ [ $# -eq 3 ] || { bad_Usage "expected 3 args, got $# ($*)"; return 1; }
4729+ local image_in=$1 kernel_in=$2 initrd_in=$3
4730+ for f in "$image_in" "$kernel_in" "$initrd_in"; do
4731+ [ -f "$f" ] || fail "$f: not a file"
4732+ done
4733+
4734+ local image="" kernel="" initrd=""
4735+ image=$(readlink -f "$image_in") ||
4736+ fail "cannot get full path to $image_in"
4737+ kernel=$(readlink -f "$kernel_in") ||
4738+ fail "cannot get full path to $kernel_in"
4739+ initrd=$(readlink -f "$initrd_in") ||
4740+ fail "cannot get full path to $initrd_in"
4741+
4742+ TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
4743+ fail "failed to make tempdir"
4744+ TEMP_D=$(cd "$TEMP_D" && pwd)
4745+ trap cleanup EXIT
4746+
4747+ local t_image t_kernel t_initrd
4748+ t_image="${TEMP_D}/image"
4749+ t_kernel="${TEMP_D}/kernel"
4750+ t_initrd="${TEMP_D}/initrd"
4751+
4752+ if [ "${#netdevs[@]}" -eq 0 ]; then
4753+ netdevs=( "$DEF_NETDEV" )
4754+ fi
4755+
4756+ local keys=""
4757+ mkdir -p "$TEMP_D/ci-seed"
4758+ if [ -n "${user_data_file}" ]; then
4759+ cat "${user_data_file}" > "$TEMP_D/ci-seed/user-data" ||
4760+ fail "failed to copy '$user_data_file' to ci-seed/user-data"
4761+ else
4762+ write_userdata "$TEMP_D/ci-seed/user-data" ||
4763+ fail "failed to write user-data"
4764+ fi
4765+ if [ -n "$user_data_add" ]; then
4766+ cat "$user_data_add" >> "$TEMP_D/ci-seed/user-data" ||
4767+ fail "failed to write additional user-data"
4768+ fi
4769+
4770+ get_ssh_pubkeys || fail "failed getting pubkeys"
4771+ keys="$_RET"
4772+ write_metadata "$TEMP_D/ci-seed/meta-data" "$keys" ||
4773+ fail "failed writing metadata"
4774+
4775+ if [ -z "$host_addr" ]; then
4776+ find_host_addr "${netdevs[@]}" ||
4777+ fail "failed to find host address. try --host-addr."
4778+ host_addr="$_RET"
4779+ fi
4780+ debug 1 "using host address: '${host_addr}'"
4781+
4782+ ## run a python web server to seed this
4783+ serv_http "$TEMP_D/ci-seed" "$webserv_port" "user-data" ||
4784+ fail "failed to web serv $TEMP_D/ci-seed on $webserv_port"
4785+ debug 1 "web server in pid $HTTP_PID serving ${TEMP_D}/ci-seed/ on port $webserv_port"
4786+ local seed_url="http://$host_addr:$webserv_port/"
4787+ if [ "${host_addr#*:}" != "$host_addr" ]; then
4788+ seed_url="http://[$host_addr]:$webserv_port/"
4789+ fi
4790+ debug 1 " ${seed_url}meta-data"
4791+
4792+ if [ "${image%.gz}" != "$image" ]; then
4793+ error "uncompressing $image_in -> temp-dir"
4794+ gzcat "$image" > "${TEMP_D}/image" ||
4795+ fail "failed uncompress of $image_in"
4796+ else
4797+ ln -s "$image" "$t_image" || fail "symlink to $image failed"
4798+ fi
4799+
4800+ ln -s "$kernel" "$t_kernel" &&
4801+ ln -s "$initrd" "$t_initrd" ||
4802+ fail "failed link to kernel or initrd"
4803+
4804+ local partition=""
4805+ get_partition "$t_image" ||
4806+ fail "failed to read partition from $image"
4807+ partition=${_RET}
4808+ [ "$part" = "0" ] && partition=""
4809+
4810+ TGT_NAME=${TEMP_D##*/}
4811+ TGT_NAME=${TGT_NAME//./-}
4812+ TGT_CONF="/etc/tgt/conf.d/$TGT_NAME.conf"
4813+ register_image "$TGT_CONF" "$TGT_NAME" "$t_image" ||
4814+ fail "failed to register image $t_image in tgt"
4815+
4816+ overlay_drive_kernel="overlayroot=tmpfs"
4817+ overlay_drive_xkvm=""
4818+ if [ -n "${overlay_disk}" ]; then
4819+ if [ "${overlay_disk}" = "temp" ]; then
4820+ overlay_disk="${TEMP_D}/overlay.img"
4821+ fi
4822+ if [ ! -f "$overlay_disk" ]; then
4823+ qemu-img create -f raw "$overlay_disk" 1G
4824+ mkfs.ext2 -L "delta" -F "$overlay_disk" >/dev/null 2>&1 ||
4825+ fail "failed mkfs on $overlay_disk"
4826+ overlay_drive_kernel="overlayroot=device:dev=LABEL=delta"
4827+ overlay_drive_xkvm="--disk=${overlay_disk},format=raw"
4828+ fi
4829+ fi
4830+
4831+ local iserver="${host_addr}" iname="$TGT_NAME" iport="$ISCSI_PORT"
4832+ local ilun="1" iuser="" ipass="" iproto="" iinitiator="maas-enlist"
4833+ local rfc="" root="" iscsi_cmdline_parms="" iscsi_start_cmd=""
4834+ local cmdline=""
4835+ get_rfc4173 "${iserver}" "$iname" "$iport" "$ilun" \
4836+ "$iuser" "$ipass" "$iproto"
4837+ rfc="$_RET"
4838+
4839+ get_cmdline_params "${iserver}" "$iname" "$iport" "$ilun" \
4840+ "$iuser" "$ipass" "$iproto" "$iinitiator"
4841+ iscsi_cmdline_parms="$_RET"
4842+
4843+ get_root_parm "$iserver" "$iname" "$iport" "$ilun" \
4844+ "$iuser" "$ipass" "$iproto" "$partition"
4845+ root="$_RET"
4846+
4847+ get_iscsi_cmd "$iserver" "$iname" "$iport" "$ilun" \
4848+ "$iuser" "$ipass" "$iproto" "$iinitiator"
4849+ iscsi_start_cmd=( "${_RET[@]}" )
4850+
4851+ render_templ "${cmdline_ip}" iinitiator="$iinitiator" ||
4852+ { error "failed rendering cmdline ip: ${cmdline_ip}"; return 1; }
4853+ cmdline_ip="$_RET"
4854+
4855+ render_templ "$cmdline_tmpl${cmdline_add:+ ${cmdline_add}}" \
4856+ iserver="$host_addr" iname="$TGT_NAME" iport="$ISCSI_PORT" \
4857+ ilun="$ilun" iuser="$iuser" ipass="$ipass" iproto="$iproto" \
4858+ iinitiator="$iinitiator" "rfc4173=$rfc" "root=$root" \
4859+ "seed_url=$seed_url" icmdline_parms="$iscsi_cmdline_parms" \
4860+ "overlay_drive=${overlay_drive_kernel}" \
4861+ "cmdline_ds=ds=nocloud-net;seedfrom=${seed_url}" \
4862+ "cmdline_ip=${cmdline_ip}" ||
4863+ { error "failed rendering cmdline"; return 1; }
4864+ cmdline="$_RET"
4865+
4866+ debug 1 "rfc4173: $rfc"
4867+ debug 1 "iscsi_cmdline_parms: $iscsi_cmdline_parms"
4868+ debug 1 "root: $root"
4869+ debug 1 "iscsi_start_cmd: ${iscsi_start_cmd[*]}"
4870+ debug 1 "cmdline=$cmdline"
4871+
4872+ local netdev_args=""
4873+ netdev_args=( )
4874+ for i in "${netdevs[@]}"; do
4875+ netdev_args[${#netdev_args[@]}]="--netdev=$i"
4876+ done
4877+
4878+ local mem="512" start="$SECONDS" ret=""
4879+ local cmd=""
4880+ cmd=(
4881+ ${BOOT_TIMEOUT:+timeout --kill-after=1m --signal=TERM $BOOT_TIMEOUT}
4882+ xkvm -v -v "${netdev_args[@]}" ${overlay_drive_xkvm} "${pt[@]}" --
4883+ -echr 0x5
4884+ -m $mem ${serial_log:+-serial "file:$serial_log"} -nographic
4885+ -kernel "${t_kernel}" -initrd "${t_initrd}"
4886+ -append "${cmdline}"
4887+ )
4888+ debug 1 "executing: ${cmd[*]}"
4889+ "${cmd[@]}"
4890+ ret=$?
4891+ debug 1 "xkvm returned $ret in $((SECONDS-start))s"
4892+ return $ret
4893+}
4894+
4895+main "$@"
4896+# vi: ts=4 expandtab
4897diff --git a/debian/tests/xkvm b/debian/tests/xkvm
4898new file mode 100755
4899index 0000000..9513723
4900--- /dev/null
4901+++ b/debian/tests/xkvm
4902@@ -0,0 +1,704 @@
4903+#!/bin/bash
4904+
4905+set -f
4906+
4907+VERBOSITY=0
4908+KVM_PID=""
4909+DRY_RUN=false
4910+TEMP_D=""
4911+DEF_BRIDGE="virbr0"
4912+TAPDEVS=( )
4913+# OVS_CLEANUP gets populated with bridge:devname pairs used with ovs
4914+OVS_CLEANUP=( )
4915+MAC_PREFIX="52:54:00:12:34"
4916+KVM="kvm"
4917+declare -A KVM_DEVOPTS
4918+
4919+error() { echo "$@" 1>&2; }
4920+fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
4921+
4922+bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
4923+randmac() {
4924+ # return random mac addr within final 3 tokens
4925+ local random=""
4926+ random=$(printf "%02x:%02x:%02x" \
4927+ "$((${RANDOM}%256))" "$((${RANDOM}%256))" "$((${RANDOM}%256))")
4928+ padmac "$random"
4929+}
4930+
4931+cleanup() {
4932+ [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
4933+ if [ -n "${KVM_PID}" ]; then
4934+ debug 1 "${0##*/} cleanup killing kvm pid '$KVM_PID'"
4935+ kill "$KVM_PID"
4936+ fi
4937+ if [ ${#TAPDEVS[@]} -ne 0 ]; then
4938+ local name item
4939+ for item in "${TAPDEVS[@]}"; do
4940+ [ "${item}" = "skip" ] && continue
4941+ debug 1 "removing" "$item"
4942+ name="${item%:*}"
4943+ if $DRY_RUN; then
4944+ error ip tuntap del mode tap "$name"
4945+ else
4946+ ip tuntap del mode tap "$name"
4947+ fi
4948+ [ $? -eq 0 ] || error "failed removal of $name"
4949+ done
4950+ if [ ${#OVS_CLEANUP[@]} -ne 0 ]; then
4951+ # with linux bridges, there seems to be no harm in just deleting
4952+ # the device (not detaching from the bridge). However, with
4953+ # ovs, you have to remove them from the bridge, or later it
4954+ # will refuse to add the same name.
4955+ error "cleaning up ovs ports: ${OVS_CLEANUP[@]}"
4956+ if ${DRY_RUN}; then
4957+ error sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}"
4958+ else
4959+ sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}"
4960+ fi
4961+ fi
4962+ fi
4963+}
4964+
4965+debug() {
4966+ local level=${1}; shift;
4967+ [ "${level}" -gt "${VERBOSITY}" ] && return
4968+ error "${@}"
4969+}
4970+
4971+Usage() {
4972+ cat <<EOF
4973+Usage: ${0##*/} [ options ] -- kvm-args [ ... ]
4974+
4975+ run kvm with a tap interface.
4976+
4977+ options:
4978+ -n | --netdev NETDEV netdev can be 'user' or a bridge.
4979+ default is to bridge to $DEF_BRIDGE
4980+ -d | --disk DISK.img attach DISK.img as a disk (via virtio)
4981+ --dry-run only report what would be done
4982+
4983+ --uefi boot with efi
4984+ --uefi-nvram=FILE boot with efi, using nvram settings in FILE
4985+ if FILE not present, copy from defaults.
4986+
4987+ NETDEV:
4988+ Above, 'NETDEV' is a comma delimited string
4989+ The first field must be
4990+ * bridge name: (br0 or virbr0): attach a device to this bridge
4991+ * literal 'user': use qemu user networking
4992+
4993+ Additional fields are optional, and can be anything that is acceptable
4994+ to kvm either as:
4995+ * '-device virtio-net-pci' option (see 'kvm -device virtio-net-pci,?')
4996+ * '-net [user|tap]' option
4997+
4998+ Example:
4999+ * xkvm --netdev br0,macaddr=:05 -- -drive file=disk.img,if=virtio -curses
5000+ attach a tap device to bridge 'br0' with mac address
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches