Merge ~waveform/ubuntu/+source/open-iscsi:merge-2.1.5-jammy into ubuntu/+source/open-iscsi:debian/sid

Proposed by Dave Jones
Status: Needs review
Proposed branch: ~waveform/ubuntu/+source/open-iscsi:merge-2.1.5-jammy
Merge into: ubuntu/+source/open-iscsi:debian/sid
Diff against target: 5527 lines (+5262/-16)
16 files modified
debian/README.Debian (+2/-2)
debian/changelog (+1337/-0)
debian/control (+13/-2)
debian/extra/startup-checks.sh (+1/-1)
debian/open-iscsi-udeb.start (+1/-1)
debian/open-iscsi.postinst (+1/-1)
debian/rules (+4/-9)
debian/tests/README-boot-test.md (+139/-0)
debian/tests/control (+4/-0)
debian/tests/get-image (+227/-0)
debian/tests/patch-image (+374/-0)
debian/tests/test-open-iscsi.py (+427/-0)
debian/tests/testlib.py (+1488/-0)
debian/tests/testsuite (+6/-0)
debian/tests/tgt-boot-test (+534/-0)
debian/tests/xkvm (+704/-0)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
git-ubuntu import Pending
Review via email: mp+414361@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

open-iscsi | 2.1.5-1 | testing | source, amd64, arm64, armel, armhf, i386, mips64el, mipsel, ppc64el, s390x

open-iscsi | 2.1.4-0ubuntu3 | jammy | source, amd64, arm64, armhf, ppc64el, riscv64, s390x

This is after a massive pick-up of our Delta by Debian in 2.1.4-1 so you had a lot to drop :-)

I found no auxiliary tags for the merge like old logical and such, I'll try to review as-is without them.

* Changelog:
  - [+] changelog entry correct version and targeted codename
  - [+] changelog entries correct
  - [+] bug references correct
  - [+] update-maintainer has been run

* Merge - Indirect Changes:
  - [+] no upstream changes that need adaptation
  - [+] no further upstream version to consider
  - [+] debian changes look safe

* Merge - Old Delta:
  - [+] dropped changes are ok to be dropped
  - [x] nothing else to drop
        Why does debian not need "d/t/test-open-iscsi.py: adopt to resolvectl (systemd v249
        compat)" they are >=249 too. If the check reveals it can be dropped with 250 please
        mention that.
  - [x] changes forwarded upstream/debian
        I've not seen it, did you forward "d/rules: remove duplicated dh_installsystemd section"
        as that seems to affect Debian as well?

* New Delta:
  - [+] no new patches added

* Git/Maintenance
  - [+] testcases added or not needed for this (has enough)
  - [+] commits are properly split (more important on -dev than on SRUs)

* Build/Test:
  - [+] build on all arch look ok
  - [+] verified PPA package installs/uninstalls
  - [x] autopkgtest against the PPA package passes
     Did you run autopkgtest against this PPA yet?
     I've seen none, remember you can check and trigger results on the PPA via
     $ lp-test-ppa ppa:waveform/open-iscsi --release jammy --showpass
     (from git+ssh://<email address hidden>/~ubuntu-server/ubuntu-helpers)

I had no time for sanity checks as I have no iscsi env atm.
But once the autopkgtests have run that should be fine.

Need-Info for the few questions above, but looks like 98% done and great :-)

review: Needs Information
Revision history for this message
Dave Jones (waveform) wrote :

> I found no auxiliary tags for the merge like old logical and such, I'll try to
> review as-is without them.

Yes, I didn't directly use git-ubuntu as there's (still) no arm builds for it. So
I just did a rebase of the old split plus the subsequent versions on top of it.

> Why does debian not need "d/t/test-open-iscsi.py: adopt to resolvectl (systemd v249
> compat)" they are >=249 too. If the check reveals it can be dropped with 250 please
> mention that.

Because the entire autopkgtest suite is part of our delta and not upstream either.
I'm guessing there are good reasons for that, possibly hinted at by the note in
the git commit "this suite should be replaced by LIO that replaced TGT in main"? In
other words, presumably the test suite is intended to be replaced by something better
(LIO?) at some point (but what's TGT ... and which main? I'm just guessing at
stuff here).

