Skip to content

Commit a545278

Browse files
committed
storage: Detect partition tables in unsupported places
These likely belong to virtual machines and we shouldn't touch them. See https://bugzilla.redhat.com/show_bug.cgi?id=2364699
1 parent 09ebd7d commit a545278

File tree

7 files changed

+63
-9
lines changed

7 files changed

+63
-9
lines changed

pkg/storaged/block/create-pages.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import { new_page } from "../pages.jsx";
4242
/* CARD must have page_name, page_location, and page_size set.
4343
*/
4444

45-
export function make_block_page(parent, block, card) {
45+
export function make_block_page(parent, block, card, options) {
4646
let is_crypto = block.IdUsage == 'crypto';
4747
let content_block = is_crypto ? client.blocks_cleartext[block.path] : block;
4848
const fstab_config = get_fstab_config(content_block || block, true);
@@ -62,7 +62,7 @@ export function make_block_page(parent, block, card) {
6262
const single_device_volume = block_btrfs_blockdev && block_btrfs_blockdev.data.num_devices === 1;
6363

6464
if (client.blocks_ptable[block.path]) {
65-
make_partition_table_page(parent, block, card);
65+
make_partition_table_page(parent, block, card, options && options.partitionable);
6666
return;
6767
}
6868

pkg/storaged/block/other.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function make_other_page(parent, block) {
4949
actions: partitionable_block_actions(block),
5050
});
5151

52-
make_block_page(parent, block, other_card);
52+
make_block_page(parent, block, other_card, { partitionable: true });
5353
}
5454

5555
const OtherCard = ({ card, block }) => {

pkg/storaged/drive/drive.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export function make_drive_page(parent, drive) {
105105
}
106106

107107
if (block.Size > 0) {
108-
make_block_page(parent, block, card);
108+
make_block_page(parent, block, card, { partitionable: true });
109109
} else {
110110
new_page(parent, card);
111111
}

pkg/storaged/mdraid/mdraid.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ export function make_mdraid_page(parent, mdraid) {
247247
if (!block) {
248248
new_page(parent, mdraid_card);
249249
} else
250-
make_block_page(parent, block, mdraid_card);
250+
make_block_page(parent, block, mdraid_card, { partitionable: true });
251251
}
252252

253253
const MDRaidCard = ({ card, mdraid, block }) => {

pkg/storaged/partitions/partition-table.jsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import cockpit from "cockpit";
2121
import React from "react";
2222
import client from "../client";
2323

24+
import { Alert } from "@patternfly/react-core/dist/esm/components/Alert/index.js";
25+
26+
import { CardBody } from "@patternfly/react-core/dist/esm/components/Card/index.js";
27+
2428
import { get_partitions } from "../utils.js";
2529
import { StorageCard, ChildrenTable, new_page, new_card } from "../pages.jsx";
2630
import { format_dialog } from "../block/format-dialog.jsx";
@@ -83,20 +87,21 @@ function make_partition_pages(parent, block) {
8387
block_ptable.Type == 'dos');
8488
}
8589

86-
export function make_partition_table_page(parent, block, next_card) {
90+
export function make_partition_table_page(parent, block, next_card, partitionable) {
8791
const block_ptable = client.blocks_ptable[block.path];
8892

8993
const parts_card = new_card({
9094
title: (block_ptable.Type
9195
? cockpit.format(_("$0 partitions"), block_ptable.Type.toLocaleUpperCase())
9296
: _("Partitions")),
9397
next: next_card,
94-
component: PartitionsCard,
98+
component: partitionable ? PartitionsCard : UnexpectedPartitionsCard,
9599
props: { },
96100
});
97101

98102
const p = new_page(parent, parts_card, { sorted: false });
99-
make_partition_pages(p, block);
103+
if (partitionable)
104+
make_partition_pages(p, block);
100105
}
101106

102107
const PartitionsCard = ({ card }) => {
@@ -109,3 +114,15 @@ const PartitionsCard = ({ card }) => {
109114
</StorageCard>
110115
);
111116
};
117+
118+
const UnexpectedPartitionsCard = ({ card }) => {
119+
return (
120+
<StorageCard card={card}>
121+
<CardBody>
122+
<Alert isInline isPlain variant="info" title={_("Unexpected partitions")}>
123+
<p>{_("Partitions are not supported on this block device. If it is used as a disk for a virtual machine, the partitions must be managed by the operating system inside the virtual machine.")}</p>
124+
</Alert>
125+
</CardBody>
126+
</StorageCard>
127+
);
128+
};

pkg/storaged/utils.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,14 +500,19 @@ export function is_available_block(client, block, honor_ignore_hint) {
500500
return !!block && client.blocks_swap[block.path];
501501
}
502502

503+
function part_is_for_vm() {
504+
const table_block = client.blocks[block_part.Table];
505+
return table_block && !client.drives[table_block.Drive] && !client.mdraids[table_block.MDRaid];
506+
}
507+
503508
return (!(block.HintIgnore && honor_ignore_hint) &&
504509
block.Size > 0 &&
505510
!has_fs_label() &&
506511
!is_mpath_member() &&
507512
!is_vdo_backing_dev() &&
508513
!is_swap() &&
509514
!block_ptable &&
510-
!(block_part && block_part.IsContainer) &&
515+
!(block_part && (block_part.IsContainer || part_is_for_vm())) &&
511516
!should_ignore(client, block.path));
512517
}
513518

@@ -524,6 +529,13 @@ export function get_available_spaces(client) {
524529
.map(make);
525530

526531
function add_free_spaces(block) {
532+
/* Only offer to create partitions on Disks and MDRaids,
533+
partition tables in other locations very likely belong to
534+
virtual machines.
535+
*/
536+
if (!client.drives[block.Drive] && !client.mdraids[block.MDRaid])
537+
return;
538+
527539
const parts = get_partitions(client, block);
528540
let i;
529541
let p;

test/verify/check-storage-lvm2

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,31 @@ class TestStorageLvm2(storagelib.StorageCase):
841841
b.wait_in_text(self.card_desc("LVM2 logical volume", "Physical volumes"), bn(disk))
842842
b.wait_in_text(self.card_desc("LVM2 logical volume", "Physical volumes"), bn(disk2))
843843

844+
def testUnsupportedPartitions(self):
845+
b = self.browser
846+
m = self.machine
847+
848+
self.login_and_go("/storage")
849+
850+
dev_1 = self.add_ram_disk(100)
851+
m.execute(f"vgcreate vgroup0 {dev_1}")
852+
self.addCleanupVG("vgroup0")
853+
m.execute("lvcreate vgroup0 -n lvol0 -l100%FREE")
854+
m.execute("parted /dev/vgroup0/lvol0 -s mktable gpt mkpart primary ext2 1M 50M")
855+
self.addCleanup(m.execute, "parted /dev/vgroup0/lvol0 -s mktable gpt; wipefs -a /dev/vgroup0/lvol0")
856+
857+
b.wait_text(self.card_row_col("Storage", row_name="lvol0", col_index=3), "GPT partitions")
858+
self.click_card_row("Storage", name="lvol0")
859+
b.wait_in_text(self.card("GPT partitions"), "Partitions are not supported on this block device.")
860+
861+
# Neither the partition nor the free space should be offered
862+
# for creating new things.
863+
864+
b.click(self.card_parent_link())
865+
b.click(self.card_parent_link())
866+
self.click_devices_dropdown("Create LVM2 volume group")
867+
b.wait_in_text("#dialog", "No disks are available")
868+
844869

845870
class TestStorageLvm2Destructive(storagelib.StorageCase):
846871

0 commit comments

Comments
 (0)