Merge lp:~blake-rouse/maas/fix-power8 into lp:~maas-committers/maas/trunk

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 4680
Proposed branch: lp:~blake-rouse/maas/fix-power8
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 913 lines (+563/-21)
15 files modified
docs/changelog.rst (+20/-0)
src/maasserver/models/node.py (+1/-1)
src/maasserver/models/partition.py (+11/-1)
src/maasserver/models/partitiontable.py (+20/-4)
src/maasserver/models/tests/test_node.py (+8/-0)
src/maasserver/models/tests/test_partition.py (+25/-1)
src/maasserver/models/tests/test_partitiontable.py (+49/-1)
src/maasserver/preseed_storage.py (+66/-8)
src/maasserver/static/js/angular/controllers/node_details_storage.js (+11/-0)
src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js (+51/-0)
src/maasserver/storage_layouts.py (+6/-1)
src/maasserver/tests/test_preseed_storage.py (+215/-1)
src/maasserver/tests/test_storage_layouts.py (+78/-1)
src/provisioningserver/boot/powerkvm.py (+1/-1)
src/provisioningserver/boot/powernv.py (+1/-1)
To merge this branch: bzr merge lp:~blake-rouse/maas/fix-power8
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+285234@code.launchpad.net

Commit message

Fix storage configuration so it adds a prep partition at the beginning of the disk for deploying PowerNV. Fix PowerNV and PowerKVM to not create the EFI partition when the storage layout is generated.

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

The abundant special-casing puts this on the slope towards spaghetti, but additional tests and documentation (chiefly in the form of comments) will alleviate that and make it easier to unravel later on.

I have several questions but no reservations other than the above, so Needs Information.

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

Thanks for the review.

"slope towards spaghetti", totally agree! But this is one branch that could not be avoided, due to the current state of MAAS in the release process. Because of Django 1.8 and migrations we cannot release any new migrations in MAAS 1.9 and this branch has a requirement to be in MAAS 1.9. The only benefit we get out of this is we get to hide this stupid partition from the user. This is also fallout on not having every architecture in our CI. If this would have existed in our CI we would have caught this very early in the MAAS 1.9 cycle and I would not be doing it now and it could have been done properly and not as some magic if case throughout the storage generation.

See inline comments for responses. Also you reviewed an earlier version of the branch, some things have already changed.

Revision history for this message
Gavin Panella (allenap) :
review: Approve
Revision history for this message
Blake Rouse (blake-rouse) wrote :

I am waiting to land this once curtin is fixed to work with the way we are creating partitions.

Once this bug is resolved and I can QA this I will land this and backport to 1.9.

https://bugs.launchpad.net/curtin/+bug/1543263

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

The attempt to merge lp:~blake-rouse/maas/fix-power8 into lp:maas failed. Below is the output from the failed tests.

