Can attach multiple ISOs to the same domain at the same time
This commit is contained in:
parent
f05ae9fd52
commit
64eb90c0a4
@ -87,8 +87,8 @@ pub struct VMInfo {
|
|||||||
pub number_vcpu: usize,
|
pub number_vcpu: usize,
|
||||||
/// Enable VNC access through admin console
|
/// Enable VNC access through admin console
|
||||||
pub vnc_access: bool,
|
pub vnc_access: bool,
|
||||||
/// Attach an ISO file
|
/// Attach ISO file(s)
|
||||||
pub iso_file: Option<String>,
|
pub iso_files: Vec<String>,
|
||||||
/// Storage - https://access.redhat.com/documentation/fr-fr/red_hat_enterprise_linux/6/html/virtualization_administration_guide/sect-virtualization-virtualized_block_devices-adding_storage_devices_to_guests#sect-Virtualization-Adding_storage_devices_to_guests-Adding_file_based_storage_to_a_guest
|
/// Storage - https://access.redhat.com/documentation/fr-fr/red_hat_enterprise_linux/6/html/virtualization_administration_guide/sect-virtualization-virtualized_block_devices-adding_storage_devices_to_guests#sect-Virtualization-Adding_storage_devices_to_guests-Adding_file_based_storage_to_a_guest
|
||||||
pub disks: Vec<Disk>,
|
pub disks: Vec<Disk>,
|
||||||
/// Network cards
|
/// Network cards
|
||||||
@ -133,7 +133,7 @@ impl VMInfo {
|
|||||||
|
|
||||||
let mut disks = vec![];
|
let mut disks = vec![];
|
||||||
|
|
||||||
if let Some(iso_file) = &self.iso_file {
|
for iso_file in &self.iso_files {
|
||||||
if !files_utils::check_file_name(iso_file) {
|
if !files_utils::check_file_name(iso_file) {
|
||||||
return Err(StructureExtraction("ISO filename is invalid!").into());
|
return Err(StructureExtraction("ISO filename is invalid!").into());
|
||||||
}
|
}
|
||||||
@ -156,12 +156,15 @@ impl VMInfo {
|
|||||||
file: path.to_string_lossy().to_string(),
|
file: path.to_string_lossy().to_string(),
|
||||||
},
|
},
|
||||||
target: DiskTargetXML {
|
target: DiskTargetXML {
|
||||||
dev: "hdc".to_string(),
|
dev: format!(
|
||||||
|
"hd{}",
|
||||||
|
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"][disks.len()]
|
||||||
|
),
|
||||||
bus: "usb".to_string(),
|
bus: "usb".to_string(),
|
||||||
},
|
},
|
||||||
readonly: Some(DiskReadOnlyXML {}),
|
readonly: Some(DiskReadOnlyXML {}),
|
||||||
boot: DiskBootXML {
|
boot: DiskBootXML {
|
||||||
order: "1".to_string(),
|
order: (disks.len() + 1).to_string(),
|
||||||
},
|
},
|
||||||
address: None,
|
address: None,
|
||||||
})
|
})
|
||||||
@ -182,7 +185,7 @@ impl VMInfo {
|
|||||||
// Check disks name for duplicates
|
// Check disks name for duplicates
|
||||||
for disk in &self.disks {
|
for disk in &self.disks {
|
||||||
if self.disks.iter().filter(|d| d.name == disk.name).count() > 1 {
|
if self.disks.iter().filter(|d| d.name == disk.name).count() > 1 {
|
||||||
return Err(StructureExtraction("Two differents disks have the same name!").into());
|
return Err(StructureExtraction("Two different disks have the same name!").into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,12 +331,13 @@ impl VMInfo {
|
|||||||
number_vcpu: domain.vcpu.body,
|
number_vcpu: domain.vcpu.body,
|
||||||
memory: convert_to_mb(&domain.memory.unit, domain.memory.memory)?,
|
memory: convert_to_mb(&domain.memory.unit, domain.memory.memory)?,
|
||||||
vnc_access: domain.devices.graphics.is_some(),
|
vnc_access: domain.devices.graphics.is_some(),
|
||||||
iso_file: domain
|
iso_files: domain
|
||||||
.devices
|
.devices
|
||||||
.disks
|
.disks
|
||||||
.iter()
|
.iter()
|
||||||
.find(|d| d.device == "cdrom")
|
.filter(|d| d.device == "cdrom")
|
||||||
.map(|d| d.source.file.rsplit_once('/').unwrap().1.to_string()),
|
.map(|d| d.source.file.rsplit_once('/').unwrap().1.to_string())
|
||||||
|
.collect(),
|
||||||
|
|
||||||
disks: domain
|
disks: domain
|
||||||
.devices
|
.devices
|
||||||
|
@ -52,7 +52,7 @@ interface VMInfoInterface {
|
|||||||
memory: number;
|
memory: number;
|
||||||
number_vcpu: number;
|
number_vcpu: number;
|
||||||
vnc_access: boolean;
|
vnc_access: boolean;
|
||||||
iso_file?: string;
|
iso_files: string[];
|
||||||
disks: VMDisk[];
|
disks: VMDisk[];
|
||||||
networks: VMNetInterface[];
|
networks: VMNetInterface[];
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ export class VMInfo implements VMInfoInterface {
|
|||||||
number_vcpu: number;
|
number_vcpu: number;
|
||||||
memory: number;
|
memory: number;
|
||||||
vnc_access: boolean;
|
vnc_access: boolean;
|
||||||
iso_file?: string;
|
iso_files: string[];
|
||||||
disks: VMDisk[];
|
disks: VMDisk[];
|
||||||
networks: VMNetInterface[];
|
networks: VMNetInterface[];
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ export class VMInfo implements VMInfoInterface {
|
|||||||
this.number_vcpu = int.number_vcpu;
|
this.number_vcpu = int.number_vcpu;
|
||||||
this.memory = int.memory;
|
this.memory = int.memory;
|
||||||
this.vnc_access = int.vnc_access;
|
this.vnc_access = int.vnc_access;
|
||||||
this.iso_file = int.iso_file;
|
this.iso_files = int.iso_files;
|
||||||
this.disks = int.disks;
|
this.disks = int.disks;
|
||||||
this.networks = int.networks;
|
this.networks = int.networks;
|
||||||
}
|
}
|
||||||
@ -96,6 +96,7 @@ export class VMInfo implements VMInfoInterface {
|
|||||||
memory: 1024,
|
memory: 1024,
|
||||||
number_vcpu: 1,
|
number_vcpu: 1,
|
||||||
vnc_access: true,
|
vnc_access: true,
|
||||||
|
iso_files: [],
|
||||||
disks: [],
|
disks: [],
|
||||||
networks: [],
|
networks: [],
|
||||||
});
|
});
|
||||||
|
@ -16,59 +16,68 @@ import Icon from "@mdi/react";
|
|||||||
export function VMSelectIsoInput(p: {
|
export function VMSelectIsoInput(p: {
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
isoList: IsoFile[];
|
isoList: IsoFile[];
|
||||||
value?: string;
|
attachedISOs: string[];
|
||||||
onChange: (newVal?: string) => void;
|
onChange: (newVal: string[]) => void;
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
if (!p.value && !p.editable) return <></>;
|
if (!p.attachedISOs && !p.editable) return <></>;
|
||||||
|
|
||||||
if (p.value) {
|
|
||||||
const iso = p.isoList.find((d) => d.filename === p.value);
|
|
||||||
return (
|
|
||||||
<ListItem
|
|
||||||
secondaryAction={
|
|
||||||
p.editable && (
|
|
||||||
<IconButton
|
|
||||||
edge="end"
|
|
||||||
aria-label="detach iso file"
|
|
||||||
onClick={() => {
|
|
||||||
p.onChange(undefined);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Tooltip title="Detach ISO file">
|
|
||||||
<DeleteIcon />
|
|
||||||
</Tooltip>
|
|
||||||
</IconButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<Avatar>
|
|
||||||
<Icon path={mdiDisc} />
|
|
||||||
</Avatar>
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText
|
|
||||||
primary={iso?.filename}
|
|
||||||
secondary={filesize(iso?.size ?? 0)}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectInput
|
<>
|
||||||
label="ISO file"
|
<SelectInput
|
||||||
editable={p.editable}
|
label="Attach an ISO file"
|
||||||
value={p.value}
|
editable={p.editable}
|
||||||
onValueChange={p.onChange}
|
value={undefined}
|
||||||
options={[
|
onValueChange={(v) => {
|
||||||
{ label: "None", value: undefined },
|
if (v) {
|
||||||
...p.isoList.map((i) => {
|
p.attachedISOs.push(v);
|
||||||
return {
|
p.onChange(p.attachedISOs);
|
||||||
label: `${i.filename} ${filesize(i.size)}`,
|
}
|
||||||
value: i.filename,
|
}}
|
||||||
};
|
options={[
|
||||||
}),
|
{ label: "None", value: undefined },
|
||||||
]}
|
...p.isoList.map((i) => {
|
||||||
/>
|
return {
|
||||||
|
label: `${i.filename} ${filesize(i.size)}`,
|
||||||
|
value: i.filename,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{p.attachedISOs.map((isoName, num) => {
|
||||||
|
const iso = p.isoList.find((d) => d.filename === isoName);
|
||||||
|
return (
|
||||||
|
<ListItem
|
||||||
|
key={num}
|
||||||
|
secondaryAction={
|
||||||
|
p.editable && (
|
||||||
|
<IconButton
|
||||||
|
edge="end"
|
||||||
|
aria-label="Detach iso file"
|
||||||
|
onClick={() => {
|
||||||
|
p.attachedISOs.splice(num, 1);
|
||||||
|
p.onChange(p.attachedISOs);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tooltip title="Detach ISO file">
|
||||||
|
<DeleteIcon />
|
||||||
|
</Tooltip>
|
||||||
|
</IconButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
<Icon path={mdiDisc} />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={iso?.filename}
|
||||||
|
secondary={filesize(iso?.size ?? 0)}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -203,9 +203,9 @@ function VMDetailsInner(
|
|||||||
<VMSelectIsoInput
|
<VMSelectIsoInput
|
||||||
editable={p.editable}
|
editable={p.editable}
|
||||||
isoList={p.isoList}
|
isoList={p.isoList}
|
||||||
value={p.vm.iso_file}
|
attachedISOs={p.vm.iso_files}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
p.vm.iso_file = v;
|
p.vm.iso_files = v;
|
||||||
p.onChange?.();
|
p.onChange?.();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
Loading…
Reference in New Issue
Block a user