Merge ~ltrager/maas:lp1798471 into maas:master

Proposed by Lee Trager
Status: Rejected
Rejected by: Adam Collard
Proposed branch: ~ltrager/maas:lp1798471
Merge into: maas:master
Diff against target: 283 lines (+131/-17)
6 files modified
src/maasserver/api/machines.py (+12/-5)
src/maasserver/api/tests/test_machine.py (+65/-0)
src/maasserver/node_action.py (+4/-0)
src/maasserver/tests/test_node_action.py (+2/-1)
src/metadataserver/tests/test_vendor_data.py (+35/-8)
src/metadataserver/vendor_data.py (+13/-3)
Reviewer Review Type Date Requested Status
Blake Rouse (community) Needs Information
MAAS Lander Needs Fixing
Alberto Donato (community) Approve
Review via email: mp+368161@code.launchpad.net

Commit message

LP: #1798471 - Add option to enable SSH during VMware ESXi deployment

To post a comment you must log in.
Revision history for this message
Alberto Donato (ack) wrote :

LGTM

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b lp1798471 lp:~ltrager/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci-jenkins.internal:8080/job/maas/job/branch-tester/6131/console
COMMIT: 2f3b4cd38141f6ef7d8197dd0be3274fdef8e61b

review: Needs Fixing
Revision history for this message
Blake Rouse (blake-rouse) wrote :

This seems very wierd as a one off option to enable SSH when it doesn't affect other images that all have SSH. Can VMware just not have SSH enabled all the time?

review: Needs Information

Unmerged commits

2f3b4cd... by Lee Trager