Get:1 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial InRelease [95.8 kB]
Hit:2 http://security.ubuntu.com/ubuntu xenial-security InRelease
Hit:3 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-updates InRelease
Hit:4 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial-backports InRelease
Get:5 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial/main Sources [1,108 kB]
Get:6 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial/universe Sources [7,717 kB]
Get:7 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial/main amd64 Packages [1,442 kB]
Get:8 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial/main Translation-en [844 kB]
Get:9 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial/universe amd64 Packages [7,352 kB]
Get:10 http://prodstack-zone-2.clouds.archive.ubuntu.com/ubuntu xenial/universe Translation-en [4,889 kB]
Fetched 23.4 MB in 34s (688 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
    --no-install-recommends install apache2 archdetect-deb 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 postgresql pxelinux python3-apt python3-bson python3-convoy python3-coverage python3-crochet python3-cssselect python3-curtin python3-dev python3-distro-info python3-django python3-django-nose python3-django-piston3 python3-docutils python3-formencode python3-hivex python3-httplib2 python3-jinja2 python3-jsonschema python3-lxml python3-mock python3-netaddr python3-netifaces python3-oauth python3-oauthlib python3-openssl python3-paramiko python3-petname python3-pexpect python3-psycopg2 python3-pyinotify python3-pyparsing python3-pyvmomi python3-seamicroclient python3-simplestreams python3-sphinx python3-tempita python3-twisted python3-txtftp python3-tz python3-yaml python3-zope.interface python-bson python-crochet python-django python-django-piston python-djorm-ext-pgarray python-formencode python-lxml python-netaddr python-netifaces python-pocket-lint python-psycopg2 python-tempita python-twisted python-yaml socat syslinux-common tgt ubuntu-cloudimage-keyring wget xvfb
Reading package lists...
Building dependency tree...
Reading state information...
apache2 is already the newest version (2.4.18-1ubuntu1).
archdetect-deb is already the newest version (1.114ubuntu2).
authbind is already the newest version (2.1.1+nmu1).
bind9 is already the newest version (1:9.10.3.dfsg.P2-4).
bind9utils is already the newest version (1:9.10.3.dfsg.P2-4).
build-essential is already the newest version (12.1ubuntu2).
curl is already the newest version (7.47.0-1ubuntu2).
debhelper is already the newest version (9.20160115ubuntu2).
dh-apport is already the newest version (2.20-0ubuntu3).
dh-systemd is already the newest version (1.28ubuntu2)....

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'docs/changelog.rst'
--- docs/changelog.rst 2016-02-17 16:12:30 +0000
+++ docs/changelog.rst 2016-02-24 16:12:28 +0000
@@ -3,6 +3,26 @@
3=========3=========
44
55
61.9.1
7=====
8
9See https://launchpad.net/maas/+milestone/1.9.1 for full details.
10
11Bug Fix Update
12--------------
13
14#1523779 Fix grub-install error on deploying power8 machines.
15
16#1526542 Skip block devices with duplicate serial numbers to fix multipath issue.
17
18#1536754 Upgrade from 1.8 to 1.9 lost connected macs in all but one network.
19
20#1532262 Fix failure to power query requests for SM15K servers.
21
22#1484696 Fix bug in apache2 maas config where it will reuse websocket connections
23 to work around a bug in apache2 itself.
24
25
61.9.0261.9.0
7=====27=====
828
929
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2016-02-19 01:46:23 +0000
+++ src/maasserver/models/node.py 2016-02-24 16:12:28 +0000
@@ -158,7 +158,7 @@
158158
159# Holds the known `bios_boot_methods`. If `bios_boot_method` is not in this159# Holds the known `bios_boot_methods`. If `bios_boot_method` is not in this
160# list then it will fallback to `DEFAULT_BIOS_BOOT_METHOD`.160# list then it will fallback to `DEFAULT_BIOS_BOOT_METHOD`.
161KNOWN_BIOS_BOOT_METHODS = ["pxe", "uefi"]161KNOWN_BIOS_BOOT_METHODS = ["pxe", "uefi", "powernv", "powerkvm"]
162162
163# Default `bios_boot_method`. See `KNOWN_BIOS_BOOT_METHOD` above for usage.163# Default `bios_boot_method`. See `KNOWN_BIOS_BOOT_METHOD` above for usage.
164DEFAULT_BIOS_BOOT_METHOD = "pxe"164DEFAULT_BIOS_BOOT_METHOD = "pxe"
165165
=== modified file 'src/maasserver/models/partition.py'
--- src/maasserver/models/partition.py 2015-12-01 18:12:59 +0000
+++ src/maasserver/models/partition.py 2016-02-24 16:12:28 +0000
@@ -180,7 +180,17 @@
180 partitions_in_table = sorted(partitions_in_table, key=attrgetter('id'))180 partitions_in_table = sorted(partitions_in_table, key=attrgetter('id'))
181 idx = partitions_in_table.index(self)181 idx = partitions_in_table.index(self)
182 if self.partition_table.table_type == PARTITION_TABLE_TYPE.GPT:182 if self.partition_table.table_type == PARTITION_TABLE_TYPE.GPT:
183 return idx + 1183 # ppc64el machines get part1 skipped when this partition is on
184 # the boot disk. This is because the prep partition is part1 and
185 # is added when the preseed for storage is generated.
186 node = self.get_node()
187 arch, _ = node.split_arch()
188 boot_disk = node.get_boot_disk()
189 if (arch == "ppc64el" and
190 self.partition_table.block_device.id == boot_disk.id):
191 return idx + 2
192 else:
193 return idx + 1
184 elif self.partition_table.table_type == PARTITION_TABLE_TYPE.MBR:194 elif self.partition_table.table_type == PARTITION_TABLE_TYPE.MBR:
185 # If more than 4 partitions then the 4th partition number is195 # If more than 4 partitions then the 4th partition number is
186 # skipped because that is used for the extended partition.196 # skipped because that is used for the extended partition.
187197
=== modified file 'src/maasserver/models/partitiontable.py'
--- src/maasserver/models/partitiontable.py 2015-12-01 18:12:59 +0000
+++ src/maasserver/models/partitiontable.py 2016-02-24 16:12:28 +0000
@@ -40,6 +40,13 @@
40PARTITION_TABLE_EXTRA_SPACE = (40PARTITION_TABLE_EXTRA_SPACE = (
41 INITIAL_PARTITION_OFFSET + END_OF_PARTITION_TABLE_SPACE)41 INITIAL_PARTITION_OFFSET + END_OF_PARTITION_TABLE_SPACE)
4242
43# The amount of space required to be reserved for the prep partition. Prep
44# partition is required by all ppc64el architectures. Because of the way the
45# system boots it requires that a 8MiB prep partition exist with grub installed
46# on that partition. Without this partition the installation of grub will fail
47# on ppc64el and will fail to boot.
48PREP_PARTITION_SIZE = 8 * 1024 * 1024 # 8MiB
49
4350
44class PartitionTable(CleanSave, TimestampedModel):51class PartitionTable(CleanSave, TimestampedModel):
45 """A partition table on a block device.52 """A partition table on a block device.
@@ -64,7 +71,7 @@
64 def get_size(self):71 def get_size(self):
65 """Total usable size of partition table."""72 """Total usable size of partition table."""
66 return round_size_to_nearest_block(73 return round_size_to_nearest_block(
67 self.block_device.size - PARTITION_TABLE_EXTRA_SPACE,74 self.block_device.size - self.get_overhead_size(),
68 PARTITION_ALIGNMENT_SIZE,75 PARTITION_ALIGNMENT_SIZE,
69 False)76 False)
7077
@@ -72,6 +79,15 @@
72 """Block size of partition table."""79 """Block size of partition table."""
73 return self.block_device.block_size80 return self.block_device.block_size
7481
82 def get_overhead_size(self):
83 """Return the total amount of extra space this partition table
84 requires."""
85 extra_space = PARTITION_TABLE_EXTRA_SPACE
86 node_arch, _ = self.block_device.node.split_arch()
87 if node_arch == "ppc64el":
88 extra_space += PREP_PARTITION_SIZE
89 return extra_space
90
75 def get_used_size(self, ignore_partitions=[]):91 def get_used_size(self, ignore_partitions=[]):
76 """Return the used size of partitions on the table."""92 """Return the used size of partitions on the table."""
77 ignore_ids = [93 ignore_ids = [
@@ -84,7 +100,7 @@
84 if used_size is None:100 if used_size is None:
85 used_size = 0101 used_size = 0
86 # The extra space taken by the partition table header is used space.102 # The extra space taken by the partition table header is used space.
87 return used_size + PARTITION_TABLE_EXTRA_SPACE103 return used_size + self.get_overhead_size()
88104
89 def get_available_size(self, ignore_partitions=[]):105 def get_available_size(self, ignore_partitions=[]):
90 """Return the remaining size available for partitions."""106 """Return the remaining size available for partitions."""
@@ -133,8 +149,8 @@
133 # placed on the boot disk.149 # placed on the boot disk.
134 if boot_disk is not None and self.block_device.id == boot_disk.id:150 if boot_disk is not None and self.block_device.id == boot_disk.id:
135 bios_boot_method = node.get_bios_boot_method()151 bios_boot_method = node.get_bios_boot_method()
136 if bios_boot_method == "uefi":152 if bios_boot_method in ["uefi", "powernv", "powerkvm"]:
137 # UEFI must always use a GPT table.153 # UEFI, PowerNV, or PowerKVM must always use a GPT table.
138 if not self.table_type:154 if not self.table_type:
139 self.table_type = PARTITION_TABLE_TYPE.GPT155 self.table_type = PARTITION_TABLE_TYPE.GPT
140 elif self.table_type != PARTITION_TABLE_TYPE.GPT:156 elif self.table_type != PARTITION_TABLE_TYPE.GPT:
141157
=== modified file 'src/maasserver/models/tests/test_node.py'
--- src/maasserver/models/tests/test_node.py 2016-02-19 01:46:23 +0000
+++ src/maasserver/models/tests/test_node.py 2016-02-24 16:12:28 +0000
@@ -390,6 +390,14 @@
390 node = factory.make_Node(bios_boot_method="uefi")390 node = factory.make_Node(bios_boot_method="uefi")
391 self.assertEqual("uefi", node.get_bios_boot_method())391 self.assertEqual("uefi", node.get_bios_boot_method())
392392
393 def test_get_bios_boot_method_returns_powernv(self):
394 node = factory.make_Node(bios_boot_method="powernv")
395 self.assertEqual("powernv", node.get_bios_boot_method())
396
397 def test_get_bios_boot_method_returns_powerkvm(self):
398 node = factory.make_Node(bios_boot_method="powerkvm")
399 self.assertEqual("powerkvm", node.get_bios_boot_method())
400
393 def test_get_bios_boot_method_fallback_to_pxe(self):401 def test_get_bios_boot_method_fallback_to_pxe(self):
394 node = factory.make_Node(bios_boot_method=factory.make_name("boot"))402 node = factory.make_Node(bios_boot_method=factory.make_name("boot"))
395 self.assertEqual("pxe", node.get_bios_boot_method())403 self.assertEqual("pxe", node.get_bios_boot_method())
396404
=== modified file 'src/maasserver/models/tests/test_partition.py'
--- src/maasserver/models/tests/test_partition.py 2015-12-01 18:12:59 +0000
+++ src/maasserver/models/tests/test_partition.py 2016-02-24 16:12:28 +0000
@@ -22,7 +22,10 @@
22 Partition,22 Partition,
23 PARTITION_ALIGNMENT_SIZE,23 PARTITION_ALIGNMENT_SIZE,
24)24)
25from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE25from maasserver.models.partitiontable import (
26 PARTITION_TABLE_EXTRA_SPACE,
27 PREP_PARTITION_SIZE,
28)
26from maasserver.testing.factory import factory29from maasserver.testing.factory import factory
27from maasserver.testing.orm import reload_object30from maasserver.testing.orm import reload_object
28from maasserver.testing.testcase import MAASServerTestCase31from maasserver.testing.testcase import MAASServerTestCase
@@ -302,6 +305,27 @@
302 self.expectThat(idx, Equals(partition.get_partition_number()))305 self.expectThat(idx, Equals(partition.get_partition_number()))
303 idx += 1306 idx += 1
304307
308 def test_get_partition_number_returns_starting_at_2_for_ppc64el(self):
309 node = factory.make_Node(
310 architecture="ppc64el/generic", bios_boot_method="uefi")
311 block_device = factory.make_PhysicalBlockDevice(
312 node=node,
313 size=(
314 (MIN_PARTITION_SIZE * 4) + PARTITION_TABLE_EXTRA_SPACE +
315 PREP_PARTITION_SIZE))
316 node.boot_disk = block_device
317 node.save()
318 partition_table = factory.make_PartitionTable(
319 block_device=block_device, table_type=PARTITION_TABLE_TYPE.GPT)
320 partitions = [
321 partition_table.add_partition(size=MIN_BLOCK_DEVICE_SIZE)
322 for _ in range(4)
323 ]
324 idx = 2
325 for partition in partitions:
326 self.expectThat(idx, Equals(partition.get_partition_number()))
327 idx += 1
328
305 def test_get_partition_number_returns_correct_numbering_for_mbr(self):329 def test_get_partition_number_returns_correct_numbering_for_mbr(self):
306 block_device = factory.make_PhysicalBlockDevice(330 block_device = factory.make_PhysicalBlockDevice(
307 size=(MIN_BLOCK_DEVICE_SIZE * 6) + PARTITION_TABLE_EXTRA_SPACE)331 size=(MIN_BLOCK_DEVICE_SIZE * 6) + PARTITION_TABLE_EXTRA_SPACE)
308332
=== modified file 'src/maasserver/models/tests/test_partitiontable.py'
--- src/maasserver/models/tests/test_partitiontable.py 2015-12-01 18:12:59 +0000
+++ src/maasserver/models/tests/test_partitiontable.py 2016-02-24 16:12:28 +0000
@@ -19,7 +19,10 @@
19 MIN_PARTITION_SIZE,19 MIN_PARTITION_SIZE,
20 PARTITION_ALIGNMENT_SIZE,20 PARTITION_ALIGNMENT_SIZE,
21)21)
22from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE22from maasserver.models.partitiontable import (
23 PARTITION_TABLE_EXTRA_SPACE,
24 PREP_PARTITION_SIZE,
25)
23from maasserver.testing.factory import factory26from maasserver.testing.factory import factory
24from maasserver.testing.testcase import MAASServerTestCase27from maasserver.testing.testcase import MAASServerTestCase
25from maasserver.utils.converters import round_size_to_nearest_block28from maasserver.utils.converters import round_size_to_nearest_block
@@ -43,6 +46,19 @@
43 False),46 False),
44 partition_table.get_size())47 partition_table.get_size())
4548
49 def test_get_size_returns_block_device_size_minus_ppc64el(self):
50 node = factory.make_Node(architecture="ppc64el/generic")
51 block_device = factory.make_PhysicalBlockDevice(node=node)
52 partition_table = factory.make_PartitionTable(
53 block_device=block_device)
54 self.assertEqual(
55 round_size_to_nearest_block(
56 partition_table.block_device.size -
57 PARTITION_TABLE_EXTRA_SPACE - PREP_PARTITION_SIZE,
58 PARTITION_ALIGNMENT_SIZE,
59 False),
60 partition_table.get_size())
61
46 def test_get_block_size_returns_block_device_block_size(self):62 def test_get_block_size_returns_block_device_block_size(self):
47 partition_table = factory.make_PartitionTable()63 partition_table = factory.make_PartitionTable()
48 self.assertEqual(64 self.assertEqual(
@@ -114,6 +130,24 @@
114 self.assertRaises(130 self.assertRaises(
115 ValidationError, partition_table.add_partition)131 ValidationError, partition_table.add_partition)
116132
133 def test_get_overhead_size(self):
134 node = factory.make_Node(bios_boot_method="pxe")
135 block_device = factory.make_PhysicalBlockDevice(node=node)
136 partition_table = factory.make_PartitionTable(
137 block_device=block_device)
138 self.assertEquals(
139 PARTITION_TABLE_EXTRA_SPACE,
140 partition_table.get_overhead_size())
141
142 def test_get_overhead_size_for_ppc64el(self):
143 node = factory.make_Node(architecture="ppc64el/generic")
144 block_device = factory.make_PhysicalBlockDevice(node=node)
145 partition_table = factory.make_PartitionTable(
146 block_device=block_device)
147 self.assertEquals(
148 PARTITION_TABLE_EXTRA_SPACE + PREP_PARTITION_SIZE,
149 partition_table.get_overhead_size())
150
117 def test_get_available_size(self):151 def test_get_available_size(self):
118 block_size = 4096152 block_size = 4096
119 device = factory.make_BlockDevice(153 device = factory.make_BlockDevice(
@@ -153,6 +187,20 @@
153 partition_table = factory.make_PartitionTable(block_device=boot_disk)187 partition_table = factory.make_PartitionTable(block_device=boot_disk)
154 self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)188 self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)
155189
190 def test_save_sets_table_type_to_gpt_for_powernv_boot(self):
191 node = factory.make_Node(
192 with_boot_disk=False, bios_boot_method="powernv")
193 boot_disk = factory.make_PhysicalBlockDevice(node=node)
194 partition_table = factory.make_PartitionTable(block_device=boot_disk)
195 self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)
196
197 def test_save_sets_table_type_to_gpt_for_powerkvm_boot(self):
198 node = factory.make_Node(
199 with_boot_disk=False, bios_boot_method="powerkvm")
200 boot_disk = factory.make_PhysicalBlockDevice(node=node)
201 partition_table = factory.make_PartitionTable(block_device=boot_disk)
202 self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)
203
156 def test_save_sets_table_type_to_gpt_for_none_boot_disk(self):204 def test_save_sets_table_type_to_gpt_for_none_boot_disk(self):
157 node = factory.make_Node(with_boot_disk=False, bios_boot_method="pxe")205 node = factory.make_Node(with_boot_disk=False, bios_boot_method="pxe")
158 factory.make_PhysicalBlockDevice(node=node)206 factory.make_PhysicalBlockDevice(node=node)
159207
=== modified file 'src/maasserver/preseed_storage.py'
--- src/maasserver/preseed_storage.py 2016-02-23 12:13:09 +0000
+++ src/maasserver/preseed_storage.py 2016-02-24 16:12:28 +0000
@@ -14,7 +14,10 @@
14 FILESYSTEM_TYPE,14 FILESYSTEM_TYPE,
15 PARTITION_TABLE_TYPE,15 PARTITION_TABLE_TYPE,
16)16)
17from maasserver.models.partitiontable import INITIAL_PARTITION_OFFSET17from maasserver.models.partitiontable import (
18 INITIAL_PARTITION_OFFSET,
19 PREP_PARTITION_SIZE,
20)
18from maasserver.models.physicalblockdevice import PhysicalBlockDevice21from maasserver.models.physicalblockdevice import PhysicalBlockDevice
19from maasserver.models.virtualblockdevice import VirtualBlockDevice22from maasserver.models.virtualblockdevice import VirtualBlockDevice
20import yaml23import yaml
@@ -26,6 +29,7 @@
26 def __init__(self, node):29 def __init__(self, node):
27 self.node = node30 self.node = node
28 self.boot_disk = node.get_boot_disk()31 self.boot_disk = node.get_boot_disk()
32 self.boot_disk_first_partition = None
29 self.operations = {33 self.operations = {
30 "disk": [],34 "disk": [],
31 "partition": [],35 "partition": [],
@@ -103,6 +107,13 @@
103 raise ValueError("Unknown block device instance: %s" % (107 raise ValueError("Unknown block device instance: %s" % (
104 block_device.__class__.__name__))108 block_device.__class__.__name__))
105109
110 def _requires_prep_partition(self, block_device):
111 """Return True if block device requires the prep partition."""
112 arch, _ = self.node.split_arch()
113 return (
114 self.boot_disk.id == block_device.id and
115 arch == "ppc64el")
116
106 def _add_partition_operations(self):117 def _add_partition_operations(self):
107 """Add all the partition operations.118 """Add all the partition operations.
108119
@@ -110,9 +121,16 @@
110 attached to the node.121 attached to the node.
111 """122 """
112 for block_device in self.node.blockdevice_set.order_by('id'):123 for block_device in self.node.blockdevice_set.order_by('id'):
124 requires_prep = self._requires_prep_partition(block_device)
113 partition_table = block_device.get_partitiontable()125 partition_table = block_device.get_partitiontable()
114 if partition_table is not None:126 if partition_table is not None:
115 for partition in partition_table.partitions.order_by('id'):127 partitions = list(partition_table.partitions.order_by('id'))
128 for idx, partition in enumerate(partitions):
129 # If this is the last partition and prep partition is
130 # required then set boot_disk_first_partition so extra
131 # space can be removed.
132 if requires_prep and idx == 0:
133 self.boot_disk_first_partition = partition
116 self.operations["partition"].append(partition)134 self.operations["partition"].append(partition)
117135
118 def _add_format_and_mount_operations(self):136 def _add_format_and_mount_operations(self):
@@ -172,21 +190,35 @@
172190
173 # Set the partition table type if a partition table exists or if this191 # Set the partition table type if a partition table exists or if this
174 # is the boot disk.192 # is the boot disk.
193 add_prep_partition = False
175 partition_table = block_device.get_partitiontable()194 partition_table = block_device.get_partitiontable()
176 if partition_table is not None:195 if partition_table is not None:
177 disk_operation["ptable"] = self._get_ptable_type(196 disk_operation["ptable"] = self._get_ptable_type(
178 partition_table)197 partition_table)
179 elif block_device.id == self.boot_disk.id:198 elif block_device.id == self.boot_disk.id:
180 if self.node.get_bios_boot_method() == "uefi":199 bios_boot_method = self.node.get_bios_boot_method()
200 node_arch, _ = self.node.split_arch()
201 if bios_boot_method in [
202 "uefi", "powernv", "powerkvm"]:
181 disk_operation["ptable"] = "gpt"203 disk_operation["ptable"] = "gpt"
204 if node_arch == "ppc64el":
205 add_prep_partition = True
182 else:206 else:
183 disk_operation["ptable"] = "msdos"207 disk_operation["ptable"] = "msdos"
184208
185 # Set this disk to be the grub device if its the boot disk.209 # Set this disk to be the grub device if it's the boot disk and doesn't
186 if self.boot_disk == block_device:210 # require a prep partition. When a prep partition is required grub
211 # must be installed on that partition and not in the partition header
212 # of that disk.
213 requires_prep = self._requires_prep_partition(block_device)
214 if self.boot_disk.id == block_device.id and not requires_prep:
187 disk_operation["grub_device"] = True215 disk_operation["grub_device"] = True
188 self.storage_config.append(disk_operation)216 self.storage_config.append(disk_operation)
189217
218 # Add the prep partition at the end of the disk when it is required.
219 if add_prep_partition:
220 self._generate_prep_partition(block_device.get_name())
221
190 def _get_ptable_type(self, partition_table):222 def _get_ptable_type(self, partition_table):
191 """Return the value for the "ptable" entry in the physical operation.223 """Return the value for the "ptable" entry in the physical operation.
192 """224 """
@@ -199,12 +231,38 @@
199 "Unknown partition table type: %s" % (231 "Unknown partition table type: %s" % (
200 partition_table.table_type))232 partition_table.table_type))
201233
234 def _generate_prep_partition(self, device_name):
235 """Generate the prep partition at the beginning of the block device."""
236 prep_part_name = "%s-part1" % (device_name)
237 partition_operation = {
238 "id": prep_part_name,
239 "name": prep_part_name,
240 "type": "partition",
241 "number": 1,
242 "offset": "%dB" % INITIAL_PARTITION_OFFSET,
243 "size": "%dB" % PREP_PARTITION_SIZE,
244 "device": device_name,
245 "wipe": "zero",
246 "flag": "prep",
247 "grub_device": True,
248 }
249 self.storage_config.append(partition_operation)
250
202 def _generate_partition_operations(self):251 def _generate_partition_operations(self):
203 """Generate all partition operations."""252 """Generate all partition operations."""
204 for partition in self.operations["partition"]:253 for partition in self.operations["partition"]:
205 self._generate_partition_operation(partition)254 if partition == self.boot_disk_first_partition:
255 # This is the first partition in the boot disk and add prep
256 # partition at the beginning of the partition table.
257 device_name = partition.partition_table.block_device.get_name()
258 self._generate_prep_partition(device_name)
259 self._generate_partition_operation(
260 partition, include_initial=False)
261 else:
262 self._generate_partition_operation(
263 partition, include_initial=True)
206264
207 def _generate_partition_operation(self, partition):265 def _generate_partition_operation(self, partition, include_initial):
208 """Generate partition operation for `partition` and place in266 """Generate partition operation for `partition` and place in
209 `storage_config`."""267 `storage_config`."""
210 partition_table = partition.partition_table268 partition_table = partition.partition_table
@@ -221,7 +279,7 @@
221 "wipe": "superblock",279 "wipe": "superblock",
222 }280 }
223 # First partition always sets the initial offset.281 # First partition always sets the initial offset.
224 if partition_number == 1:282 if partition_number == 1 and include_initial:
225 partition_operation["offset"] = "%sB" % INITIAL_PARTITION_OFFSET283 partition_operation["offset"] = "%sB" % INITIAL_PARTITION_OFFSET
226 if partition.bootable:284 if partition.bootable:
227 partition_operation["flag"] = "boot"285 partition_operation["flag"] = "boot"
228286
=== modified file 'src/maasserver/static/js/angular/controllers/node_details_storage.js'
--- src/maasserver/static/js/angular/controllers/node_details_storage.js 2016-02-02 14:20:45 +0000
+++ src/maasserver/static/js/angular/controllers/node_details_storage.js 2016-02-24 16:12:28 +0000
@@ -51,6 +51,7 @@
51 var END_OF_PARTITION_TABLE_SPACE = 1024 * 1024;51 var END_OF_PARTITION_TABLE_SPACE = 1024 * 1024;
52 var PARTITION_TABLE_EXTRA_SPACE = INITIAL_PARTITION_OFFSET +52 var PARTITION_TABLE_EXTRA_SPACE = INITIAL_PARTITION_OFFSET +
53 END_OF_PARTITION_TABLE_SPACE;53 END_OF_PARTITION_TABLE_SPACE;
54 var PREP_PARTITION_SIZE = 8 * 1024 * 1024;
5455
55 // From models/partition.py - must be kept in sync.56 // From models/partition.py - must be kept in sync.
56 var PARTITION_ALIGNMENT_SIZE = 4 * 1024 * 1024;57 var PARTITION_ALIGNMENT_SIZE = 4 * 1024 * 1024;
@@ -855,6 +856,11 @@
855 || disk.original.partition_table_type === "") {856 || disk.original.partition_table_type === "") {
856 // Disk has no partition table, so reserve space for it.857 // Disk has no partition table, so reserve space for it.
857 space_to_reserve = PARTITION_TABLE_EXTRA_SPACE;858 space_to_reserve = PARTITION_TABLE_EXTRA_SPACE;
859 // ppc64el node requires that space be saved for the prep
860 // partition.
861 if($scope.node.architecture.indexOf("ppc64el") === 0) {
862 space_to_reserve += PREP_PARTITION_SIZE;
863 }
858 }864 }
859 return ConverterService.roundByBlockSize(865 return ConverterService.roundByBlockSize(
860 disk.original.available_size - space_to_reserve,866 disk.original.available_size - space_to_reserve,
@@ -1130,6 +1136,11 @@
1130 if(disk.original.partition_table_type === "mbr" &&1136 if(disk.original.partition_table_type === "mbr" &&
1131 length > 2) {1137 length > 2) {
1132 return disk.name + "-part" + (length + 2);1138 return disk.name + "-part" + (length + 2);
1139 } else if($scope.node.architecture.indexOf("ppc64el") === 0 &&
1140 disk.original.is_boot) {
1141 // Boot disk on ppc64el machines skip the first partition as
1142 // its reserved for the prep partition.
1143 return disk.name + "-part" + (length + 2);
1133 } else {1144 } else {
1134 return disk.name + "-part" + (length + 1);1145 return disk.name + "-part" + (length + 1);
1135 }1146 }
11361147
=== 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 2016-02-02 14:20:45 +0000
+++ src/maasserver/static/js/angular/controllers/tests/test_node_details_storage.js 2016-02-24 16:12:28 +0000
@@ -101,6 +101,7 @@
101 var node, updateNodeSpy, canEditSpy;101 var node, updateNodeSpy, canEditSpy;
102 beforeEach(function() {102 beforeEach(function() {
103 node = {103 node = {
104 architecture: "amd64/generic",
104 disks: []105 disks: []
105 };106 };
106 updateNodeSpy = jasmine.createSpy("updateNode");107 updateNodeSpy = jasmine.createSpy("updateNode");
@@ -1455,6 +1456,25 @@
1455 expect($scope.canAddPartition(disk)).toBe(false);1456 expect($scope.canAddPartition(disk)).toBe(false);
1456 });1457 });
14571458
1459 it("returns false if available_size is less than partition size " +
1460 "when node is ppc64el architecture",
1461 function() {
1462 var controller = makeController();
1463 var disk = {
1464 type: "physical",
1465 fstype: "",
1466 original: {
1467 partition_table_type: null,
1468 available_size: (2.5 * 1024 * 1024) + (8 * 1024 * 1024),
1469 block_size: 1024
1470 }
1471 };
1472 node.architecture = "ppc64el/generic";
1473 spyOn($scope, "isAllStorageDisabled").and.returnValue(false);
1474 $scope.isSuperUser = function() { return true; };
1475 expect($scope.canAddPartition(disk)).toBe(false);
1476 });
1477
1458 it("returns false if not super user", function() {1478 it("returns false if not super user", function() {
1459 var controller = makeController();1479 var controller = makeController();
1460 var disk = {1480 var disk = {
@@ -2350,6 +2370,37 @@
2350 expect($scope.getAddPartitionName(disk)).toBe(name + "-part3");2370 expect($scope.getAddPartitionName(disk)).toBe(name + "-part3");
2351 });2371 });
23522372
2373 it("returns disk.name with -part2 for ppc64el", function() {
2374 node.architecture = "ppc64el/generic";
2375 var controller = makeController();
2376 var name = makeName("sda");
2377 var disk = {
2378 name: name,
2379 original: {
2380 is_boot: true,
2381 partition_table_type: "gpt"
2382 }
2383 };
2384
2385 expect($scope.getAddPartitionName(disk)).toBe(name + "-part2");
2386 });
2387
2388 it("returns disk.name with -part4 for ppc64el", function() {
2389 node.architecture = "ppc64el/generic";
2390 var controller = makeController();
2391 var name = makeName("sda");
2392 var disk = {
2393 name: name,
2394 original: {
2395 is_boot: true,
2396 partition_table_type: "gpt",
2397 partitions: [{}, {}]
2398 }
2399 };
2400
2401 expect($scope.getAddPartitionName(disk)).toBe(name + "-part4");
2402 });
2403
2353 it("returns disk.name with -part3 for MBR", function() {2404 it("returns disk.name with -part3 for MBR", function() {
2354 var controller = makeController();2405 var controller = makeController();
2355 var name = makeName("sda");2406 var name = makeName("sda");
23562407
=== modified file 'src/maasserver/storage_layouts.py'
--- src/maasserver/storage_layouts.py 2015-12-01 18:12:59 +0000
+++ src/maasserver/storage_layouts.py 2016-02-24 16:12:28 +0000
@@ -169,7 +169,12 @@
169 from maasserver.models.partitiontable import PartitionTable169 from maasserver.models.partitiontable import PartitionTable
170 boot_partition_table = PartitionTable.objects.create(170 boot_partition_table = PartitionTable.objects.create(
171 block_device=self.boot_disk)171 block_device=self.boot_disk)
172 if boot_partition_table.table_type == PARTITION_TABLE_TYPE.GPT:172 bios_boot_method = self.node.get_bios_boot_method()
173 node_arch, _ = self.node.split_arch()
174 if (boot_partition_table.table_type == PARTITION_TABLE_TYPE.GPT and
175 bios_boot_method == "uefi" and node_arch != "ppc64el"):
176 # Add EFI partition only if booting UEFI and not a ppc64el
177 # architecture.
173 efi_partition = boot_partition_table.add_partition(178 efi_partition = boot_partition_table.add_partition(
174 size=EFI_PARTITION_SIZE, bootable=True)179 size=EFI_PARTITION_SIZE, bootable=True)
175 Filesystem.objects.create(180 Filesystem.objects.create(
176181
=== modified file 'src/maasserver/tests/test_preseed_storage.py'
--- src/maasserver/tests/test_preseed_storage.py 2016-02-23 12:13:09 +0000
+++ src/maasserver/tests/test_preseed_storage.py 2016-02-24 16:12:28 +0000
@@ -20,7 +20,10 @@
20 RAID,20 RAID,
21 VolumeGroup,21 VolumeGroup,
22)22)
23from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE23from maasserver.models.partitiontable import (
24 PARTITION_TABLE_EXTRA_SPACE,
25 PREP_PARTITION_SIZE,
26)
24from maasserver.preseed_storage import compose_curtin_storage_config27from maasserver.preseed_storage import compose_curtin_storage_config
25from maasserver.testing.factory import factory28from maasserver.testing.factory import factory
26from maasserver.testing.testcase import MAASServerTestCase29from maasserver.testing.testcase import MAASServerTestCase
@@ -770,6 +773,217 @@
770 self.assertStorageConfig(self.STORAGE_CONFIG, config)773 self.assertStorageConfig(self.STORAGE_CONFIG, config)
771774
772775
776class TestSimplePower8Layout(MAASServerTestCase, AssertStorageConfigMixin):
777
778 STORAGE_CONFIG = dedent("""\
779 config:
780 - id: sda
781 name: sda
782 type: disk
783 wipe: superblock
784 ptable: gpt
785 model: QEMU HARDDISK
786 serial: QM00001
787 - id: sda-part1
788 name: sda-part1
789 type: partition
790 number: 1
791 offset: 4194304B
792 size: 8388608B
793 device: sda
794 wipe: zero
795 flag: prep
796 grub_device: True
797 - id: sda-part2
798 name: sda-part2
799 type: partition
800 number: 2
801 uuid: f74ff260-2a5b-4a36-b1b8-37f746b946bf
802 size: 8573157376B
803 wipe: superblock
804 device: sda
805 - id: sda-part2_format
806 type: format
807 fstype: ext4
808 label: root
809 uuid: 90a69b22-e281-4c5b-8df9-b09514f27ba1
810 volume: sda-part2
811 - id: sda-part2_mount
812 type: mount
813 path: /
814 device: sda-part2_format
815 """)
816
817 def test__renders_expected_output(self):
818 node = factory.make_Node(
819 status=NODE_STATUS.ALLOCATED, architecture="ppc64el/generic",
820 bios_boot_method="uefi", with_boot_disk=False)
821 boot_disk = factory.make_PhysicalBlockDevice(
822 node=node, size=8 * 1024 ** 3, name="sda",
823 model="QEMU HARDDISK", serial="QM00001") # 8 GiB
824 partition_table = factory.make_PartitionTable(
825 table_type=PARTITION_TABLE_TYPE.GPT, block_device=boot_disk)
826 root_partition = factory.make_Partition(
827 partition_table=partition_table,
828 uuid="f74ff260-2a5b-4a36-b1b8-37f746b946bf",
829 size=(
830 (8 * 1024 ** 3) - PARTITION_TABLE_EXTRA_SPACE -
831 PREP_PARTITION_SIZE),
832 bootable=False)
833 factory.make_Filesystem(
834 partition=root_partition, fstype=FILESYSTEM_TYPE.EXT4,
835 uuid="90a69b22-e281-4c5b-8df9-b09514f27ba1", label="root",
836 mount_point="/", mount_options=None)
837 node._create_acquired_filesystems()
838 config = compose_curtin_storage_config(node)
839 self.assertStorageConfig(self.STORAGE_CONFIG, config)
840
841
842class TestPower8ExtraSpaceLayout(
843 MAASServerTestCase, AssertStorageConfigMixin):
844
845 STORAGE_CONFIG = dedent("""\
846 config:
847 - id: sda
848 name: sda
849 type: disk
850 wipe: superblock
851 ptable: gpt
852 model: QEMU HARDDISK
853 serial: QM00001
854 - id: sda-part1
855 name: sda-part1
856 type: partition
857 number: 1
858 offset: 4194304B
859 size: 8388608B
860 device: sda
861 wipe: zero
862 flag: prep
863 grub_device: True
864 - id: sda-part2
865 name: sda-part2
866 type: partition
867 number: 2
868 uuid: f74ff260-2a5b-4a36-b1b8-37f746b946bf
869 size: 7507804160B
870 wipe: superblock
871 device: sda
872 - id: sda-part2_format
873 type: format
874 fstype: ext4
875 label: root
876 uuid: 90a69b22-e281-4c5b-8df9-b09514f27ba1
877 volume: sda-part2
878 - id: sda-part2_mount
879 type: mount
880 path: /
881 device: sda-part2_format
882 """)
883
884 def test__renders_expected_output(self):
885 node = factory.make_Node(
886 status=NODE_STATUS.ALLOCATED, architecture="ppc64el/generic",
887 bios_boot_method="uefi", with_boot_disk=False)
888 boot_disk = factory.make_PhysicalBlockDevice(
889 node=node, size=8 * 1024 ** 3, name="sda",
890 model="QEMU HARDDISK", serial="QM00001") # 8 GiB
891 partition_table = factory.make_PartitionTable(
892 table_type=PARTITION_TABLE_TYPE.GPT, block_device=boot_disk)
893 root_partition = factory.make_Partition(
894 partition_table=partition_table,
895 uuid="f74ff260-2a5b-4a36-b1b8-37f746b946bf",
896 size=(7 * 1024 ** 3) - PARTITION_TABLE_EXTRA_SPACE,
897 bootable=False)
898 factory.make_Filesystem(
899 partition=root_partition, fstype=FILESYSTEM_TYPE.EXT4,
900 uuid="90a69b22-e281-4c5b-8df9-b09514f27ba1", label="root",
901 mount_point="/", mount_options=None)
902 node._create_acquired_filesystems()
903 config = compose_curtin_storage_config(node)
904 self.assertStorageConfig(self.STORAGE_CONFIG, config)
905
906
907class TestPower8NoPartitionTableLayout(
908 MAASServerTestCase, AssertStorageConfigMixin):
909
910 STORAGE_CONFIG = dedent("""\
911 config:
912 - id: sda
913 name: sda
914 type: disk
915 wipe: superblock
916 ptable: gpt
917 model: QEMU HARDDISK
918 serial: QM00001
919 - id: sdb
920 name: sdb
921 type: disk
922 wipe: superblock
923 ptable: gpt
924 model: QEMU HARDDISK
925 serial: QM00002
926 - id: sdb-part1
927 name: sdb-part1
928 type: partition
929 number: 1
930 offset: 4194304B
931 size: 8388608B
932 device: sdb
933 wipe: zero
934 flag: prep
935 grub_device: True
936 - id: sda-part1
937 name: sda-part1
938 type: partition
939 number: 1
940 uuid: f74ff260-2a5b-4a36-b1b8-37f746b946bf
941 offset: 4194304B
942 size: 8573157376B
943 wipe: superblock
944 device: sda
945 - id: sda-part1_format
946 type: format
947 fstype: ext4
948 label: root
949 uuid: 90a69b22-e281-4c5b-8df9-b09514f27ba1
950 volume: sda-part1
951 - id: sda-part1_mount
952 type: mount
953 path: /
954 device: sda-part1_format
955 """)
956
957 def test__renders_expected_output(self):
958 node = factory.make_Node(
959 status=NODE_STATUS.ALLOCATED, architecture="ppc64el/generic",
960 bios_boot_method="uefi", with_boot_disk=False)
961 root_disk = factory.make_PhysicalBlockDevice(
962 node=node, size=8 * 1024 ** 3, name="sda",
963 model="QEMU HARDDISK", serial="QM00001") # 8 GiB
964 partition_table = factory.make_PartitionTable(
965 table_type=PARTITION_TABLE_TYPE.GPT, block_device=root_disk)
966 boot_disk = factory.make_PhysicalBlockDevice(
967 node=node, size=8 * 1024 ** 3, name="sdb",
968 model="QEMU HARDDISK", serial="QM00002") # 8 GiB
969 node.boot_disk = boot_disk
970 node.save()
971 root_partition = factory.make_Partition(
972 partition_table=partition_table,
973 uuid="f74ff260-2a5b-4a36-b1b8-37f746b946bf",
974 size=(
975 (8 * 1024 ** 3) - PARTITION_TABLE_EXTRA_SPACE -
976 PREP_PARTITION_SIZE),
977 bootable=False)
978 factory.make_Filesystem(
979 partition=root_partition, fstype=FILESYSTEM_TYPE.EXT4,
980 uuid="90a69b22-e281-4c5b-8df9-b09514f27ba1", label="root",
981 mount_point="/", mount_options=None)
982 node._create_acquired_filesystems()
983 config = compose_curtin_storage_config(node)
984 self.assertStorageConfig(self.STORAGE_CONFIG, config)
985
986
773def shuffled(things):987def shuffled(things):
774 things = list(things)988 things = list(things)
775 random.shuffle(things)989 random.shuffle(things)
776990
=== modified file 'src/maasserver/tests/test_storage_layouts.py'
--- src/maasserver/tests/test_storage_layouts.py 2016-01-21 17:03:28 +0000
+++ src/maasserver/tests/test_storage_layouts.py 2016-02-24 16:12:28 +0000
@@ -20,7 +20,10 @@
20 MAX_PARTITION_SIZE_FOR_MBR,20 MAX_PARTITION_SIZE_FOR_MBR,
21 PARTITION_ALIGNMENT_SIZE,21 PARTITION_ALIGNMENT_SIZE,
22)22)
23from maasserver.models.partitiontable import PARTITION_TABLE_EXTRA_SPACE23from maasserver.models.partitiontable import (
24 PARTITION_TABLE_EXTRA_SPACE,
25 PREP_PARTITION_SIZE,
26)
24from maasserver.storage_layouts import (27from maasserver.storage_layouts import (
25 BcacheStorageLayout,28 BcacheStorageLayout,
26 BcacheStorageLayoutBase,29 BcacheStorageLayoutBase,
@@ -54,6 +57,20 @@
54 return factory.make_Node(*args, **kwargs)57 return factory.make_Node(*args, **kwargs)
5558
5659
60def make_ppc64el_Node_with_powernv_boot_method(*args, **kwargs):
61 kwargs['bios_boot_method'] = "powernv"
62 kwargs['with_boot_disk'] = False
63 kwargs['architecture'] = "ppc64el/generic"
64 return factory.make_Node(*args, **kwargs)
65
66
67def make_ppc64el_Node_with_uefi_boot_method(*args, **kwargs):
68 kwargs['bios_boot_method'] = "powerkvm"
69 kwargs['with_boot_disk'] = False
70 kwargs['architecture'] = "ppc64el/generic"
71 return factory.make_Node(*args, **kwargs)
72
73
57class TestFormHelpers(MAASServerTestCase):74class TestFormHelpers(MAASServerTestCase):
5875
59 def test_get_storage_layout_choices(self):76 def test_get_storage_layout_choices(self):
@@ -505,6 +522,66 @@
505 mount_point="/",522 mount_point="/",
506 ))523 ))
507524
525 def test__creates_layout_for_powernv(self):
526 node = make_ppc64el_Node_with_powernv_boot_method()
527 boot_disk = factory.make_PhysicalBlockDevice(
528 node=node, size=LARGE_BLOCK_DEVICE)
529 layout = FlatStorageLayout(node)
530 layout.configure()
531
532 # Validate partition table.
533 partition_table = boot_disk.get_partitiontable()
534 self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)
535
536 # Validate root partition.
537 partitions = partition_table.partitions.order_by('id').all()
538 root_partition = partitions[0]
539 self.assertIsNotNone(root_partition)
540 self.assertEqual(
541 round_size_to_nearest_block(
542 boot_disk.size - PARTITION_TABLE_EXTRA_SPACE -
543 PREP_PARTITION_SIZE,
544 PARTITION_ALIGNMENT_SIZE,
545 False),
546 root_partition.size)
547 self.assertThat(
548 root_partition.get_effective_filesystem(),
549 MatchesStructure.byEquality(
550 fstype=FILESYSTEM_TYPE.EXT4,
551 label="root",
552 mount_point="/",
553 ))
554
555 def test__creates_layout_for_powerkvm(self):
556 node = make_ppc64el_Node_with_uefi_boot_method()
557 boot_disk = factory.make_PhysicalBlockDevice(
558 node=node, size=LARGE_BLOCK_DEVICE)
559 layout = FlatStorageLayout(node)
560 layout.configure()
561
562 # Validate partition table.
563 partition_table = boot_disk.get_partitiontable()
564 self.assertEqual(PARTITION_TABLE_TYPE.GPT, partition_table.table_type)
565
566 # Validate root partition.
567 partitions = partition_table.partitions.order_by('id').all()
568 root_partition = partitions[0]
569 self.assertIsNotNone(root_partition)
570 self.assertEqual(
571 round_size_to_nearest_block(
572 boot_disk.size - PARTITION_TABLE_EXTRA_SPACE -
573 PREP_PARTITION_SIZE,
574 PARTITION_ALIGNMENT_SIZE,
575 False),
576 root_partition.size)
577 self.assertThat(
578 root_partition.get_effective_filesystem(),
579 MatchesStructure.byEquality(
580 fstype=FILESYSTEM_TYPE.EXT4,
581 label="root",
582 mount_point="/",
583 ))
584
508 def test__creates_layout_with_uefi_defaults(self):585 def test__creates_layout_with_uefi_defaults(self):
509 node = make_Node_with_uefi_boot_method()586 node = make_Node_with_uefi_boot_method()
510 boot_disk = factory.make_PhysicalBlockDevice(587 boot_disk = factory.make_PhysicalBlockDevice(
511588
=== modified file 'src/provisioningserver/boot/powerkvm.py'
--- src/provisioningserver/boot/powerkvm.py 2015-12-01 18:12:59 +0000
+++ src/provisioningserver/boot/powerkvm.py 2016-02-24 16:12:28 +0000
@@ -33,7 +33,7 @@
33class PowerKVMBootMethod(BootMethod):33class PowerKVMBootMethod(BootMethod):
3434
35 name = "powerkvm"35 name = "powerkvm"
36 bios_boot_method = "pxe"36 bios_boot_method = "powerkvm"
37 template_subdir = None37 template_subdir = None
38 bootloader_path = "bootppc64.bin"38 bootloader_path = "bootppc64.bin"
39 bootloader_arches = ['ppc64el']39 bootloader_arches = ['ppc64el']
4040
=== modified file 'src/provisioningserver/boot/powernv.py'
--- src/provisioningserver/boot/powernv.py 2015-12-01 18:12:59 +0000
+++ src/provisioningserver/boot/powernv.py 2016-02-24 16:12:28 +0000
@@ -61,7 +61,7 @@
61class PowerNVBootMethod(BootMethod):61class PowerNVBootMethod(BootMethod):
6262
63 name = "powernv"63 name = "powernv"
64 bios_boot_method = "pxe"64 bios_boot_method = "powernv"
65 template_subdir = "pxe"65 template_subdir = "pxe"
66 bootloader_path = "pxelinux.0"66 bootloader_path = "pxelinux.0"
67 arch_octet = "00:0E"67 arch_octet = "00:0E"