> I've not seen it, did you forward "d/rules: remove duplicated dh_installsystemd
> section" as that seems to affect Debian as well?

I've *reported* it upstream (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1004014),
but not sent our patch as we only activate the socket, whilst Debian activates both
socket *and* service in d/rules, so our patch likely isn't what they want.

That said, I'm not entirely sure what the intent is in Debian for this, as they did
merge other socket-activation-only bits but kept d/rules largely unchanged? Anyway,
not being certain what the intent is, I warned about the duplication but will leave
it to their discretion how they wish to fix it.

> Did you run autopkgtest against this PPA yet?
> I've seen none, remember you can check and trigger results on the PPA via
> $ lp-test-ppa ppa:waveform/open-iscsi --release jammy --showpass
> (from git+ssh://<email address hidden>/~ubuntu-server/ubuntu-helpers)

Erm, not sure I can -- I don't think I have the authority to launch autopkgtests
(your otherwise fine script runs with no error exit code, but doesn't appear to
actually launch for me).
anything for me)

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

Thanks for the explanation and filing that Debian bug.

So the new delta can next time be folded with our autopkgtest delta.

Tests are good as well (as discussed in chat I started them for you):
  open-iscsi @ amd64:
    20.01.22 13:05:09 Log 🗒️ ✅ Triggers: ['open-iscsi/2.1.5-1ubuntu1']
      install PASS ✅
      testsuite PASS ✅
      nested PASS ✅
  open-iscsi @ arm64:
    20.01.22 13:04:24 Log 🗒️ ✅ Triggers: ['open-iscsi/2.1.5-1ubuntu1']
      install PASS ✅
      testsuite PASS ✅
      nested PASS ✅
  open-iscsi @ armhf:
    20.01.22 12:50:30 Log 🗒️ ✅ Triggers: ['open-iscsi/2.1.5-1ubuntu1']
  open-iscsi @ ppc64el:
    20.01.22 12:58:44 Log 🗒️ ✅ Triggers: ['open-iscsi/2.1.5-1ubuntu1']
      install PASS ✅
      testsuite PASS ✅
      nested PASS ✅
  open-iscsi @ s390x:
    20.01.22 12:55:20 Log 🗒️ ✅ Triggers: ['open-iscsi/2.1.5-1ubuntu1']
      install PASS ✅
      testsuite PASS ✅
      nested PASS ✅

Armhf skips (ok) as they have no isolation-machine

Therefore +1 then, LGTM

P.S. yes LIO is the new and better userspace compared to TGT

review: Approve
Revision history for this message
Dave Jones (waveform) wrote :

Do I need to do anything else to have this merged (preferably preserving the branch history for future users?), or is that an automatic process at this point?

Revision history for this message
Dave Jones (waveform) wrote :

Hmmm, just ran into something rather worrying while taking a look at the dbus merge: apparently recent versions of debhelper (including our version in jammy) have broken --no-stop-on-upgrade (or its deprecated alias --no-restart-on-upgrade): https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=994204

