Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Jul 4, 2023
1 parent 64f7eb1 commit a1cce29
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 22 deletions.
15 changes: 13 additions & 2 deletions pkg/storaged/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -977,12 +977,23 @@ function stratis3_start() {
[false, ["", ""]]);
};

client.stratis_set_overprovisioning = (pool, flag) => {
// DBusProxy is smart enough to allow
// "pool.Overprovisioning = flag" to just work,
// but we want to catch any error directly.
return stratis.call(pool.path, "org.freedesktop.DBus.Properties", "Set",
["org.storage.stratis3.pool." + stratis3_interface_revision,
"Overprovisioning",
cockpit.variant("b", flag)
]);
};

client.stratis_list_keys = () => {
return client.stratis_manager.ListKeys();
};

client.stratis_create_filesystem = (pool, name) => {
return pool.CreateFilesystems([[name, [false, ""]]]);
client.stratis_create_filesystem = (pool, name, size) => {
return pool.CreateFilesystems([[name, size ? [true, size.toString()] : [false, ""]]]);
};

client.features.stratis = true;
Expand Down
8 changes: 6 additions & 2 deletions pkg/storaged/fsys-panel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,12 @@ export class FilesystemsPanel extends React.Component {
{ title: "Stratis" },
{ title: mount },
{
title: <StorageUsageBar stats={[Number(fs.Used[0] && Number(fs.Used[1])), pool_total]}
critical={1} total={total} offset={offsets[i]} />,
title: (pool.Overprovisioning
? <StorageUsageBar stats={[Number(fs.Used[0] && Number(fs.Used[1])), pool_total]}
critical={1} total={total} offset={offsets[i]} />
: <StorageUsageBar stats={[Number(fs.Used[0] && Number(fs.Used[1])), Number(fs.Size)]}
critical={0.95} />
),
props: { className: "pf-v5-u-text-align-right" }
}
]
Expand Down
68 changes: 51 additions & 17 deletions pkg/storaged/stratis-details.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { SidePanel } from "./side-panel.jsx";
import {
dialog_open,
TextInput, PassInput, SelectOne, SelectSpaces,
CheckBoxes,
CheckBoxes, SizeSlider,
BlockingMessage, TeardownMessage,
init_active_usage_processes
} from "./dialog.jsx";
Expand Down Expand Up @@ -305,6 +305,13 @@ export const StratisPoolDetails = ({ client, pool }) => {
{
validate: name => validate_fs_name(null, name)
}),
SizeSlider("size", _("Size"),
{
visible: () => !pool.Overprovisioning,
min: fsys_min_size,
max: pool_free,
round: 512
}),
TextInput("mount_point", _("Mount point"),
{
validate: (val, values, variant) => {
Expand Down Expand Up @@ -355,7 +362,7 @@ export const StratisPoolDetails = ({ client, pool }) => {
Title: _("Create and mount"),
Variants: [{ tag: "nomount", Title: _("Create only") }],
action: function (vals) {
return client.stratis_create_filesystem(pool, vals.name)
return client.stratis_create_filesystem(pool, vals.name, vals.size)
.then(std_reply)
.then(result => {
if (result[0])
Expand Down Expand Up @@ -390,7 +397,7 @@ export const StratisPoolDetails = ({ client, pool }) => {
<DescriptionListTerm className="control-DescriptionListTerm">{_("storage", "UUID")}</DescriptionListTerm>
<DescriptionListDescription>{ pool.Uuid }</DescriptionListDescription>
</DescriptionListGroup>
{ use &&
{ pool.Overprovisioning && use &&
<DescriptionListGroup>
<DescriptionListTerm className="control-DescriptionListTerm">{_("storage", "Usage")}</DescriptionListTerm>
<DescriptionListDescription className="pf-v5-u-align-self-center">
Expand All @@ -405,9 +412,25 @@ export const StratisPoolDetails = ({ client, pool }) => {

const sidebar = <StratisPoolSidebar client={client} pool={pool} />;

function render_fsys(fsys, offset, total) {
const overhead = pool.TotalPhysicalUsed[0] ? (Number(pool.TotalPhysicalUsed[1]) - total) : 0;
const pool_total = Number(pool.TotalPhysicalSize) - overhead;
const offsets = [];
let fsys_total_used = 0;
let fsys_total_size = 0;
filesystems.forEach(fs => {
offsets.push(fsys_total_used);
fsys_total_used += fs.Used[0] ? Number(fs.Used[1]) : 0;
fsys_total_size += Number(fs.Size);
});

const overhead = pool.TotalPhysicalUsed[0] ? (Number(pool.TotalPhysicalUsed[1]) - fsys_total_used) : 0;
const pool_total = Number(pool.TotalPhysicalSize) - overhead;
let pool_free = pool_total - fsys_total_size;
const fsys_min_size = 512 * 1024 * 1024;

// leave some margin since the above computation does not seem to
// be exactly right when snapshots are involved.
pool_free -= filesystems.length * 1024 * 1024;

function render_fsys(fsys, offset) {
const block = client.slashdevs_block[fsys.Devnode];

if (!block) {
Expand Down Expand Up @@ -448,6 +471,15 @@ export const StratisPoolDetails = ({ client, pool }) => {
}

function snapshot_fsys() {
if (!pool.Overprovisioning && pool_free < Number(fsys.Size)) {
dialog_open({
Title: _("Not enough space"),
Body: cockpit.format(_("There is not enough space in the pool to make a snapshot of this filesystem. At least $0 are required but only $1 are available."),
fmt_size(Number(fsys.Size)), fmt_size(pool_free))
});
return;
}

dialog_open({
Title: cockpit.format(_("Create a snapshot of filesystem $0"), fsys.Name),
Fields: [
Expand Down Expand Up @@ -598,8 +630,12 @@ export const StratisPoolDetails = ({ client, pool }) => {
title: mount_point
},
{
title: <StorageUsageBar stats={[Number(fsys.Used[0] && Number(fsys.Used[1])), pool_total]}
critical={1} total={total} offset={offset} />,
title: (pool.Overprovisioning
? <StorageUsageBar stats={[Number(fsys.Used[0] && Number(fsys.Used[1])), pool_total]}
critical={1} total={fsys_total_used} offset={offset} />
: <StorageUsageBar stats={[Number(fsys.Used[0] && Number(fsys.Used[1])), Number(fsys.Size)]}
critical={0.95} />
),
props: { className: "pf-v5-u-text-align-right" }
},
{
Expand All @@ -615,18 +651,16 @@ export const StratisPoolDetails = ({ client, pool }) => {
};
}

const offsets = [];
let total = 0;
filesystems.forEach(fs => {
offsets.push(total);
total += fs.Used[0] ? Number(fs.Used[1]) : 0;
});

const rows = filesystems.map((fs, i) => render_fsys(fs, offsets[i], total));
const rows = filesystems.map((fs, i) => render_fsys(fs, offsets[i]));

const content = (
<Card>
<CardHeader actions={{ actions: <><StorageButton onClick={create_fs}>{_("Create new filesystem")}</StorageButton></> }}>
<CardHeader actions={{
actions: <StorageButton onClick={create_fs}
excuse={!pool.Overprovisioning && pool_free < fsys_min_size ? _("Not enough space for new filesystems") : null}>
{_("Create new filesystem")}
</StorageButton>
}}>
<CardTitle component="h2">{_("Filesystems")}</CardTitle>

</CardHeader>
Expand Down
18 changes: 17 additions & 1 deletion pkg/storaged/stratis-panel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ export function create_stratis_pool(client) {
value: name,
validate: name => validate_pool_name(client, null, name)
}),
CheckBoxes("managed", "",
{
fields: [
{ tag: "on", title: _("Manage filesystem sizes") }
]
}),
CheckBoxes("encrypt", "",
{
fields: [
Expand Down Expand Up @@ -162,7 +168,17 @@ export function create_stratis_pool(client) {
const devs = paths.map(p => decode_filename(client.blocks[p].PreferredDevice));

function create(key_desc) {
return client.stratis_create_pool(vals.name, devs, key_desc).then(std_reply);
return client.stratis_create_pool(vals.name, devs, key_desc)
.then(std_reply)
.then(result => {
if (vals.managed.on && result[0]) {
const path = result[1][0];
return client.wait_for(() => client.stratis_pools[path])
.then(pool => {
client.stratis_set_overprovisioning(pool, false);
});
}
});
}

if (vals.encrypt.on) {
Expand Down
66 changes: 66 additions & 0 deletions test/verify/check-storage-stratis
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,72 @@ class TestStorageStratis(storagelib.StorageCase):
self.assertIn("noauto", m.execute("findmnt --fstab -n -o OPTIONS /foo"))
destroy()

def testManagedSizes(self):
m = self.machine
b = self.browser

self.login_and_go("/storage")

dev_1 = "/dev/sda"
m.add_disk("4G", serial="DISK1")
b.wait_in_text("#drives", dev_1)

# Create a "managed" pool
self.dialog_with_retry(trigger=lambda: self.devices_dropdown("Create Stratis pool"),
expect=lambda: (self.dialog_is_present('disks', dev_1) and
self.dialog_check({"name": "pool0"})),
values={"managed.on": True, "disks": {dev_1: True}})
b.wait_in_text("#devices", "pool0")

b.click('.sidepanel-row:contains("pool0")')
b.wait_visible('#storage-detail')

# Create a small filesystem
b.click("button:contains(Create new filesystem)")
self.dialog({'name': 'fsys1',
'size': 900,
'mount_point': '/run/fsys1'})
b.wait_in_text("#detail-content", "fsys1")

# Make a snapshot of it
self.content_dropdown_action(1, "Snapshot")
self.dialog({'name': 'fsys1-copy',
'mount_point': '/run/fsys1-copy'})
b.wait_in_text("#detail-content", "fsys1-copy")

# And another filesystem
b.click("button:contains(Create new filesystem)")
self.dialog({'name': 'fsys2',
'size': 800,
'mount_point': '/run/fsys2'})
b.wait_in_text("#detail-content", "fsys2")

# And fill the rest by accepting the default size
b.click("button:contains(Create new filesystem)")
self.dialog({'name': 'fsys3',
'mount_point': '/run/fsys3'})
b.wait_in_text("#detail-content", "fsys3")
b.wait_visible("button:contains(Create new filesystem):disabled")

# Snapshots are impossible now
self.content_dropdown_action(2, "Snapshot")
self.dialog_wait_open()
b.wait_in_text('#dialog', "Not enough space")
self.dialog_cancel()
self.dialog_wait_close()

# Delete a filesystem, and make another snapshot
self.content_dropdown_action(1, "Delete")
self.confirm()
b.wait_visible("button:contains(Create new filesystem):not(:disabled)")
self.content_dropdown_action(2, "Snapshot")
self.dialog({'name': 'fsys2-copy',
'mount_point': '/run/fsys2-copy'})
b.wait_in_text("#detail-content", "fsys2-copy")

# And the pool should be full again
b.wait_visible("button:contains(Create new filesystem):disabled")


@testlib.skipImage("No Stratis", "debian-*", "ubuntu-*", "arch")
class TestStoragePackagesStratis(packagelib.PackageCase, storagelib.StorageCase):
Expand Down

0 comments on commit a1cce29

Please sign in to comment.