The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3553
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === This adds API support to get/edit the container metadata.yaml, as well as editing template files. Also, it adds `lxc config metadata [show|edit] <container>` Closes #2823
From ab8d925a5cc34051f18522dc42c97ab753c4d0cf Mon Sep 17 00:00:00 2001 From: Alberto Donato <alberto.don...@canonical.com> Date: Thu, 13 Jul 2017 10:41:36 +0200 Subject: [PATCH 1/3] Add API for editing containers metadata.yaml Signed-off-by: Alberto Donato <alberto.don...@canonical.com> --- client/interfaces.go | 3 ++ client/lxd_containers.go | 32 ++++++++++++ doc/api-extensions.md | 5 ++ doc/rest-api.md | 62 +++++++++++++++++++++++ lxc/config.go | 123 ++++++++++++++++++++++++++++++++++++++++++++++ lxd/api_1.0.go | 2 + lxd/container_lxc.go | 6 +-- lxd/container_metadata.go | 71 ++++++++++++++++++++++++++ lxd/containers.go | 6 +++ lxd/images.go | 21 ++------ po/de.po | 85 +++++++++++++++++++++++++------- po/el.po | 67 ++++++++++++++++++------- po/fr.po | 85 +++++++++++++++++++++++++------- po/it.po | 67 ++++++++++++++++++------- po/ja.po | 67 ++++++++++++++++++------- po/lxd.pot | 64 +++++++++++++++++------- po/nl.po | 67 ++++++++++++++++++------- po/ru.po | 85 +++++++++++++++++++++++++------- po/sr.po | 67 ++++++++++++++++++------- po/sv.po | 67 ++++++++++++++++++------- po/tr.po | 67 ++++++++++++++++++------- shared/api/image.go | 15 ++++++ test/main.sh | 2 + test/suites/config.sh | 17 +++++++ 24 files changed, 924 insertions(+), 229 deletions(-) create mode 100644 lxd/container_metadata.go diff --git a/client/interfaces.go b/client/interfaces.go index d146c1ddf..bf6075a45 100644 --- a/client/interfaces.go +++ b/client/interfaces.go @@ -86,6 +86,9 @@ type ContainerServer interface { GetContainerLogfile(name string, filename string) (content io.ReadCloser, err error) DeleteContainerLogfile(name string, filename string) (err error) + GetContainerMetadata(name string) (*api.ImageMetadata, string, error) + SetContainerMetadata(name string, ETag string, metadata api.ImageMetadata) error + // Event handling functions GetEvents() (listener *EventListener, err error) diff --git a/client/lxd_containers.go b/client/lxd_containers.go index 9d4cb6bce..8706855bc 100644 --- a/client/lxd_containers.go +++ b/client/lxd_containers.go @@ -1261,3 +1261,35 @@ func (r *ProtocolLXD) DeleteContainerLogfile(name string, filename string) error return nil } + +// GetContainerMetadata returns container metadata +func (r *ProtocolLXD) GetContainerMetadata(name string) (*api.ImageMetadata, string, error) { + if !r.HasExtension("container_edit_metadata") { + return nil, "", fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + } + + metadata := api.ImageMetadata{} + + url := fmt.Sprintf("/containers/%s/metadata", name) + etag, err := r.queryStruct("GET", url, nil, "", &metadata) + if err != nil { + return nil, "", err + } + + return &metadata, etag, err +} + +// Set the content of the container metadata file. +func (r *ProtocolLXD) SetContainerMetadata(name string, ETag string, metadata api.ImageMetadata) error { + if !r.HasExtension("container_edit_metadata") { + return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + } + + url := fmt.Sprintf("/containers/%s/metadata", name) + _, _, err := r.query("PUT", url, metadata, ETag) + if err != nil { + return err + } + + return nil +} diff --git a/doc/api-extensions.md b/doc/api-extensions.md index bc3dd2d61..b930d21f7 100644 --- a/doc/api-extensions.md +++ b/doc/api-extensions.md @@ -292,3 +292,8 @@ X-LXD-type can now be "symlink" with the request content being the target path. ## container\_push\_target This adds the "target" field to POST /1.0/containers/NAME which can be used to have the source LXD host connect to the target during migration. + +## container\_edit\_metadata +This adds support for editing a container metadata.yaml and related templates +via API, by accessing urls under /1.0/containers/NAME/metadata. It can be used +to edit a container before publishing an image from it. diff --git a/doc/rest-api.md b/doc/rest-api.md index 354bf5929..c3bf9b5d2 100644 --- a/doc/rest-api.md +++ b/doc/rest-api.md @@ -190,6 +190,7 @@ won't work and PUT needs to be used instead. * /1.0/containers/\<name\>/state * /1.0/containers/\<name\>/logs * /1.0/containers/\<name\>/logs/\<logfile\> + * /1.0/containers/\<name\>/metadata * /1.0/events * /1.0/images * /1.0/images/\<fingerprint\> @@ -1177,6 +1178,67 @@ Return: * Operation: Sync * Return: empty response or standard error +## /1.0/containers/\<name\>/metadata +### GET +* Description: Container metadata +* Authentication: trusted +* Operation: Sync +* Return: dict representing container metadata + +Return: + + { + "architecture": "x86_64", + "creation_date": 1477146654, + "expiry_date": 0, + "properties": { + "architecture": "x86_64", + "description": "Busybox x86_64", + "name": "busybox-x86_64", + "os": "Busybox" + }, + "templates": { + "/template": { + "when": [ + "" + ], + "create_only": false, + "template": "template.tpl", + "properties": {} + } + } + } + +### PUT (ETag supported) + * Description: Replaces container metadata + * Authentication: trusted + * Operation: sync + * Return: standard return value or standard error + +Input: + + { + "architecture": "x86_64", + "creation_date": 1477146654, + "expiry_date": 0, + "properties": { + "architecture": "x86_64", + "description": "Busybox x86_64", + "name": "busybox-x86_64", + "os": "Busybox" + }, + "templates": { + "/template": { + "when": [ + "" + ], + "create_only": false, + "template": "template.tpl", + "properties": {} + } + } + } + ## /1.0/events This URL isn't a real REST API endpoint, instead doing a GET query on it will upgrade the connection to a websocket on which notifications will diff --git a/lxc/config.go b/lxc/config.go index 6bc2fd06d..6c949a7ae 100644 --- a/lxc/config.go +++ b/lxc/config.go @@ -56,6 +56,30 @@ func (c *configCmd) configEditHelp() string { ### Note that the name is shown but cannot be changed`) } +func (c *configCmd) metadataEditHelp() string { + return i18n.G( + `### This is a yaml representation of the container metadata. +### Any line starting with a '# will be ignored. +### +### A sample configuration looks like: +### +### architecture: x86_64 +### creation_date: 1477146654 +### expiry_date: 0 +### properties: +### architecture: x86_64 +### description: Busybox x86_64 +### name: busybox-x86_64 +### os: Busybox +### templates: +### /template: +### when: +### - "" +### create_only: false +### template: template.tpl +### properties: {}`) +} + func (c *configCmd) usage() string { return i18n.G( `Usage: lxc config <subcommand> [options] @@ -79,6 +103,11 @@ lxc config show [<remote>:][container] [--expanded] lxc config edit [<remote>:][container] Edit configuration, either by launching external editor or reading STDIN. +*Container metadata* + +lxc config metadata show [<remote>:][container] + Show the container metadata.yaml content. + *Device management* lxc config device add [<remote>:]<container> <device> <type> [key=value...] @@ -583,6 +612,41 @@ func (c *configCmd) run(conf *config.Config, args []string) error { return c.doContainerConfigEdit(d, container) + case "metadata": + if len(args) < 3 { + return errArgs + } + + remote, container, err := conf.ParseRemote(args[2]) + if err != nil { + return err + } + + d, err := conf.GetContainerServer(remote) + if err != nil { + return err + } + + switch args[1] { + case "show": + metadata, _, err := d.GetContainerMetadata(container) + if err != nil { + return err + } + content, err := yaml.Marshal(metadata) + if err != nil { + return err + } + fmt.Printf("%s", content) + return nil + + case "edit": + return c.doContainerMetadataEdit(d, container) + + default: + return errArgs + } + default: return errArgs } @@ -1120,3 +1184,62 @@ func (c *configCmd) deviceShow(conf *config.Config, which string, args []string) fmt.Printf(string(data)) return nil } + +func (c *configCmd) doContainerMetadataEdit(client lxd.ContainerServer, name string) error { + if !termios.IsTerminal(int(syscall.Stdin)) { + metadata := api.ImageMetadata{} + content, err := ioutil.ReadAll(os.Stdin) + if err != nil { + return err + } + + err = yaml.Unmarshal(content, &metadata) + if err != nil { + return err + } + return client.SetContainerMetadata(name, "", metadata) + } + + metadata, etag, err := client.GetContainerMetadata(name) + if err != nil { + return err + } + origContent, err := yaml.Marshal(metadata) + if err != nil { + return err + } + + // Spawn the editor + content, err := shared.TextEditor("", []byte(c.metadataEditHelp()+"\n\n"+string(origContent))) + if err != nil { + return err + } + + for { + err = yaml.Unmarshal(content, &metadata) + if err == nil { + err = client.SetContainerMetadata(name, etag, *metadata) + } + + // Respawn the editor + if err != nil { + fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) + fmt.Println(i18n.G("Press enter to start the editor again")) + + _, err := os.Stdin.Read(make([]byte, 1)) + if err != nil { + return err + } + + content, err = shared.TextEditor("", content) + if err != nil { + return err + } + continue + } + + break + } + + return nil +} diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go index 46f7b5459..dd125c0e7 100644 --- a/lxd/api_1.0.go +++ b/lxd/api_1.0.go @@ -26,6 +26,7 @@ var api10 = []Command{ containerSnapshotsCmd, containerSnapshotCmd, containerExecCmd, + containerMetadataCmd, aliasCmd, aliasesCmd, eventsCmd, @@ -112,6 +113,7 @@ func api10Get(d *Daemon, r *http.Request) Response { "id_map_base", "file_symlinks", "container_push_target", + "container_edit_metadata", }, APIStatus: "stable", APIVersion: version.APIVersion, diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index d5eebbf91..1920f8a19 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -4146,7 +4146,7 @@ func (c *containerLXC) Export(w io.Writer, properties map[string]string) error { } // Fill in the metadata - meta := imageMetadata{} + meta := api.ImageMetadata{} meta.Architecture = arch meta.CreationDate = time.Now().UTC().Unix() meta.Properties = properties @@ -4191,7 +4191,7 @@ func (c *containerLXC) Export(w io.Writer, properties map[string]string) error { return err } - metadata := new(imageMetadata) + metadata := new(api.ImageMetadata) err = yaml.Unmarshal(content, &metadata) if err != nil { tw.Close() @@ -4486,7 +4486,7 @@ func (c *containerLXC) templateApplyNow(trigger string) error { return err } - metadata := new(imageMetadata) + metadata := new(api.ImageMetadata) err = yaml.Unmarshal(content, &metadata) if err != nil { diff --git a/lxd/container_metadata.go b/lxd/container_metadata.go new file mode 100644 index 000000000..5b235bf3e --- /dev/null +++ b/lxd/container_metadata.go @@ -0,0 +1,71 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "os" + "path/filepath" + + "gopkg.in/yaml.v2" + + "github.com/gorilla/mux" + + "github.com/lxc/lxd/shared/api" +) + +func containerMetadataGet(d *Daemon, r *http.Request) Response { + name := mux.Vars(r)["name"] + metadataPath, err := getContainerMetadataPath(d, name) + if err != nil { + return SmartError(err) + } + + metadataFile, err := os.Open(metadataPath) + if err != nil { + return InternalError(err) + } + + data, err := ioutil.ReadAll(metadataFile) + if err != nil { + return InternalError(err) + } + metadata := api.ImageMetadata{} + err = yaml.Unmarshal([]byte(data), &metadata) + if err != nil { + return SmartError(err) + } + return SyncResponse(true, metadata) +} + +func containerMetadataPut(d *Daemon, r *http.Request) Response { + name := mux.Vars(r)["name"] + metadataPath, err := getContainerMetadataPath(d, name) + if err != nil { + return SmartError(err) + } + + metadata := api.ImageMetadata{} + if err := json.NewDecoder(r.Body).Decode(&metadata); err != nil { + return BadRequest(err) + } + + data, err := yaml.Marshal(metadata) + if err != nil { + return BadRequest(err) + } + if err := ioutil.WriteFile(metadataPath, data, 0644); err != nil { + InternalError(err) + } + + return EmptySyncResponse +} + +// Return the path of the container metadata file +func getContainerMetadataPath(d *Daemon, cname string) (string, error) { + c, err := containerLoadByName(d, cname) + if err != nil { + return "", err + } + return filepath.Join(c.Path(), "metadata.yaml"), nil +} diff --git a/lxd/containers.go b/lxd/containers.go index 3345879ef..92d795ace 100644 --- a/lxd/containers.go +++ b/lxd/containers.go @@ -58,6 +58,12 @@ var containerExecCmd = Command{ post: containerExecPost, } +var containerMetadataCmd = Command{ + name: "containers/{name}/metadata", + get: containerMetadataGet, + put: containerMetadataPut, +} + type containerAutostartList []container func (slice containerAutostartList) Len() int { diff --git a/lxd/images.go b/lxd/images.go index 9b04cff4b..5d6029cb8 100644 --- a/lxd/images.go +++ b/lxd/images.go @@ -203,21 +203,6 @@ func compressFile(path string, compress string) (string, error) { return outfile.Name(), nil } -type templateEntry struct { - When []string `yaml:"when"` - CreateOnly bool `yaml:"create_only"` - Template string `yaml:"template"` - Properties map[string]string `yaml:"properties"` -} - -type imageMetadata struct { - Architecture string `yaml:"architecture"` - CreationDate int64 `yaml:"creation_date"` - ExpiryDate int64 `yaml:"expiry_date"` - Properties map[string]string `yaml:"properties"` - Templates map[string]*templateEntry `yaml:"templates"` -} - /* * This function takes a container or snapshot from the local image server and * exports it as an image. @@ -435,7 +420,7 @@ func imgPostURLInfo(d *Daemon, req api.ImagesPost, op *operation) (*api.Image, e func getImgPostInfo(d *Daemon, r *http.Request, builddir string, post *os.File) (*api.Image, error) { info := api.Image{} - var imageMeta *imageMetadata + var imageMeta *api.ImageMetadata logger := logging.AddContext(logger.Log, log.Ctx{"function": "getImgPostInfo"}) public, _ := strconv.Atoi(r.Header.Get("X-LXD-public")) @@ -776,7 +761,7 @@ func imagesPost(d *Daemon, r *http.Request) Response { return OperationResponse(op) } -func getImageMetadata(fname string) (*imageMetadata, error) { +func getImageMetadata(fname string) (*api.ImageMetadata, error) { metadataName := "metadata.yaml" compressionArgs, _, err := detectCompression(fname) @@ -800,7 +785,7 @@ func getImageMetadata(fname string) (*imageMetadata, error) { return nil, fmt.Errorf("Could not extract image %s from tar: %v (%s)", metadataName, err, outputLines[0]) } - metadata := imageMetadata{} + metadata := api.ImageMetadata{} err = yaml.Unmarshal([]byte(output), &metadata) if err != nil { diff --git a/po/de.po b/po/de.po index 450a54e19..dfabdb852 100644 --- a/po/de.po +++ b/po/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: LXD\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: 2017-02-14 17:11+0000\n" "Last-Translator: Tim Rose <t...@netlope.de>\n" "Language-Team: German <https://hosted.weblate.org/projects/linux-containers/" @@ -114,6 +114,48 @@ msgstr "" "###\n" "### Der Name wird zwar angezeigt, lässt sich jedoch nicht ändern.\n" +#: lxc/config.go:60 +#, fuzzy +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" +"### Dies ist eine Darstellung der Konfiguration in yaml.\n" +"### Jede Zeile die mit '# beginnt wird ignoriert.\n" +"###\n" +"### Beispiel einer Konfiguration:\n" +"### name: container1\n" +"### profiles:\n" +"### - default\n" +"### config:\n" +"### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" +"### devices:\n" +"### homedir:\n" +"### path: /extra\n" +"### source: /home/user\n" +"### type: disk\n" +"### ephemeral: false\n" +"###\n" +"### Der Name wird zwar angezeigt, lässt sich jedoch nicht ändern.\n" + #: lxc/image.go:62 #, fuzzy msgid "" @@ -290,7 +332,7 @@ msgstr "Bytes empfangen" msgid "Bytes sent" msgstr "Bytes gesendet" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -311,17 +353,17 @@ msgstr "ERSTELLT AM" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -352,7 +394,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "kann nicht zum selben Container Namen kopieren" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, fuzzy, c-format msgid "Config parsing error: %s" @@ -426,12 +468,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, fuzzy, c-format msgid "Device %s added to %s" msgstr "Gerät %s wurde zu %s hinzugefügt\n" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, fuzzy, c-format msgid "Device %s removed from %s" msgstr "Gerät %s wurde von %s entfernt\n" @@ -462,7 +504,7 @@ msgstr " Prozessorauslastung:" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -506,7 +548,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -573,7 +615,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -616,7 +658,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 #, fuzzy msgid "Invalid certificate" msgstr "Akzeptiere Zertifikat" @@ -758,7 +800,7 @@ msgstr "Profil %s erstellt\n" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 #, fuzzy msgid "No certificate provided to add" msgstr "Kein Zertifikat zum hinzufügen bereitgestellt" @@ -773,7 +815,7 @@ msgstr "Kein Zertifikat für diese Verbindung" msgid "No device found for this storage volume." msgstr "Kein Zertifikat für diese Verbindung" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "Kein Fingerabdruck angegeben." @@ -857,7 +899,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1145,13 +1187,13 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 #, fuzzy msgid "The device already exists" msgstr "entfernte Instanz %s existiert bereits" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 #, fuzzy msgid "The device doesn't exist" msgstr "entfernte Instanz %s existiert nicht" @@ -1284,7 +1326,7 @@ msgstr "" "Benutzung: lxc [Unterbefehl] [Optionen]\n" "Verfügbare Befehle:\n" -#: lxc/config.go:60 +#: lxc/config.go:84 #, fuzzy msgid "" "Usage: lxc config <subcommand> [options]\n" @@ -1309,6 +1351,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/el.po b/po/el.po index df3be41b5..51aa464c6 100644 --- a/po/el.po +++ b/po/el.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: 2017-02-14 08:00+0000\n" "Last-Translator: Simos Xenitellis <simos...@gmail.com>\n" "Language-Team: Greek <https://hosted.weblate.org/projects/linux-containers/" @@ -71,6 +71,30 @@ msgid "" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -202,7 +226,7 @@ msgstr "" msgid "Bytes sent" msgstr "" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -223,17 +247,17 @@ msgstr "" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -263,7 +287,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -335,12 +359,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -371,7 +395,7 @@ msgstr " Χρήση CPU:" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -413,7 +437,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -477,7 +501,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -519,7 +543,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -657,7 +681,7 @@ msgstr " Χρήση δικτύου:" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -669,7 +693,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -750,7 +774,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1029,12 +1053,12 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 msgid "The device already exists" msgstr "" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1156,7 +1180,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "" "Usage: lxc config <subcommand> [options]\n" "\n" @@ -1180,6 +1204,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/fr.po b/po/fr.po index 7c88aa3a3..245a808f1 100644 --- a/po/fr.po +++ b/po/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: LXD\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: 2017-06-07 15:24+0000\n" "Last-Translator: Stéphane Graber <stgra...@stgraber.org>\n" "Language-Team: French <https://hosted.weblate.org/projects/linux-containers/" @@ -109,6 +109,48 @@ msgstr "" "###\n" "### Notez que le nom est affiché mais ne peut être modifié" +#: lxc/config.go:60 +#, fuzzy +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" +"### Ceci est une réprésentation yaml de la configuration.\n" +"### Toute ligne commençant par un '# sera ignorée.\n" +"###\n" +"### Un exemple de configuration ressemble à :\n" +"### name: container1\n" +"### profiles:\n" +"### - default\n" +"### config:\n" +"### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" +"### devices:\n" +"### homedir:\n" +"### path: /extra\n" +"### source: /home/user\n" +"### type: disk\n" +"### ephemeral: false\n" +"###\n" +"### Notez que le nom est affiché mais ne peut être modifié" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -280,7 +322,7 @@ msgstr "Octets reçus" msgid "Bytes sent" msgstr "Octets émis" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "COMMON NAME" @@ -301,18 +343,18 @@ msgstr "CRÉÉ À" msgid "Can't pull a directory without --recursive" msgstr "impossible de récupérer un répertoire sans --recursive" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "Impossible de lire depuis stdin : %s" -#: lxc/config.go:169 +#: lxc/config.go:198 #, fuzzy, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" "Impossible de désaffecter la clé '%s', elle n'est pas définie actuellement." -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -343,7 +385,7 @@ msgstr "Commandes:" msgid "Config key/value to apply to the new container" msgstr "Clé/valeur de configuration à appliquer au nouveau conteneur" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -416,12 +458,12 @@ msgstr "PILOTE" msgid "Define a compression algorithm: for image or none" msgstr "Définir un algorithme de compression : pour image ou aucun" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "Périphérique %s ajouté à %s" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "Périphérique %s retiré de %s" @@ -452,7 +494,7 @@ msgstr " Disque utilisé :" msgid "EPHEMERAL" msgstr "ÉPHÉMÈRE" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "DATE D'EXPIRATION" @@ -494,7 +536,7 @@ msgstr "N'expire jamais" msgid "Exporting the image: %s" msgstr "Import de l'image : %s" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "EMPREINTE" @@ -560,7 +602,7 @@ msgstr "IPv4" msgid "IPV6" msgstr "IPv6" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "DATE D'ÉMISSION" @@ -607,7 +649,7 @@ msgstr "Image copiée avec succès !" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "Schème d'URL invalide \"%s\" in \"%s\"" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "Certificat invalide" @@ -747,7 +789,7 @@ msgstr " Réseau utilisé :" msgid "New alias to define at target" msgstr "Nouvel alias à définir sur la cible" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "Un certificat à ajouter n'a pas été fourni" @@ -760,7 +802,7 @@ msgstr "Aucun périphérique existant pour ce réseau" msgid "No device found for this storage volume." msgstr "Aucun périphérique existant pour ce réseau" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "Aucune empreinte n'a été indiquée." @@ -842,7 +884,7 @@ msgstr "Pid : %d" msgid "Press enter to open the editor again" msgstr "Appuyer sur Entrée pour ouvrir à nouveau l'éditeur" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "Appuyer sur Entrée pour lancer à nouveau l'éditeur" @@ -1130,13 +1172,13 @@ msgid "The container you are starting doesn't have any network attached to it." msgstr "" "Le conteneur que vous démarrez n'est attaché à aucune interface réseau." -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 #, fuzzy msgid "The device already exists" msgstr "Le périphérique n'existe pas" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "Le périphérique n'existe pas" @@ -1268,7 +1310,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "Utilisation : lxc <commande> [options]" -#: lxc/config.go:60 +#: lxc/config.go:84 #, fuzzy msgid "" "Usage: lxc config <subcommand> [options]\n" @@ -1293,6 +1335,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/it.po b/po/it.po index 1d36629ca..edbba09c2 100644 --- a/po/it.po +++ b/po/it.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: 2017-06-15 22:46+0000\n" "Last-Translator: Alberto Donato <alberto.don...@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/linux-containers/" @@ -85,6 +85,30 @@ msgid "" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -223,7 +247,7 @@ msgstr "Bytes ricevuti" msgid "Bytes sent" msgstr "Byte inviati" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -243,17 +267,17 @@ msgstr "CREATO IL" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -283,7 +307,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -355,12 +379,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -390,7 +414,7 @@ msgstr "" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -432,7 +456,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -496,7 +520,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -538,7 +562,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -674,7 +698,7 @@ msgstr "" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -686,7 +710,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -767,7 +791,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1046,13 +1070,13 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 #, fuzzy msgid "The device already exists" msgstr "il remote %s esiste già" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1174,7 +1198,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "" "Usage: lxc config <subcommand> [options]\n" "\n" @@ -1198,6 +1222,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/ja.po b/po/ja.po index 557f50af6..3a66645b6 100644 --- a/po/ja.po +++ b/po/ja.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: LXD\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: 2017-03-23 12:03+0000\n" "Last-Translator: KATOH Yasufumi <ka...@jazz.email.ne.jp>\n" "Language-Team: Japanese <https://hosted.weblate.org/projects/linux-" @@ -71,6 +71,30 @@ msgid "" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -202,7 +226,7 @@ msgstr "受信バイト数" msgid "Bytes sent" msgstr "送信バイト数" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -224,17 +248,17 @@ msgid "Can't pull a directory without --recursive" msgstr "" "ディレクトリを pull する場合は --recursive オプションを使用してください" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "標準入力から読み込めません: %s" -#: lxc/config.go:169 +#: lxc/config.go:198 #, fuzzy, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "キー '%s' が指定されていないので削除できません。" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "キー '%s' が指定されていないので削除できません。" @@ -264,7 +288,7 @@ msgstr "コマンド:" msgid "Config key/value to apply to the new container" msgstr "新しいコンテナに適用するキー/値の設定" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -337,12 +361,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "圧縮アルゴリズムを指定します: 圧縮アルゴリズム名 or none" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "デバイス %s が %s に追加されました" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "デバイス %s が %s から削除されました" @@ -372,7 +396,7 @@ msgstr "ディスク使用量:" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -414,7 +438,7 @@ msgstr "失効日時: 失効しない" msgid "Exporting the image: %s" msgstr "イメージのインポート中: %s" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -480,7 +504,7 @@ msgstr "IPV4" msgid "IPV6" msgstr "IPV6" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -524,7 +548,7 @@ msgstr "イメージのコピーが成功しました!" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "不正な URL スキーム \"%s\" (\"%s\" 内)" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "不正な証明書です" @@ -663,7 +687,7 @@ msgstr "ネットワーク使用状況:" msgid "New alias to define at target" msgstr "新しいエイリアスを定義する" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "追加すべき証明書が提供されていません" @@ -675,7 +699,7 @@ msgstr "このネットワークに対するデバイスがありません" msgid "No device found for this storage volume." msgstr "このストレージボリュームに対するデバイスがありません。" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "フィンガープリントが指定されていません。" @@ -756,7 +780,7 @@ msgstr "Pid: %d" msgid "Press enter to open the editor again" msgstr "再度エディタを開くためには Enter キーを押します" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "再度エディタを起動するには Enter キーを押します" @@ -1038,13 +1062,13 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "起動しようとしたコンテナに接続されているネットワークがありません。" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 #, fuzzy msgid "The device already exists" msgstr "リモート %s は既に存在します" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "デバイスが存在しません" @@ -1180,7 +1204,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "使い方: lxc <コマンド> [オプション]" -#: lxc/config.go:60 +#: lxc/config.go:84 #, fuzzy msgid "" "Usage: lxc config <subcommand> [options]\n" @@ -1205,6 +1229,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/lxd.pot b/po/lxd.pot index dbfa7c209..bfa5ca373 100644 --- a/po/lxd.pot +++ b/po/lxd.pot @@ -7,7 +7,7 @@ msgid "" msgstr "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" - "POT-Creation-Date: 2017-07-12 00:41+0200\n" + "POT-Creation-Date: 2017-07-14 10:35+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <l...@li.org>\n" @@ -65,6 +65,29 @@ msgid "### This is a yaml representation of the configuration.\n" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "### This is a yaml representation of the container metadata.\n" + "### Any line starting with a '# will be ignored.\n" + "###\n" + "### A sample configuration looks like:\n" + "###\n" + "### architecture: x86_64\n" + "### creation_date: 1477146654\n" + "### expiry_date: 0\n" + "### properties:\n" + "### architecture: x86_64\n" + "### description: Busybox x86_64\n" + "### name: busybox-x86_64\n" + "### os: Busybox\n" + "### templates:\n" + "### /template:\n" + "### when:\n" + "### - \"\"\n" + "### create_only: false\n" + "### template: template.tpl\n" + "### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "### This is a yaml representation of the image properties.\n" "### Any line starting with a '# will be ignored.\n" @@ -193,7 +216,7 @@ msgstr "" msgid "Bytes sent" msgstr "" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -213,17 +236,17 @@ msgstr "" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -253,7 +276,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" msgstr "" @@ -323,12 +346,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -358,7 +381,7 @@ msgstr "" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -400,7 +423,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -464,7 +487,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -506,7 +529,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -641,7 +664,7 @@ msgstr "" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -653,7 +676,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -734,7 +757,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1011,11 +1034,11 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 msgid "The device already exists" msgstr "" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1135,7 +1158,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "Usage: lxc config <subcommand> [options]\n" "\n" "Change container or server configuration options.\n" @@ -1157,6 +1180,11 @@ msgid "Usage: lxc config <subcommand> [options]\n" "lxc config edit [<remote>:][container]\n" " Edit configuration, either by launching external editor or reading STDIN.\n" "\n" + "*Container metadata*\n" + "\n" + "lxc config metadata show [<remote>:][container]\n" + " Show the container metadata.yaml content.\n" + "\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/nl.po b/po/nl.po index a005e30f2..101f50f7f 100644 --- a/po/nl.po +++ b/po/nl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -68,6 +68,30 @@ msgid "" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -199,7 +223,7 @@ msgstr "" msgid "Bytes sent" msgstr "" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -219,17 +243,17 @@ msgstr "" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -259,7 +283,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -331,12 +355,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -366,7 +390,7 @@ msgstr "" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -408,7 +432,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -472,7 +496,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -514,7 +538,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -650,7 +674,7 @@ msgstr "" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -662,7 +686,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -743,7 +767,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1022,12 +1046,12 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 msgid "The device already exists" msgstr "" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1149,7 +1173,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "" "Usage: lxc config <subcommand> [options]\n" "\n" @@ -1173,6 +1197,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/ru.po b/po/ru.po index 148c7b953..68104bb71 100644 --- a/po/ru.po +++ b/po/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: 2017-06-06 13:55+0000\n" "Last-Translator: Александр Киль <shor...@gmail.com>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/linux-containers/" @@ -106,6 +106,48 @@ msgstr "" "###\n" "### Обратите внимание, что имя отображается, но не может быть изменено" +#: lxc/config.go:60 +#, fuzzy +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" +"### Это представление конфигурации в формате YAML. \n" +"### Любая строка начинающаяся с '#' будет игнорироваться.\n" +"###\n" +"### Пример конфигурации:\n" +"### name: container1\n" +"### profiles:\n" +"### - default\n" +"### config:\n" +"### volatile.eth0.hwaddr: 00:16:3e:e9:f8:7f\n" +"### devices:\n" +"### homedir:\n" +"### path: /extra\n" +"### source: /home/user\n" +"### type: disk\n" +"### ephemeral: false\n" +"###\n" +"### Обратите внимание, что имя отображается, но не может быть изменено" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -271,7 +313,7 @@ msgstr "Получено байтов" msgid "Bytes sent" msgstr "Отправлено байтов" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "ОБЩЕЕ ИМЯ" @@ -292,17 +334,17 @@ msgstr "СОЗДАН" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "Невозможно прочитать из стандартного ввода: %s" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -332,7 +374,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -404,12 +446,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -440,7 +482,7 @@ msgstr " Использование диска:" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -482,7 +524,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "Копирование образа: %s" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -546,7 +588,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -588,7 +630,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -726,7 +768,7 @@ msgstr " Использование сети:" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -738,7 +780,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -819,7 +861,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1098,12 +1140,12 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 msgid "The device already exists" msgstr "" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1228,7 +1270,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "" "Usage: lxc config <subcommand> [options]\n" "\n" @@ -1252,6 +1294,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/sr.po b/po/sr.po index 47ae3c04f..f8a7d4290 100644 --- a/po/sr.po +++ b/po/sr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -68,6 +68,30 @@ msgid "" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -199,7 +223,7 @@ msgstr "" msgid "Bytes sent" msgstr "" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -219,17 +243,17 @@ msgstr "" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -259,7 +283,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -331,12 +355,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -366,7 +390,7 @@ msgstr "" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -408,7 +432,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -472,7 +496,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -514,7 +538,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -650,7 +674,7 @@ msgstr "" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -662,7 +686,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -743,7 +767,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1022,12 +1046,12 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 msgid "The device already exists" msgstr "" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1149,7 +1173,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "" "Usage: lxc config <subcommand> [options]\n" "\n" @@ -1173,6 +1197,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/sv.po b/po/sv.po index fe126ed67..a5c7c37aa 100644 --- a/po/sv.po +++ b/po/sv.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -68,6 +68,30 @@ msgid "" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -199,7 +223,7 @@ msgstr "" msgid "Bytes sent" msgstr "" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -219,17 +243,17 @@ msgstr "" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -259,7 +283,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -331,12 +355,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -366,7 +390,7 @@ msgstr "" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -408,7 +432,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -472,7 +496,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -514,7 +538,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -650,7 +674,7 @@ msgstr "" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -662,7 +686,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -743,7 +767,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1022,12 +1046,12 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 msgid "The device already exists" msgstr "" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1149,7 +1173,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "" "Usage: lxc config <subcommand> [options]\n" "\n" @@ -1173,6 +1197,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/po/tr.po b/po/tr.po index ffc13f253..7fe893057 100644 --- a/po/tr.po +++ b/po/tr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: lxd\n" "Report-Msgid-Bugs-To: lxc-devel@lists.linuxcontainers.org\n" -"POT-Creation-Date: 2017-07-12 00:41+0200\n" +"POT-Creation-Date: 2017-07-14 08:35+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" @@ -68,6 +68,30 @@ msgid "" "### Note that the name is shown but cannot be changed" msgstr "" +#: lxc/config.go:60 +msgid "" +"### This is a yaml representation of the container metadata.\n" +"### Any line starting with a '# will be ignored.\n" +"###\n" +"### A sample configuration looks like:\n" +"###\n" +"### architecture: x86_64\n" +"### creation_date: 1477146654\n" +"### expiry_date: 0\n" +"### properties:\n" +"### architecture: x86_64\n" +"### description: Busybox x86_64\n" +"### name: busybox-x86_64\n" +"### os: Busybox\n" +"### templates:\n" +"### /template:\n" +"### when:\n" +"### - \"\"\n" +"### create_only: false\n" +"### template: template.tpl\n" +"### properties: {}" +msgstr "" + #: lxc/image.go:62 msgid "" "### This is a yaml representation of the image properties.\n" @@ -199,7 +223,7 @@ msgstr "" msgid "Bytes sent" msgstr "" -#: lxc/config.go:349 +#: lxc/config.go:378 msgid "COMMON NAME" msgstr "" @@ -219,17 +243,17 @@ msgstr "" msgid "Can't pull a directory without --recursive" msgstr "" -#: lxc/config.go:156 lxc/network.go:542 +#: lxc/config.go:185 lxc/network.go:542 #, c-format msgid "Can't read from stdin: %s" msgstr "" -#: lxc/config.go:169 +#: lxc/config.go:198 #, c-format msgid "Can't unset key '%s', it's not currently set" msgstr "" -#: lxc/config.go:211 lxc/config.go:237 +#: lxc/config.go:240 lxc/config.go:266 #, c-format msgid "Can't unset key '%s', it's not currently set." msgstr "" @@ -259,7 +283,7 @@ msgstr "" msgid "Config key/value to apply to the new container" msgstr "" -#: lxc/config.go:647 lxc/config.go:712 lxc/image.go:1120 lxc/network.go:418 +#: lxc/config.go:715 lxc/config.go:780 lxc/image.go:1120 lxc/network.go:418 #: lxc/profile.go:267 lxc/storage.go:576 lxc/storage.go:935 #, c-format msgid "Config parsing error: %s" @@ -331,12 +355,12 @@ msgstr "" msgid "Define a compression algorithm: for image or none" msgstr "" -#: lxc/config.go:803 +#: lxc/config.go:871 #, c-format msgid "Device %s added to %s" msgstr "" -#: lxc/config.go:1039 +#: lxc/config.go:1107 #, c-format msgid "Device %s removed from %s" msgstr "" @@ -366,7 +390,7 @@ msgstr "" msgid "EPHEMERAL" msgstr "" -#: lxc/config.go:351 +#: lxc/config.go:380 msgid "EXPIRY DATE" msgstr "" @@ -408,7 +432,7 @@ msgstr "" msgid "Exporting the image: %s" msgstr "" -#: lxc/config.go:348 lxc/image.go:229 lxc/image.go:1066 +#: lxc/config.go:377 lxc/image.go:229 lxc/image.go:1066 msgid "FINGERPRINT" msgstr "" @@ -472,7 +496,7 @@ msgstr "" msgid "IPV6" msgstr "" -#: lxc/config.go:350 +#: lxc/config.go:379 msgid "ISSUE DATE" msgstr "" @@ -514,7 +538,7 @@ msgstr "" msgid "Invalid URL scheme \"%s\" in \"%s\"" msgstr "" -#: lxc/config.go:329 +#: lxc/config.go:358 msgid "Invalid certificate" msgstr "" @@ -650,7 +674,7 @@ msgstr "" msgid "New alias to define at target" msgstr "" -#: lxc/config.go:360 +#: lxc/config.go:389 msgid "No certificate provided to add" msgstr "" @@ -662,7 +686,7 @@ msgstr "" msgid "No device found for this storage volume." msgstr "" -#: lxc/config.go:392 +#: lxc/config.go:421 msgid "No fingerprint specified." msgstr "" @@ -743,7 +767,7 @@ msgstr "" msgid "Press enter to open the editor again" msgstr "" -#: lxc/config.go:648 lxc/config.go:713 lxc/image.go:1121 +#: lxc/config.go:716 lxc/config.go:781 lxc/image.go:1121 msgid "Press enter to start the editor again" msgstr "" @@ -1022,12 +1046,12 @@ msgstr "" msgid "The container you are starting doesn't have any network attached to it." msgstr "" -#: lxc/config.go:770 lxc/config.go:787 +#: lxc/config.go:838 lxc/config.go:855 msgid "The device already exists" msgstr "" -#: lxc/config.go:833 lxc/config.go:845 lxc/config.go:881 lxc/config.go:899 -#: lxc/config.go:945 lxc/config.go:962 lxc/config.go:1005 lxc/config.go:1023 +#: lxc/config.go:901 lxc/config.go:913 lxc/config.go:949 lxc/config.go:967 +#: lxc/config.go:1013 lxc/config.go:1030 lxc/config.go:1073 lxc/config.go:1091 msgid "The device doesn't exist" msgstr "" @@ -1149,7 +1173,7 @@ msgstr "" msgid "Usage: lxc <command> [options]" msgstr "" -#: lxc/config.go:60 +#: lxc/config.go:84 msgid "" "Usage: lxc config <subcommand> [options]\n" "\n" @@ -1173,6 +1197,11 @@ msgid "" " Edit configuration, either by launching external editor or reading " "STDIN.\n" "\n" +"*Container metadata*\n" +"\n" +"lxc config metadata show [<remote>:][container]\n" +" Show the container metadata.yaml content.\n" +"\n" "*Device management*\n" "\n" "lxc config device add [<remote>:]<container> <device> <type> [key=value...]\n" diff --git a/shared/api/image.go b/shared/api/image.go index 814c0981d..c1335dfc1 100644 --- a/shared/api/image.go +++ b/shared/api/image.go @@ -102,3 +102,18 @@ type ImageAliasesEntry struct { Name string `json:"name" yaml:"name"` } + +type TemplateEntry struct { + When []string `json:"when" yaml:"when"` + CreateOnly bool `json:"create_only" yaml:"create_only"` + Template string `json:"template" yaml:"template"` + Properties map[string]string `json:"properties" yaml:"properties"` +} + +type ImageMetadata struct { + Architecture string `json:"architecture" yaml:"architecture"` + CreationDate int64 `json:"creation_date" yaml:"creation_date"` + ExpiryDate int64 `json:"expiry_date" yaml:"expiry_date"` + Properties map[string]string `json:"properties" yaml:"properties"` + Templates map[string]*TemplateEntry `json:"templates" yaml:"templates"` +} diff --git a/test/main.sh b/test/main.sh index 9fc18d525..a332e5554 100755 --- a/test/main.sh +++ b/test/main.sh @@ -616,6 +616,8 @@ run_test test_snap_restore "snapshot restores" run_test test_config_profiles "profiles and configuration" run_test test_config_edit "container configuration edit" run_test test_config_edit_container_snapshot_pool_config "container and snapshot volume configuration edit" +run_test test_metadata_show "container metadata show" +run_test test_metadata_edit "contaimer metadata edit" run_test test_server_config "server configuration" run_test test_filemanip "file manipulations" run_test test_network "network management" diff --git a/test/suites/config.sh b/test/suites/config.sh index 1a943a72f..5c0c269bf 100644 --- a/test/suites/config.sh +++ b/test/suites/config.sh @@ -260,3 +260,20 @@ test_config_edit_container_snapshot_pool_config() { lxc storage volume show "$storage_pool" container/c1/s1 | grep -q 'description: baz' lxc delete c1 } + +test_metadata_show() { + ensure_import_testimage + + lxc init testimage c + # metadata for the container are printed + lxc config metadata show c | grep -q Busybox +} + +test_metadata_edit() { + ensure_import_testimage + + lxc init testimage c + lxc config metadata show c | sed 's/Busybox/BB/' | lxc config metadata edit c + # metadata have been updated + lxc config metadata show c | grep -q BB +} From 81842f9d495054ec9a9b8e3bd69f3b98f1088362 Mon Sep 17 00:00:00 2001 From: Alberto Donato <alberto.don...@canonical.com> Date: Fri, 14 Jul 2017 11:53:41 +0200 Subject: [PATCH 2/3] Add API for managing container template files Signed-off-by: Alberto Donato <alberto.don...@canonical.com> --- doc/rest-api.md | 50 ++++++++++++++++ lxd/api_1.0.go | 2 + lxd/container_metadata.go | 149 +++++++++++++++++++++++++++++++++++++++++++++- lxd/containers.go | 13 ++++ test/main.sh | 4 ++ test/suites/config.sh | 37 +++++++++++- 6 files changed, 252 insertions(+), 3 deletions(-) diff --git a/doc/rest-api.md b/doc/rest-api.md index c3bf9b5d2..a4519e0db 100644 --- a/doc/rest-api.md +++ b/doc/rest-api.md @@ -191,6 +191,8 @@ won't work and PUT needs to be used instead. * /1.0/containers/\<name\>/logs * /1.0/containers/\<name\>/logs/\<logfile\> * /1.0/containers/\<name\>/metadata + * /1.0/containers/\<name\>/metadata/templates + * /1.0/containers/\<name\>/metadata/templates/\<template\> * /1.0/events * /1.0/images * /1.0/images/\<fingerprint\> @@ -1239,6 +1241,54 @@ Input: } } +## /1.0/containers/\<name\>/metadata/templates +### GET +* Description: List container templates +* Authentication: trusted +* Operation: Sync +* Return: a list with container template names + +Return: + + [ + "template.tpl", + "hosts.tpl" + ] + +## POST +* Description: Add a continer template +* Authentication: trusted +* Operation: Sync +* Return: standard return value or standard error + +Input: + * Standard http file upload. + * The request must contain the `X-LXD-filename` header, which is used as name + of the created template file. + + +## /1.0/containers/\<name\>/metadata/templates/\<template\> +### GET +* Description: Content of a container template +* Authentication: trusted +* Operation: Sync +* Return: the content of the template + +### PUT +* Description: Replace content of a template +* Authentication: trusted +* Operation: Sync +* Return: standard return value or standard error + +Input: + * Standard http file upload. + +### DELETE +* Description: Delete a container template +* Authentication: trusted +* Operation: Sync +* Return: standard return value or standard error + ## /1.0/events This URL isn't a real REST API endpoint, instead doing a GET query on it will upgrade the connection to a websocket on which notifications will diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go index dd125c0e7..9828ebb63 100644 --- a/lxd/api_1.0.go +++ b/lxd/api_1.0.go @@ -27,6 +27,8 @@ var api10 = []Command{ containerSnapshotCmd, containerExecCmd, containerMetadataCmd, + containerMetadataTemplatesCmd, + containerMetadataTemplateCmd, aliasCmd, aliasesCmd, eventsCmd, diff --git a/lxd/container_metadata.go b/lxd/container_metadata.go index 5b235bf3e..d2754b27f 100644 --- a/lxd/container_metadata.go +++ b/lxd/container_metadata.go @@ -2,15 +2,18 @@ package main import ( "encoding/json" + "fmt" "io/ioutil" "net/http" "os" "path/filepath" + "strings" "gopkg.in/yaml.v2" "github.com/gorilla/mux" + "github.com/lxc/lxd/shared" "github.com/lxc/lxd/shared/api" ) @@ -31,7 +34,7 @@ func containerMetadataGet(d *Daemon, r *http.Request) Response { return InternalError(err) } metadata := api.ImageMetadata{} - err = yaml.Unmarshal([]byte(data), &metadata) + err = yaml.Unmarshal(data, &metadata) if err != nil { return SmartError(err) } @@ -61,6 +64,129 @@ func containerMetadataPut(d *Daemon, r *http.Request) Response { return EmptySyncResponse } +// Return a list of templates used in a container +func containerMetadataTemplatesGet(d *Daemon, r *http.Request) Response { + name := mux.Vars(r)["name"] + templatesPath, err := getContainerTemplatesPath(d, name) + if err != nil { + return SmartError(err) + } + + filesInfo, err := ioutil.ReadDir(templatesPath) + if err != nil { + return InternalError(err) + } + + templates := []string{} + for _, info := range filesInfo { + if !info.IsDir() { + templates = append(templates, info.Name()) + } + } + return SyncResponse(true, templates) +} + +// Add a container template file +func containerMetadataTemplatesPost(d *Daemon, r *http.Request) Response { + name := mux.Vars(r)["name"] + templateName := r.Header.Get("X-LXD-filename") + if templateName == "" { + return BadRequest(fmt.Errorf("Missing X-LXD-filename header")) + } + templatePath, err := getContainerTemplatePath(d, name, templateName) + if err != nil { + return SmartError(err) + } + + if shared.PathExists(templatePath) { + return BadRequest(fmt.Errorf("Template already exists")) + } + + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return SmartError(err) + } + + template, err := os.OpenFile(templatePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return SmartError(err) + } + defer template.Close() + _, err = template.Write(data) + if err != nil { + return SmartError(err) + } + + return EmptySyncResponse +} + +// Return the content of a container template +func containerMetadataTemplateGet(d *Daemon, r *http.Request) Response { + name := mux.Vars(r)["name"] + templateName := mux.Vars(r)["template"] + templatePath, err := getContainerTemplatePath(d, name, templateName) + if err != nil { + return SmartError(err) + } + if !shared.PathExists(templatePath) { + return NotFound + } + + files := make([]fileResponseEntry, 1) + files[0].identifier = templateName + files[0].path = templatePath + files[0].filename = templateName + return FileResponse(r, files, nil, false) +} + +// Update the content of a container template +func containerMetadataTemplatePut(d *Daemon, r *http.Request) Response { + name := mux.Vars(r)["name"] + templateName := mux.Vars(r)["template"] + templatePath, err := getContainerTemplatePath(d, name, templateName) + if err != nil { + return SmartError(err) + } + if !shared.PathExists(templatePath) { + return NotFound + } + + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return SmartError(err) + } + template, err := os.OpenFile(templatePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return SmartError(err) + } + defer template.Close() + _, err = template.Write(data) + if err != nil { + return SmartError(err) + } + + return EmptySyncResponse +} + +// Delete a container template +func containerMetadataTemplateDelete(d *Daemon, r *http.Request) Response { + name := mux.Vars(r)["name"] + templateName := mux.Vars(r)["template"] + templatePath, err := getContainerTemplatePath(d, name, templateName) + if err != nil { + return SmartError(err) + } + if !shared.PathExists(templatePath) { + return NotFound + } + + err = os.Remove(templatePath) + if err != nil { + return InternalError(err) + } + return EmptySyncResponse +} + // Return the path of the container metadata file func getContainerMetadataPath(d *Daemon, cname string) (string, error) { c, err := containerLoadByName(d, cname) @@ -69,3 +195,24 @@ func getContainerMetadataPath(d *Daemon, cname string) (string, error) { } return filepath.Join(c.Path(), "metadata.yaml"), nil } + +// Return the path of the container templates dir +func getContainerTemplatesPath(d *Daemon, cname string) (string, error) { + c, err := containerLoadByName(d, cname) + if err != nil { + return "", err + } + return filepath.Join(c.Path(), "templates"), nil +} + +// Return +func getContainerTemplatePath(d *Daemon, cname string, filename string) (string, error) { + if strings.Contains(filename, "/") { + return "", fmt.Errorf("Invalid template filename") + } + templatesPath, err := getContainerTemplatesPath(d, cname) + if err != nil { + return "", err + } + return filepath.Join(templatesPath, filename), nil +} diff --git a/lxd/containers.go b/lxd/containers.go index 92d795ace..49179c562 100644 --- a/lxd/containers.go +++ b/lxd/containers.go @@ -64,6 +64,19 @@ var containerMetadataCmd = Command{ put: containerMetadataPut, } +var containerMetadataTemplatesCmd = Command{ + name: "containers/{name}/metadata/templates", + get: containerMetadataTemplatesGet, + post: containerMetadataTemplatesPost, +} + +var containerMetadataTemplateCmd = Command{ + name: "containers/{name}/metadata/templates/{template}", + get: containerMetadataTemplateGet, + put: containerMetadataTemplatePut, + delete: containerMetadataTemplateDelete, +} + type containerAutostartList []container func (slice containerAutostartList) Len() int { diff --git a/test/main.sh b/test/main.sh index a332e5554..30c7fcda2 100755 --- a/test/main.sh +++ b/test/main.sh @@ -618,6 +618,10 @@ run_test test_config_edit "container configuration edit" run_test test_config_edit_container_snapshot_pool_config "container and snapshot volume configuration edit" run_test test_metadata_show "container metadata show" run_test test_metadata_edit "contaimer metadata edit" +run_test test_metadata_template_list "contaimer template list" +run_test test_metadata_template_content "contaimer template content" +run_test test_metadata_template_add "container template add" +run_test test_metadata_template_remove "container template remove" run_test test_server_config "server configuration" run_test test_filemanip "file manipulations" run_test test_network "network management" diff --git a/test/suites/config.sh b/test/suites/config.sh index 5c0c269bf..1f9b09056 100644 --- a/test/suites/config.sh +++ b/test/suites/config.sh @@ -263,17 +263,50 @@ test_config_edit_container_snapshot_pool_config() { test_metadata_show() { ensure_import_testimage - lxc init testimage c + # metadata for the container are printed lxc config metadata show c | grep -q Busybox } test_metadata_edit() { ensure_import_testimage - lxc init testimage c + lxc config metadata show c | sed 's/Busybox/BB/' | lxc config metadata edit c # metadata have been updated lxc config metadata show c | grep -q BB } + +test_metadata_template_list() { + ensure_import_testimage + lxc init testimage c + + # the GET response contains the template + curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates | grep -q template.tpl +} + +test_metadata_template_content() { + ensure_import_testimage + lxc init testimage c + + curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates/template.tpl | grep -q "name:" +} + +test_metadata_template_add() { + ensure_import_testimage + lxc init testimage c + + curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates -H "X-LXD-filename: my.tpl" -d "some content" + curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates/my.tpl | grep -q "some content" +} + +test_metadata_template_remove() { + ensure_import_testimage + lxc init testimage c + + curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates -H "X-LXD-filename: my.tpl" -d "some content" + curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates/my.tpl -X DELETE + # the template is no longer there + ! (curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates | grep my.tpl) +} From 30146950fe626175c49021d76c0c77ae3ba15739 Mon Sep 17 00:00:00 2001 From: Alberto Donato <alberto.don...@canonical.com> Date: Fri, 14 Jul 2017 17:56:36 +0200 Subject: [PATCH 3/3] Expose all template operations under /metadata/templates Signed-off-by: Alberto Donato <alberto.don...@canonical.com> --- doc/rest-api.md | 23 ++++----- lxd/api_1.0.go | 1 - lxd/container_metadata.go | 120 ++++++++++++++++++---------------------------- lxd/containers.go | 15 ++---- test/suites/config.sh | 12 ++--- 5 files changed, 66 insertions(+), 105 deletions(-) diff --git a/doc/rest-api.md b/doc/rest-api.md index a4519e0db..81eaaf0dd 100644 --- a/doc/rest-api.md +++ b/doc/rest-api.md @@ -192,7 +192,6 @@ won't work and PUT needs to be used instead. * /1.0/containers/\<name\>/logs/\<logfile\> * /1.0/containers/\<name\>/metadata * /1.0/containers/\<name\>/metadata/templates - * /1.0/containers/\<name\>/metadata/templates/\<template\> * /1.0/events * /1.0/images * /1.0/images/\<fingerprint\> @@ -1255,7 +1254,13 @@ Return: "hosts.tpl" ] -## POST +### GET (?path=\<template\>) +* Description: Content of a container template +* Authentication: trusted +* Operation: Sync +* Return: the content of the template + +## POST (?path=\<template\>) * Description: Add a continer template * Authentication: trusted * Operation: Sync @@ -1263,18 +1268,8 @@ Return: Input: * Standard http file upload. - * The request must contain the `X-LXD-filename` header, which is used as name - of the created template file. - - -## /1.0/containers/\<name\>/metadata/templates/\<template\> -### GET -* Description: Content of a container template -* Authentication: trusted -* Operation: Sync -* Return: the content of the template -### PUT +### PUT (?path=\<template\>) * Description: Replace content of a template * Authentication: trusted * Operation: Sync @@ -1283,7 +1278,7 @@ Input: Input: * Standard http file upload. -### DELETE +### DELETE (?path=\<template\>) * Description: Delete a container template * Authentication: trusted * Operation: Sync diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go index 9828ebb63..9adfc2c2f 100644 --- a/lxd/api_1.0.go +++ b/lxd/api_1.0.go @@ -28,7 +28,6 @@ var api10 = []Command{ containerExecCmd, containerMetadataCmd, containerMetadataTemplatesCmd, - containerMetadataTemplateCmd, aliasCmd, aliasesCmd, eventsCmd, diff --git a/lxd/container_metadata.go b/lxd/container_metadata.go index d2754b27f..e38995cb1 100644 --- a/lxd/container_metadata.go +++ b/lxd/container_metadata.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "io" "io/ioutil" "net/http" "os" @@ -64,114 +65,85 @@ func containerMetadataPut(d *Daemon, r *http.Request) Response { return EmptySyncResponse } -// Return a list of templates used in a container +// Return a list of templates used in a container or the content of a template func containerMetadataTemplatesGet(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] - templatesPath, err := getContainerTemplatesPath(d, name) - if err != nil { - return SmartError(err) - } + templateName := r.FormValue("path") - filesInfo, err := ioutil.ReadDir(templatesPath) - if err != nil { - return InternalError(err) - } + if templateName == "" { + // List templates + templatesPath, err := getContainerTemplatesPath(d, name) + if err != nil { + return SmartError(err) + } + + filesInfo, err := ioutil.ReadDir(templatesPath) + if err != nil { + return InternalError(err) + } - templates := []string{} - for _, info := range filesInfo { - if !info.IsDir() { - templates = append(templates, info.Name()) + templates := []string{} + for _, info := range filesInfo { + if !info.IsDir() { + templates = append(templates, info.Name()) + } + } + return SyncResponse(true, templates) + } else { + // Return the content of the template + templatePath, err := getContainerTemplatePath(d, name, templateName) + if err != nil { + return SmartError(err) } + if !shared.PathExists(templatePath) { + return NotFound + } + + files := make([]fileResponseEntry, 1) + files[0].identifier = templateName + files[0].path = templatePath + files[0].filename = templateName + return FileResponse(r, files, nil, false) } - return SyncResponse(true, templates) } // Add a container template file -func containerMetadataTemplatesPost(d *Daemon, r *http.Request) Response { +func containerMetadataTemplatesPostPut(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] - templateName := r.Header.Get("X-LXD-filename") + templateName := r.FormValue("path") if templateName == "" { - return BadRequest(fmt.Errorf("Missing X-LXD-filename header")) + return BadRequest(fmt.Errorf("missing path argument")) } templatePath, err := getContainerTemplatePath(d, name, templateName) if err != nil { return SmartError(err) } - if shared.PathExists(templatePath) { + if r.Method == "POST" && shared.PathExists(templatePath) { return BadRequest(fmt.Errorf("Template already exists")) } - data, err := ioutil.ReadAll(r.Body) - if err != nil { - return SmartError(err) - } - template, err := os.OpenFile(templatePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { return SmartError(err) } defer template.Close() - _, err = template.Write(data) - if err != nil { - return SmartError(err) - } - - return EmptySyncResponse -} -// Return the content of a container template -func containerMetadataTemplateGet(d *Daemon, r *http.Request) Response { - name := mux.Vars(r)["name"] - templateName := mux.Vars(r)["template"] - templatePath, err := getContainerTemplatePath(d, name, templateName) + _, err = io.Copy(template, r.Body) if err != nil { - return SmartError(err) - } - if !shared.PathExists(templatePath) { - return NotFound - } - - files := make([]fileResponseEntry, 1) - files[0].identifier = templateName - files[0].path = templatePath - files[0].filename = templateName - return FileResponse(r, files, nil, false) -} - -// Update the content of a container template -func containerMetadataTemplatePut(d *Daemon, r *http.Request) Response { - name := mux.Vars(r)["name"] - templateName := mux.Vars(r)["template"] - templatePath, err := getContainerTemplatePath(d, name, templateName) - if err != nil { - return SmartError(err) - } - if !shared.PathExists(templatePath) { - return NotFound - } - - data, err := ioutil.ReadAll(r.Body) - if err != nil { - return SmartError(err) - } - template, err := os.OpenFile(templatePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - return SmartError(err) - } - defer template.Close() - _, err = template.Write(data) - if err != nil { - return SmartError(err) + return InternalError(err) } return EmptySyncResponse } // Delete a container template -func containerMetadataTemplateDelete(d *Daemon, r *http.Request) Response { +func containerMetadataTemplatesDelete(d *Daemon, r *http.Request) Response { name := mux.Vars(r)["name"] - templateName := mux.Vars(r)["template"] + templateName := r.FormValue("path") + if templateName == "" { + return BadRequest(fmt.Errorf("missing path argument")) + } templatePath, err := getContainerTemplatePath(d, name, templateName) if err != nil { return SmartError(err) diff --git a/lxd/containers.go b/lxd/containers.go index 49179c562..a48a4b51d 100644 --- a/lxd/containers.go +++ b/lxd/containers.go @@ -65,16 +65,11 @@ var containerMetadataCmd = Command{ } var containerMetadataTemplatesCmd = Command{ - name: "containers/{name}/metadata/templates", - get: containerMetadataTemplatesGet, - post: containerMetadataTemplatesPost, -} - -var containerMetadataTemplateCmd = Command{ - name: "containers/{name}/metadata/templates/{template}", - get: containerMetadataTemplateGet, - put: containerMetadataTemplatePut, - delete: containerMetadataTemplateDelete, + name: "containers/{name}/metadata/templates", + get: containerMetadataTemplatesGet, + post: containerMetadataTemplatesPostPut, + put: containerMetadataTemplatesPostPut, + delete: containerMetadataTemplatesDelete, } type containerAutostartList []container diff --git a/test/suites/config.sh b/test/suites/config.sh index 1f9b09056..8e8ecd2b8 100644 --- a/test/suites/config.sh +++ b/test/suites/config.sh @@ -290,23 +290,23 @@ test_metadata_template_content() { ensure_import_testimage lxc init testimage c - curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates/template.tpl | grep -q "name:" + curl -s --unix-socket "${LXD_DIR}/unix.socket" "lxd/1.0/containers/c/metadata/templates?path=template.tpl" | grep -q "name:" } test_metadata_template_add() { ensure_import_testimage lxc init testimage c - curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates -H "X-LXD-filename: my.tpl" -d "some content" - curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates/my.tpl | grep -q "some content" + curl -s --unix-socket "${LXD_DIR}/unix.socket" "lxd/1.0/containers/c/metadata/templates?path=my.tpl" -H 'Content-type: application/octet-stream' -d "some content" + curl -s --unix-socket "${LXD_DIR}/unix.socket" "lxd/1.0/containers/c/metadata/templates?path=my.tpl" | grep -q "some content" } test_metadata_template_remove() { ensure_import_testimage lxc init testimage c - curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates -H "X-LXD-filename: my.tpl" -d "some content" - curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates/my.tpl -X DELETE + curl -s --unix-socket "${LXD_DIR}/unix.socket" "lxd/1.0/containers/c/metadata/templates?path=my.tpl" -H 'Content-type: application/octet-stream' -d "some content" + curl -s --unix-socket "${LXD_DIR}/unix.socket" "lxd/1.0/containers/c/metadata/templates?path=my.tpl" -X DELETE # the template is no longer there - ! (curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates | grep my.tpl) + ! (curl -s --unix-socket "${LXD_DIR}/unix.socket" lxd/1.0/containers/c/metadata/templates | grep -q my.tpl) }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel