diff --git a/doc/api-extensions.md b/doc/api-extensions.md index b6a4739bfb99..ebee354c48c3 100644 --- a/doc/api-extensions.md +++ b/doc/api-extensions.md @@ -2434,3 +2434,10 @@ This feature was added to prevent data loss which can happen when custom block v ## `instance_import_conversion` Adds the ability to convert images from different formats (e.g. VMDK or QCow2) into RAW image format and import them as LXD instances. + +## `instance_create_start` + +Adds a `start` field to the `POST /1.0/instances` API which when set +to `true` will have the instance automatically start upon creation. + +In this scenario, the creation and startup is part of a single background operation. diff --git a/doc/howto/instances_create.md b/doc/howto/instances_create.md index 95610a85e0c9..4643b9fb1b8d 100644 --- a/doc/howto/instances_create.md +++ b/doc/howto/instances_create.md @@ -74,6 +74,19 @@ To start an instance, send a PUT request to change the instance state: See {ref}`instances-manage-start` for more information. +If you would like to start the instance upon creation, set the `start` property to true. The following example will create the container, then start it: + + lxc query --request POST /1.0/instances --data '{ + "name": "", + "source": { + "alias": "", + "protocol": "simplestreams", + "server": "", + "type": "image" + }, + "start": true + }' + ```` ````{group-tab} UI diff --git a/doc/rest-api.yaml b/doc/rest-api.yaml index a34c70073eb3..9565ceb4ba8e 100644 --- a/doc/rest-api.yaml +++ b/doc/rest-api.yaml @@ -2752,6 +2752,11 @@ definitions: x-go-name: Restore source: $ref: '#/definitions/InstanceSource' + start: + description: Whether to start the instance after creation + example: true + type: boolean + x-go-name: Start stateful: description: Whether the instance currently has saved state on disk example: false diff --git a/lxc/init.go b/lxc/init.go index d9f416d8da09..18f34277603c 100644 --- a/lxc/init.go +++ b/lxc/init.go @@ -81,11 +81,11 @@ func (c *cmdInit) run(cmd *cobra.Command, args []string) error { return nil } - _, _, err = c.create(c.global.conf, args) + _, _, err = c.create(c.global.conf, args, false) return err } -func (c *cmdInit) create(conf *config.Config, args []string) (lxd.InstanceServer, string, error) { +func (c *cmdInit) create(conf *config.Config, args []string, launch bool) (lxd.InstanceServer, string, error) { var name string var image string var remote string @@ -164,10 +164,18 @@ func (c *cmdInit) create(conf *config.Config, args []string) (lxd.InstanceServer } if !c.global.flagQuiet { - if name == "" { - fmt.Printf(i18n.G("Creating the instance") + "\n") + if d.HasExtension("instance_create_start") && launch { + if name == "" { + fmt.Printf(i18n.G("Launching the instance") + "\n") + } else { + fmt.Printf(i18n.G("Launching %s")+"\n", name) + } } else { - fmt.Printf(i18n.G("Creating %s")+"\n", name) + if name == "" { + fmt.Printf(i18n.G("Creating the instance") + "\n") + } else { + fmt.Printf(i18n.G("Creating %s")+"\n", name) + } } } @@ -252,6 +260,7 @@ func (c *cmdInit) create(conf *config.Config, args []string) (lxd.InstanceServer Name: name, InstanceType: c.flagType, Type: instanceDBType, + Start: launch, } req.Config = configMap diff --git a/lxc/launch.go b/lxc/launch.go index fa7e57d84859..50cc5ec4e337 100644 --- a/lxc/launch.go +++ b/lxc/launch.go @@ -58,11 +58,16 @@ func (c *cmdLaunch) run(cmd *cobra.Command, args []string) error { } // Call the matching code from init - d, name, err := c.init.create(conf, args) + d, name, err := c.init.create(conf, args, true) if err != nil { return err } + // Check if the instance was started by the server. + if d.HasExtension("instance_create_start") { + return nil + } + // Get the remote var remote string if len(args) == 2 { diff --git a/lxd/instances_post.go b/lxd/instances_post.go index e2509b4dfa2e..e4cce80a081f 100644 --- a/lxd/instances_post.go +++ b/lxd/instances_post.go @@ -124,7 +124,13 @@ func createFromImage(s *state.State, r *http.Request, p api.Project, profiles [] return err } - return instanceCreateFromImage(s, img, args, op) + // Actually create the instance. + err = instanceCreateFromImage(s, img, args, op) + if err != nil { + return err + } + + return instanceCreateFinish(s, req, args) } resources := map[string][]api.URL{} @@ -175,8 +181,13 @@ func createFromNone(s *state.State, r *http.Request, projectName string, profile } run := func(op *operations.Operation) error { + // Actually create the instance. _, err := instanceCreateAsEmpty(s, args) - return err + if err != nil { + return err + } + + return instanceCreateFinish(s, req, args) } resources := map[string][]api.URL{} @@ -602,6 +613,7 @@ func createFromCopy(s *state.State, r *http.Request, projectName string, profile } run := func(op *operations.Operation) error { + // Actually create the instance. _, err := instanceCreateAsCopy(s, instanceCreateAsCopyOpts{ sourceInstance: source, targetInstance: args, @@ -614,7 +626,7 @@ func createFromCopy(s *state.State, r *http.Request, projectName string, profile return err } - return nil + return instanceCreateFinish(s, req, args) } resources := map[string][]api.URL{} @@ -701,8 +713,9 @@ func createFromBackup(s *state.State, r *http.Request, projectName string, data } // Check project permissions. + var req api.InstancesPost err = s.DB.Cluster.Transaction(s.ShutdownCtx, func(ctx context.Context, tx *db.ClusterTx) error { - req := api.InstancesPost{ + req = api.InstancesPost{ InstancePut: bInfo.Config.Container.Writable(), Name: bInfo.Name, Source: api.InstanceSource{}, // Only relevant for "copy" or "migration", but may not be nil. @@ -838,7 +851,8 @@ func createFromBackup(s *state.State, r *http.Request, projectName string, data } runRevert.Success() - return nil + + return instanceCreateFinish(s, &req, db.InstanceArgs{Name: bInfo.Name, Project: bInfo.Project}) } resources := map[string][]api.URL{} @@ -1488,3 +1502,19 @@ func clusterCopyContainerInternal(s *state.State, r *http.Request, source instan // Run the migration return createFromMigration(s, nil, projectName, profiles, req) } + +// instanceCreateFinish finalizes the creation process of an instance by starting it based on +// the Start field of the request. +func instanceCreateFinish(s *state.State, req *api.InstancesPost, args db.InstanceArgs) error { + if req == nil || !req.Start { + return nil + } + + // Start the instance. + inst, err := instance.LoadByProjectAndName(s, args.Project, args.Name) + if err != nil { + return fmt.Errorf("Failed to load the instance: %w", err) + } + + return inst.Start(false) +} diff --git a/po/ar.po b/po/ar.po index 17b5ea24c7e0..f66a817d03d0 100644 --- a/po/ar.po +++ b/po/ar.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxd@lists.canonical.com\n" -"POT-Creation-Date: 2024-07-02 10:12-0700\n" +"POT-Creation-Date: 2024-07-24 14:26-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -766,7 +766,7 @@ msgstr "" msgid "As neither could be found, the raw SPICE socket can be found at:" msgstr "" -#: lxc/init.go:324 lxc/rebuild.go:130 +#: lxc/init.go:333 lxc/rebuild.go:130 msgid "Asked for a VM but image is of type container" msgstr "" @@ -871,7 +871,7 @@ msgstr "" msgid "Bad key/value pair: %s" msgstr "" -#: lxc/copy.go:139 lxc/init.go:224 lxc/move.go:380 lxc/project.go:129 +#: lxc/copy.go:139 lxc/init.go:232 lxc/move.go:380 lxc/project.go:129 #, c-format msgid "Bad key=value pair: %q" msgstr "" @@ -1492,12 +1492,12 @@ msgstr "" msgid "Created: %s" msgstr "" -#: lxc/init.go:170 +#: lxc/init.go:177 #, c-format msgid "Creating %s" msgstr "" -#: lxc/init.go:168 +#: lxc/init.go:175 msgid "Creating the instance" msgstr "" @@ -1819,7 +1819,7 @@ msgstr "" msgid "Device: %s" msgstr "" -#: lxc/init.go:384 +#: lxc/init.go:393 msgid "Didn't get any affected image, instance or snapshot from server" msgstr "" @@ -2864,7 +2864,7 @@ msgstr "" msgid "Instance name is mandatory" msgstr "" -#: lxc/init.go:395 +#: lxc/init.go:404 #, c-format msgid "Instance name is: %s" msgstr "" @@ -3051,6 +3051,15 @@ msgstr "" msgid "Last used: never" msgstr "" +#: lxc/init.go:171 +#, c-format +msgid "Launching %s" +msgstr "" + +#: lxc/init.go:169 +msgid "Launching the instance" +msgstr "" + #: lxc/info.go:220 #, c-format msgid "Link detected: %v" @@ -4930,7 +4939,7 @@ msgstr "" msgid "Retrieve the instance's console log" msgstr "" -#: lxc/init.go:338 +#: lxc/init.go:347 #, c-format msgid "Retrieving image: %s" msgstr "" @@ -5565,7 +5574,7 @@ msgstr "" msgid "Start instances" msgstr "" -#: lxc/launch.go:82 +#: lxc/launch.go:87 #, c-format msgid "Starting %s" msgstr "" @@ -5770,7 +5779,7 @@ msgid "" "restarted" msgstr "" -#: lxc/init.go:416 +#: lxc/init.go:425 msgid "The instance you are starting doesn't have any network attached to it." msgstr "" @@ -5931,11 +5940,11 @@ msgstr "" msgid "Timestamps:" msgstr "" -#: lxc/init.go:418 +#: lxc/init.go:427 msgid "To attach a network to an instance, use: lxc network attach" msgstr "" -#: lxc/init.go:417 +#: lxc/init.go:426 msgid "To create a new network, use: lxc network create" msgstr "" @@ -6008,7 +6017,7 @@ msgstr "" msgid "Trust token for %s: " msgstr "" -#: lxc/action.go:287 lxc/launch.go:114 +#: lxc/action.go:287 lxc/launch.go:119 #, c-format msgid "Try `lxc info --show-log %s` for more info" msgstr "" diff --git a/po/ber.po b/po/ber.po index 6d5b62e1e4d4..86092f64c6fa 100644 --- a/po/ber.po +++ b/po/ber.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxd@lists.canonical.com\n" -"POT-Creation-Date: 2024-07-02 10:12-0700\n" +"POT-Creation-Date: 2024-07-24 14:26-0700\n" "PO-Revision-Date: 2022-03-10 15:10+0000\n" "Last-Translator: Anonymous \n" "Language-Team: Berber \n" "Language-Team: Bulgarian \n" "Language-Team: Catalan \n" "Language-Team: Czech \n" "Language-Team: German \n" "Language-Team: Greek \n" "Language-Team: Esperanto \n" "Language-Team: Spanish \n" "Language-Team: Persian \n" "Language-Team: Finnish \n" "Language-Team: French \n" "Language-Team: Hebrew \n" "Language-Team: Hindi \n" "Language-Team: Indonesian \n" "Language-Team: Italian \n" "Language-Team: Japanese \n" "Language-Team: Korean \n" "Language-Team: LANGUAGE \n" @@ -728,7 +728,7 @@ msgstr "" msgid "As neither could be found, the raw SPICE socket can be found at:" msgstr "" -#: lxc/init.go:324 lxc/rebuild.go:130 +#: lxc/init.go:333 lxc/rebuild.go:130 msgid "Asked for a VM but image is of type container" msgstr "" @@ -830,7 +830,7 @@ msgstr "" msgid "Bad key/value pair: %s" msgstr "" -#: lxc/copy.go:139 lxc/init.go:224 lxc/move.go:380 lxc/project.go:129 +#: lxc/copy.go:139 lxc/init.go:232 lxc/move.go:380 lxc/project.go:129 #, c-format msgid "Bad key=value pair: %q" msgstr "" @@ -1405,12 +1405,12 @@ msgstr "" msgid "Created: %s" msgstr "" -#: lxc/init.go:170 +#: lxc/init.go:177 #, c-format msgid "Creating %s" msgstr "" -#: lxc/init.go:168 +#: lxc/init.go:175 msgid "Creating the instance" msgstr "" @@ -1613,7 +1613,7 @@ msgstr "" msgid "Device: %s" msgstr "" -#: lxc/init.go:384 +#: lxc/init.go:393 msgid "Didn't get any affected image, instance or snapshot from server" msgstr "" @@ -2617,7 +2617,7 @@ msgstr "" msgid "Instance name is mandatory" msgstr "" -#: lxc/init.go:395 +#: lxc/init.go:404 #, c-format msgid "Instance name is: %s" msgstr "" @@ -2798,6 +2798,15 @@ msgstr "" msgid "Last used: never" msgstr "" +#: lxc/init.go:171 +#, c-format +msgid "Launching %s" +msgstr "" + +#: lxc/init.go:169 +msgid "Launching the instance" +msgstr "" + #: lxc/info.go:220 #, c-format msgid "Link detected: %v" @@ -4554,7 +4563,7 @@ msgstr "" msgid "Retrieve the instance's console log" msgstr "" -#: lxc/init.go:338 +#: lxc/init.go:347 #, c-format msgid "Retrieving image: %s" msgstr "" @@ -5154,7 +5163,7 @@ msgstr "" msgid "Start instances" msgstr "" -#: lxc/launch.go:82 +#: lxc/launch.go:87 #, c-format msgid "Starting %s" msgstr "" @@ -5354,7 +5363,7 @@ msgstr "" msgid "The instance is currently running. Use --force to have it stopped and restarted" msgstr "" -#: lxc/init.go:416 +#: lxc/init.go:425 msgid "The instance you are starting doesn't have any network attached to it." msgstr "" @@ -5509,11 +5518,11 @@ msgstr "" msgid "Timestamps:" msgstr "" -#: lxc/init.go:418 +#: lxc/init.go:427 msgid "To attach a network to an instance, use: lxc network attach" msgstr "" -#: lxc/init.go:417 +#: lxc/init.go:426 msgid "To create a new network, use: lxc network create" msgstr "" @@ -5584,7 +5593,7 @@ msgstr "" msgid "Trust token for %s: " msgstr "" -#: lxc/action.go:287 lxc/launch.go:114 +#: lxc/action.go:287 lxc/launch.go:119 #, c-format msgid "Try `lxc info --show-log %s` for more info" msgstr "" diff --git a/po/mr.po b/po/mr.po index 955f972e13e2..8d2f4fd94103 100644 --- a/po/mr.po +++ b/po/mr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxd@lists.canonical.com\n" -"POT-Creation-Date: 2024-07-02 10:12-0700\n" +"POT-Creation-Date: 2024-07-24 14:26-0700\n" "PO-Revision-Date: 2022-03-10 15:10+0000\n" "Last-Translator: Anonymous \n" "Language-Team: Marathi \n" "Language-Team: Norwegian Bokmål \n" "Language-Team: Dutch \n" "Language-Team: Punjabi \n" "Language-Team: Polish \n" "Language-Team: Portuguese (Brazil) ,=: %s" msgid "Bad key/value pair: %s" msgstr "par de chave/valor inválido %s" -#: lxc/copy.go:139 lxc/init.go:224 lxc/move.go:380 lxc/project.go:129 +#: lxc/copy.go:139 lxc/init.go:232 lxc/move.go:380 lxc/project.go:129 #, fuzzy, c-format msgid "Bad key=value pair: %q" msgstr "par de chave=valor inválido %s" @@ -1801,12 +1801,12 @@ msgstr "" msgid "Created: %s" msgstr "Criado: %s" -#: lxc/init.go:170 +#: lxc/init.go:177 #, c-format msgid "Creating %s" msgstr "Criando %s" -#: lxc/init.go:168 +#: lxc/init.go:175 #, fuzzy msgid "Creating the instance" msgstr "Criando %s" @@ -2146,7 +2146,7 @@ msgstr "" msgid "Device: %s" msgstr "Em cache: %s" -#: lxc/init.go:384 +#: lxc/init.go:393 msgid "Didn't get any affected image, instance or snapshot from server" msgstr "" @@ -3236,7 +3236,7 @@ msgstr "" msgid "Instance name is mandatory" msgstr "" -#: lxc/init.go:395 +#: lxc/init.go:404 #, c-format msgid "Instance name is: %s" msgstr "" @@ -3425,6 +3425,16 @@ msgstr "" msgid "Last used: never" msgstr "" +#: lxc/init.go:171 +#, fuzzy, c-format +msgid "Launching %s" +msgstr "Criando %s" + +#: lxc/init.go:169 +#, fuzzy +msgid "Launching the instance" +msgstr "Criando %s" + #: lxc/info.go:220 #, fuzzy, c-format msgid "Link detected: %v" @@ -5390,7 +5400,7 @@ msgstr "" msgid "Retrieve the instance's console log" msgstr "" -#: lxc/init.go:338 +#: lxc/init.go:347 #, c-format msgid "Retrieving image: %s" msgstr "" @@ -6069,7 +6079,7 @@ msgstr "" msgid "Start instances" msgstr "" -#: lxc/launch.go:82 +#: lxc/launch.go:87 #, c-format msgid "Starting %s" msgstr "" @@ -6279,7 +6289,7 @@ msgid "" "restarted" msgstr "" -#: lxc/init.go:416 +#: lxc/init.go:425 msgid "The instance you are starting doesn't have any network attached to it." msgstr "" @@ -6442,11 +6452,11 @@ msgstr "" msgid "Timestamps:" msgstr "" -#: lxc/init.go:418 +#: lxc/init.go:427 msgid "To attach a network to an instance, use: lxc network attach" msgstr "" -#: lxc/init.go:417 +#: lxc/init.go:426 msgid "To create a new network, use: lxc network create" msgstr "" @@ -6519,7 +6529,7 @@ msgstr "" msgid "Trust token for %s: " msgstr "" -#: lxc/action.go:287 lxc/launch.go:114 +#: lxc/action.go:287 lxc/launch.go:119 #, c-format msgid "Try `lxc info --show-log %s` for more info" msgstr "" diff --git a/po/ru.po b/po/ru.po index f636555b1069..1a73189e1e18 100644 --- a/po/ru.po +++ b/po/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxd@lists.canonical.com\n" -"POT-Creation-Date: 2024-07-02 10:12-0700\n" +"POT-Creation-Date: 2024-07-24 14:26-0700\n" "PO-Revision-Date: 2022-03-10 15:06+0000\n" "Last-Translator: Александр Киль \n" "Language-Team: Russian \n" "Language-Team: Sinhala \n" "Language-Team: Slovenian \n" "Language-Team: Serbian \n" "Language-Team: Swedish \n" "Language-Team: Telugu \n" "Language-Team: Turkish \n" "Language-Team: Tamazight (Central Atlas) \n" "Language-Team: Uyghur \n" "Language-Team: Ukrainian \n" "Language-Team: Chinese (Simplified) \n" "Language-Team: Chinese (Traditional)