Merge ~chad.smith/cloud-init:bug/1840080-ubuntu-drivers-emit-latelink-v2 into cloud-init:master
- Git
- lp:~chad.smith/cloud-init
- bug/1840080-ubuntu-drivers-emit-latelink-v2
- Merge into master
Status: | Merged |
---|---|
Approved by: | Dan Watkins |
Approved revision: | 2eb8eee7281a84a832f865a7ddd0edabe534e987 |
Merge reported by: | Server Team CI bot |
Merged at revision: | not available |
Proposed branch: | ~chad.smith/cloud-init:bug/1840080-ubuntu-drivers-emit-latelink-v2 |
Merge into: | cloud-init:master |
Diff against target: |
310 lines (+130/-36) 3 files modified
cloudinit/config/cc_ubuntu_drivers.py (+48/-10) cloudinit/config/tests/test_ubuntu_drivers.py (+80/-25) cloudinit/tests/helpers.py (+2/-1) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
cloud-init Commiters | Pending | ||
Review via email: mp+371546@code.launchpad.net |
Commit message
ubuntu-drivers: call db_x_loadtempla
Emit a script allowing cloud-init to set linux/nvidia/
debconf selection to true. This avoids having to call
debconf-
linux-restricte
Cloud-init loads this debconf template and sets the value to true in the
debconf database by sourcing debconf's /usr/share/
uses db_x_loadtempla
linux/nvidia/
LP: #1840080
Description of the change
Server Team CI bot (server-team-bot) wrote : | # |
Ryan Harper (raharper) wrote : | # |
some inline comments/
Chad Smith (chad.smith) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:71fcd42be63
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:48733aa42ac
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:cdd846983dc
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
FAILED: Ubuntu LTS: Integration
Click here to trigger a rebuild:
https:/
Chad Smith (chad.smith) wrote : | # |
Just validated on Eoan that this package properly sets up linux/nvidia/
The ubuntu-
As it is, this behavior paves the way for the ubuntu-
# cloud-init properly registers and sets linux/nvidia/
ubuntu@
cloud-init linux/nvidia/
cloud-init cloud-init/
# ubuntu-
dpkg -l | egrep 'cloud-
ii cloud-init 19.2-21-
ii cloud-initramfs
ii cloud-initramfs
ii libnvidia-
ii libnvidia-
ii nvidia-
ii nvidia-
ii nvidia-
ii ubuntu-
### If we manually install linux-modules-
ubuntu@
cloud-init linux/nvidia/
linux-modules-
# from dpkg -l on eoan-proposed
ii linux-modules-
Ryan Harper (raharper) wrote : | # |
Implementation looks great. One suggestion on the template description.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:cdd846983dc
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:8da37261c56
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:19dbf5e1449
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
Autolanding: FAILED
More details in the following jenkins job:
https:/
Executed test runs:
FAILED: Checkout
Dan Watkins (oddbloke) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
Autolanding: FAILED
More details in the following jenkins job:
https:/
Executed test runs:
FAILED: Checkout
Server Team CI bot (server-team-bot) wrote : | # |
Autolanding: FAILED
More details in the following jenkins job:
https:/
Executed test runs:
FAILED: Checkout
Server Team CI bot (server-team-bot) : | # |
Server Team CI bot (server-team-bot) wrote : | # |
Autolanding: FAILED
Unapproved changes made after approval.
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
IN_PROGRESS: Declarative: Post Actions
Server Team CI bot (server-team-bot) : | # |
Preview Diff
1 | diff --git a/cloudinit/config/cc_ubuntu_drivers.py b/cloudinit/config/cc_ubuntu_drivers.py | |||
2 | index 4da34ee..297451d 100644 | |||
3 | --- a/cloudinit/config/cc_ubuntu_drivers.py | |||
4 | +++ b/cloudinit/config/cc_ubuntu_drivers.py | |||
5 | @@ -2,13 +2,14 @@ | |||
6 | 2 | 2 | ||
7 | 3 | """Ubuntu Drivers: Interact with third party drivers in Ubuntu.""" | 3 | """Ubuntu Drivers: Interact with third party drivers in Ubuntu.""" |
8 | 4 | 4 | ||
9 | 5 | import os | ||
10 | 5 | from textwrap import dedent | 6 | from textwrap import dedent |
11 | 6 | 7 | ||
12 | 7 | from cloudinit.config import cc_apt_configure | ||
13 | 8 | from cloudinit.config.schema import ( | 8 | from cloudinit.config.schema import ( |
14 | 9 | get_schema_doc, validate_cloudconfig_schema) | 9 | get_schema_doc, validate_cloudconfig_schema) |
15 | 10 | from cloudinit import log as logging | 10 | from cloudinit import log as logging |
16 | 11 | from cloudinit.settings import PER_INSTANCE | 11 | from cloudinit.settings import PER_INSTANCE |
17 | 12 | from cloudinit import temp_utils | ||
18 | 12 | from cloudinit import type_utils | 13 | from cloudinit import type_utils |
19 | 13 | from cloudinit import util | 14 | from cloudinit import util |
20 | 14 | 15 | ||
21 | @@ -65,6 +66,33 @@ OLD_UBUNTU_DRIVERS_STDERR_NEEDLE = ( | |||
22 | 65 | __doc__ = get_schema_doc(schema) # Supplement python help() | 66 | __doc__ = get_schema_doc(schema) # Supplement python help() |
23 | 66 | 67 | ||
24 | 67 | 68 | ||
25 | 69 | # Use a debconf template to configure a global debconf variable | ||
26 | 70 | # (linux/nvidia/latelink) setting this to "true" allows the | ||
27 | 71 | # 'linux-restricted-modules' deb to accept the NVIDIA EULA and the package | ||
28 | 72 | # will automatically link the drivers to the running kernel. | ||
29 | 73 | |||
30 | 74 | # EOL_XENIAL: can then drop this script and use python3-debconf which is only | ||
31 | 75 | # available in Bionic and later. Can't use python3-debconf currently as it | ||
32 | 76 | # isn't in Xenial and doesn't yet support X_LOADTEMPLATEFILE debconf command. | ||
33 | 77 | |||
34 | 78 | NVIDIA_DEBCONF_CONTENT = """\ | ||
35 | 79 | Template: linux/nvidia/latelink | ||
36 | 80 | Type: boolean | ||
37 | 81 | Default: true | ||
38 | 82 | Description: Late-link NVIDIA kernel modules? | ||
39 | 83 | Enable this to link the NVIDIA kernel modules in cloud-init and | ||
40 | 84 | make them available for use. | ||
41 | 85 | """ | ||
42 | 86 | |||
43 | 87 | NVIDIA_DRIVER_LATELINK_DEBCONF_SCRIPT = """\ | ||
44 | 88 | #!/bin/sh | ||
45 | 89 | # Allow cloud-init to trigger EULA acceptance via registering a debconf | ||
46 | 90 | # template to set linux/nvidia/latelink true | ||
47 | 91 | . /usr/share/debconf/confmodule | ||
48 | 92 | db_x_loadtemplatefile "$1" cloud-init | ||
49 | 93 | """ | ||
50 | 94 | |||
51 | 95 | |||
52 | 68 | def install_drivers(cfg, pkg_install_func): | 96 | def install_drivers(cfg, pkg_install_func): |
53 | 69 | if not isinstance(cfg, dict): | 97 | if not isinstance(cfg, dict): |
54 | 70 | raise TypeError( | 98 | raise TypeError( |
55 | @@ -90,17 +118,27 @@ def install_drivers(cfg, pkg_install_func): | |||
56 | 90 | if version_cfg: | 118 | if version_cfg: |
57 | 91 | driver_arg += ':{}'.format(version_cfg) | 119 | driver_arg += ':{}'.format(version_cfg) |
58 | 92 | 120 | ||
60 | 93 | LOG.debug("Installing NVIDIA drivers (%s=%s, version=%s)", | 121 | LOG.debug("Installing and activating NVIDIA drivers (%s=%s, version=%s)", |
61 | 94 | cfgpath, nv_acc, version_cfg if version_cfg else 'latest') | 122 | cfgpath, nv_acc, version_cfg if version_cfg else 'latest') |
62 | 95 | 123 | ||
71 | 96 | # Setting NVIDIA latelink confirms acceptance of EULA for the package | 124 | # Register and set debconf selection linux/nvidia/latelink = true |
72 | 97 | # linux-restricted-modules | 125 | tdir = temp_utils.mkdtemp(needs_exe=True) |
73 | 98 | # Reference code defining debconf variable is here | 126 | debconf_file = os.path.join(tdir, 'nvidia.template') |
74 | 99 | # https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/ | 127 | debconf_script = os.path.join(tdir, 'nvidia-debconf.sh') |
75 | 100 | # linux-restricted-modules/+git/eoan/tree/debian/templates/ | 128 | try: |
76 | 101 | # nvidia.templates.in | 129 | util.write_file(debconf_file, NVIDIA_DEBCONF_CONTENT) |
77 | 102 | selections = b'linux-restricted-modules linux/nvidia/latelink boolean true' | 130 | util.write_file( |
78 | 103 | cc_apt_configure.debconf_set_selections(selections) | 131 | debconf_script, |
79 | 132 | util.encode_text(NVIDIA_DRIVER_LATELINK_DEBCONF_SCRIPT), | ||
80 | 133 | mode=0o755) | ||
81 | 134 | util.subp([debconf_script, debconf_file]) | ||
82 | 135 | except Exception as e: | ||
83 | 136 | util.logexc( | ||
84 | 137 | LOG, "Failed to register NVIDIA debconf template: %s", str(e)) | ||
85 | 138 | raise | ||
86 | 139 | finally: | ||
87 | 140 | if os.path.isdir(tdir): | ||
88 | 141 | util.del_dir(tdir) | ||
89 | 104 | 142 | ||
90 | 105 | try: | 143 | try: |
91 | 106 | util.subp(['ubuntu-drivers', 'install', '--gpgpu', driver_arg]) | 144 | util.subp(['ubuntu-drivers', 'install', '--gpgpu', driver_arg]) |
92 | diff --git a/cloudinit/config/tests/test_ubuntu_drivers.py b/cloudinit/config/tests/test_ubuntu_drivers.py | |||
93 | index 6a763bd..4695269 100644 | |||
94 | --- a/cloudinit/config/tests/test_ubuntu_drivers.py | |||
95 | +++ b/cloudinit/config/tests/test_ubuntu_drivers.py | |||
96 | @@ -1,6 +1,7 @@ | |||
97 | 1 | # This file is part of cloud-init. See LICENSE file for license information. | 1 | # This file is part of cloud-init. See LICENSE file for license information. |
98 | 2 | 2 | ||
99 | 3 | import copy | 3 | import copy |
100 | 4 | import os | ||
101 | 4 | 5 | ||
102 | 5 | from cloudinit.tests.helpers import CiTestCase, skipUnlessJsonSchema, mock | 6 | from cloudinit.tests.helpers import CiTestCase, skipUnlessJsonSchema, mock |
103 | 6 | from cloudinit.config.schema import ( | 7 | from cloudinit.config.schema import ( |
104 | @@ -9,11 +10,27 @@ from cloudinit.config import cc_ubuntu_drivers as drivers | |||
105 | 9 | from cloudinit.util import ProcessExecutionError | 10 | from cloudinit.util import ProcessExecutionError |
106 | 10 | 11 | ||
107 | 11 | MPATH = "cloudinit.config.cc_ubuntu_drivers." | 12 | MPATH = "cloudinit.config.cc_ubuntu_drivers." |
108 | 13 | M_TMP_PATH = MPATH + "temp_utils.mkdtemp" | ||
109 | 12 | OLD_UBUNTU_DRIVERS_ERROR_STDERR = ( | 14 | OLD_UBUNTU_DRIVERS_ERROR_STDERR = ( |
110 | 13 | "ubuntu-drivers: error: argument <command>: invalid choice: 'install' " | 15 | "ubuntu-drivers: error: argument <command>: invalid choice: 'install' " |
111 | 14 | "(choose from 'list', 'autoinstall', 'devices', 'debug')\n") | 16 | "(choose from 'list', 'autoinstall', 'devices', 'debug')\n") |
112 | 15 | 17 | ||
113 | 16 | 18 | ||
114 | 19 | class AnyTempScriptAndDebconfFile(object): | ||
115 | 20 | |||
116 | 21 | def __init__(self, tmp_dir, debconf_file): | ||
117 | 22 | self.tmp_dir = tmp_dir | ||
118 | 23 | self.debconf_file = debconf_file | ||
119 | 24 | |||
120 | 25 | def __eq__(self, cmd): | ||
121 | 26 | if not len(cmd) == 2: | ||
122 | 27 | return False | ||
123 | 28 | script, debconf_file = cmd | ||
124 | 29 | if bool(script.startswith(self.tmp_dir) and script.endswith('.sh')): | ||
125 | 30 | return debconf_file == self.debconf_file | ||
126 | 31 | return False | ||
127 | 32 | |||
128 | 33 | |||
129 | 17 | class TestUbuntuDrivers(CiTestCase): | 34 | class TestUbuntuDrivers(CiTestCase): |
130 | 18 | cfg_accepted = {'drivers': {'nvidia': {'license-accepted': True}}} | 35 | cfg_accepted = {'drivers': {'nvidia': {'license-accepted': True}}} |
131 | 19 | install_gpgpu = ['ubuntu-drivers', 'install', '--gpgpu', 'nvidia'] | 36 | install_gpgpu = ['ubuntu-drivers', 'install', '--gpgpu', 'nvidia'] |
132 | @@ -28,20 +45,23 @@ class TestUbuntuDrivers(CiTestCase): | |||
133 | 28 | {'drivers': {'nvidia': {'license-accepted': "TRUE"}}}, | 45 | {'drivers': {'nvidia': {'license-accepted': "TRUE"}}}, |
134 | 29 | schema=drivers.schema, strict=True) | 46 | schema=drivers.schema, strict=True) |
135 | 30 | 47 | ||
137 | 31 | @mock.patch(MPATH + "cc_apt_configure.debconf_set_selections") | 48 | @mock.patch(M_TMP_PATH) |
138 | 32 | @mock.patch(MPATH + "util.subp", return_value=('', '')) | 49 | @mock.patch(MPATH + "util.subp", return_value=('', '')) |
139 | 33 | @mock.patch(MPATH + "util.which", return_value=False) | 50 | @mock.patch(MPATH + "util.which", return_value=False) |
140 | 34 | def _assert_happy_path_taken( | 51 | def _assert_happy_path_taken( |
142 | 35 | self, config, m_which, m_subp, m_debconf_set_selections): | 52 | self, config, m_which, m_subp, m_tmp): |
143 | 36 | """Positive path test through handle. Package should be installed.""" | 53 | """Positive path test through handle. Package should be installed.""" |
144 | 54 | tdir = self.tmp_dir() | ||
145 | 55 | debconf_file = os.path.join(tdir, 'nvidia.template') | ||
146 | 56 | m_tmp.return_value = tdir | ||
147 | 37 | myCloud = mock.MagicMock() | 57 | myCloud = mock.MagicMock() |
148 | 38 | drivers.handle('ubuntu_drivers', config, myCloud, None, None) | 58 | drivers.handle('ubuntu_drivers', config, myCloud, None, None) |
149 | 39 | self.assertEqual([mock.call(['ubuntu-drivers-common'])], | 59 | self.assertEqual([mock.call(['ubuntu-drivers-common'])], |
150 | 40 | myCloud.distro.install_packages.call_args_list) | 60 | myCloud.distro.install_packages.call_args_list) |
155 | 41 | self.assertEqual([mock.call(self.install_gpgpu)], | 61 | self.assertEqual( |
156 | 42 | m_subp.call_args_list) | 62 | [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)), |
157 | 43 | m_debconf_set_selections.assert_called_with( | 63 | mock.call(self.install_gpgpu)], |
158 | 44 | b'linux-restricted-modules linux/nvidia/latelink boolean true') | 64 | m_subp.call_args_list) |
159 | 45 | 65 | ||
160 | 46 | def test_handle_does_package_install(self): | 66 | def test_handle_does_package_install(self): |
161 | 47 | self._assert_happy_path_taken(self.cfg_accepted) | 67 | self._assert_happy_path_taken(self.cfg_accepted) |
162 | @@ -52,20 +72,33 @@ class TestUbuntuDrivers(CiTestCase): | |||
163 | 52 | new_config['drivers']['nvidia']['license-accepted'] = true_value | 72 | new_config['drivers']['nvidia']['license-accepted'] = true_value |
164 | 53 | self._assert_happy_path_taken(new_config) | 73 | self._assert_happy_path_taken(new_config) |
165 | 54 | 74 | ||
169 | 55 | @mock.patch(MPATH + "cc_apt_configure.debconf_set_selections") | 75 | @mock.patch(M_TMP_PATH) |
170 | 56 | @mock.patch(MPATH + "util.subp", side_effect=ProcessExecutionError( | 76 | @mock.patch(MPATH + "util.subp") |
168 | 57 | stdout='No drivers found for installation.\n', exit_code=1)) | ||
171 | 58 | @mock.patch(MPATH + "util.which", return_value=False) | 77 | @mock.patch(MPATH + "util.which", return_value=False) |
173 | 59 | def test_handle_raises_error_if_no_drivers_found(self, m_which, m_subp, _): | 78 | def test_handle_raises_error_if_no_drivers_found( |
174 | 79 | self, m_which, m_subp, m_tmp): | ||
175 | 60 | """If ubuntu-drivers doesn't install any drivers, raise an error.""" | 80 | """If ubuntu-drivers doesn't install any drivers, raise an error.""" |
176 | 81 | tdir = self.tmp_dir() | ||
177 | 82 | debconf_file = os.path.join(tdir, 'nvidia.template') | ||
178 | 83 | m_tmp.return_value = tdir | ||
179 | 61 | myCloud = mock.MagicMock() | 84 | myCloud = mock.MagicMock() |
180 | 85 | |||
181 | 86 | def fake_subp(cmd): | ||
182 | 87 | if cmd[0].startswith(tdir): | ||
183 | 88 | return | ||
184 | 89 | raise ProcessExecutionError( | ||
185 | 90 | stdout='No drivers found for installation.\n', exit_code=1) | ||
186 | 91 | m_subp.side_effect = fake_subp | ||
187 | 92 | |||
188 | 62 | with self.assertRaises(Exception): | 93 | with self.assertRaises(Exception): |
189 | 63 | drivers.handle( | 94 | drivers.handle( |
190 | 64 | 'ubuntu_drivers', self.cfg_accepted, myCloud, None, None) | 95 | 'ubuntu_drivers', self.cfg_accepted, myCloud, None, None) |
191 | 65 | self.assertEqual([mock.call(['ubuntu-drivers-common'])], | 96 | self.assertEqual([mock.call(['ubuntu-drivers-common'])], |
192 | 66 | myCloud.distro.install_packages.call_args_list) | 97 | myCloud.distro.install_packages.call_args_list) |
195 | 67 | self.assertEqual([mock.call(self.install_gpgpu)], | 98 | self.assertEqual( |
196 | 68 | m_subp.call_args_list) | 99 | [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)), |
197 | 100 | mock.call(self.install_gpgpu)], | ||
198 | 101 | m_subp.call_args_list) | ||
199 | 69 | self.assertIn('ubuntu-drivers found no drivers for installation', | 102 | self.assertIn('ubuntu-drivers found no drivers for installation', |
200 | 70 | self.logs.getvalue()) | 103 | self.logs.getvalue()) |
201 | 71 | 104 | ||
202 | @@ -113,19 +146,25 @@ class TestUbuntuDrivers(CiTestCase): | |||
203 | 113 | myLog.debug.call_args_list[0][0][0]) | 146 | myLog.debug.call_args_list[0][0][0]) |
204 | 114 | self.assertEqual(0, m_install_drivers.call_count) | 147 | self.assertEqual(0, m_install_drivers.call_count) |
205 | 115 | 148 | ||
207 | 116 | @mock.patch(MPATH + "cc_apt_configure.debconf_set_selections") | 149 | @mock.patch(M_TMP_PATH) |
208 | 117 | @mock.patch(MPATH + "util.subp", return_value=('', '')) | 150 | @mock.patch(MPATH + "util.subp", return_value=('', '')) |
209 | 118 | @mock.patch(MPATH + "util.which", return_value=True) | 151 | @mock.patch(MPATH + "util.which", return_value=True) |
211 | 119 | def test_install_drivers_no_install_if_present(self, m_which, m_subp, _): | 152 | def test_install_drivers_no_install_if_present( |
212 | 153 | self, m_which, m_subp, m_tmp): | ||
213 | 120 | """If 'ubuntu-drivers' is present, no package install should occur.""" | 154 | """If 'ubuntu-drivers' is present, no package install should occur.""" |
214 | 155 | tdir = self.tmp_dir() | ||
215 | 156 | debconf_file = os.path.join(tdir, 'nvidia.template') | ||
216 | 157 | m_tmp.return_value = tdir | ||
217 | 121 | pkg_install = mock.MagicMock() | 158 | pkg_install = mock.MagicMock() |
218 | 122 | drivers.install_drivers(self.cfg_accepted['drivers'], | 159 | drivers.install_drivers(self.cfg_accepted['drivers'], |
219 | 123 | pkg_install_func=pkg_install) | 160 | pkg_install_func=pkg_install) |
220 | 124 | self.assertEqual(0, pkg_install.call_count) | 161 | self.assertEqual(0, pkg_install.call_count) |
221 | 125 | self.assertEqual([mock.call('ubuntu-drivers')], | 162 | self.assertEqual([mock.call('ubuntu-drivers')], |
222 | 126 | m_which.call_args_list) | 163 | m_which.call_args_list) |
225 | 127 | self.assertEqual([mock.call(self.install_gpgpu)], | 164 | self.assertEqual( |
226 | 128 | m_subp.call_args_list) | 165 | [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)), |
227 | 166 | mock.call(self.install_gpgpu)], | ||
228 | 167 | m_subp.call_args_list) | ||
229 | 129 | 168 | ||
230 | 130 | def test_install_drivers_rejects_invalid_config(self): | 169 | def test_install_drivers_rejects_invalid_config(self): |
231 | 131 | """install_drivers should raise TypeError if not given a config dict""" | 170 | """install_drivers should raise TypeError if not given a config dict""" |
232 | @@ -134,21 +173,33 @@ class TestUbuntuDrivers(CiTestCase): | |||
233 | 134 | drivers.install_drivers("mystring", pkg_install_func=pkg_install) | 173 | drivers.install_drivers("mystring", pkg_install_func=pkg_install) |
234 | 135 | self.assertEqual(0, pkg_install.call_count) | 174 | self.assertEqual(0, pkg_install.call_count) |
235 | 136 | 175 | ||
239 | 137 | @mock.patch(MPATH + "cc_apt_configure.debconf_set_selections") | 176 | @mock.patch(M_TMP_PATH) |
240 | 138 | @mock.patch(MPATH + "util.subp", side_effect=ProcessExecutionError( | 177 | @mock.patch(MPATH + "util.subp") |
238 | 139 | stderr=OLD_UBUNTU_DRIVERS_ERROR_STDERR, exit_code=2)) | ||
241 | 140 | @mock.patch(MPATH + "util.which", return_value=False) | 178 | @mock.patch(MPATH + "util.which", return_value=False) |
242 | 141 | def test_install_drivers_handles_old_ubuntu_drivers_gracefully( | 179 | def test_install_drivers_handles_old_ubuntu_drivers_gracefully( |
244 | 142 | self, m_which, m_subp, _): | 180 | self, m_which, m_subp, m_tmp): |
245 | 143 | """Older ubuntu-drivers versions should emit message and raise error""" | 181 | """Older ubuntu-drivers versions should emit message and raise error""" |
246 | 182 | tdir = self.tmp_dir() | ||
247 | 183 | debconf_file = os.path.join(tdir, 'nvidia.template') | ||
248 | 184 | m_tmp.return_value = tdir | ||
249 | 144 | myCloud = mock.MagicMock() | 185 | myCloud = mock.MagicMock() |
250 | 186 | |||
251 | 187 | def fake_subp(cmd): | ||
252 | 188 | if cmd[0].startswith(tdir): | ||
253 | 189 | return | ||
254 | 190 | raise ProcessExecutionError( | ||
255 | 191 | stderr=OLD_UBUNTU_DRIVERS_ERROR_STDERR, exit_code=2) | ||
256 | 192 | m_subp.side_effect = fake_subp | ||
257 | 193 | |||
258 | 145 | with self.assertRaises(Exception): | 194 | with self.assertRaises(Exception): |
259 | 146 | drivers.handle( | 195 | drivers.handle( |
260 | 147 | 'ubuntu_drivers', self.cfg_accepted, myCloud, None, None) | 196 | 'ubuntu_drivers', self.cfg_accepted, myCloud, None, None) |
261 | 148 | self.assertEqual([mock.call(['ubuntu-drivers-common'])], | 197 | self.assertEqual([mock.call(['ubuntu-drivers-common'])], |
262 | 149 | myCloud.distro.install_packages.call_args_list) | 198 | myCloud.distro.install_packages.call_args_list) |
265 | 150 | self.assertEqual([mock.call(self.install_gpgpu)], | 199 | self.assertEqual( |
266 | 151 | m_subp.call_args_list) | 200 | [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)), |
267 | 201 | mock.call(self.install_gpgpu)], | ||
268 | 202 | m_subp.call_args_list) | ||
269 | 152 | self.assertIn('WARNING: the available version of ubuntu-drivers is' | 203 | self.assertIn('WARNING: the available version of ubuntu-drivers is' |
270 | 153 | ' too old to perform requested driver installation', | 204 | ' too old to perform requested driver installation', |
271 | 154 | self.logs.getvalue()) | 205 | self.logs.getvalue()) |
272 | @@ -160,17 +211,21 @@ class TestUbuntuDriversWithVersion(TestUbuntuDrivers): | |||
273 | 160 | 'drivers': {'nvidia': {'license-accepted': True, 'version': '123'}}} | 211 | 'drivers': {'nvidia': {'license-accepted': True, 'version': '123'}}} |
274 | 161 | install_gpgpu = ['ubuntu-drivers', 'install', '--gpgpu', 'nvidia:123'] | 212 | install_gpgpu = ['ubuntu-drivers', 'install', '--gpgpu', 'nvidia:123'] |
275 | 162 | 213 | ||
277 | 163 | @mock.patch(MPATH + "cc_apt_configure.debconf_set_selections") | 214 | @mock.patch(M_TMP_PATH) |
278 | 164 | @mock.patch(MPATH + "util.subp", return_value=('', '')) | 215 | @mock.patch(MPATH + "util.subp", return_value=('', '')) |
279 | 165 | @mock.patch(MPATH + "util.which", return_value=False) | 216 | @mock.patch(MPATH + "util.which", return_value=False) |
281 | 166 | def test_version_none_uses_latest(self, m_which, m_subp, _): | 217 | def test_version_none_uses_latest(self, m_which, m_subp, m_tmp): |
282 | 218 | tdir = self.tmp_dir() | ||
283 | 219 | debconf_file = os.path.join(tdir, 'nvidia.template') | ||
284 | 220 | m_tmp.return_value = tdir | ||
285 | 167 | myCloud = mock.MagicMock() | 221 | myCloud = mock.MagicMock() |
286 | 168 | version_none_cfg = { | 222 | version_none_cfg = { |
287 | 169 | 'drivers': {'nvidia': {'license-accepted': True, 'version': None}}} | 223 | 'drivers': {'nvidia': {'license-accepted': True, 'version': None}}} |
288 | 170 | drivers.handle( | 224 | drivers.handle( |
289 | 171 | 'ubuntu_drivers', version_none_cfg, myCloud, None, None) | 225 | 'ubuntu_drivers', version_none_cfg, myCloud, None, None) |
290 | 172 | self.assertEqual( | 226 | self.assertEqual( |
292 | 173 | [mock.call(['ubuntu-drivers', 'install', '--gpgpu', 'nvidia'])], | 227 | [mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)), |
293 | 228 | mock.call(['ubuntu-drivers', 'install', '--gpgpu', 'nvidia'])], | ||
294 | 174 | m_subp.call_args_list) | 229 | m_subp.call_args_list) |
295 | 175 | 230 | ||
296 | 176 | def test_specifying_a_version_doesnt_override_license_acceptance(self): | 231 | def test_specifying_a_version_doesnt_override_license_acceptance(self): |
297 | diff --git a/cloudinit/tests/helpers.py b/cloudinit/tests/helpers.py | |||
298 | index f41180f..23fddd0 100644 | |||
299 | --- a/cloudinit/tests/helpers.py | |||
300 | +++ b/cloudinit/tests/helpers.py | |||
301 | @@ -198,7 +198,8 @@ class CiTestCase(TestCase): | |||
302 | 198 | prefix="ci-%s." % self.__class__.__name__) | 198 | prefix="ci-%s." % self.__class__.__name__) |
303 | 199 | else: | 199 | else: |
304 | 200 | tmpd = tempfile.mkdtemp(dir=dir) | 200 | tmpd = tempfile.mkdtemp(dir=dir) |
306 | 201 | self.addCleanup(functools.partial(shutil.rmtree, tmpd)) | 201 | self.addCleanup( |
307 | 202 | functools.partial(shutil.rmtree, tmpd, ignore_errors=True)) | ||
308 | 202 | return tmpd | 203 | return tmpd |
309 | 203 | 204 | ||
310 | 204 | def tmp_path(self, path, dir=None): | 205 | def tmp_path(self, path, dir=None): |
FAILED: Continuous integration, rev:044f9d692eb ca82186b9159a69 e75816ad99f998 /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 1060/
https:/
Executed test runs:
SUCCESS: Checkout
FAILED: Unit & Style Tests
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 1060//rebuild
https:/