Skip to content

Commit

Permalink
lxc: Support attach/detach snapshot disk devices
Browse files Browse the repository at this point in the history
Signed-off-by: Wesley Hershberger <[email protected]>
  • Loading branch information
MggMuggins committed Feb 12, 2025
1 parent 0aacd6d commit cc24a1b
Showing 1 changed file with 29 additions and 10 deletions.
39 changes: 29 additions & 10 deletions lxc/storage_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ func parseVolume(defaultType string, name string) (volName string, volType strin
return volName, volType
}

func parseVolumeSnapshot(defaultType string, name string) (volName string, volType string, snapshot string) {
volName, volType = parseVolume(defaultType, name)

parts := strings.SplitN(volName, "/", 2)
if len(parts) == 2 {
volName, snapshot = parts[0], parts[1]
}

return volName, volType, snapshot
}

func (c *cmdStorageVolume) command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("volume")
Expand Down Expand Up @@ -164,7 +175,7 @@ type cmdStorageVolumeAttach struct {

func (c *cmdStorageVolumeAttach) command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("attach", i18n.G("[<remote>:]<pool> [<type>/]<volume> <instance> [<device name>] [<path>]"))
cmd.Use = usage("attach", i18n.G("[<remote>:]<pool> [<type>/]<volume>[/<snapshot>] <instance> [<device name>] [<path>]"))
cmd.Short = i18n.G("Attach new storage volumes to instances")
cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
`Attach new storage volumes to instances
Expand Down Expand Up @@ -211,7 +222,7 @@ func (c *cmdStorageVolumeAttach) run(cmd *cobra.Command, args []string) error {
return errors.New(i18n.G("Missing pool name"))
}

volName, volType := parseVolume("custom", args[1])
volName, volType, snapshot := parseVolumeSnapshot("custom", args[1])
if volType != "custom" && volType != "virtual-machine" {
return errors.New(i18n.G(`Only "custom" and "virtual-machine" volumes can be attached to instances`))
}
Expand Down Expand Up @@ -268,6 +279,10 @@ func (c *cmdStorageVolumeAttach) run(cmd *cobra.Command, args []string) error {
device["source-type"] = volType
}

if snapshot != "" {
device["snapshot"] = snapshot
}

// Add the device to the instance
err = instanceDeviceAdd(resource.server, args[2], devName, device)
if err != nil {
Expand All @@ -286,7 +301,7 @@ type cmdStorageVolumeAttachProfile struct {

func (c *cmdStorageVolumeAttachProfile) command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("attach-profile", i18n.G("[<remote:>]<pool> [<type>/]<volume> <profile> [<device name>] [<path>]"))
cmd.Use = usage("attach-profile", i18n.G("[<remote:>]<pool> [<type>/]<volume>[/<snapshot>] <profile> [<device name>] [<path>]"))
cmd.Short = i18n.G("Attach new storage volumes to profiles")
cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
`Attach new storage volumes to profiles
Expand Down Expand Up @@ -348,7 +363,7 @@ func (c *cmdStorageVolumeAttachProfile) run(cmd *cobra.Command, args []string) e
devPath = args[4]
}

volName, volType := parseVolume("custom", args[1])
volName, volType, snapshot := parseVolumeSnapshot("custom", args[1])
if volType != "custom" && volType != "virtual-machine" {
return errors.New(i18n.G(`Only "custom" and "virtual-machine" volumes can be attached to profiles`))
}
Expand Down Expand Up @@ -376,6 +391,10 @@ func (c *cmdStorageVolumeAttachProfile) run(cmd *cobra.Command, args []string) e
device["source-type"] = volType
}

if snapshot != "" {
device["snapshot"] = snapshot
}

// Add the device to the instance
err = profileDeviceAdd(resource.server, args[2], devName, device)
if err != nil {
Expand Down Expand Up @@ -817,7 +836,7 @@ type cmdStorageVolumeDetach struct {

func (c *cmdStorageVolumeDetach) command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("detach", i18n.G("[<remote>:]<pool> [<type>/]<volume> <instance> [<device name>]"))
cmd.Use = usage("detach", i18n.G("[<remote>:]<pool> [<type>/]<volume>[/<snapshot>] <instance> [<device name>]"))
cmd.Short = i18n.G("Detach storage volumes from instances")
cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
`Detach storage volumes from instances`))
Expand Down Expand Up @@ -874,7 +893,7 @@ func (c *cmdStorageVolumeDetach) run(cmd *cobra.Command, args []string) error {
return err
}

volName, volType := parseVolume("custom", args[1])
volName, volType, snapshot := parseVolumeSnapshot("custom", args[1])

// Find the device
if devName == "" {
Expand All @@ -884,7 +903,7 @@ func (c *cmdStorageVolumeDetach) run(cmd *cobra.Command, args []string) error {
sourceType = d["source-type"]
}

if d["type"] == "disk" && d["pool"] == resource.name && volType == sourceType && volName == d["source"] {
if d["type"] == "disk" && d["pool"] == resource.name && volType == sourceType && volName == d["source"] && snapshot == d["snapshot"] {
if devName != "" {
return errors.New(i18n.G("More than one device matches, specify the device name"))
}
Expand Down Expand Up @@ -922,7 +941,7 @@ type cmdStorageVolumeDetachProfile struct {

func (c *cmdStorageVolumeDetachProfile) command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("detach-profile", i18n.G("[<remote:>]<pool> [<type>/]<volume> <profile> [<device name>]"))
cmd.Use = usage("detach-profile", i18n.G("[<remote:>]<pool> [<type>/]<volume>[/<snapshot>] <profile> [<device name>]"))
cmd.Short = i18n.G("Detach storage volumes from profiles")
cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
`Detach storage volumes from profiles`))
Expand Down Expand Up @@ -978,7 +997,7 @@ func (c *cmdStorageVolumeDetachProfile) run(cmd *cobra.Command, args []string) e
return err
}

volName, volType := parseVolume("custom", args[1])
volName, volType, snapshot := parseVolumeSnapshot("custom", args[1])

// Find the device
if devName == "" {
Expand All @@ -988,7 +1007,7 @@ func (c *cmdStorageVolumeDetachProfile) run(cmd *cobra.Command, args []string) e
sourceType = d["source-type"]
}

if d["type"] == "disk" && d["pool"] == resource.name && volType == sourceType && volName == d["source"] {
if d["type"] == "disk" && d["pool"] == resource.name && volType == sourceType && volName == d["source"] && snapshot == d["snapshot"] {
if devName != "" {
return errors.New(i18n.G("More than one device matches, specify the device name"))
}
Expand Down

0 comments on commit cc24a1b

Please sign in to comment.