Merge lp:~raharper/curtin/trunk.fix-raid-over-iscsi into lp:~curtin-dev/curtin/trunk

Proposed by Ryan Harper
Status: Merged
Merged at revision: 526
Proposed branch: lp:~raharper/curtin/trunk.fix-raid-over-iscsi
Merge into: lp:~curtin-dev/curtin/trunk
Diff against target: 154 lines (+95/-5)
5 files modified
curtin/block/iscsi.py (+9/-0)
curtin/commands/install.py (+17/-5)
curtin/util.py (+14/-0)
tests/unittests/test_util.py (+51/-0)
tests/vmtests/test_mdadm_iscsi.py (+4/-0)
To merge this branch: bzr merge lp:~raharper/curtin/trunk.fix-raid-over-iscsi
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
Scott Moser (community) Approve
Review via email: mp+330309@code.launchpad.net

Description of the change

install: ensure iscsi service is running to handle shutdown properly

In some cases it is problematic to shutdown the iscsi targets (like raid
over iscsi). Instead of introducing extra work to stop multi-layer
storage devices during the install of curtin, this patch addresses the
core issue around iscsi termination; ensuring the iscsi service is active
prior to shutting down. In Artful, the open-iscsi service does not
automatically start if iscsi configuration is not present during boot;
curtin will restart/start the service if the storage configuration
contains iscsi disks.

This approach successfully passes all of the iscsi configurations
(plain, lvm over iscsi, and raid over iscsi).

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ryan Harper (raharper) wrote :

./tools/jenkins-runner -p 4 tests/vmtests/test_mdadm_bcache.py tests/vmtests/test_mdadm_iscsi.py tests/vmtests/test_raid5_bcache.py tests/vmtests/test_iscsi.py tests/vmtests/test_lvm_iscsi.py

...

Ran 489 tests in 2308.432s

OK (SKIP=2)

Revision history for this message
Scott Moser (smoser) wrote :

so somewhere during block-meta iscsi will get started if not already running?

Revision history for this message
Ryan Harper (raharper) :
526. By Ryan Harper

merge from trunk

527. By Ryan Harper

uses_systemd: add caching, drop target_path use, ephemeral only

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

mainly just need to somehow document this in code for the point later when someone says "what is going on here... we start a service just to handle shutdown ! ?"

528. By Ryan Harper

Add additional documentation in install.py on why we restart iscsi service

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

this is fine.
my only comment is that 'sdpath' is wierd as an argument and i'd never expect anythign to use it.

i realize it is just for testing. Woudl it be better to just use 'os.path.isdir()' rather than the lstat? and then you could easily mock the response to that.

529. By Ryan Harper

Replace os.lstat with os.path.isdir; drop sdpath arg; adjust unittests

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

i approve, just fix the vestigial 'sdpath' uses.

review: Approve
530. By Ryan Harper

