Merge lp:~ltrager/maas/validate_storage into lp:~maas-committers/maas/trunk

Proposed by Lee Trager
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 4506
Proposed branch: lp:~ltrager/maas/validate_storage
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 411 lines (+212/-13)
11 files modified
src/maasserver/models/node.py (+74/-1)
src/maasserver/models/tests/test_filesystem.py (+4/-1)
src/maasserver/models/tests/test_node.py (+33/-2)
src/maasserver/models/tests/test_virtualblockdevice.py (+14/-0)
src/maasserver/models/virtualblockdevice.py (+34/-0)
src/maasserver/static/js/angular/controllers/node_details_storage.js (+8/-0)
src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js (+14/-0)
src/maasserver/static/partials/node-details.html (+9/-0)
src/maasserver/testing/factory.py (+5/-1)
src/maasserver/websockets/handlers/node.py (+1/-0)
src/maasserver/websockets/handlers/tests/test_node.py (+16/-8)
To merge this branch: bzr merge lp:~ltrager/maas/validate_storage
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+277402@code.launchpad.net

Commit message

Validate a node has a boot device and / is mounted before deploying

Description of the change

This patch validates that the node has a boot device and has / mounted somewhere before deploying. This also adds an error message to the UI when this is not the case. I modified the make_Node method to also create a partition and mount it at '/' since we now require it to be a valid bootable node.

I also made two small fixes for the previous validate node on network patch
* I was raising a validation error with just the error message. If we don't return a dictionary the error doesn't display in the UI.
* Rename the on_network tests to not include 'managed'

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) wrote :

Haven't reviewed the code but please add one more check.

Make sure that a /boot partition exists not on a bcache device if the / partition is on a bcache devices.

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

We now check if / is on a bcache block device, if we are we check if /boot is mounted not on a bcache device. I also made the error message more specific to why the storage layout isn't valid.

Revision history for this message
Gavin Panella (allenap) wrote :

Lots of comments. I think there are a few things that need fixing before it can be landed. I'm worried about how the new methods will perform. I won't block landing based on that but it would be good if you could do something about it.

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

Thanks for the review. I've gone over and responded to your comments below. The performance issues you are seeing are all due to validating that / isn't on bcache. In order to check if a partition/block device is on bcache I need to check the parent devices. There isn't currently a relation between child and parent so I have to iterate over all the blockdevices the node has until I find the partition/block device in question.

There are only two ways I can think of that will improve performance
1. Modify the schema so we have a relation between child(virtual block devices, and partitions), and parent(block devices, partitions)
2. Don't check if / is on bcache.

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

I stand corrected. A partition/block device can have two file systems. One is the filesystem the administrator sets another is the one a user sets. I now use the get_effective_filesystem() method which returns the correct filesystem depending on what the node status is.

The only place I use the first() method is getting the filesystem_group for a cache_set.

Revision history for this message
Gavin Panella (allenap) wrote :

Replies to diff comments.

Revision history for this message
Gavin Panella (allenap) wrote :

This seems sane to me. Just change storage_layout_status's "Valid" return value to something that doesn't make me think you're a troll from the PHP camp and it's good to go.

Actually, hold up, there's no test for the change to node-details.html. Better get your Angular boots on. If you really want to land this now, undo the change to node-details.html and propose it separately with a test.

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

I took your suggestion and renamed storage_layout_status to storage_layout_issues which returns a list of possible errors. With that change I also added a function to node_details_storage.js which detects if there is something in $scope.node.storage_layout_issues so we can test the change to node-details.html.

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (983.9 KiB)

The attempt to merge lp:~ltrager/maas/validate_storage into lp:maas failed. Below is the output from the failed tests.

