Merge ~ltrager/maas:lp1830303 into maas:master

Proposed by Lee Trager
Status: Merged
Approved by: Lee Trager
Approved revision: 5e0d730b8446631248dd0328f171bb14a3545386
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~ltrager/maas:lp1830303
Merge into: maas:master
Diff against target: 289 lines (+66/-39)
11 files modified
src/maasserver/api/tests/test_vmfs_datastores.py (+8/-1)
src/maasserver/api/vmfs_datastores.py (+14/-0)
src/maasserver/models/filesystemgroup.py (+3/-0)
src/maasserver/models/tests/test_filesystemgroup.py (+9/-0)
src/maasserver/static/js/angular/controllers/node_details_storage.js (+2/-2)
src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js (+5/-9)
src/maasserver/static/partials/nodedetails/storage/datastores.html (+3/-3)
src/maasserver/static/partials/nodedetails/storage/disks-partitions.html (+3/-3)
src/maasserver/tests/test_preseed_storage.py (+18/-0)
src/maasserver/websockets/handlers/node.py (+1/-11)
src/maasserver/websockets/handlers/tests/test_machine.py (+0/-10)
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+367887@code.launchpad.net

Commit message

LP: #1830303 - Show the VMFS datastore mount point.

The UI and API now both show the VMFS datastore mount point. While VMware
ESXi's UI shows /vmfs/volumes/<UUID> MAAS shows
/vmfs/volumes/<datastore name>. This is because VMware ESXi does not allow
you to specify the UUID so there is no way to know what it is. On a deployed
VMware ESXi system /vmfs/volumes/<datastore name> is a symbolic link to
/vmfs/volumes/<UUID>.

To post a comment you must log in.
Revision history for this message
Anthony Dillon (ya-bo-ng) wrote :

Lee, used_for is also used in the disks-partitions.html L886.

Revision history for this message
Martin Storey (cassiocassio) wrote :

Lee: if the user copies that path that we are able to show in the GUI

- does is reliably point to the real path post deploy? can they e.g. use it in scripts etc?

- is there any way, or any value in extracting the real path back into the MAAS UI post-deploy? That's not currently MAAS's business, right?

Revision history for this message
Lee Trager (ltrager) wrote :

Thanks for the review. I've fixed the remaining sections which contained used_for === "VMFS Datastore" and verified all messages, options are working.

What this change does is add a filesystem on top of the datastore which properly defines where the datastore will be mounted. The current path given(e.g /dev/disk/by-dname/sda) is the Linux block device path and does not exist in VMware. The new path(/vmfs/volumes/<datastore name>) does exist on a deployed ESXi host so scripts can use that path. There currently isn't a way for storage data to be sent back post-deployment but the new path is valid.

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

Looks good.

I like the addition of filesystem on top of the datastore, because that is true it is a filesystem.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
~ltrager/maas:lp1830303 updated
5e0d730... by Lee Trager