Drop useless tmp_dir() in uses_systemd unittest

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'curtin/block/iscsi.py'
2--- curtin/block/iscsi.py 2017-08-31 19:22:08 +0000
3+++ curtin/block/iscsi.py 2017-09-12 21:16:54 +0000
4@@ -195,6 +195,15 @@
5 return target_nodes_location
6
7
8+def restart_iscsi_service():
9+ LOG.info('restarting iscsi service')
10+ if util.uses_systemd():
11+ cmd = ['systemctl', 'reload-or-restart', 'open-iscsi']
12+ else:
13+ cmd = ['service', 'open-iscsi', 'restart']
14+ util.subp(cmd, capture=True)
15+
16+
17 def save_iscsi_config(iscsi_disk):
18 state = util.load_command_environment()
19 # A nodes directory will be created in the same directory as the
20
21=== modified file 'curtin/commands/install.py'
22--- curtin/commands/install.py 2017-08-31 18:41:35 +0000
23+++ curtin/commands/install.py 2017-09-12 21:16:54 +0000
24@@ -479,11 +479,23 @@
25 copy_install_log(logfile, workingd.target, log_target_path)
26 # unmount everything (including iscsi disks)
27 util.do_umount(workingd.target, recursive=True)
28- # disconnect configured iscsi disks
29- LOG.info("Disconnecting iscsi targets (if present)")
30- for iscsi_disk in iscsi.get_iscsi_disks_from_config(cfg):
31- LOG.info("Attempting to disconnect %s", iscsi_disk)
32- iscsi_disk.disconnect()
33+
34+ # The open-iscsi service in the ephemeral environment handles
35+ # disconnecting active sessions. On Artful release the systemd
36+ # unit file has conditionals that are not met at boot time and
37+ # results in open-iscsi service not being started; This breaks
38+ # shutdown on Artful releases.
39+ # Additionally, in release < Artful, if the storage configuration
40+ # is layered, like RAID over iscsi volumes, then disconnecting iscsi
41+ # sessions before stopping the raid device hangs.
42+ # As it turns out, letting the open-iscsi service take down the
43+ # session last is the cleanest way to handle all releases regardless
44+ # of what may be layered on top of the iscsi disks.
45+ #
46+ # Check if storage configuration has iscsi volumes and if so ensure
47+ # iscsi service is active before exiting install
48+ if iscsi.get_iscsi_disks_from_config(cfg):
49+ iscsi.restart_iscsi_service()
50
51 shutil.rmtree(workingd.top)
52
53
54=== modified file 'curtin/util.py'
55--- curtin/util.py 2017-06-26 16:48:30 +0000
56+++ curtin/util.py 2017-09-12 21:16:54 +0000
57@@ -58,6 +58,7 @@
58 _INSTALLED_MAIN = '/usr/bin/curtin'
59
60 _LSB_RELEASE = {}
61+_USES_SYSTEMD = None
62 _HAS_UNSHARE_PID = None
63
64 _DNS_REDIRECT_IP = None
65@@ -1400,4 +1401,17 @@
66 return data
67
68
69+def uses_systemd():
70+ """ Check if current enviroment uses systemd by testing if
71+ /run/systemd/system is a directory; only present if
72+ systemd is available on running system.
73+ """
74+
75+ global _USES_SYSTEMD
76+ if _USES_SYSTEMD is None:
77+ _USES_SYSTEMD = os.path.isdir('/run/systemd/system')
78+
79+ return _USES_SYSTEMD
80+
81+
82 # vi: ts=4 expandtab syntax=python
83
84=== modified file 'tests/unittests/test_util.py'
85--- tests/unittests/test_util.py 2017-08-03 19:31:49 +0000
86+++ tests/unittests/test_util.py 2017-09-12 21:16:54 +0000
87@@ -851,4 +851,55 @@
88 }, observed)
89
90
91+class TestUsesSystemd(CiTestCase):
92+
93+ def setUp(self):
94+ super(TestUsesSystemd, self).setUp()
95+ self._reset_cache()
96+ self.add_patch('curtin.util.os.path.isdir', 'mock_isdir')
97+
98+ def _reset_cache(self):
99+ util._USES_SYSTEMD = None
100+
101+ def test_uses_systemd_on_systemd(self):
102+ """ Test that uses_systemd returns True if sdpath is a dir """
103+ # systemd_enabled
104+ self.mock_isdir.return_value = True
105+ result = util.uses_systemd()
106+ self.assertEqual(True, result)
107+ self.assertEqual(1, len(self.mock_isdir.call_args_list))
108+
109+ def test_uses_systemd_cached(self):
110+ """Test that we cache the uses_systemd result"""
111+
112+ # reset_cache should ensure it's unset
113+ self.assertEqual(None, util._USES_SYSTEMD)
114+
115+ # systemd enabled
116+ self.mock_isdir.return_value = True
117+
118+ # first time
119+ first_result = util.uses_systemd()
120+
121+ # check the cache value
122+ self.assertEqual(first_result, util._USES_SYSTEMD)
123+
124+ # second time
125+ second_result = util.uses_systemd()
126+
127+ # results should match between tries
128+ self.assertEqual(True, first_result)
129+ self.assertEqual(True, second_result)
130+
131+ # isdir should only be called once
132+ self.assertEqual(1, len(self.mock_isdir.call_args_list))
133+
134+ def test_uses_systemd_on_non_systemd(self):
135+ """ Test that uses_systemd returns False if sdpath is not a dir """
136+ # systemd not available
137+ self.mock_isdir.return_value = False
138+ result = util.uses_systemd()
139+ self.assertEqual(False, result)
140+
141+
142 # vi: ts=4 expandtab syntax=python
143
144=== modified file 'tests/vmtests/test_mdadm_iscsi.py'
145--- tests/vmtests/test_mdadm_iscsi.py 2017-08-02 15:46:35 +0000
146+++ tests/vmtests/test_mdadm_iscsi.py 2017-09-12 21:16:54 +0000
147@@ -36,3 +36,7 @@
148
149 class ZestyTestIscsiMdadm(relbase.zesty, TestMdadmIscsiAbs):
150 __test__ = True
151+
152+
153+class ArtfulTestIscsiMdadm(relbase.artful, TestMdadmIscsiAbs):
154+ __test__ = True

Subscribers

People subscribed via source and target branches