LP: #1798471 - Add option to enable SSH during VMware ESXi deployment

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/machines.py b/src/maasserver/api/machines.py
2index ab5ab67..48a436b 100644
3--- a/src/maasserver/api/machines.py
4+++ b/src/maasserver/api/machines.py
5@@ -657,6 +657,9 @@ class MachineHandler(NodeHandler, OwnerDataMixin, PowerMixin):
6 @param (boolean) "vcenter_registration" [required=false] If false, do
7 not send globally defined VMware vCenter credentials to the machine.
8
9+ @param (boolean) "enable_ssh" [required=false] Send runcmd's to enable
10+ SSH(VMware ESXi only).
11+
12 @success (http-status-code) "200" 200
13 @success (json) "success-json" A JSON object containing information
14 about the deployed machine.
15@@ -745,11 +748,15 @@ class MachineHandler(NodeHandler, OwnerDataMixin, PowerMixin):
16 raise MAASAPIBadRequest(
17 "Failed to render preseed: %s" % e)
18
19- if machine.osystem == 'esxi' and request.user.has_perm(
20- NodePermission.admin, machine):
21- if get_optional_param(
22- request.POST, 'vcenter_registration', default=True,
23- validator=StringBool):
24+ if machine.osystem == 'esxi':
25+ machine.enable_ssh = get_optional_param(
26+ request.POST, 'enable_ssh', default=False,
27+ validator=StringBool)
28+ machine.save()
29+ if (request.user.has_perm(NodePermission.admin, machine) and
30+ get_optional_param(
31+ request.POST, 'vcenter_registration', default=True,
32+ validator=StringBool)):
33 NodeMetadata.objects.update_or_create(
34 node=machine, key='vcenter_registration',
35 defaults={'value': 'True'})
36diff --git a/src/maasserver/api/tests/test_machine.py b/src/maasserver/api/tests/test_machine.py
37index 6eb2cd6..62c1b5d 100644
38--- a/src/maasserver/api/tests/test_machine.py
39+++ b/src/maasserver/api/tests/test_machine.py
40@@ -826,6 +826,71 @@ class TestMachineAPI(APITestCase.ForUser):
41 bridge_all=True, bridge_fd=7,
42 bridge_stp=True, comment=None))
43
44+ def test_POST_deploy_disables_ssh_on_esxi_by_default(self):
45+ self.patch(node_module.Node, "_start")
46+ self.patch(machines_module, "get_curtin_merged_config")
47+ machine = factory.make_Node(
48+ owner=self.user, interface=True,
49+ power_type='manual',
50+ status=NODE_STATUS.READY,
51+ architecture=make_usable_architecture(self))
52+ osystem = make_usable_osystem(self, 'esxi', ['6.7'])
53+ distro_series = osystem['default_release']
54+ response = self.client.post(
55+ self.get_machine_uri(machine), {
56+ 'op': 'deploy',
57+ 'distro_series': distro_series,
58+ })
59+ self.assertEqual(
60+ (http.client.OK, machine.system_id),
61+ (response.status_code,
62+ json_load_bytes(response.content)['system_id']))
63+ self.assertFalse(reload_object(machine).enable_ssh)
64+
65+ def test_POST_deploy_enables_ssh_on_esxi(self):
66+ self.patch(node_module.Node, "_start")
67+ self.patch(machines_module, "get_curtin_merged_config")
68+ machine = factory.make_Node(
69+ owner=self.user, interface=True,
70+ power_type='manual',
71+ status=NODE_STATUS.READY,
72+ architecture=make_usable_architecture(self))
73+ osystem = make_usable_osystem(self, 'esxi', ['6.7'])
74+ distro_series = osystem['default_release']
75+ response = self.client.post(
76+ self.get_machine_uri(machine), {
77+ 'op': 'deploy',
78+ 'distro_series': distro_series,
79+ 'enable_ssh': True,
80+ })
81+ self.assertEqual(
82+ (http.client.OK, machine.system_id),
83+ (response.status_code,
84+ json_load_bytes(response.content)['system_id']))
85+ self.assertTrue(reload_object(machine).enable_ssh)
86+
87+ def test_POST_deploy_enables_ssh_does_nothing_on_other_os(self):
88+ self.patch(node_module.Node, "_start")
89+ self.patch(machines_module, "get_curtin_merged_config")
90+ machine = factory.make_Node(
91+ owner=self.user, interface=True,
92+ power_type='manual',
93+ status=NODE_STATUS.READY,
94+ architecture=make_usable_architecture(self))
95+ osystem = make_usable_osystem(self)
96+ distro_series = osystem['default_release']
97+ response = self.client.post(
98+ self.get_machine_uri(machine), {
99+ 'op': 'deploy',
100+ 'distro_series': distro_series,
101+ 'enable_ssh': True,
102+ })
103+ self.assertEqual(
104+ (http.client.OK, machine.system_id),
105+ (response.status_code,
106+ json_load_bytes(response.content)['system_id']))
107+ self.assertFalse(reload_object(machine).enable_ssh)
108+
109 def test_POST_deploy_stores_vcenter_registration_by_default(self):
110 self.become_admin()
111 self.patch(node_module.Node, "_start")
112diff --git a/src/maasserver/node_action.py b/src/maasserver/node_action.py
113index 32239ec..c95a564 100644
114--- a/src/maasserver/node_action.py
115+++ b/src/maasserver/node_action.py
116@@ -481,6 +481,10 @@ class Deploy(NodeAction):
117 self.node.osystem = configs['default_osystem']
118 self.node.distro_series = configs['default_distro_series']
119 self.node.save()
120+
121+ # SSH can only be enabled for VMware ESXi over the API.
122+ self.node.enable_ssh = False
123+
124 try:
125 self.node.hwe_kernel = validate_hwe_kernel(
126 hwe_kernel, self.node.min_hwe_kernel,
127diff --git a/src/maasserver/tests/test_node_action.py b/src/maasserver/tests/test_node_action.py
128index 7b3e256..56375d0 100644
129--- a/src/maasserver/tests/test_node_action.py
130+++ b/src/maasserver/tests/test_node_action.py
131@@ -707,7 +707,7 @@ class TestDeployAction(MAASServerTestCase):
132 request.user = user
133 node = factory.make_Node(
134 interface=True, status=NODE_STATUS.READY,
135- power_type='manual', owner=None)
136+ power_type='manual', owner=None, enable_ssh=True)
137 mock_get_curtin_config = self.patch(
138 node_action_module, 'get_curtin_config')
139 mock_node_start = self.patch(node, 'start')
140@@ -732,6 +732,7 @@ class TestDeployAction(MAASServerTestCase):
141 self.expectThat(node.osystem, Equals("ubuntu"))
142 self.expectThat(node.distro_series, Equals("bionic"))
143 self.expectThat(node.install_kvm, Equals(True))
144+ self.assertFalse(node.enable_ssh)
145
146 def test_Deploy_raises_NodeActionError_on_install_kvm_if_os_missing(self):
147 user = factory.make_admin()
148diff --git a/src/metadataserver/tests/test_vendor_data.py b/src/metadataserver/tests/test_vendor_data.py
149index 7d7a350..1bff5af 100644
150--- a/src/metadataserver/tests/test_vendor_data.py
151+++ b/src/metadataserver/tests/test_vendor_data.py
152@@ -306,19 +306,42 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase):
153
154 def test_does_nothing_if_not_vmware(self):
155 mock_get_configs = self.patch(Config.objects, 'get_configs')
156- node = factory.make_Node(owner=factory.make_admin())
157+ node = factory.make_Node(owner=factory.make_admin(), netboot=False)
158 config = get_vendor_data(node)
159 self.assertThat(mock_get_configs, MockNotCalled())
160 self.assertDictEqual({}, config)
161
162+ def test_does_nothing_if_netbooted(self):
163+ mock_get_configs = self.patch(Config.objects, 'get_configs')
164+ node = factory.make_Node(
165+ osystem='esxi', owner=factory.make_admin(), netboot=True)
166+ config = get_vendor_data(node)
167+ self.assertThat(mock_get_configs, MockNotCalled())
168+ self.assertDictEqual({}, config)
169+
170+ def test_enables_ssh(self):
171+ node = factory.make_Node(
172+ osystem='esxi', owner=factory.make_admin(), enable_ssh=True,
173+ netboot=False)
174+ config = get_vendor_data(node)
175+ self.assertDictEqual(
176+ {'runcmd': [
177+ ['vim-cmd', 'hostsvc/enable_ssh'],
178+ ['vim-cmd', 'hostsvc/start_ssh'],
179+ ['vim-cmd', 'hostsvc/enable_esx_shell'],
180+ ['vim-cmd', 'hostsvc/start_esx_shell'],
181+ ]}, config)
182+
183 def test_returns_nothing_if_no_values_set(self):
184- node = factory.make_Node(osystem='esxi', owner=factory.make_admin())
185+ node = factory.make_Node(
186+ osystem='esxi', owner=factory.make_admin(), netboot=False)
187 node.nodemetadata_set.create(key='vcenter_registration', value='True')
188 config = get_vendor_data(node)
189 self.assertDictEqual({}, config)
190
191 def test_returns_vcenter_yaml(self):
192- node = factory.make_Node(osystem='esxi', owner=factory.make_admin())
193+ node = factory.make_Node(
194+ osystem='esxi', owner=factory.make_admin(), netboot=False)
195 node.nodemetadata_set.create(key='vcenter_registration', value='True')
196 vcenter = {
197 'vcenter_server': factory.make_name('vcenter_server'),
198@@ -337,7 +360,8 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase):
199
200 def test_returns_vcenter_yaml_if_rbac_admin(self):
201 rbac = self.useFixture(RBACEnabled())
202- node = factory.make_Node(osystem='esxi', owner=factory.make_User())
203+ node = factory.make_Node(
204+ osystem='esxi', owner=factory.make_User(), netboot=False)
205 node.nodemetadata_set.create(key='vcenter_registration', value='True')
206 rbac.store.add_pool(node.pool)
207 rbac.store.allow(node.owner.username, node.pool, 'admin-machines')
208@@ -358,7 +382,8 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase):
209
210 def test_returns_nothing_if_rbac_user(self):
211 rbac = self.useFixture(RBACEnabled())
212- node = factory.make_Node(osystem='esxi', owner=factory.make_User())
213+ node = factory.make_Node(
214+ osystem='esxi', owner=factory.make_User(), netboot=False)
215 node.nodemetadata_set.create(key='vcenter_registration', value='True')
216 rbac.store.add_pool(node.pool)
217 rbac.store.allow(node.owner.username, node.pool, 'deploy-machines')
218@@ -374,7 +399,7 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase):
219 self.assertDictEqual({}, config)
220
221 def test_returns_nothing_if_no_user(self):
222- node = factory.make_Node(osystem='esxi')
223+ node = factory.make_Node(osystem='esxi', netboot=False)
224 for i in ['server', 'username', 'password', 'datacenter']:
225 key = 'vcenter_%s' % i
226 Config.objects.set_config(key, factory.make_name(key))
227@@ -382,7 +407,8 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase):
228 self.assertDictEqual({}, config)
229
230 def test_returns_nothing_if_user(self):
231- node = factory.make_Node(osystem='esxi', owner=factory.make_User())
232+ node = factory.make_Node(
233+ osystem='esxi', owner=factory.make_User(), netboot=False)
234 for i in ['server', 'username', 'password', 'datacenter']:
235 key = 'vcenter_%s' % i
236 Config.objects.set_config(key, factory.make_name(key))
237@@ -390,7 +416,8 @@ class TestGenerateVcenterConfiguration(MAASServerTestCase):
238 self.assertDictEqual({}, config)
239
240 def test_returns_nothing_if_vcenter_registration_not_set(self):
241- node = factory.make_Node(osystem='esxi', owner=factory.make_admin())
242+ node = factory.make_Node(
243+ osystem='esxi', owner=factory.make_admin(), netboot=False)
244 for i in ['server', 'username', 'password', 'datacenter']:
245 key = 'vcenter_%s' % i
246 Config.objects.set_config(key, factory.make_name(key))
247diff --git a/src/metadataserver/vendor_data.py b/src/metadataserver/vendor_data.py
248index 5010302..93ec9a6 100644
249--- a/src/metadataserver/vendor_data.py
250+++ b/src/metadataserver/vendor_data.py
251@@ -35,7 +35,7 @@ def get_vendor_data(node):
252 generate_rack_controller_configuration(node),
253 generate_kvm_pod_configuration(node),
254 generate_ephemeral_deployment_network_configuration(node),
255- generate_vcenter_configuration(node),
256+ generate_esxi_configuration(node),
257 ))
258
259
260@@ -202,11 +202,21 @@ def generate_kvm_pod_configuration(node):
261 yield "packages", packages
262
263
264-def generate_vcenter_configuration(node):
265+def generate_esxi_configuration(node):
266 """Generate vendor config when deploying ESXi."""
267- if node.osystem != 'esxi':
268+ if node.osystem != 'esxi' or node.netboot:
269 # Only return vcenter credentials if vcenter is being deployed.
270 return
271+ # By default VMware ESXi disables SSH and strongly discourages users from
272+ # enabling. Only enable if told to do so, otherwise keep image default.
273+ if node.enable_ssh:
274+ yield 'runcmd', [
275+ ['vim-cmd', 'hostsvc/enable_ssh'],
276+ ['vim-cmd', 'hostsvc/start_ssh'],
277+ # Enable the local shell as well.
278+ ['vim-cmd', 'hostsvc/enable_esx_shell'],
279+ ['vim-cmd', 'hostsvc/start_esx_shell'],
280+ ]
281 if not node.owner or not node.owner.has_perm(NodePermission.admin, node):
282 # VMware vCenter credentials are only given to machines deployed by
283 # administrators.

Subscribers

People subscribed via source and target branches