diff --git a/web/src/client/storage.js b/web/src/client/storage.js index 66a92956bf..39a5d5c19a 100644 --- a/web/src/client/storage.js +++ b/web/src/client/storage.js @@ -31,6 +31,7 @@ const STORAGE_IFACE = "org.opensuse.Agama.Storage1"; const STORAGE_JOBS_NAMESPACE = "/org/opensuse/Agama/Storage1/jobs"; const STORAGE_JOB_IFACE = "org.opensuse.Agama.Storage1.Job"; const STORAGE_SYSTEM_NAMESPACE = "/org/opensuse/Agama/Storage1/system"; +const STORAGE_STAGING_NAMESPACE = "/org/opensuse/Agama/Storage1/staging"; const PROPOSAL_IFACE = "org.opensuse.Agama.Storage1.Proposal"; const PROPOSAL_CALCULATOR_IFACE = "org.opensuse.Agama.Storage1.Proposal.Calculator"; const ISCSI_INITIATOR_IFACE = "org.opensuse.Agama.Storage1.ISCSI.Initiator"; @@ -107,7 +108,9 @@ class DevicesManager { * @returns {Promise} * * @typedef {object} StorageDevice - * @property {string} sid - Internal id that is used as D-Bus object basename + * @property {string} sid - Storage ID + * @property {string} name - Device name + * @property {string} description - Device description * @property {boolean} isDrive - Whether the device is a drive * @property {string} type - Type of device ("disk", "raid", "multipath", "dasd", "md") * @property {string} [vendor] @@ -122,8 +125,10 @@ class DevicesManager { * @property {string[]} [wires] - Multipath wires (only for "multipath" type) * @property {string} [level] - MD RAID level (only for "md" type) * @property {string} [uuid] + * @property {number} [start] - First block of the region (only for block devices) * @property {boolean} [active] - * @property {string} [name] - Block device name + * @property {boolean} [encrypted] - Whether the device is encrypted (only for block devices) + * @property {boolean} [isEFI] - Whether the device is an EFI partition (only for partition) * @property {number} [size] * @property {number} [recoverableSize] * @property {string[]} [systems] - Name of the installed systems @@ -131,18 +136,36 @@ class DevicesManager { * @property {string[]} [udevPaths] * @property {PartitionTable} [partitionTable] * @property {Filesystem} [filesystem] + * @property {Component} [component] - When it is used as component of other devices + * @property {StorageDevice[]} [physicalVolumes] - Only for LVM VGs + * @property {StorageDevice[]} [logicalVolumes] - Only for LVM VGs * * @typedef {object} PartitionTable * @property {string} type * @property {StorageDevice[]} partitions + * @property {PartitionSlot[]} unusedSlots * @property {number} unpartitionedSize - Total size not assigned to any partition * + * @typedef {object} PartitionSlot + * @property {number} start + * @property {number} size + * + * @typedef {object} Component + * @property {string} type + * @property {string[]} deviceNames + * * @typedef {object} Filesystem * @property {string} type - * @property {boolean} isEFI + * @property {string} [mountPath] */ async getDevices() { const buildDevice = (path, dbusDevices) => { + const addDeviceProperties = (device, dbusProperties) => { + device.sid = dbusProperties.SID.v; + device.name = dbusProperties.Name.v; + device.description = dbusProperties.Description.v; + }; + const addDriveProperties = (device, dbusProperties) => { device.isDrive = true; device.type = dbusProperties.Type.v; @@ -173,7 +196,8 @@ class DevicesManager { const addBlockProperties = (device, blockProperties) => { device.active = blockProperties.Active.v; - device.name = blockProperties.Name.v; + device.encrypted = blockProperties.Encrypted.v; + device.start = blockProperties.Start.v; device.size = blockProperties.Size.v; device.recoverableSize = blockProperties.RecoverableSize.v; device.systems = blockProperties.Systems.v; @@ -181,19 +205,40 @@ class DevicesManager { device.udevPaths = blockProperties.UdevPaths.v; }; + const addPartitionProperties = (device, partitionProperties) => { + device.type = "partition"; + device.isEFI = partitionProperties.EFI.v; + }; + + const addLvmVgProperties = (device, lvmVgProperties) => { + device.type = "lvmVg"; + device.size = lvmVgProperties.Size.v; + device.physicalVolumes = lvmVgProperties.PhysicalVolumes.v.map(d => buildDevice(d, dbusDevices)); + device.logicalVolumes = lvmVgProperties.LogicalVolumes.v.map(d => buildDevice(d, dbusDevices)); + }; + + const addLvmLvProperties = (device) => { + device.type = "lvmLv"; + }; + const addPtableProperties = (device, ptableProperties) => { + const buildPartitionSlot = ([start, size]) => ({ start, size }); const partitions = ptableProperties.Partitions.v.map(p => buildDevice(p, dbusDevices)); device.partitionTable = { type: ptableProperties.Type.v, partitions, - unpartitionedSize: device.size - partitions.reduce((s, p) => s + p.size, 0) + unpartitionedSize: device.size - partitions.reduce((s, p) => s + p.size, 0), + unusedSlots: ptableProperties.UnusedSlots.v.map(buildPartitionSlot) }; }; const addFilesystemProperties = (device, filesystemProperties) => { + const buildMountPath = path => path.length > 0 ? path : undefined; + const buildLabel = label => label.length > 0 ? label : undefined; device.filesystem = { type: filesystemProperties.Type.v, - isEFI: filesystemProperties.EFI.v + mountPath: buildMountPath(filesystemProperties.MountPath.v), + label: buildLabel(filesystemProperties.Label.v) }; }; @@ -206,6 +251,8 @@ class DevicesManager { const device = { sid: path.split("/").pop(), + name: "", + description: "", isDrive: false, type: "" }; @@ -213,6 +260,9 @@ class DevicesManager { const dbusDevice = dbusDevices[path]; if (!dbusDevice) return device; + const deviceProperties = dbusDevice["org.opensuse.Agama.Storage1.Device"]; + if (deviceProperties !== undefined) addDeviceProperties(device, deviceProperties); + const driveProperties = dbusDevice["org.opensuse.Agama.Storage1.Drive"]; if (driveProperties !== undefined) addDriveProperties(device, driveProperties); @@ -228,6 +278,15 @@ class DevicesManager { const blockProperties = dbusDevice["org.opensuse.Agama.Storage1.Block"]; if (blockProperties !== undefined) addBlockProperties(device, blockProperties); + const partitionProperties = dbusDevice["org.opensuse.Agama.Storage1.Partition"]; + if (partitionProperties !== undefined) addPartitionProperties(device, partitionProperties); + + const lvmVgProperties = dbusDevice["org.opensuse.Agama.Storage1.LVM.VolumeGroup"]; + if (lvmVgProperties !== undefined) addLvmVgProperties(device, lvmVgProperties); + + const lvmLvProperties = dbusDevice["org.opensuse.Agama.Storage1.LVM.LogicalVolume"]; + if (lvmLvProperties !== undefined) addLvmLvProperties(device, lvmLvProperties); + const ptableProperties = dbusDevice["org.opensuse.Agama.Storage1.PartitionTable"]; if (ptableProperties !== undefined) addPtableProperties(device, ptableProperties); @@ -313,7 +372,7 @@ class ProposalManager { async getAvailableDevices() { const findDevice = (devices, path) => { const sid = path.split("/").pop(); - const device = devices.find(d => d.sid === sid); + const device = devices.find(d => d.sid === Number(sid)); if (device === undefined) console.log("D-Bus object not found: ", path); @@ -388,6 +447,7 @@ class ProposalManager { const buildAction = dbusAction => { return { + device: dbusAction.Device.v, text: dbusAction.Text.v, subvol: dbusAction.Subvol.v, delete: dbusAction.Delete.v @@ -1467,6 +1527,7 @@ class StorageBaseClient { constructor(address = undefined) { this.client = new DBusClient(StorageBaseClient.SERVICE, address); this.system = new DevicesManager(this.client, STORAGE_SYSTEM_NAMESPACE); + this.staging = new DevicesManager(this.client, STORAGE_STAGING_NAMESPACE); this.proposal = new ProposalManager(this.client, this.system); this.iscsi = new ISCSIManager(StorageBaseClient.SERVICE, address); this.dasd = new DASDManager(StorageBaseClient.SERVICE, address);