[lxc-devel] [lxd/master] Support editing container metadata and templates over API
albertodonato on Github
lxc-bot at linuxcontainers.org
Fri Jul 14 16:05:55 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 475 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170714/5352608d/attachment.bin>
-------------- next part --------------
From ab8d925a5cc34051f18522dc42c97ab753c4d0cf Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at 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.donato at 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 at 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 <tim at 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 at 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.65 at 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 at 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 <stgraber at 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 at 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.donato at 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 at 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 <karma at 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 at 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 at ADDRESS>\n"
"Language-Team: LANGUAGE <LL at 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 at 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 at 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: Александр Киль <shorrey at 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 at 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 at 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 at 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.donato at 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.donato at 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.donato at 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.donato at 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)
}
More information about the lxc-devel
mailing list