Fix failing test

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/tests/test_vmfs_datastores.py b/src/maasserver/api/tests/test_vmfs_datastores.py
2index 15f405a..4eed96d 100644
3--- a/src/maasserver/api/tests/test_vmfs_datastores.py
4+++ b/src/maasserver/api/tests/test_vmfs_datastores.py
5@@ -13,6 +13,7 @@ from maasserver.enum import (
6 FILESYSTEM_GROUP_TYPE,
7 NODE_STATUS,
8 )
9+from maasserver.models.filesystemgroup import VMFS
10 from maasserver.models.partition import MIN_PARTITION_SIZE
11 from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE
12 from maasserver.storage_layouts import VMFS6StorageLayout
13@@ -149,7 +150,9 @@ class TestVMFSDatastoreAPI(APITestCase.ForUser):
14 self.get_vmfs_uri(vmfs))
15
16 def test_GET(self):
17- vmfs = factory.make_VMFS()
18+ part = factory.make_Partition()
19+ name = factory.make_name('datastore')
20+ vmfs = VMFS.objects.create_vmfs(name, [part])
21
22 response = self.client.get(self.get_vmfs_uri(vmfs))
23 self.assertThat(response, HasStatusCode(http.client.OK))
24@@ -162,6 +165,10 @@ class TestVMFSDatastoreAPI(APITestCase.ForUser):
25 'name': Equals(vmfs.name),
26 'size': Equals(vmfs.get_size()),
27 'human_size': Equals(human_readable_bytes(vmfs.get_size())),
28+ 'filesystem': Equals({
29+ 'fstype': 'vmfs6',
30+ 'mount_point': '/vmfs/volumes/%s' % name,
31+ }),
32 }))
33 self.assertEquals(
34 vmfs.filesystems.count(), len(parsed_result['devices']))
35diff --git a/src/maasserver/api/vmfs_datastores.py b/src/maasserver/api/vmfs_datastores.py
36index 07bc76c..e8c6a9a 100644
37--- a/src/maasserver/api/vmfs_datastores.py
38+++ b/src/maasserver/api/vmfs_datastores.py
39@@ -34,6 +34,7 @@ DISPLAYED_VMFS_DATASTORE_FIELDS = (
40 'devices',
41 'size',
42 'human_size',
43+ 'filesystem',
44 )
45
46
47@@ -160,6 +161,19 @@ class VmfsDatastoreHandler(OperationsHandler):
48 for filesystem in vmfs.filesystems.all()
49 ]
50
51+ @classmethod
52+ def filesystem(cls, vmfs):
53+ # XXX: This is almost the same as
54+ # m.api.partitions.PartitionHandler.filesystem.
55+ filesystem = vmfs.virtual_device.get_effective_filesystem()
56+ if filesystem is not None:
57+ return {
58+ 'fstype': filesystem.fstype,
59+ 'mount_point': filesystem.mount_point,
60+ }
61+ else:
62+ return None
63+
64 def read(self, request, system_id, id):
65 """@description-title Read a VMFS datastore.
66 @description Read a VMFS datastore with the given id on the machine
67diff --git a/src/maasserver/models/filesystemgroup.py b/src/maasserver/models/filesystemgroup.py
68index 38edce7..3993d8e 100644
69--- a/src/maasserver/models/filesystemgroup.py
70+++ b/src/maasserver/models/filesystemgroup.py
71@@ -292,6 +292,9 @@ class VMFSManager(BaseFilesystemGroupManager):
72 fstype=FILESYSTEM_TYPE.VMFS6, partition=partition,
73 filesystem_group=vmfs)
74 vmfs.save(force_update=True)
75+ vmfs.virtual_device.filesystem_set.create(
76+ fstype=FILESYSTEM_TYPE.VMFS6,
77+ mount_point='/vmfs/volumes/%s' % name)
78 return vmfs
79
80
81diff --git a/src/maasserver/models/tests/test_filesystemgroup.py b/src/maasserver/models/tests/test_filesystemgroup.py
82index c815abf..ce2cb7d 100644
83--- a/src/maasserver/models/tests/test_filesystemgroup.py
84+++ b/src/maasserver/models/tests/test_filesystemgroup.py
85@@ -32,6 +32,7 @@ from maasserver.models.filesystemgroup import (
86 RAID,
87 RAID_SUPERBLOCK_OVERHEAD,
88 RAIDManager,
89+ VMFS,
90 VolumeGroup,
91 VolumeGroupManager,
92 )
93@@ -878,6 +879,14 @@ class TestFilesystemGroup(MAASServerTestCase):
94 vmfs = factory.make_VMFS()
95 self.assertTrue(vmfs.is_vmfs())
96
97+ def test_creating_vmfs_automatically_creates_mounted_fs(self):
98+ part = factory.make_Partition()
99+ name = factory.make_name('datastore')
100+ vmfs = VMFS.objects.create_vmfs(name, [part])
101+ self.assertEquals(
102+ '/vmfs/volumes/%s' % name,
103+ vmfs.virtual_device.get_effective_filesystem().mount_point)
104+
105 def test_can_save_new_filesystem_group_without_filesystems(self):
106 fsgroup = FilesystemGroup(
107 group_type=FILESYSTEM_GROUP_TYPE.LVM_VG,
108diff --git a/src/maasserver/static/js/angular/controllers/node_details_storage.js b/src/maasserver/static/js/angular/controllers/node_details_storage.js
109index 749abca..440ff2b 100644
110--- a/src/maasserver/static/js/angular/controllers/node_details_storage.js
111+++ b/src/maasserver/static/js/angular/controllers/node_details_storage.js
112@@ -48,7 +48,7 @@ export function removeAvailableByNew() {
113 export function datastoresOnly() {
114 return function(filesystems) {
115 return filesystems.filter(filesystem => {
116- return filesystem.used_for === "VMFS Datastore";
117+ return filesystem.parent_type == "vmfs6";
118 });
119 };
120 }
121@@ -2396,7 +2396,7 @@ export function NodeStorageController(
122 // Returns warning text based on number of datastores
123 $scope.getRemoveDatastoreWarningText = function(disks) {
124 var datastores = disks.filter(function(disk) {
125- return disk.used_for === "VMFS Datastore";
126+ return disk.parent_type === "vmfs6";
127 });
128 var warningText = "Are you sure you want to remove this datastore?";
129
130diff --git a/src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js b/src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js
131index 4428c2b..0b4799c 100644
132--- a/src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js
133+++ b/src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js
134@@ -5384,14 +5384,12 @@ describe("NodeStorageController", function() {
135 makeController();
136 var disks = [
137 {
138- used_for: "VMFS Datastore"
139+ parent_type: "vmfs6"
140 },
141 {
142- used_for: "VMFS Datastore"
143+ parent_type: "vmfs6"
144 },
145- {
146- used_for: "GPT partitioned with 1 partition"
147- }
148+ {}
149 ];
150 expect($scope.getRemoveDatastoreWarningText(disks)).toBe(
151 "Are you sure you want to remove this datastore?"
152@@ -5402,11 +5400,9 @@ describe("NodeStorageController", function() {
153 makeController();
154 var disks = [
155 {
156- used_for: "VMFS Datastore"
157+ parent_type: "vmfs6"
158 },
159- {
160- used_for: "GPT partitioned with 1 partition"
161- }
162+ {}
163 ];
164 expect($scope.getRemoveDatastoreWarningText(disks)).toBe(
165 "Are you sure you want to remove this datastore? " +
166diff --git a/src/maasserver/static/partials/nodedetails/storage/datastores.html b/src/maasserver/static/partials/nodedetails/storage/datastores.html
167index 26cea59..0308eaf 100644
168--- a/src/maasserver/static/partials/nodedetails/storage/datastores.html
169+++ b/src/maasserver/static/partials/nodedetails/storage/datastores.html
170@@ -20,11 +20,11 @@
171 No datastores defined.
172 </td>
173 </tr>
174- <tr class="p-table__row" data-ng-repeat="filesystem in node.disks" data-ng-class="{ 'is-active': filesystem.$selected }" data-ng-if="filesystem.used_for == 'VMFS Datastore'">
175+ <tr class="p-table__row" data-ng-repeat="filesystem in node.disks" data-ng-class="{ 'is-active': filesystem.$selected }" data-ng-if="filesystem.parent_type == 'vmfs6'">
176 <td role="gridcell" class="p-table__cell" aria-label="Name" title="{$ filesystem.name $}">{$ filesystem.name $}</td>
177 <td role="gridcell" class="p-table__cell" aria-label="Filesystem" title="VMFS6">VMFS6</td>
178 <td role="gridcell" class="p-table__cell" aria-label="Size" title="{$ filesystem.size_human $}">{$ filesystem.size_human $}</td>
179- <td role="gridcell" class="p-table__cell" aria-label="Mount point" title="{$ filesystem.path $}">{$ filesystem.path $}</td>
180+ <td role="gridcell" class="p-table__cell" aria-label="Mount point" title="{$ filesystem.filesystem.mount_point $}">{$ filesystem.filesystem.mount_point $}</td>
181 <td role="gridcell" class="p-table__cell p-table--action-cell u-align--right">
182 <div class="p-contextual-menu" toggle-ctrl data-ng-if="!isAllStorageDisabled()">
183 <button class="p-button--base p-contextual-menu__toggle" aria-controls="#{$ item.name $}-menu"
184@@ -108,4 +108,4 @@
185 </tr>
186 </tbody>
187 </table>
188-</div>
189\ No newline at end of file
190+</div>
191diff --git a/src/maasserver/static/partials/nodedetails/storage/disks-partitions.html b/src/maasserver/static/partials/nodedetails/storage/disks-partitions.html
192index 4661058..6100bbc 100644
193--- a/src/maasserver/static/partials/nodedetails/storage/disks-partitions.html
194+++ b/src/maasserver/static/partials/nodedetails/storage/disks-partitions.html
195@@ -848,10 +848,10 @@
196 <p>{$ datastores.new.filesystem $}</p>
197 </div>
198 </div>
199- <div class="p-form__group" data-ng-if="datastores.new.path">
200+ <div class="p-form__group" data-ng-if="datastores.new.filesystem.mount_point">
201 <label for="datastore-mountpoint" class="p-form__label">Mount point</label>
202 <div class="p-form__control">
203- <p>{$ datastores.new.path $}</p>
204+ <p>{$ datastores.new.filesystem.mount_point $}</p>
205 </div>
206 </div>
207 </div>
208@@ -895,7 +895,7 @@
209 <div class="p-form__group">
210 <label for="datastore-mountpoint" class="p-form__label">Mount point</label>
211 <div class="p-form__control">
212- <p>{$ datastores.old.path $}</p>
213+ <p>{$ datastores.old.filesystem.mount_point $}</p>
214 </div>
215 </div>
216 </div>
217diff --git a/src/maasserver/tests/test_preseed_storage.py b/src/maasserver/tests/test_preseed_storage.py
218index 2fb4771..0cec35b 100644
219--- a/src/maasserver/tests/test_preseed_storage.py
220+++ b/src/maasserver/tests/test_preseed_storage.py
221@@ -2194,6 +2194,24 @@ class TestVMFS(MAASServerTestCase, AssertStorageConfigMixin):
222 type: vmfs6
223 devices:
224 - sdc-part1
225+ - id: datastore1_format
226+ type: format
227+ fstype: vmfs6
228+ volume: datastore1
229+ label: null
230+ - id: datastore2_format
231+ type: format
232+ fstype: vmfs6
233+ volume: datastore2
234+ label: null
235+ - id: datastore1_mount
236+ type: mount
237+ device: datastore1_format
238+ path: /vmfs/volumes/datastore1
239+ - id: datastore2_mount
240+ type: mount
241+ device: datastore2_format
242+ path: /vmfs/volumes/datastore2
243 """)
244
245 def test__renders_expected_output(self):
246diff --git a/src/maasserver/websockets/handlers/node.py b/src/maasserver/websockets/handlers/node.py
247index f9fd714..6334ece 100644
248--- a/src/maasserver/websockets/handlers/node.py
249+++ b/src/maasserver/websockets/handlers/node.py
250@@ -334,17 +334,7 @@ class NodeHandler(TimestampedModelHandler):
251 # UI knows that these partitions are in use.
252 if detected_layout == "vmfs6":
253 for disk in data["disks"]:
254- if disk.get("parent", {}).get("type") == "vmfs6":
255- disk["used_for"] = "VMFS Datastore"
256- disk["filesystem"] = {
257- "id": -1,
258- "label": "RESERVED",
259- "mount_point": "RESERVED",
260- "mount_options": None,
261- "fstype": None,
262- "is_format_fstype": False
263- }
264- elif disk["id"] == layout_bd.id:
265+ if disk["id"] == layout_bd.id:
266 for partition in disk["partitions"]:
267 partition["used_for"] = (
268 "VMware ESXi OS partition")
269diff --git a/src/maasserver/websockets/handlers/tests/test_machine.py b/src/maasserver/websockets/handlers/tests/test_machine.py
270index 53b12b5..8f295c5 100644
271--- a/src/maasserver/websockets/handlers/tests/test_machine.py
272+++ b/src/maasserver/websockets/handlers/tests/test_machine.py
273@@ -745,16 +745,6 @@ class TestMachineHandler(MAASServerTestCase):
274 "fstype": None,
275 "is_format_fstype": False,
276 }, partition["filesystem"])
277- else:
278- self.assertEquals("VMFS Datastore", disk["used_for"])
279- self.assertDictEqual({
280- "id": -1,
281- "label": "RESERVED",
282- "mount_point": "RESERVED",
283- "mount_options": None,
284- "fstype": None,
285- "is_format_fstype": False,
286- }, disk["filesystem"])
287
288 def test_dehydrate_power_parameters_returns_None_when_empty(self):
289 owner = factory.make_User()

Subscribers

People subscribed via source and target branches