Hit http://security.ubuntu.com xenial-security InRelease
Get:1 http://nova.clouds.archive.ubuntu.com xenial InRelease [218 kB]
Hit http://nova.clouds.archive.ubuntu.com xenial-updates InRelease
Hit http://security.ubuntu.com xenial-security/main Sources
Hit http://security.ubuntu.com xenial-security/universe Sources
Hit http://security.ubuntu.com xenial-security/main amd64 Packages
Hit http://security.ubuntu.com xenial-security/universe amd64 Packages
Hit http://security.ubuntu.com xenial-security/main Translation-en
Hit http://security.ubuntu.com xenial-security/universe Translation-en
Get:2 http://nova.clouds.archive.ubuntu.com xenial/main Sources [1,117 kB]
Get:3 http://nova.clouds.archive.ubuntu.com xenial/universe Sources [7,461 kB]
Get:4 http://nova.clouds.archive.ubuntu.com xenial/main amd64 Packages [1,441 kB]
Get:5 http://nova.clouds.archive.ubuntu.com xenial/universe amd64 Packages [6,950 kB]
Get:6 http://nova.clouds.archive.ubuntu.com xenial/main Translation-en [841 kB]
Get:7 http://nova.clouds.archive.ubuntu.com xenial/universe Translation-en [4,705 kB]
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main Sources
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe Sources
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com xenial-updates/universe Translation-en
Fetched 22.7 MB in 13s (1,725 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
    --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm pep8 phantomjs postgresql pxelinux pyflakes python-apt python-bson python-convoy python-coverage python-crochet python-cssselect python-curtin python-dev python-distro-info python-django python-django16 python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-extras python-fixtures python-flake8 python-formencode python-hivex python-httplib2 python-jinja2 python-jsonschema python-lxml python-mock python-netaddr python-netifaces python-nose python-oauth python-openssl python-paramiko python-pexpect python-pip python-pocket-lint python-psycopg2 python-pyinotify python-pyparsing python-seamicroclient python-simplejson python-simplestreams python-sphinx python-subunit python-tempita python-testresources python-testscenarios python-testtools python-twisted python-txtftp python-tz python-unittest2 python-virtualenv python-yaml python-zope.interface socat syslinux-common tgt ubuntu-cloudimage-keyring virtualenv wget xvfb
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2015-11-13 20:01:04 +0000
+++ src/maasserver/models/node.py 2015-11-17 23:04:09 +0000
@@ -63,6 +63,7 @@
63from maasserver.enum import (63from maasserver.enum import (
64 ALLOCATED_NODE_STATUSES,64 ALLOCATED_NODE_STATUSES,
65 FILESYSTEM_FORMAT_TYPE_CHOICES_DICT,65 FILESYSTEM_FORMAT_TYPE_CHOICES_DICT,
66 FILESYSTEM_TYPE,
66 INTERFACE_LINK_TYPE,67 INTERFACE_LINK_TYPE,
67 INTERFACE_TYPE,68 INTERFACE_TYPE,
68 IPADDRESS_FAMILY,69 IPADDRESS_FAMILY,
@@ -760,6 +761,73 @@
760 event_action=action,761 event_action=action,
761 event_description=description)762 event_description=description)
762763
764 def storage_layout_issues(self):
765 """Return any errors with the storage layout.
766
767 Checks that the node has / mounted. If / is mounted on bcache check
768 that /boot is mounted and is not on bcache."""
769 def on_bcache(obj):
770 if obj.type == "physical":
771 return False
772 elif obj.type == "partition":
773 return on_bcache(obj.partition_table.block_device)
774 for parent in obj.virtualblockdevice.get_parents():
775 if((parent.type != "physical" and on_bcache(parent)) or
776 (parent.get_effective_filesystem().fstype in
777 [FILESYSTEM_TYPE.BCACHE_CACHE,
778 FILESYSTEM_TYPE.BCACHE_BACKING])):
779 return True
780 return False
781
782 has_boot = False
783 root_mounted = False
784 root_on_bcache = False
785 boot_mounted = False
786
787 for block_device in self.blockdevice_set.all():
788 if block_device.is_boot_disk():
789 has_boot = True
790 pt = block_device.get_partitiontable()
791 if pt is not None:
792 for partition in pt.partitions.all():
793 fs = partition.get_effective_filesystem()
794 if fs is None:
795 continue
796 if fs.mount_point == '/':
797 root_mounted = True
798 if on_bcache(block_device):
799 root_on_bcache = True
800 else:
801 # If / is mounted and its not on bcache the system
802 # is bootable
803 return []
804 elif (fs.mount_point == '/boot' and
805 not on_bcache(block_device)):
806 boot_mounted = True
807 else:
808 fs = block_device.get_effective_filesystem()
809 if fs is None:
810 continue
811 if fs.mount_point == '/':
812 root_mounted = True
813 if on_bcache(block_device):
814 root_on_bcache = True
815 else:
816 # If / is mounted and its not on bcache the system
817 # is bootable.
818 return []
819 elif fs.mount_point == '/boot' and not on_bcache(block_device):
820 boot_mounted = True
821 issues = []
822 if not has_boot:
823 issues.append("Node must have boot disk.")
824 if not root_mounted:
825 issues.append("Node must have / mounted.")
826 if root_mounted and root_on_bcache and not boot_mounted:
827 issues.append("Because / is on a bcache volume you must create "
828 "/boot on a non-bcache volume")
829 return issues
830
763 def on_network(self):831 def on_network(self):
764 """Return true if the node is connected to a managed network."""832 """Return true if the node is connected to a managed network."""
765 for interface in self.interface_set.all():833 for interface in self.interface_set.all():
@@ -772,7 +840,12 @@
772 def _start_deployment(self):840 def _start_deployment(self):
773 """Mark a node as being deployed."""841 """Mark a node as being deployed."""
774 if self.on_network() is False:842 if self.on_network() is False:
775 raise ValidationError("Node must be configured to use a network")843 raise ValidationError(
844 {"network":
845 ["Node must be configured to use a network"]})
846 storage_layout_issues = self.storage_layout_issues()
847 if len(storage_layout_issues) > 0:
848 raise ValidationError({"storage": storage_layout_issues})
776 self.status = NODE_STATUS.DEPLOYING849 self.status = NODE_STATUS.DEPLOYING
777 self.save()850 self.save()
778851
779852
=== modified file 'src/maasserver/models/tests/test_filesystem.py'
--- src/maasserver/models/tests/test_filesystem.py 2015-10-27 20:53:16 +0000
+++ src/maasserver/models/tests/test_filesystem.py 2015-11-17 23:04:09 +0000
@@ -29,6 +29,9 @@
2929
30 def test_filter_by_node(self):30 def test_filter_by_node(self):
31 node = factory.make_Node()31 node = factory.make_Node()
32 boot_bd = node.blockdevice_set.first()
33 root_partition = boot_bd.partitiontable_set.first().partitions.first()
34 root_fs = root_partition.filesystem_set.first()
32 block_device = factory.make_PhysicalBlockDevice(node=node)35 block_device = factory.make_PhysicalBlockDevice(node=node)
33 bd_for_partitions = factory.make_PhysicalBlockDevice(node=node)36 bd_for_partitions = factory.make_PhysicalBlockDevice(node=node)
34 partition_table = factory.make_PartitionTable(37 partition_table = factory.make_PartitionTable(
@@ -37,7 +40,7 @@
37 filesystem_on_bd = factory.make_Filesystem(block_device=block_device)40 filesystem_on_bd = factory.make_Filesystem(block_device=block_device)
38 filesystem_on_partition = factory.make_Filesystem(partition=partition)41 filesystem_on_partition = factory.make_Filesystem(partition=partition)
39 self.assertItemsEqual(42 self.assertItemsEqual(
40 [filesystem_on_bd, filesystem_on_partition],43 [root_fs, filesystem_on_bd, filesystem_on_partition],
41 Filesystem.objects.filter_by_node(node))44 Filesystem.objects.filter_by_node(node))
4245
4346
4447
=== modified file 'src/maasserver/models/tests/test_node.py'
--- src/maasserver/models/tests/test_node.py 2015-11-10 18:12:57 +0000
+++ src/maasserver/models/tests/test_node.py 2015-11-17 23:04:09 +0000
@@ -3774,15 +3774,46 @@
37743774
3775 self.assertThat(release_auto_ips, MockCalledOnceWith())3775 self.assertThat(release_auto_ips, MockCalledOnceWith())
37763776
3777 def test_connected_to_managed_network_true_when_connected(self):3777 def test_on_network_returns_true_when_connected(self):
3778 node = factory.make_Node_with_Interface_on_Subnet(3778 node = factory.make_Node_with_Interface_on_Subnet(
3779 status=NODE_STATUS.ALLOCATED)3779 status=NODE_STATUS.ALLOCATED)
3780 self.assertTrue(node.on_network())3780 self.assertTrue(node.on_network())
37813781
3782 def test_connected_to_managed_network_false_when_not_connected(self):3782 def test_on_network_returns_false_when_not_connected(self):
3783 node = factory.make_Node(status=NODE_STATUS.ALLOCATED)3783 node = factory.make_Node(status=NODE_STATUS.ALLOCATED)
3784 self.assertFalse(node.on_network())3784 self.assertFalse(node.on_network())
37853785
3786 def test_storage_layout_issues_is_valid_when_flat(self):
3787 node = factory.make_Node()
3788 self.assertEquals([], node.storage_layout_issues())
3789
3790 def test_storage_layout_issues_returns_valid_with_boot_and_bcache(self):
3791 node = factory.make_Node(with_boot_disk=False)
3792 boot_partition = factory.make_Partition(node=node)
3793 factory.make_Filesystem(partition=boot_partition, mount_point='/boot')
3794 fs_group = factory.make_FilesystemGroup(
3795 node=node, group_type=FILESYSTEM_GROUP_TYPE.BCACHE)
3796 bcache = fs_group.virtual_device
3797 factory.make_Filesystem(block_device=bcache, mount_point="/")
3798 self.assertEquals([], node.storage_layout_issues())
3799
3800 def test_storage_layout_issues_returns_invalid_when_no_disk(self):
3801 node = factory.make_Node(with_boot_disk=False)
3802 self.assertEquals(["Node must have boot disk.",
3803 "Node must have / mounted."],
3804 node.storage_layout_issues())
3805
3806 def test_storage_layout_issues_returns_invalid_when_root_on_bcache(self):
3807 node = factory.make_Node(with_boot_disk=False)
3808 factory.make_Partition(node=node)
3809 fs_group = factory.make_FilesystemGroup(
3810 node=node, group_type=FILESYSTEM_GROUP_TYPE.BCACHE)
3811 bcache = fs_group.virtual_device
3812 factory.make_Filesystem(block_device=bcache, mount_point="/")
3813 self.assertEquals(["Because / is on a bcache volume you must create "
3814 "/boot on a non-bcache volume"],
3815 node.storage_layout_issues())
3816
37863817
3787class TestNode_Stop(MAASServerTestCase):3818class TestNode_Stop(MAASServerTestCase):
3788 """Tests for Node.stop()."""3819 """Tests for Node.stop()."""
37893820
=== modified file 'src/maasserver/models/tests/test_virtualblockdevice.py'
--- src/maasserver/models/tests/test_virtualblockdevice.py 2015-08-14 13:48:59 +0000
+++ src/maasserver/models/tests/test_virtualblockdevice.py 2015-11-17 23:04:09 +0000
@@ -159,3 +159,17 @@
159 uuid = uuid4()159 uuid = uuid4()
160 block_device = factory.make_VirtualBlockDevice(uuid=uuid)160 block_device = factory.make_VirtualBlockDevice(uuid=uuid)
161 self.assertEquals('%s' % uuid, block_device.uuid)161 self.assertEquals('%s' % uuid, block_device.uuid)
162
163 def test_get_parents_finds_devices(self):
164 node = factory.make_Node()
165 factory.make_FilesystemGroup(
166 node=node,
167 group_type=factory.pick_enum(
168 FILESYSTEM_GROUP_TYPE, but_not=FILESYSTEM_GROUP_TYPE.LVM_VG))
169 fs_group_disks = [block_device.blockdevice_ptr
170 for block_device in
171 node.physicalblockdevice_set.all()
172 if not block_device.is_boot_disk()]
173 virtualblockdevice = node.virtualblockdevice_set.first()
174 self.assertEqual(
175 len(fs_group_disks), len(virtualblockdevice.get_parents()))
162176
=== modified file 'src/maasserver/models/virtualblockdevice.py'
--- src/maasserver/models/virtualblockdevice.py 2015-11-16 06:26:17 +0000
+++ src/maasserver/models/virtualblockdevice.py 2015-11-17 23:04:09 +0000
@@ -137,3 +137,37 @@
137 if not self.uuid:137 if not self.uuid:
138 self.uuid = uuid4()138 self.uuid = uuid4()
139 return super(VirtualBlockDevice, self).save(*args, **kwargs)139 return super(VirtualBlockDevice, self).save(*args, **kwargs)
140
141 def get_parents(self):
142 """Return the blockdevices and partition which make up this device."""
143 def check_fs_group(obj):
144 fs = obj.get_effective_filesystem()
145 if fs is None:
146 return False
147 if fs.filesystem_group is not None:
148 fs_group = fs.filesystem_group
149 elif fs.cache_set is not None:
150 # A block device/partition can only have one cache_set
151 fs_group = fs.cache_set.filesystemgroup_set.first()
152 else:
153 return False
154 for virtual_device in fs_group.virtual_devices.all():
155 if virtual_device.id == self.id:
156 return True
157 return False
158
159 parents = []
160 # We need to check all of the nodes block devices incase
161 # we have nested virtual block devices.
162 for block_device in self.node.blockdevice_set.all():
163 if block_device.id == self.id:
164 continue
165 if check_fs_group(block_device):
166 parents.append(block_device)
167 pt = block_device.get_partitiontable()
168 if pt is None:
169 continue
170 for partition in pt.partitions.all():
171 if check_fs_group(partition):
172 parents.append(partition)
173 return parents
140174
=== modified file 'src/maasserver/static/js/angular/controllers/node_details_storage.js'
--- src/maasserver/static/js/angular/controllers/node_details_storage.js 2015-11-10 17:36:38 +0000
+++ src/maasserver/static/js/angular/controllers/node_details_storage.js 2015-11-17 23:04:09 +0000
@@ -1913,4 +1913,12 @@
1913 return false;1913 return false;
1914 }1914 }
1915 };1915 };
1916
1917 // Returns true if there are storage layout errors
1918 $scope.hasStorageLayoutIssues = function() {
1919 if(angular.isObject($scope.node)) {
1920 return $scope.node.storage_layout_issues.length > 0;
1921 }
1922 return false;
1923 };
1916 }]);1924 }]);
19171925
=== modified file 'src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js'
--- src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js 2015-11-10 17:36:38 +0000
+++ src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js 2015-11-17 23:04:09 +0000
@@ -4744,4 +4744,18 @@
4744 expect($scope.isAllStorageDisabled()).toBe(true);4744 expect($scope.isAllStorageDisabled()).toBe(true);
4745 });4745 });
4746 });4746 });
4747
4748 describe("hasStorageLayoutIssues", function() {
4749 it("true when node.storage_layout_issues has issues", function() {
4750 var controller = makeController();
4751 $scope.node.storage_layout_issues = [makeName("issue")];
4752 expect($scope.hasStorageLayoutIssues()).toBe(true);
4753 });
4754
4755 it("false when node.storage_layout_issues has no issues", function() {
4756 var controller = makeController();
4757 $scope.node.storage_layout_issues = [];
4758 expect($scope.hasStorageLayoutIssues()).toBe(false);
4759 });
4760 });
4747});4761});
47484762
=== modified file 'src/maasserver/static/partials/node-details.html'
--- src/maasserver/static/partials/node-details.html 2015-11-14 00:32:02 +0000
+++ src/maasserver/static/partials/node-details.html 2015-11-17 23:04:09 +0000
@@ -772,6 +772,15 @@
772 </li>772 </li>
773 </ul>773 </ul>
774 </div>774 </div>
775 <div class="twelve-col error ng-hide" data-ng-show="hasStorageLayoutIssues()">
776 <div data-ng-repeat="issue in node.storage_layout_issues">
777 <ul class="flash-messages">
778 <li class="flash-messages__item error">
779 {$ issue $}
780 </li>
781 </ul>
782 </div>
783 </div>
775 <div class="twelve-col padding-bottom no-margin">784 <div class="twelve-col padding-bottom no-margin">
776 <h3>File systems</h3>785 <h3>File systems</h3>
777 <section class="table">786 <section class="table">
778787
=== modified file 'src/maasserver/testing/factory.py'
--- src/maasserver/testing/factory.py 2015-11-12 19:57:04 +0000
+++ src/maasserver/testing/factory.py 2015-11-17 23:04:09 +0000
@@ -32,6 +32,7 @@
32from django.utils import timezone32from django.utils import timezone
33from maasserver.clusterrpc.power_parameters import get_power_types33from maasserver.clusterrpc.power_parameters import get_power_types
34from maasserver.enum import (34from maasserver.enum import (
35 ALLOCATED_NODE_STATUSES,
35 BOOT_RESOURCE_FILE_TYPE,36 BOOT_RESOURCE_FILE_TYPE,
36 BOOT_RESOURCE_TYPE,37 BOOT_RESOURCE_TYPE,
37 CACHE_MODE_TYPE,38 CACHE_MODE_TYPE,
@@ -330,7 +331,10 @@
330 self.make_Interface(331 self.make_Interface(
331 INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan, fabric=fabric)332 INTERFACE_TYPE.PHYSICAL, node=node, vlan=vlan, fabric=fabric)
332 if installable and with_boot_disk:333 if installable and with_boot_disk:
333 self.make_PhysicalBlockDevice(node=node)334 root_partition = self.make_Partition(node=node)
335 acquired = node.status in ALLOCATED_NODE_STATUSES
336 self.make_Filesystem(
337 partition=root_partition, mount_point='/', acquired=acquired)
334338
335 # Update the 'updated'/'created' fields with a call to 'update'339 # Update the 'updated'/'created' fields with a call to 'update'
336 # preventing a call to save() from overriding the values.340 # preventing a call to save() from overriding the values.
337341
=== modified file 'src/maasserver/websockets/handlers/node.py'
--- src/maasserver/websockets/handlers/node.py 2015-11-10 23:41:49 +0000
+++ src/maasserver/websockets/handlers/node.py 2015-11-17 23:04:09 +0000
@@ -313,6 +313,7 @@
313 {'key': key, 'ui': ui}313 {'key': key, 'ui': ui}
314 for key, ui in FILESYSTEM_FORMAT_TYPE_CHOICES314 for key, ui in FILESYSTEM_FORMAT_TYPE_CHOICES
315 ]315 ]
316 data["storage_layout_issues"] = obj.storage_layout_issues()
316317
317 # Events318 # Events
318 data["events"] = self.dehydrate_events(obj)319 data["events"] = self.dehydrate_events(obj)
319320
=== modified file 'src/maasserver/websockets/handlers/tests/test_node.py'
--- src/maasserver/websockets/handlers/tests/test_node.py 2015-11-12 23:20:54 +0000
+++ src/maasserver/websockets/handlers/tests/test_node.py 2015-11-17 23:04:09 +0000
@@ -165,6 +165,7 @@
165 "disable_ipv4": node.disable_ipv4,165 "disable_ipv4": node.disable_ipv4,
166 "physical_disk_count": node.physicalblockdevice_set.count(),166 "physical_disk_count": node.physicalblockdevice_set.count(),
167 "disks": disks,167 "disks": disks,
168 "storage_layout_issues": node.storage_layout_issues(),
168 "supported_filesystems": [169 "supported_filesystems": [
169 {'key': key, 'ui': ui}170 {'key': key, 'ui': ui}
170 for key, ui in FILESYSTEM_FORMAT_TYPE_CHOICES],171 for key, ui in FILESYSTEM_FORMAT_TYPE_CHOICES],
@@ -1471,20 +1472,23 @@
1471 interface=True,1472 interface=True,
1472 architecture=architecture,1473 architecture=architecture,
1473 status=NODE_STATUS.ALLOCATED)1474 status=NODE_STATUS.ALLOCATED)
1474 partition_table = factory.make_PartitionTable(node=node)1475 block_device = factory.make_BlockDevice(node=node)
1476 partition_table = factory.make_PartitionTable(
1477 block_device=block_device, node=node)
1475 size = partition_table.block_device.size / 21478 size = partition_table.block_device.size / 2
1476 handler.create_partition({1479 handler.create_partition({
1477 'system_id': node.system_id,1480 'system_id': node.system_id,
1478 'block_id': partition_table.block_device_id,1481 'block_id': partition_table.block_device_id,
1479 'partition_size': size1482 'partition_size': size
1480 })1483 })
1484 partition = partition_table.partitions.first()
1481 self.assertEquals(1485 self.assertEquals(
1482 1, Partition.objects.count())1486 2, Partition.objects.count())
1483 self.assertEquals(1487 self.assertEquals(
1484 human_readable_bytes(1488 human_readable_bytes(
1485 round_size_to_nearest_block(1489 round_size_to_nearest_block(
1486 size, PARTITION_ALIGNMENT_SIZE, False)),1490 size, PARTITION_ALIGNMENT_SIZE, False)),
1487 human_readable_bytes(Partition.objects.first().size))1491 human_readable_bytes(partition.size))
14881492
1489 def test_create_partition_with_filesystem(self):1493 def test_create_partition_with_filesystem(self):
1490 user = factory.make_admin()1494 user = factory.make_admin()
@@ -1494,7 +1498,10 @@
1494 interface=True,1498 interface=True,
1495 architecture=architecture,1499 architecture=architecture,
1496 status=NODE_STATUS.ALLOCATED)1500 status=NODE_STATUS.ALLOCATED)
1497 partition_table = factory.make_PartitionTable(node=node)1501 block_device = factory.make_BlockDevice(node=node)
1502 partition_table = factory.make_PartitionTable(
1503 block_device=block_device, node=node)
1504 partition = partition_table.partitions.first()
1498 size = partition_table.block_device.size / 21505 size = partition_table.block_device.size / 2
1499 fstype = factory.pick_choice(FILESYSTEM_FORMAT_TYPE_CHOICES)1506 fstype = factory.pick_choice(FILESYSTEM_FORMAT_TYPE_CHOICES)
1500 mount_point = factory.make_absolute_path()1507 mount_point = factory.make_absolute_path()
@@ -1505,19 +1512,20 @@
1505 'fstype': fstype,1512 'fstype': fstype,
1506 'mount_point': mount_point,1513 'mount_point': mount_point,
1507 })1514 })
1515 partition = partition_table.partitions.first()
1508 self.assertEquals(1516 self.assertEquals(
1509 1, Partition.objects.count())1517 2, Partition.objects.count())
1510 self.assertEquals(1518 self.assertEquals(
1511 human_readable_bytes(1519 human_readable_bytes(
1512 round_size_to_nearest_block(1520 round_size_to_nearest_block(
1513 size, PARTITION_ALIGNMENT_SIZE, False)),1521 size, PARTITION_ALIGNMENT_SIZE, False)),
1514 human_readable_bytes(Partition.objects.first().size))1522 human_readable_bytes(partition.size))
1515 self.assertEquals(1523 self.assertEquals(
1516 fstype,1524 fstype,
1517 Partition.objects.first().get_effective_filesystem().fstype)1525 partition.get_effective_filesystem().fstype)
1518 self.assertEquals(1526 self.assertEquals(
1519 mount_point,1527 mount_point,
1520 Partition.objects.first().get_effective_filesystem().mount_point)1528 partition.get_effective_filesystem().mount_point)
15211529
1522 def test_create_cache_set_for_partition(self):1530 def test_create_cache_set_for_partition(self):
1523 user = factory.make_admin()1531 user = factory.make_admin()