Skip to content

Commit

Permalink
fix(instance): support snapshot based instance
Browse files Browse the repository at this point in the history
This PR allow users to create an instance from a snapshot directly
without creating an image.
It's already supported by the APIs.

Signed-off-by: Mathieu Tortuyaux <[email protected]>
  • Loading branch information
tormath1 committed Jun 12, 2024
1 parent ff6cc36 commit 7ea13bb
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ EXAMPLES:
Create an instance with volumes from snapshots
scw instance server create image=ubuntu_focal root-volume=local:<snapshot_id> additional-volumes.0=block:<snapshot_id>

Create and start an instance from a snapshot
scw instance server create image=none root-volume=local:<snapshot_id>

Use an existing IP
ip=$(scw instance ip create | grep id | awk '{ print $2 }')
scw instance server create image=ubuntu_focal ip=$ip
Expand Down
44 changes: 30 additions & 14 deletions internal/namespaces/instance/v1/custom_server_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ func serverCreateCommand() *core.Command {
Short: "Create an instance with volumes from snapshots",
ArgsJSON: `{"image":"ubuntu_focal","root_volume":"local:<snapshot_id>","additional_volumes":["block:<snapshot_id>"]}`,
},
{
Short: "Create and start an instance from a snapshot",
ArgsJSON: `{"image":"none","root_volume":"local:<snapshot_id>"}`,
},
{
Short: "Use an existing IP",
Raw: `ip=$(scw instance ip create | grep id | awk '{ print $2 }')
Expand Down Expand Up @@ -231,6 +235,8 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac
// - An image label
//
switch {
case args.Image == "none":
break
case !validation.IsUUID(args.Image):
// For retro-compatibility, we replace dashes with underscores
imageLabel := strings.Replace(args.Image, "-", "_", -1)
Expand All @@ -250,22 +256,32 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac
serverReq.Image = args.Image
}

getImageResponse, err := apiInstance.GetImage(&instance.GetImageRequest{
Zone: args.Zone,
ImageID: serverReq.Image,
})
if err != nil {
logger.Warningf("cannot get image %s: %s", serverReq.Image, err)
}
var (
getImageResponse *instance.GetImageResponse
serverType *instance.ServerType
)
if args.Image != "none" {
var err error
getImageResponse, err = apiInstance.GetImage(&instance.GetImageRequest{
Zone: args.Zone,
ImageID: serverReq.Image,
})
if err != nil {
logger.Warningf("cannot get image %s: %s", serverReq.Image, err)
}

serverType := getServerType(apiInstance, serverReq.Zone, serverReq.CommercialType)
serverType = getServerType(apiInstance, serverReq.Zone, serverReq.CommercialType)

if serverType != nil && getImageResponse != nil {
if err := validateImageServerTypeCompatibility(getImageResponse.Image, serverType, serverReq.CommercialType); err != nil {
return nil, err
if serverType != nil && getImageResponse != nil {
if err := validateImageServerTypeCompatibility(getImageResponse.Image, serverType, serverReq.CommercialType); err != nil {
return nil, err
}
} else {
logger.Warningf("skipping image server-type compatibility validation")
}
} else {
logger.Warningf("skipping image server-type compatibility validation")
getImageResponse = nil
serverType = nil
}

//
Expand Down Expand Up @@ -315,7 +331,7 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac
}

// Validate root volume type and size.
if getImageResponse != nil {
if args.Image != "none" && getImageResponse != nil {
if err := validateRootVolume(getImageResponse.Image.RootVolume.Size, volumes["0"]); err != nil {
return nil, err
}
Expand All @@ -324,7 +340,7 @@ func instanceServerCreateRun(ctx context.Context, argsI interface{}) (i interfac
}

// Validate total local volume sizes.
if serverType != nil && getImageResponse != nil {
if args.Image != "none" && serverType != nil && getImageResponse != nil {
if err := validateLocalVolumeSizes(volumes, serverType, serverReq.CommercialType, getImageResponse.Image.RootVolume.Size); err != nil {
return nil, err
}
Expand Down

0 comments on commit 7ea13bb

Please sign in to comment.