Merge ~paelzer/ubuntu/+source/open-iscsi:merge-2.1.2-1-HIRSUTE into ubuntu/+source/open-iscsi:debian/sid

Proposed by Christian Ehrhardt 
Status: Merged
Approved by: Christian Ehrhardt 
Approved revision: 9901a74c936ce0e9b0f918463d0f80798f201f32
Merge reported by: Christian Ehrhardt 
Merged at revision: 9901a74c936ce0e9b0f918463d0f80798f201f32
Proposed branch: ~paelzer/ubuntu/+source/open-iscsi:merge-2.1.2-1-HIRSUTE
Merge into: ubuntu/+source/open-iscsi:debian/sid
Diff against target: 5399 lines (+4913/-71)
25 files modified
debian/changelog (+1066/-0)
debian/control (+9/-7)
debian/extra/initramfs.hook (+1/-1)
debian/extra/initramfs.local-bottom (+20/-0)
debian/extra/initramfs.local-top (+30/-2)
debian/extra/net-interface-handler (+80/-0)
debian/iscsi-network-interface.rules (+3/-0)
debian/iscsid.service (+1/-1)
debian/open-iscsi.finalrd (+40/-0)
debian/open-iscsi.postinst (+25/-40)
debian/open-iscsi.service (+6/-6)
debian/patches/lp1755858-default-iscsid_conf-to-iscsid_socket.patch (+28/-0)
debian/patches/series (+1/-0)
debian/rules (+30/-10)
debian/tests/README-boot-test.md (+139/-0)
debian/tests/control (+4/-0)
debian/tests/get-image (+227/-0)
debian/tests/install (+5/-2)
debian/tests/patch-image (+374/-0)
debian/tests/test-open-iscsi.py (+426/-0)
debian/tests/testlib.py (+1153/-0)
debian/tests/testsuite (+7/-0)
debian/tests/tgt-boot-test (+534/-0)
debian/tests/xkvm (+704/-0)
dev/null (+0/-2)
Reviewer Review Type Date Requested Status
Robie Basak Needs Fixing
Canonical Server Pending
git-ubuntu developers Pending
Review via email: mp+394815@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

One more MP under the "carry as-is until one can spend more time" banner.
To be clear, we have a lot of Delta and discussions were going on. But
to further push or drop some this would need more time than a drive-by merge.

PPA: https://launchpad.net/~ci-train-ppa-service/+archive/ubuntu/4364/+packages
Old-MP (for old Delta discussion as reference): https://code.launchpad.net/~rafaeldtinoco/ubuntu/+source/open-iscsi/+git/open-iscsi/+merge/389567

Note on git histoy:
- The old imports/merges/history were a bit odd
- upload/2.1.1-1ubuntu2 does not fully match pkg/ubuntu/hirsute-devel by
  changes in .gitignore
- Never the less the parenting/history of pkg/ubuntu/hirsute-devel is totally
  broken and instead I'll start off of the better upload/2.1.1-1ubuntu2 which
  I used to create "split".
- You can use the tags, starting with *logical* things make sense again
 * [new tag] lp9999999/logical/2.1.1-1ubuntu2 -> lp9999999/logical/2.1.1-1ubuntu2
 * [new tag] lp9999999/new/debian -> lp9999999/new/debian
 * [new tag] lp9999999/old/debian -> lp9999999/old/debian
 * [new tag] lp9999999/old/ubuntu -> lp9999999/old/ubuntu
 * [new tag] lp9999999/reconstruct/2.1.1-1ubuntu2 -> lp9999999/reconstruct/2.1.1-1ubuntu2
 * [new tag] lp9999999/split/2.1.1-1ubuntu2 -> lp9999999/split/2.1.1-1ubuntu2

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

FYI: I tried to drop the FTFBS fix for gcc10 as you'd think Debian builds that as well.
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=957630
But on ppc64/s390x we still hit build errors due to that and need to retain hat delta.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Tests done all good except i386 which is ok to fail.
=> https://bileto.ubuntu.com/excuses/4364/hirsute.html

Revision history for this message
Robie Basak (racb) wrote :

Not being familiar with this extensive Ubuntu delta, I particularly appreciate the use of our workflow to break the delta down with clear explanations in git commits and changelog entries. Thank you!

This looks good to me except for two possible issues I spotted.

1) I don't think 6c13643 "Don't FTBFS due to warnings new in gcc10" is needed any more with this new upstream release. My local test build without it succeeded.

2) I think 5dd176f "refresh to match 2.1.2" is broken. Before, it resulted in the line:

    iscsid.startup = /bin/systemctl start iscsid.socket

whereas now it results in:

    iscsid.startup = /bin/systemctl start iscsid.socket iscsiuio.socket

No need for a re-review after you've looked at these.

Finally, not a problem with the final result, but I thought I'd mention that I think you've drifted from the original intention of what the logical tag means, which made it harder for me to review this MP. I ended up making my own logical tag to review against instead. I would have expected 71f3193 to be squashed into 1d16906 and 41112bd squashed into 90684c2 before you tagged it logical. Otherwise the range-diff doesn't match when reviewing.

review: Needs Fixing
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

1) I don't think 6c13643 "Don't FTBFS due to warnings new in gcc10" is needed any more with this new upstream release. My local test build without it succeeded.

=> I thought the same, had it test built and it fails on ppc64&s390x still without this

2) 5dd176f

I'll look into that, the surrounding context had some noise distracting me.
Indeed I have alinged to what the comment said, but to match the old delta the line has dropped iscsiuio.socket indeed
Awesome spotting on the review.
Fixed

And about logical - this was not intentionally different. The problem is that some squashing only becomes obvious once you are 3/4 through the merge. I did not go back to refresh logical with those, but yeah I might do so next time.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

To ssh://git.launchpad.net/~usd-import-team/ubuntu/+source/open-iscsi
 * [new tag] upload/2.1.2-1ubuntu1 -> upload/2.1.2-1ubuntu1

Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading open-iscsi_2.1.2-1ubuntu1.dsc: done.
  Uploading open-iscsi_2.1.2.orig.tar.gz: done.
  Uploading open-iscsi_2.1.2-1ubuntu1.debian.tar.xz: done.
  Uploading open-iscsi_2.1.2-1ubuntu1_source.buildinfo: done.
  Uploading open-iscsi_2.1.2-1ubuntu1_source.changes: done.
Successfully uploaded packages.

Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

Migrated

Preview Diff

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

Subscribers

People subscribed via source and target branches