That would imply that open-iscsi *will* restart on upgrade when this merge gets built by this version of debhelper. In dbus, Debian have worked around this (https://salsa.debian.org/utopia-team/dbus/-/commit/4c5195a13c69364dce50063afac368930ec75c91), but I don't really want to start playing whack-a-mole patching things that shouldn't be restarted (I'd rather get this fixed in debhelper itself). However, if we do fix this in debhelper, we should hold off on merging this until that fix lands (so that the resulting package gets built "correctly").

Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote (last edit ):

The debhelper bug mentioned in the comment above was already fixed in Ubuntu (more info LP: #1959054). Since the changes submitted here were already reviewed and approved by Christian, I'll be moving forward and uploading this version of open-iscsi before we reach feature freeze.

Revision history for this message
Lucas Kanashiro (lucaskanashiro) wrote :

Package uploaded:

$ dput ubuntu ../open-iscsi_2.1.5-1ubuntu1_source.changes
Checking signature on .changes
gpg: ../open-iscsi_2.1.5-1ubuntu1_source.changes: Valid signature from F823A2729883C97C
Checking signature on .dsc
gpg: ../open-iscsi_2.1.5-1ubuntu1.dsc: Valid signature from F823A2729883C97C
Package includes an .orig.tar.gz file although the debian revision suggests
that it might not be required. Multiple uploads of the .orig.tar.gz may be
rejected by the upload queue management software.
Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading open-iscsi_2.1.5-1ubuntu1.dsc: done.
  Uploading open-iscsi_2.1.5.orig.tar.gz: done.
  Uploading open-iscsi_2.1.5-1ubuntu1.debian.tar.xz: done.
  Uploading open-iscsi_2.1.5-1ubuntu1_source.buildinfo: done.
  Uploading open-iscsi_2.1.5-1ubuntu1_source.changes: done.
Successfully uploaded packages.

Unmerged commits

9390f03... by Dave Jones

reconstruct-changelog

aafcf6f... by Christian Ehrhardt 

update-maintainer

d0eb9b6... by Christian Ehrhardt 

merge-changelogs

18923c8... by Dave Jones

* [a0e81aa] d/t/test-open-iscsi.py: adopt to resolvectl (systemd v249 compat)

23f13fd... by Christian Ehrhardt 

d/control: Transition from libopeniscsiusr0.2.0 to libopeniscsiusr

We had
  libopeniscsiusr0.2.0 2.1.3-1ubuntu6
Containing file
  /usr/lib/x86_64-linux-gnu/libopeniscsiusr.so.0.2.0
Debian now finally resolved that, but in differnt package name
  libopeniscsiusr 2.1.4-0ubuntu1~impishppa1
Also all dependencies flipped to the new package name,
but we need to ensure a proper install ordering.

Otherwise this happens:
  Preparing to unpack .../libopeniscsiusr_2.1.4-0ubuntu1~impishppa1_amd64.deb ...
  Unpacking libopeniscsiusr (2.1.4-0ubuntu1~impishppa1) ...
  dpkg: error processing archive /var/cache/apt/archives/libopeniscsiusr_2.1.4-0ubuntu1~impishppa1_amd64.deb (--unpack):
   trying to overwrite '/usr/lib/x86_64-linux-gnu/libopeniscsiusr.so.0.2.0', which is also in package libopeniscsiusr0.2.0 2.1.3-1ubuntu6
  Preparing to unpack .../open-iscsi_2.1.4-0ubuntu1~impishppa1_amd64.deb ...
  Unpacking open-iscsi (2.1.4-0ubuntu1~impishppa1) over (2.1.3-1ubuntu6) ...
  Errors were encountered while processing:
   /var/cache/apt/archives/libopeniscsiusr_2.1.4-0ubuntu1~impishppa1_amd64.deb

For Debian that was a new package in 2.1.3-5, but for an Ubuntu user
that is case #5 of https://wiki.debian.org/PackageTransition
So we need to add breaks and a transitional.

This change can be dropped ater 22.04 as then all valid upgrade paths have gone
through this.

Signed-off-by: Christian Ehrhardt <email address hidden>

71e0296... by Christian Ehrhardt 

Ubuntu-only: d/README.Debian, d/extra/startup-checks.sh, d/open-iscsi-udeb.start, d/open-iscsi.postinst: Apply Ubuntu branding to iqn initiator name

Signed-off-by: Christian Ehrhardt <email address hidden>

ac59125... by Rafael David Tinoco

* Stop producing udebs on i386 where we no longer have d-i or a kernel.

6cc78c0... by Dave Jones

* d/rules: correct duplicated dh_installsystemd section

abe7c3c... by Rafael David Tinoco

* debian/tests: Add Ubuntu autopkgtest suite:
  - d/t/README-boot-test.md: document test design
  - d/t/control: register testsuite
  - d/t/get-image: helper to fetch an ubuntu cloud image
  - d/t/patch-image: helper to modify an ubuntu cloud image
  - d/test-open-iscsi.py, d/t/testlib.py: various qa regression tests
  - d/t/testsuite: helper to invoke qa regression tests
  - d/t/tgt-boot-test: test using tgt to boot from iscsi
  - d/t/xkvm: helper to spawn a VM

  Note: this suite should be replaced by LIO that replaced TGT in main.

Preview Diff

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

Subscribers

People subscribed via source and target branches