[lxc-devel] [lxd/master] Add support for config key columns in 'lxc list'

sean-jc on Github lxc-bot at linuxcontainers.org
Fri Jun 24 15:29:43 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 703 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160624/0a8c2c1f/attachment.bin>
-------------- next part --------------
From 448c8b0f10120e2e45b36e97740981c12331070b Mon Sep 17 00:00:00 2001
From: Sean Christopherson <sean.j.christopherson at intel.com>
Date: Thu, 23 Jun 2016 08:14:47 -0700
Subject: [PATCH] Add support for config key columns in 'lxc list'

Extend column option for table format to accept a separated list of
attributes to display.  Attributes can be specified using pre-defined
shorthand chars (existing functionality) or via config keys (new).

Move syntactic checking functionality into shared/container.go so
that LXC can perform basic validation of config keys.

Signed-off-by: Sean Christopherson <sean.j.christopherson at intel.com>
---
 lxc/list.go         | 120 +++++++++++++++---
 lxc/list_test.go    | 158 ++++++++++++++++++++++++
 lxd/container.go    | 123 ++-----------------
 po/de.po            | 305 ++++++++++++++++++++++++++--------------------
 po/fr.po            | 305 ++++++++++++++++++++++++++--------------------
 po/ja.po            | 345 ++++++++++++++++++++++++++++++----------------------
 po/lxd.pot          |  71 +++++++----
 shared/container.go | 116 ++++++++++++++++++
 shared/util.go      |  12 ++
 9 files changed, 983 insertions(+), 572 deletions(-)

diff --git a/lxc/list.go b/lxc/list.go
index 12afac8..6e2f9b7 100644
--- a/lxc/list.go
+++ b/lxc/list.go
@@ -6,6 +6,7 @@ import (
 	"os"
 	"regexp"
 	"sort"
+	"strconv"
 	"strings"
 	"sync"
 
@@ -54,9 +55,9 @@ const (
 )
 
 type listCmd struct {
-	chosenColumnRunes string
-	fast              bool
-	format            string
+	columnsRaw string
+	fast       bool
+	format     string
 }
 
 func (c *listCmd) showByDefault() bool {
@@ -79,7 +80,13 @@ The filters are:
  * "s.privileged=1" will do the same
 * A regular expression matching a configuration item or its value. (e.g. volatile.eth0.hwaddr=00:16:3e:.*)
 
-Columns for table format are:
+The -c option takes a comma separated list of arguments that control
+which container attributes to output when displaying in table format.
+Column arguments are either pre-defined shorthand chars (see below),
+or (extended) config keys.  Commas between consecutive shorthand chars
+are optional.
+
+Pre-defined shorthand chars:
 * 4 - IPv4 address
 * 6 - IPv6 address
 * a - architecture
@@ -92,13 +99,27 @@ Columns for table format are:
 * S - number of snapshots
 * t - type (persistent or ephemeral)
 
+Config key syntax: key[:name][:maxWidth]
+* key      - The (extended) config key to display
+* name     - Name to display in the column header, defaults to the key
+             if not specified or if empty (to allow defining maxWidth
+             without a custom name, e.g. user.key::0)
+* maxWidth - Max width of the column (longer results are truncated).
+             -1 == unlimited
+              0 == width of column header
+             >0 == max width in chars
+             Default is -1 (unlimited)
+
 Default column layout: ns46tS
-Fast column layout: nsacPt`)
+Fast column layout: nsacPt
+
+Example: lxc list -c n,volatile.base_image:"BASE IMAGE":0,s46,volatile.eth0.hwaddr:MAC
+`)
 }
 
 func (c *listCmd) flags() {
-	gnuflag.StringVar(&c.chosenColumnRunes, "c", "ns46tS", i18n.G("Columns"))
-	gnuflag.StringVar(&c.chosenColumnRunes, "columns", "ns46tS", i18n.G("Columns"))
+	gnuflag.StringVar(&c.columnsRaw, "c", "ns46tS", i18n.G("Columns"))
+	gnuflag.StringVar(&c.columnsRaw, "columns", "ns46tS", i18n.G("Columns"))
 	gnuflag.StringVar(&c.format, "format", "table", i18n.G("Format"))
 	gnuflag.BoolVar(&c.fast, "fast", false, i18n.G("Fast mode (same as --columns=nsacPt"))
 }
@@ -373,7 +394,16 @@ func (c *listCmd) run(config *lxd.Config, args []string) error {
 		cts = append(cts, cinfo)
 	}
 
-	columns_map := map[rune]column{
+	columns, err := c.parseColumns()
+	if err != nil {
+		return err
+	}
+
+	return c.listContainers(d, cts, filters, columns)
+}
+
+func (c *listCmd) parseColumns() ([]column, error) {
+	columnsShorthandMap := map[rune]column{
 		'4': column{i18n.G("IPV4"), c.IP4ColumnData, true, false},
 		'6': column{i18n.G("IPV6"), c.IP6ColumnData, true, false},
 		'a': column{i18n.G("ARCHITECTURE"), c.ArchitectureColumnData, false, false},
@@ -388,19 +418,79 @@ func (c *listCmd) run(config *lxd.Config, args []string) error {
 	}
 
 	if c.fast {
-		c.chosenColumnRunes = "nsacPt"
+		c.columnsRaw = "nsacPt"
 	}
 
+	columnList := strings.Split(c.columnsRaw, ",")
+
 	columns := []column{}
-	for _, columnRune := range c.chosenColumnRunes {
-		if column, ok := columns_map[columnRune]; ok {
-			columns = append(columns, column)
+	for _, columnEntry := range columnList {
+		if columnEntry == "" {
+			return nil, fmt.Errorf("Empty column entry (redundant, leading or trailing command) in '%s'", c.columnsRaw)
+		}
+
+		// Config keys always contain a period, parse anything without a
+		// period as a series of shorthand runes.
+		if !strings.Contains(columnEntry, ".") {
+			for _, columnRune := range columnEntry {
+				if column, ok := columnsShorthandMap[columnRune]; ok {
+					columns = append(columns, column)
+				} else {
+					return nil, fmt.Errorf("Unknown column shorthand char '%c' in '%s'", columnRune, columnEntry)
+				}
+			}
 		} else {
-			return fmt.Errorf("%s does contain invalid column characters\n", c.chosenColumnRunes)
+			cc := strings.Split(columnEntry, ":")
+			if len(cc) > 3 {
+				return nil, fmt.Errorf("Invalid config key column format (too many fields): '%s'", columnEntry)
+			}
+
+			k := cc[0]
+			if _, err := shared.ConfigKeyChecker(k); err != nil {
+				return nil, fmt.Errorf("Invalid config key '%s' in '%s'", k, columnEntry)
+			}
+
+			column := column{Name: k}
+			if len(cc) > 1 {
+				if len(cc[1]) == 0 && len(cc) != 3 {
+					return nil, fmt.Errorf("Invalid name in '%s', empty string is only allowed when defining maxWidth", columnEntry)
+				}
+				column.Name = cc[1]
+			}
+
+			maxWidth := -1
+			if len(cc) > 2 {
+				temp, err := strconv.ParseInt(cc[2], 10, 64)
+				if err != nil {
+					return nil, fmt.Errorf("Invalid max width (must be an integer) '%s' in '%s'", cc[2], columnEntry)
+				}
+				if temp < -1 {
+					return nil, fmt.Errorf("Invalid max width (must -1, 0 or a positive integer) '%s' in '%s'", cc[2], columnEntry)
+				}
+				if temp == 0 {
+					maxWidth = len(column.Name)
+				} else {
+					maxWidth = int(temp)
+				}
+			}
+
+			column.Data = func(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string {
+				v, ok := cInfo.Config[k]
+				if !ok {
+					v, ok = cInfo.ExpandedConfig[k]
+				}
+
+				// Truncate the data according to the max width.  A negative max width
+				// indicates there is no effective limit.
+				if maxWidth > 0 && len(v) > maxWidth {
+					return v[:maxWidth]
+				}
+				return v
+			}
+			columns = append(columns, column)
 		}
 	}
-
-	return c.listContainers(d, cts, filters, columns)
+	return columns, nil
 }
 
 func (c *listCmd) nameColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string {
diff --git a/lxc/list_test.go b/lxc/list_test.go
index 47e8135..ae4fe0f 100644
--- a/lxc/list_test.go
+++ b/lxc/list_test.go
@@ -1,6 +1,10 @@
 package main
 
 import (
+	"bytes"
+	"math/rand"
+	"strconv"
+	"strings"
 	"testing"
 
 	"github.com/lxc/lxd/shared"
@@ -45,3 +49,157 @@ func TestShouldShow(t *testing.T) {
 		t.Errorf("value filter didn't work")
 	}
 }
+
+// Used by TestColumns and TestInvalidColumns
+const shorthand = "46aclnpPsSt"
+const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+
+func TestColumns(t *testing.T) {
+	keys := make([]string, 0, len(shared.KnownContainerConfigKeys))
+	for k := range shared.KnownContainerConfigKeys {
+		keys = append(keys, k)
+	}
+
+	randShorthand := func(buffer *bytes.Buffer) {
+		buffer.WriteByte(shorthand[rand.Intn(len(shorthand))])
+	}
+
+	randString := func(buffer *bytes.Buffer) {
+		l := rand.Intn(20)
+		if l == 0 {
+			l = rand.Intn(20) + 20
+		}
+		for i := 0; i < l; i++ {
+			buffer.WriteByte(alphanum[rand.Intn(len(alphanum))])
+		}
+	}
+
+	randConfigKey := func(buffer *bytes.Buffer) {
+		// Unconditionally prepend a comma so that we don't create an invalid
+		// column string, redundant commas will be handled immediately prior
+		// to parsing the string.
+		buffer.WriteRune(',')
+
+		switch rand.Intn(4) {
+		case 0:
+			buffer.WriteString(keys[rand.Intn(len(keys))])
+		case 1:
+			buffer.WriteString("user.")
+			randString(buffer)
+		case 2:
+			buffer.WriteString("environment.")
+			randString(buffer)
+		case 3:
+			if rand.Intn(2) == 0 {
+				buffer.WriteString("volatile.")
+				randString(buffer)
+				buffer.WriteString(".hwaddr")
+			} else {
+				buffer.WriteString("volatile.")
+				randString(buffer)
+				buffer.WriteString(".name")
+			}
+		}
+
+		// Randomize the optional fields in a single shot.  Empty names are legal
+		// when specifying the max width, append an extra colon in this case.
+		opt := rand.Intn(8)
+		if opt&1 != 0 {
+			buffer.WriteString(":")
+			randString(buffer)
+		} else if opt != 0 {
+			buffer.WriteString(":")
+		}
+
+		switch opt {
+		case 2, 3:
+			buffer.WriteString(":-1")
+		case 4, 5:
+			buffer.WriteString(":0")
+		case 6, 7:
+			buffer.WriteRune(':')
+			buffer.WriteString(strconv.FormatUint(uint64(rand.Uint32()), 10))
+		}
+
+		// Unconditionally append a comma so that we don't create an invalid
+		// column string, redundant commas will be handled immediately prior
+		// to parsing the string.
+		buffer.WriteRune(',')
+	}
+
+	for i := 0; i < 1000; i++ {
+		go func() {
+			var buffer bytes.Buffer
+
+			l := rand.Intn(10)
+			if l == 0 {
+				l = rand.Intn(10) + 10
+			}
+
+			num := l
+			for j := 0; j < l; j++ {
+				switch rand.Intn(5) {
+				case 0:
+					if buffer.Len() > 0 {
+						buffer.WriteRune(',')
+						num--
+					} else {
+						randShorthand(&buffer)
+					}
+
+				case 1, 2:
+					randShorthand(&buffer)
+				case 3, 4:
+					randConfigKey(&buffer)
+				}
+			}
+
+			// Generate the column string, removing any leading, trailing or duplicate commas.
+			raw := shared.RemoveDuplicatesFromString(strings.Trim(buffer.String(), ","), ",")
+
+			list := listCmd{columnsRaw: raw}
+
+			columns, err := list.parseColumns()
+			if err != nil {
+				t.Errorf("Failed to parse columns string.  Input: %s, Error: %s", raw, err)
+			}
+			if len(columns) != num {
+				t.Errorf("Did not generate correct number of columns.  Expected: %d, Actual: %d, Input: %s", num, len(columns), raw)
+			}
+		}()
+	}
+}
+
+func TestInvalidColumns(t *testing.T) {
+	run := func(raw string) {
+		list := listCmd{columnsRaw: raw}
+		_, err := list.parseColumns()
+		if err == nil {
+			t.Errorf("Expected error from parseColumns, received nil.  Input: %s", raw)
+		}
+	}
+
+	for _, v := range alphanum {
+		if !strings.ContainsRune(shorthand, v) {
+			run(string(v))
+		}
+	}
+
+	run(",")
+	run(",a")
+	run("a,")
+	run("4,,6")
+	run(".")
+	run(":")
+	run("::")
+	run(".key:")
+	run("user.key:")
+	run("user.key::")
+	run(":user.key")
+	run(":user.key:0")
+	run("user.key::-2")
+	run("user.key:name:-2")
+	run("volatile")
+	run("base_image")
+	run("volatile.image")
+}
diff --git a/lxd/container.go b/lxd/container.go
index df19988..dd1038c 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -4,7 +4,6 @@ import (
 	"fmt"
 	"io"
 	"os"
-	"strconv"
 	"strings"
 	"time"
 
@@ -37,84 +36,17 @@ func containerValidName(name string) error {
 }
 
 func containerValidConfigKey(d *Daemon, key string, value string) error {
-	isInt64 := func(key string, value string) error {
-		if value == "" {
-			return nil
-		}
-
-		_, err := strconv.ParseInt(value, 10, 64)
-		if err != nil {
-			return fmt.Errorf("Invalid value for an integer: %s", value)
-		}
-
-		return nil
+	f, err := shared.ConfigKeyChecker(key)
+	if err != nil {
+		return err
 	}
-
-	isBool := func(key string, value string) error {
-		if value == "" {
-			return nil
-		}
-
-		if !shared.StringInSlice(strings.ToLower(value), []string{"true", "false", "yes", "no", "1", "0", "on", "off"}) {
-			return fmt.Errorf("Invalid value for a boolean: %s", value)
-		}
-
-		return nil
+	if err = f(value); err != nil {
+		return err
 	}
-
-	isOneOf := func(key string, value string, valid []string) error {
-		if value == "" {
-			return nil
-		}
-
-		if !shared.StringInSlice(value, valid) {
-			return fmt.Errorf("Invalid value: %s (not one of %s)", value, valid)
-		}
-
-		return nil
+	if key == "raw.lxc" {
+		return lxcValidConfig(value)
 	}
-
-	switch key {
-	case "boot.autostart":
-		return isBool(key, value)
-	case "boot.autostart.delay":
-		return isInt64(key, value)
-	case "boot.autostart.priority":
-		return isInt64(key, value)
-	case "boot.host_shutdown_timeout":
-		return isInt64(key, value)
-	case "limits.cpu":
-		return nil
-	case "limits.cpu.allowance":
-		return nil
-	case "limits.cpu.priority":
-		return isInt64(key, value)
-	case "limits.disk.priority":
-		return isInt64(key, value)
-	case "limits.memory":
-		return nil
-	case "limits.memory.enforce":
-		return isOneOf(key, value, []string{"soft", "hard"})
-	case "limits.memory.swap":
-		return isBool(key, value)
-	case "limits.memory.swap.priority":
-		return isInt64(key, value)
-	case "limits.network.priority":
-		return isInt64(key, value)
-	case "limits.processes":
-		return isInt64(key, value)
-	case "linux.kernel_modules":
-		return nil
-	case "security.privileged":
-		return isBool(key, value)
-	case "security.nesting":
-		return isBool(key, value)
-	case "security.syscalls.blacklist_default":
-		return isBool(key, value)
-	case "security.syscalls.blacklist_compat":
-		if err := isBool(key, value); err != nil {
-			return err
-		}
+	if key == "security.syscalls.blacklist_compat" {
 		for _, arch := range d.architectures {
 			if arch == shared.ARCH_64BIT_INTEL_X86 ||
 				arch == shared.ARCH_64BIT_ARMV8_LITTLE_ENDIAN ||
@@ -123,45 +55,8 @@ func containerValidConfigKey(d *Daemon, key string, value string) error {
 			}
 		}
 		return fmt.Errorf("security.syscalls.blacklist_compat is only valid on x86_64")
-	case "security.syscalls.blacklist":
-		return nil
-	case "security.syscalls.whitelist":
-		return nil
-	case "raw.apparmor":
-		return nil
-	case "raw.lxc":
-		return lxcValidConfig(value)
-	case "raw.seccomp":
-		return nil
-	case "volatile.apply_template":
-		return nil
-	case "volatile.base_image":
-		return nil
-	case "volatile.last_state.idmap":
-		return nil
-	case "volatile.last_state.power":
-		return nil
-	}
-
-	if strings.HasPrefix(key, "volatile.") {
-		if strings.HasSuffix(key, ".hwaddr") {
-			return nil
-		}
-
-		if strings.HasSuffix(key, ".name") {
-			return nil
-		}
-	}
-
-	if strings.HasPrefix(key, "environment.") {
-		return nil
-	}
-
-	if strings.HasPrefix(key, "user.") {
-		return nil
 	}
-
-	return fmt.Errorf("Bad key: %s", key)
+	return nil
 }
 
 func containerValidDeviceConfigKey(t, k string) bool {
diff --git a/po/de.po b/po/de.po
index 81b8e11..40ab65f 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: 2016-04-25 14:47-0500\n"
+"POT-Creation-Date: 2016-06-24 08:22-0700\n"
 "PO-Revision-Date: 2015-06-13 06:10+0200\n"
 "Last-Translator: Felix Engelmann <felix-lxd at nlogn.org>\n"
 "Language-Team: \n"
@@ -67,7 +67,7 @@ msgstr ""
 "###\n"
 "### Der Name wird zwar angezeigt, lässt sich jedoch nicht ändern.\n"
 
-#: lxc/image.go:83
+#: lxc/image.go:85
 #, fuzzy
 msgid ""
 "### This is a yaml representation of the image properties.\n"
@@ -123,7 +123,7 @@ msgstr ""
 "###\n"
 "### Der Name wird zwar angezeigt, lässt sich jedoch nicht ändern.\n"
 
-#: lxc/image.go:583
+#: lxc/image.go:603
 #, c-format
 msgid "%s (%d more)"
 msgstr ""
@@ -133,19 +133,19 @@ msgstr ""
 msgid "'/' not allowed in snapshot name"
 msgstr "'/' ist kein gültiges Zeichen im Namen eines Sicherungspunktes\n"
 
-#: lxc/profile.go:251
+#: lxc/profile.go:253
 msgid "(none)"
 msgstr ""
 
-#: lxc/image.go:604 lxc/image.go:633
+#: lxc/image.go:624 lxc/image.go:666
 msgid "ALIAS"
 msgstr ""
 
-#: lxc/image.go:608
+#: lxc/image.go:628
 msgid "ARCH"
 msgstr ""
 
-#: lxc/list.go:378
+#: lxc/list.go:409
 msgid "ARCHITECTURE"
 msgstr ""
 
@@ -153,12 +153,12 @@ msgstr ""
 msgid "Accept certificate"
 msgstr "Akzeptiere Zertifikat"
 
-#: lxc/remote.go:256
+#: lxc/remote.go:269
 #, c-format
 msgid "Admin password for %s: "
 msgstr "Administrator Passwort für %s: "
 
-#: lxc/image.go:347
+#: lxc/image.go:356
 #, fuzzy
 msgid "Aliases:"
 msgstr "Aliasse:\n"
@@ -167,12 +167,12 @@ msgstr "Aliasse:\n"
 msgid "An environment variable of the form HOME=/home/foo"
 msgstr ""
 
-#: lxc/image.go:330 lxc/info.go:90
+#: lxc/image.go:339 lxc/info.go:90
 #, fuzzy, c-format
 msgid "Architecture: %s"
 msgstr "Architektur: %s\n"
 
-#: lxc/image.go:351
+#: lxc/image.go:360
 #, c-format
 msgid "Auto update: %s"
 msgstr ""
@@ -189,11 +189,11 @@ msgstr ""
 msgid "Bytes sent"
 msgstr ""
 
-#: lxc/config.go:270
+#: lxc/config.go:274
 msgid "COMMON NAME"
 msgstr ""
 
-#: lxc/list.go:379
+#: lxc/list.go:410
 msgid "CREATED AT"
 msgstr ""
 
@@ -207,11 +207,11 @@ msgstr ""
 msgid "Can't unset key '%s', it's not currently set."
 msgstr ""
 
-#: lxc/profile.go:417
+#: lxc/profile.go:419
 msgid "Cannot provide container name to list"
 msgstr ""
 
-#: lxc/remote.go:206
+#: lxc/remote.go:219
 #, fuzzy, c-format
 msgid "Certificate fingerprint: %x"
 msgstr "Fingerabdruck des Zertifikats: % x\n"
@@ -227,11 +227,11 @@ msgstr ""
 "\n"
 "lxd %s <Name>\n"
 
-#: lxc/remote.go:279
+#: lxc/remote.go:292
 msgid "Client certificate stored at server: "
 msgstr "Gespeichertes Nutzerzertifikat auf dem Server: "
 
-#: lxc/list.go:99 lxc/list.go:100
+#: lxc/list.go:121 lxc/list.go:122
 msgid "Columns"
 msgstr ""
 
@@ -240,12 +240,12 @@ msgstr ""
 msgid "Config key/value to apply to the new container"
 msgstr "kann nicht zum selben Container Namen kopieren"
 
-#: lxc/config.go:500 lxc/config.go:565 lxc/image.go:687 lxc/profile.go:215
+#: lxc/config.go:531 lxc/config.go:596 lxc/image.go:720 lxc/profile.go:217
 #, fuzzy, c-format
 msgid "Config parsing error: %s"
 msgstr "YAML Analyse Fehler %v\n"
 
-#: lxc/main.go:37
+#: lxc/main.go:29
 msgid "Connection refused; is LXD running?"
 msgstr ""
 
@@ -263,7 +263,7 @@ msgstr ""
 msgid "Container published with fingerprint: %s"
 msgstr "Abbild mit Fingerabdruck %s importiert\n"
 
-#: lxc/image.go:155
+#: lxc/image.go:157
 msgid "Copy aliases from source"
 msgstr "Kopiere Aliasse von der Quelle"
 
@@ -279,12 +279,12 @@ msgstr ""
 "\n"
 "lxc copy <Quelle> <Ziel>\n"
 
-#: lxc/image.go:268
+#: lxc/image.go:271
 #, c-format
 msgid "Copying the image: %s"
 msgstr ""
 
-#: lxc/remote.go:221
+#: lxc/remote.go:234
 msgid "Could not create server cert dir"
 msgstr "Kann Verzeichnis für Zertifikate auf dem Server nicht erstellen"
 
@@ -308,7 +308,7 @@ msgid ""
 "lxc snapshot u1 snap0"
 msgstr ""
 
-#: lxc/image.go:335 lxc/info.go:92
+#: lxc/image.go:344 lxc/info.go:92
 #, c-format
 msgid "Created: %s"
 msgstr ""
@@ -323,7 +323,7 @@ msgstr ""
 msgid "Creating the container"
 msgstr "kann nicht zum selben Container Namen kopieren"
 
-#: lxc/image.go:607 lxc/image.go:635
+#: lxc/image.go:627 lxc/image.go:668
 msgid "DESCRIPTION"
 msgstr ""
 
@@ -343,29 +343,29 @@ msgstr ""
 "Entfernt einen Container (oder Sicherungspunkt) und alle dazugehörigen\n"
 "Daten (Konfiguration, Sicherungspunkte, ...).\n"
 
-#: lxc/config.go:617
+#: lxc/config.go:648
 #, fuzzy, c-format
 msgid "Device %s added to %s"
 msgstr "Gerät %s wurde zu %s hinzugefügt\n"
 
-#: lxc/config.go:804
+#: lxc/config.go:835
 #, fuzzy, c-format
 msgid "Device %s removed from %s"
 msgstr "Gerät %s wurde von %s entfernt\n"
 
-#: lxc/list.go:462
+#: lxc/list.go:554
 msgid "EPHEMERAL"
 msgstr ""
 
-#: lxc/config.go:272
+#: lxc/config.go:276
 msgid "EXPIRY DATE"
 msgstr ""
 
-#: lxc/main.go:55
+#: lxc/main.go:41
 msgid "Enables debug mode."
 msgstr "Aktiviert Debug Modus"
 
-#: lxc/main.go:54
+#: lxc/main.go:40
 msgid "Enables verbose mode."
 msgstr "Aktiviert ausführliche Ausgabe"
 
@@ -397,24 +397,24 @@ msgstr ""
 "\n"
 "lxc exec <Container> [--env EDITOR=/usr/bin/vim]... <Befehl>\n"
 
-#: lxc/image.go:339
+#: lxc/image.go:348
 #, c-format
 msgid "Expires: %s"
 msgstr ""
 
-#: lxc/image.go:341
+#: lxc/image.go:350
 msgid "Expires: never"
 msgstr ""
 
-#: lxc/config.go:269 lxc/image.go:605 lxc/image.go:634
+#: lxc/config.go:273 lxc/image.go:625 lxc/image.go:667
 msgid "FINGERPRINT"
 msgstr ""
 
-#: lxc/list.go:102
+#: lxc/list.go:124
 msgid "Fast mode (same as --columns=nsacPt"
 msgstr ""
 
-#: lxc/image.go:328
+#: lxc/image.go:337
 #, fuzzy, c-format
 msgid "Fingerprint: %s"
 msgstr "Fingerabdruck: %s\n"
@@ -430,7 +430,7 @@ msgstr ""
 "\n"
 "lxc finger <remote>\n"
 
-#: lxc/action.go:37
+#: lxc/action.go:37 lxc/action.go:38
 msgid "Force the container to shutdown."
 msgstr "Herunterfahren des Containers erzwingen."
 
@@ -438,50 +438,50 @@ msgstr "Herunterfahren des Containers erzwingen."
 msgid "Force the removal of stopped containers."
 msgstr ""
 
-#: lxc/main.go:56
+#: lxc/main.go:42
 msgid "Force using the local unix socket."
 msgstr ""
 
-#: lxc/list.go:101
+#: lxc/image.go:160 lxc/list.go:123
 msgid "Format"
 msgstr ""
 
-#: lxc/main.go:138
+#: lxc/remote.go:67
 #, fuzzy
 msgid "Generating a client certificate. This may take a minute..."
 msgstr "Generiere Nutzerzertifikat. Dies kann wenige Minuten dauern...\n"
 
-#: lxc/list.go:376
+#: lxc/list.go:407
 msgid "IPV4"
 msgstr ""
 
-#: lxc/list.go:377
+#: lxc/list.go:408
 msgid "IPV6"
 msgstr ""
 
-#: lxc/config.go:271
+#: lxc/config.go:275
 msgid "ISSUE DATE"
 msgstr ""
 
-#: lxc/main.go:146
+#: lxc/main.go:132
 msgid ""
 "If this is your first time using LXD, you should also run: sudo lxd init"
 msgstr ""
 
-#: lxc/main.go:57
+#: lxc/main.go:43
 msgid "Ignore aliases when determining what command to run."
 msgstr ""
 
-#: lxc/action.go:40
+#: lxc/action.go:41
 #, fuzzy
 msgid "Ignore the container state (only for start)."
 msgstr "Herunterfahren des Containers erzwingen."
 
-#: lxc/image.go:273
+#: lxc/image.go:276
 msgid "Image copied successfully!"
 msgstr ""
 
-#: lxc/image.go:419
+#: lxc/image.go:428
 #, fuzzy, c-format
 msgid "Image imported with fingerprint: %s"
 msgstr "Abbild mit Fingerabdruck %s importiert\n"
@@ -514,16 +514,21 @@ msgstr ""
 "Beispiel:\n"
 "lxc launch ubuntu u1\n"
 
-#: lxc/remote.go:122
+#: lxc/remote.go:137
 #, c-format
 msgid "Invalid URL scheme \"%s\" in \"%s\""
 msgstr ""
 
+#: lxc/config.go:254
+#, fuzzy
+msgid "Invalid certificate"
+msgstr "Akzeptiere Zertifikat"
+
 #: lxc/init.go:30 lxc/init.go:35
 msgid "Invalid configuration key"
 msgstr ""
 
-#: lxc/file.go:190
+#: lxc/file.go:195
 #, c-format
 msgid "Invalid source %s"
 msgstr "Ungültige Quelle %s"
@@ -537,11 +542,15 @@ msgstr "Ungültiges Ziel %s"
 msgid "Ips:"
 msgstr ""
 
-#: lxc/image.go:156
+#: lxc/image.go:158
 msgid "Keep the image up to date after initial copy"
 msgstr ""
 
-#: lxc/main.go:35
+#: lxc/list.go:411
+msgid "LAST USED AT"
+msgstr ""
+
+#: lxc/main.go:27
 msgid "LXD socket not found; is LXD installed and running?"
 msgstr ""
 
@@ -591,7 +600,7 @@ msgstr ""
 "\n"
 "lxc info [<remote>:]Container [--show-log]\n"
 
-#: lxc/list.go:67
+#: lxc/list.go:68
 #, fuzzy
 msgid ""
 "Lists the available resources.\n"
@@ -612,11 +621,18 @@ msgid ""
 "* A regular expression matching a configuration item or its value. (e.g. "
 "volatile.eth0.hwaddr=00:16:3e:.*)\n"
 "\n"
-"Columns for table format are:\n"
+"The -c option takes a comma separated list of arguments that control\n"
+"which container attributes to output when displaying in table format.\n"
+"Column arguments are either pre-defined shorthand chars (see below),\n"
+"or (extended) config keys.  Commas between consecutive shorthand chars\n"
+"are optional.\n"
+"\n"
+"Pre-defined shorthand chars:\n"
 "* 4 - IPv4 address\n"
 "* 6 - IPv6 address\n"
 "* a - architecture\n"
 "* c - creation date\n"
+"* l - last used date\n"
 "* n - name\n"
 "* p - pid of container init process\n"
 "* P - profiles\n"
@@ -624,8 +640,22 @@ msgid ""
 "* S - number of snapshots\n"
 "* t - type (persistent or ephemeral)\n"
 "\n"
+"Config key syntax: key[:name][:maxWidth]\n"
+"* key      - The (extended) config key to display\n"
+"* name     - Name to display in the column header, defaults to the key\n"
+"             if not specified or if empty (to allow defining maxWidth\n"
+"             without a custom name, e.g. user.key::0)\n"
+"* maxWidth - Max width of the column (longer results are truncated).\n"
+"             -1 == unlimited\n"
+"              0 == width of column header\n"
+"             >0 == max width in chars\n"
+"             Default is -1 (unlimited)\n"
+"\n"
 "Default column layout: ns46tS\n"
-"Fast column layout: nsacPt"
+"Fast column layout: nsacPt\n"
+"\n"
+"Example: lxc list -c n,volatile.base_image:\"BASE IMAGE\":0,s46,volatile."
+"eth0.hwaddr:MAC\n"
 msgstr ""
 "Listet vorhandene Ressourcen.\n"
 "\n"
@@ -646,7 +676,7 @@ msgstr ""
 msgid "Log:"
 msgstr ""
 
-#: lxc/image.go:154
+#: lxc/image.go:156
 msgid "Make image public"
 msgstr "Veröffentliche Abbild"
 
@@ -674,16 +704,21 @@ msgid ""
 "             cat profile.yml | lxc profile edit <profile> # read from "
 "profile.yml\n"
 "\n"
-"lxc profile apply <container> <profiles>\n"
-"    Apply a comma-separated list of profiles to a container, in order.\n"
+"lxc profile assign <container> <profiles>\n"
+"    Assign a comma-separated list of profiles to a container, in order.\n"
 "    All profiles passed in this call (and only those) will be applied\n"
-"    to the specified container.\n"
-"    Example: lxc profile apply foo default,bar # Apply default and bar\n"
-"             lxc profile apply foo default # Only default is active\n"
-"             lxc profile apply '' # no profiles are applied anymore\n"
-"             lxc profile apply bar,default # Apply default second now\n"
-"lxc profile apply-add <container> <profile>\n"
-"lxc profile apply-remove <container> <profile>\n"
+"    to the specified container, i.e. it sets the list of profiles exactly "
+"to\n"
+"    those specified in this command. To add/remove a particular profile from "
+"a\n"
+"    container, use {add|remove} below.\n"
+"    Example: lxc profile assign foo default,bar # Apply default and bar\n"
+"             lxc profile assign foo default # Only default is active\n"
+"             lxc profile assign '' # no profiles are applied anymore\n"
+"             lxc profile assign bar,default # Apply default second now\n"
+"lxc profile add <container> <profile> # add a profile to a container\n"
+"lxc profile remove <container> <profile> # remove the profile from a "
+"container\n"
 "\n"
 "Devices:\n"
 "lxc profile device list <profile>                                   List "
@@ -889,7 +924,7 @@ msgstr ""
 "lxc remote get-default                                                    "
 "Gibt die Standard Instanz aus.\n"
 
-#: lxc/image.go:93
+#: lxc/image.go:95
 msgid ""
 "Manipulate container images.\n"
 "\n"
@@ -920,8 +955,8 @@ msgid ""
 "    The auto-update flag instructs the server to keep this image up to\n"
 "    date. It requires the source to be an alias and for it to be public.\n"
 "\n"
-"lxc image delete [remote:]<image>\n"
-"    Delete an image from the LXD image store.\n"
+"lxc image delete [remote:]<image> [remote:][<image>...]\n"
+"    Delete one or more images from the LXD image store.\n"
 "\n"
 "lxc image export [remote:]<image>\n"
 "    Export an image from the LXD image store into a distributable tarball.\n"
@@ -929,7 +964,7 @@ msgid ""
 "lxc image info [remote:]<image>\n"
 "    Print everything LXD knows about a given image.\n"
 "\n"
-"lxc image list [remote:] [filter]\n"
+"lxc image list [remote:] [filter] [--format table|json]\n"
 "    List images in the LXD image store. Filters may be of the\n"
 "    <key>=<value> form for property based filtering, or part of the image\n"
 "    hash or part of the image alias name.\n"
@@ -980,7 +1015,7 @@ msgid ""
 "lxc monitor --type=logging"
 msgstr ""
 
-#: lxc/file.go:178
+#: lxc/file.go:183
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 "Mehr als eine Datei herunterzuladen, aber das Ziel ist kein Verzeichnis"
@@ -1001,16 +1036,16 @@ msgstr ""
 "\n"
 "lxc move <Quelle> <Ziel>\n"
 
-#: lxc/action.go:63
+#: lxc/action.go:64
 #, fuzzy
 msgid "Must supply container name for: "
 msgstr "der Name des Ursprung Containers muss angegeben werden"
 
-#: lxc/list.go:380 lxc/remote.go:363
+#: lxc/list.go:412 lxc/remote.go:376
 msgid "NAME"
 msgstr ""
 
-#: lxc/remote.go:337 lxc/remote.go:342
+#: lxc/remote.go:350 lxc/remote.go:355
 msgid "NO"
 msgstr ""
 
@@ -1019,32 +1054,32 @@ msgstr ""
 msgid "Name: %s"
 msgstr ""
 
-#: lxc/image.go:157 lxc/publish.go:33
+#: lxc/image.go:159 lxc/publish.go:33
 msgid "New alias to define at target"
 msgstr ""
 
-#: lxc/config.go:281
+#: lxc/config.go:285
 #, fuzzy
 msgid "No certificate provided to add"
 msgstr "Kein Zertifikat zum hinzufügen bereitgestellt"
 
-#: lxc/config.go:304
+#: lxc/config.go:308
 msgid "No fingerprint specified."
 msgstr "Kein Fingerabdruck angegeben."
 
-#: lxc/remote.go:107
+#: lxc/remote.go:122
 msgid "Only https URLs are supported for simplestreams"
 msgstr ""
 
-#: lxc/image.go:411
+#: lxc/image.go:420
 msgid "Only https:// is supported for remote image import."
 msgstr ""
 
-#: lxc/help.go:63 lxc/main.go:122
+#: lxc/help.go:63 lxc/main.go:108
 msgid "Options:"
 msgstr ""
 
-#: lxc/image.go:506
+#: lxc/image.go:524
 #, c-format
 msgid "Output is in %s"
 msgstr ""
@@ -1053,23 +1088,23 @@ msgstr ""
 msgid "Override the terminal mode (auto, interactive or non-interactive)"
 msgstr ""
 
-#: lxc/list.go:464
+#: lxc/list.go:556
 msgid "PERSISTENT"
 msgstr ""
 
-#: lxc/list.go:381
+#: lxc/list.go:413
 msgid "PID"
 msgstr ""
 
-#: lxc/list.go:382
+#: lxc/list.go:414
 msgid "PROFILES"
 msgstr ""
 
-#: lxc/remote.go:365
+#: lxc/remote.go:378
 msgid "PROTOCOL"
 msgstr ""
 
-#: lxc/image.go:606 lxc/remote.go:366
+#: lxc/image.go:626 lxc/remote.go:379
 msgid "PUBLIC"
 msgstr ""
 
@@ -1091,7 +1126,7 @@ msgstr "Alternatives config Verzeichnis."
 msgid "Path to an alternate server directory."
 msgstr "Alternatives config Verzeichnis."
 
-#: lxc/main.go:39
+#: lxc/main.go:31
 msgid "Permisson denied, are you in the lxd group?"
 msgstr ""
 
@@ -1111,11 +1146,11 @@ msgstr ""
 "\n"
 "lxd help [—all]\n"
 
-#: lxc/profile.go:216
+#: lxc/profile.go:218
 msgid "Press enter to open the editor again"
 msgstr ""
 
-#: lxc/config.go:501 lxc/config.go:566 lxc/image.go:688
+#: lxc/config.go:532 lxc/config.go:597 lxc/image.go:721
 msgid "Press enter to start the editor again"
 msgstr ""
 
@@ -1147,22 +1182,22 @@ msgstr ""
 msgid "Processes: %d"
 msgstr "Profil %s erstellt\n"
 
-#: lxc/profile.go:272
+#: lxc/profile.go:274
 #, fuzzy, c-format
 msgid "Profile %s added to %s"
 msgstr "Profil %s wurde auf %s angewandt\n"
 
-#: lxc/profile.go:167
+#: lxc/profile.go:169
 #, fuzzy, c-format
 msgid "Profile %s created"
 msgstr "Profil %s erstellt\n"
 
-#: lxc/profile.go:237
+#: lxc/profile.go:239
 #, fuzzy, c-format
 msgid "Profile %s deleted"
 msgstr "Profil %s gelöscht\n"
 
-#: lxc/profile.go:303
+#: lxc/profile.go:305
 #, fuzzy, c-format
 msgid "Profile %s removed from %s"
 msgstr "Gerät %s wurde von %s entfernt\n"
@@ -1172,7 +1207,7 @@ msgstr "Gerät %s wurde von %s entfernt\n"
 msgid "Profile to apply to the new container"
 msgstr "kann nicht zum selben Container Namen kopieren"
 
-#: lxc/profile.go:253
+#: lxc/profile.go:255
 #, fuzzy, c-format
 msgid "Profiles %s applied to %s"
 msgstr "Profil %s wurde auf %s angewandt\n"
@@ -1182,7 +1217,7 @@ msgstr "Profil %s wurde auf %s angewandt\n"
 msgid "Profiles: %s"
 msgstr "Profil %s erstellt\n"
 
-#: lxc/image.go:343
+#: lxc/image.go:352
 #, fuzzy
 msgid "Properties:"
 msgstr "Eigenschaften:\n"
@@ -1191,7 +1226,7 @@ msgstr "Eigenschaften:\n"
 msgid "Public image server"
 msgstr ""
 
-#: lxc/image.go:331
+#: lxc/image.go:340
 #, fuzzy, c-format
 msgid "Public: %s"
 msgstr "Öffentlich: %s\n"
@@ -1226,27 +1261,27 @@ msgstr ""
 msgid "Retrieving image: %s"
 msgstr ""
 
-#: lxc/image.go:609
+#: lxc/image.go:629
 msgid "SIZE"
 msgstr ""
 
-#: lxc/list.go:383
+#: lxc/list.go:415
 msgid "SNAPSHOTS"
 msgstr ""
 
-#: lxc/list.go:384
+#: lxc/list.go:416
 msgid "STATE"
 msgstr ""
 
-#: lxc/remote.go:367
+#: lxc/remote.go:380
 msgid "STATIC"
 msgstr ""
 
-#: lxc/remote.go:214
+#: lxc/remote.go:227
 msgid "Server certificate NACKed by user"
 msgstr "Server Zertifikat vom Benutzer nicht akzeptiert"
 
-#: lxc/remote.go:276
+#: lxc/remote.go:289
 msgid "Server doesn't trust us after adding our cert"
 msgstr ""
 "Der Server vertraut uns nicht nachdem er unser Zertifikat hinzugefügt hat"
@@ -1289,7 +1324,7 @@ msgstr "Zeigt alle Befehle (nicht nur die interessanten)"
 msgid "Show the container's last 100 log lines?"
 msgstr "Zeige die letzten 100 Zeilen Protokoll des Containers?"
 
-#: lxc/image.go:329
+#: lxc/image.go:338
 #, fuzzy, c-format
 msgid "Size: %.2fMB"
 msgstr "Größe: %.2vMB\n"
@@ -1298,7 +1333,7 @@ msgstr "Größe: %.2vMB\n"
 msgid "Snapshots:"
 msgstr ""
 
-#: lxc/image.go:353
+#: lxc/image.go:362
 msgid "Source:"
 msgstr ""
 
@@ -1320,7 +1355,7 @@ msgstr ""
 msgid "Stopping container failed!"
 msgstr "Anhalten des Containers fehlgeschlagen!"
 
-#: lxc/action.go:39
+#: lxc/action.go:40
 #, fuzzy
 msgid "Store the container state (only for stop)."
 msgstr "Herunterfahren des Containers erzwingen."
@@ -1333,7 +1368,7 @@ msgstr ""
 msgid "Swap (peak)"
 msgstr ""
 
-#: lxc/list.go:385
+#: lxc/list.go:417
 msgid "TYPE"
 msgstr ""
 
@@ -1347,8 +1382,8 @@ msgid ""
 "restarted."
 msgstr ""
 
-#: lxc/config.go:645 lxc/config.go:657 lxc/config.go:690 lxc/config.go:708
-#: lxc/config.go:746 lxc/config.go:764
+#: lxc/config.go:676 lxc/config.go:688 lxc/config.go:721 lxc/config.go:739
+#: lxc/config.go:777 lxc/config.go:795
 #, fuzzy
 msgid "The device doesn't exist"
 msgstr "entfernte Instanz %s existiert nicht"
@@ -1366,21 +1401,21 @@ msgstr ""
 msgid "Time to wait for the container before killing it."
 msgstr "Wartezeit bevor der Container gestoppt wird."
 
-#: lxc/image.go:332
+#: lxc/image.go:341
 #, fuzzy
 msgid "Timestamps:"
 msgstr "Zeitstempel:\n"
 
-#: lxc/main.go:147
+#: lxc/main.go:133
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/image.go:402
+#: lxc/image.go:411
 #, c-format
 msgid "Transferring image: %d%%"
 msgstr ""
 
-#: lxc/action.go:93 lxc/launch.go:132
+#: lxc/action.go:94 lxc/launch.go:132
 #, c-format
 msgid "Try `lxc info --show-log %s` for more info"
 msgstr ""
@@ -1393,24 +1428,24 @@ msgstr ""
 msgid "Type: persistent"
 msgstr ""
 
-#: lxc/image.go:610
+#: lxc/image.go:630
 msgid "UPLOAD DATE"
 msgstr ""
 
-#: lxc/remote.go:364
+#: lxc/remote.go:377
 msgid "URL"
 msgstr ""
 
-#: lxc/remote.go:82
+#: lxc/remote.go:97
 msgid "Unable to read remote TLS certificate"
 msgstr ""
 
-#: lxc/image.go:337
+#: lxc/image.go:346
 #, c-format
 msgid "Uploaded: %s"
 msgstr ""
 
-#: lxc/main.go:122
+#: lxc/main.go:108
 #, fuzzy, c-format
 msgid "Usage: %s"
 msgstr ""
@@ -1446,11 +1481,11 @@ msgstr "Zustand des laufenden Containers sichern oder nicht"
 msgid "Whether to show the expanded configuration"
 msgstr ""
 
-#: lxc/remote.go:339 lxc/remote.go:344
+#: lxc/remote.go:352 lxc/remote.go:357
 msgid "YES"
 msgstr ""
 
-#: lxc/main.go:66
+#: lxc/main.go:52
 msgid "`lxc config profile` is deprecated, please use `lxc profile`"
 msgstr ""
 
@@ -1459,19 +1494,19 @@ msgid "bad number of things scanned from image, container or snapshot"
 msgstr ""
 "Falsche Anzahl an Objekten im Abbild, Container oder Sicherungspunkt gelesen."
 
-#: lxc/action.go:89
+#: lxc/action.go:90
 msgid "bad result type from action"
 msgstr ""
 
-#: lxc/copy.go:78
+#: lxc/copy.go:99
 msgid "can't copy to the same container name"
 msgstr "kann nicht zum selben Container Namen kopieren"
 
-#: lxc/remote.go:327
+#: lxc/remote.go:340
 msgid "can't remove the default remote"
 msgstr ""
 
-#: lxc/remote.go:353
+#: lxc/remote.go:366
 msgid "default"
 msgstr ""
 
@@ -1479,20 +1514,20 @@ msgstr ""
 msgid "didn't get any affected image, container or snapshot from server"
 msgstr ""
 
-#: lxc/image.go:323
+#: lxc/image.go:332
 msgid "disabled"
 msgstr ""
 
-#: lxc/image.go:325
+#: lxc/image.go:334
 msgid "enabled"
 msgstr ""
 
-#: lxc/main.go:25 lxc/main.go:159
+#: lxc/main.go:22 lxc/main.go:144
 #, fuzzy, c-format
 msgid "error: %v"
 msgstr "Fehler: %v\n"
 
-#: lxc/help.go:40 lxc/main.go:117
+#: lxc/help.go:40 lxc/main.go:103
 #, fuzzy, c-format
 msgid "error: unknown command: %s"
 msgstr "Fehler: unbekannter Befehl: %s\n"
@@ -1501,40 +1536,40 @@ msgstr "Fehler: unbekannter Befehl: %s\n"
 msgid "got bad version"
 msgstr "Versionskonflikt"
 
-#: lxc/image.go:318 lxc/image.go:586
+#: lxc/image.go:327 lxc/image.go:606
 msgid "no"
 msgstr ""
 
-#: lxc/copy.go:101
+#: lxc/copy.go:122
 msgid "not all the profiles from the source exist on the target"
 msgstr "nicht alle Profile der Quelle sind am Ziel vorhanden."
 
-#: lxc/remote.go:207
+#: lxc/remote.go:220
 #, fuzzy
 msgid "ok (y/n)?"
 msgstr "OK (y/n)? "
 
-#: lxc/main.go:266 lxc/main.go:270
+#: lxc/main.go:277 lxc/main.go:281
 #, c-format
 msgid "processing aliases failed %s\n"
 msgstr ""
 
-#: lxc/remote.go:389
+#: lxc/remote.go:402
 #, c-format
 msgid "remote %s already exists"
 msgstr "entfernte Instanz %s existiert bereits"
 
-#: lxc/remote.go:319 lxc/remote.go:381 lxc/remote.go:416 lxc/remote.go:432
+#: lxc/remote.go:332 lxc/remote.go:394 lxc/remote.go:429 lxc/remote.go:445
 #, c-format
 msgid "remote %s doesn't exist"
 msgstr "entfernte Instanz %s existiert nicht"
 
-#: lxc/remote.go:302
+#: lxc/remote.go:315
 #, c-format
 msgid "remote %s exists as <%s>"
 msgstr "entfernte Instanz %s existiert als <%s>"
 
-#: lxc/remote.go:323 lxc/remote.go:385 lxc/remote.go:420
+#: lxc/remote.go:336 lxc/remote.go:398 lxc/remote.go:433
 #, c-format
 msgid "remote %s is static and cannot be modified"
 msgstr ""
@@ -1556,11 +1591,11 @@ msgstr ""
 msgid "unreachable return reached"
 msgstr ""
 
-#: lxc/main.go:199
+#: lxc/main.go:209
 msgid "wrong number of subcommand arguments"
 msgstr "falsche Anzahl an Parametern für Unterbefehl"
 
-#: lxc/delete.go:45 lxc/image.go:320 lxc/image.go:590
+#: lxc/delete.go:45 lxc/image.go:329 lxc/image.go:610
 msgid "yes"
 msgstr ""
 
diff --git a/po/fr.po b/po/fr.po
index 90f536b..6d5e56e 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: 2016-04-25 14:47-0500\n"
+"POT-Creation-Date: 2016-06-24 08:22-0700\n"
 "PO-Revision-Date: 2015-02-26 02:05-0600\n"
 "Last-Translator: Stéphane Graber <stgraber at ubuntu.com\n"
 "Language-Team: French <fr at li.org>\n"
@@ -49,7 +49,7 @@ msgid ""
 "### Note that the name is shown but cannot be changed"
 msgstr ""
 
-#: lxc/image.go:83
+#: lxc/image.go:85
 msgid ""
 "### This is a yaml representation of the image properties.\n"
 "### Any line starting with a '# will be ignored.\n"
@@ -80,7 +80,7 @@ msgid ""
 "### Note that the name is shown but cannot be changed"
 msgstr ""
 
-#: lxc/image.go:583
+#: lxc/image.go:603
 #, c-format
 msgid "%s (%d more)"
 msgstr ""
@@ -90,19 +90,19 @@ msgstr ""
 msgid "'/' not allowed in snapshot name"
 msgstr "'/' n'est pas autorisé dans le nom d'un instantané (snapshot)\n"
 
-#: lxc/profile.go:251
+#: lxc/profile.go:253
 msgid "(none)"
 msgstr ""
 
-#: lxc/image.go:604 lxc/image.go:633
+#: lxc/image.go:624 lxc/image.go:666
 msgid "ALIAS"
 msgstr ""
 
-#: lxc/image.go:608
+#: lxc/image.go:628
 msgid "ARCH"
 msgstr ""
 
-#: lxc/list.go:378
+#: lxc/list.go:409
 msgid "ARCHITECTURE"
 msgstr ""
 
@@ -110,12 +110,12 @@ msgstr ""
 msgid "Accept certificate"
 msgstr ""
 
-#: lxc/remote.go:256
+#: lxc/remote.go:269
 #, c-format
 msgid "Admin password for %s: "
 msgstr "Mot de passe administrateur pour %s: "
 
-#: lxc/image.go:347
+#: lxc/image.go:356
 msgid "Aliases:"
 msgstr ""
 
@@ -123,12 +123,12 @@ msgstr ""
 msgid "An environment variable of the form HOME=/home/foo"
 msgstr ""
 
-#: lxc/image.go:330 lxc/info.go:90
+#: lxc/image.go:339 lxc/info.go:90
 #, c-format
 msgid "Architecture: %s"
 msgstr ""
 
-#: lxc/image.go:351
+#: lxc/image.go:360
 #, c-format
 msgid "Auto update: %s"
 msgstr ""
@@ -145,11 +145,11 @@ msgstr ""
 msgid "Bytes sent"
 msgstr ""
 
-#: lxc/config.go:270
+#: lxc/config.go:274
 msgid "COMMON NAME"
 msgstr ""
 
-#: lxc/list.go:379
+#: lxc/list.go:410
 msgid "CREATED AT"
 msgstr ""
 
@@ -163,11 +163,11 @@ msgstr ""
 msgid "Can't unset key '%s', it's not currently set."
 msgstr ""
 
-#: lxc/profile.go:417
+#: lxc/profile.go:419
 msgid "Cannot provide container name to list"
 msgstr ""
 
-#: lxc/remote.go:206
+#: lxc/remote.go:219
 #, fuzzy, c-format
 msgid "Certificate fingerprint: %x"
 msgstr "Empreinte du certificat: % x\n"
@@ -180,11 +180,11 @@ msgid ""
 "lxc %s <name> [<name>...]"
 msgstr "Change l'état du conteneur à %s.\n"
 
-#: lxc/remote.go:279
+#: lxc/remote.go:292
 msgid "Client certificate stored at server: "
 msgstr "Certificat client enregistré avec le serveur: "
 
-#: lxc/list.go:99 lxc/list.go:100
+#: lxc/list.go:121 lxc/list.go:122
 msgid "Columns"
 msgstr ""
 
@@ -192,12 +192,12 @@ msgstr ""
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
-#: lxc/config.go:500 lxc/config.go:565 lxc/image.go:687 lxc/profile.go:215
+#: lxc/config.go:531 lxc/config.go:596 lxc/image.go:720 lxc/profile.go:217
 #, fuzzy, c-format
 msgid "Config parsing error: %s"
 msgstr "erreur: %v\n"
 
-#: lxc/main.go:37
+#: lxc/main.go:29
 msgid "Connection refused; is LXD running?"
 msgstr ""
 
@@ -215,7 +215,7 @@ msgstr ""
 msgid "Container published with fingerprint: %s"
 msgstr "Empreinte du certificat: % x\n"
 
-#: lxc/image.go:155
+#: lxc/image.go:157
 msgid "Copy aliases from source"
 msgstr ""
 
@@ -227,12 +227,12 @@ msgid ""
 "ephemeral|e]"
 msgstr ""
 
-#: lxc/image.go:268
+#: lxc/image.go:271
 #, c-format
 msgid "Copying the image: %s"
 msgstr ""
 
-#: lxc/remote.go:221
+#: lxc/remote.go:234
 msgid "Could not create server cert dir"
 msgstr "Le dossier de stockage des certificats serveurs n'a pas pû être créé"
 
@@ -256,7 +256,7 @@ msgid ""
 "lxc snapshot u1 snap0"
 msgstr ""
 
-#: lxc/image.go:335 lxc/info.go:92
+#: lxc/image.go:344 lxc/info.go:92
 #, c-format
 msgid "Created: %s"
 msgstr ""
@@ -270,7 +270,7 @@ msgstr ""
 msgid "Creating the container"
 msgstr ""
 
-#: lxc/image.go:607 lxc/image.go:635
+#: lxc/image.go:627 lxc/image.go:668
 msgid "DESCRIPTION"
 msgstr ""
 
@@ -285,29 +285,29 @@ msgid ""
 "snapshots, ...)."
 msgstr ""
 
-#: lxc/config.go:617
+#: lxc/config.go:648
 #, c-format
 msgid "Device %s added to %s"
 msgstr ""
 
-#: lxc/config.go:804
+#: lxc/config.go:835
 #, c-format
 msgid "Device %s removed from %s"
 msgstr ""
 
-#: lxc/list.go:462
+#: lxc/list.go:554
 msgid "EPHEMERAL"
 msgstr ""
 
-#: lxc/config.go:272
+#: lxc/config.go:276
 msgid "EXPIRY DATE"
 msgstr ""
 
-#: lxc/main.go:55
+#: lxc/main.go:41
 msgid "Enables debug mode."
 msgstr "Active le mode de déboguage."
 
-#: lxc/main.go:54
+#: lxc/main.go:40
 msgid "Enables verbose mode."
 msgstr "Active le mode verbeux."
 
@@ -336,24 +336,24 @@ msgid ""
 "AND stdout are terminals (stderr is ignored)."
 msgstr "Exécute la commande spécifiée dans un conteneur.\n"
 
-#: lxc/image.go:339
+#: lxc/image.go:348
 #, c-format
 msgid "Expires: %s"
 msgstr ""
 
-#: lxc/image.go:341
+#: lxc/image.go:350
 msgid "Expires: never"
 msgstr ""
 
-#: lxc/config.go:269 lxc/image.go:605 lxc/image.go:634
+#: lxc/config.go:273 lxc/image.go:625 lxc/image.go:667
 msgid "FINGERPRINT"
 msgstr ""
 
-#: lxc/list.go:102
+#: lxc/list.go:124
 msgid "Fast mode (same as --columns=nsacPt"
 msgstr ""
 
-#: lxc/image.go:328
+#: lxc/image.go:337
 #, fuzzy, c-format
 msgid "Fingerprint: %s"
 msgstr "Empreinte du certificat: % x\n"
@@ -366,7 +366,7 @@ msgid ""
 "lxc finger <remote>"
 msgstr "Contacte LXD pour voir s'il est fonctionel.\n"
 
-#: lxc/action.go:37
+#: lxc/action.go:37 lxc/action.go:38
 msgid "Force the container to shutdown."
 msgstr "Force l'arrêt du conteneur."
 
@@ -374,50 +374,50 @@ msgstr "Force l'arrêt du conteneur."
 msgid "Force the removal of stopped containers."
 msgstr ""
 
-#: lxc/main.go:56
+#: lxc/main.go:42
 msgid "Force using the local unix socket."
 msgstr ""
 
-#: lxc/list.go:101
+#: lxc/image.go:160 lxc/list.go:123
 msgid "Format"
 msgstr ""
 
-#: lxc/main.go:138
+#: lxc/remote.go:67
 #, fuzzy
 msgid "Generating a client certificate. This may take a minute..."
 msgstr "Géneration d'un certificat client. Ceci peut prendre une minute...\n"
 
-#: lxc/list.go:376
+#: lxc/list.go:407
 msgid "IPV4"
 msgstr ""
 
-#: lxc/list.go:377
+#: lxc/list.go:408
 msgid "IPV6"
 msgstr ""
 
-#: lxc/config.go:271
+#: lxc/config.go:275
 msgid "ISSUE DATE"
 msgstr ""
 
-#: lxc/main.go:146
+#: lxc/main.go:132
 msgid ""
 "If this is your first time using LXD, you should also run: sudo lxd init"
 msgstr ""
 
-#: lxc/main.go:57
+#: lxc/main.go:43
 msgid "Ignore aliases when determining what command to run."
 msgstr ""
 
-#: lxc/action.go:40
+#: lxc/action.go:41
 #, fuzzy
 msgid "Ignore the container state (only for start)."
 msgstr "Force l'arrêt du conteneur."
 
-#: lxc/image.go:273
+#: lxc/image.go:276
 msgid "Image copied successfully!"
 msgstr ""
 
-#: lxc/image.go:419
+#: lxc/image.go:428
 #, fuzzy, c-format
 msgid "Image imported with fingerprint: %s"
 msgstr "Empreinte du certificat: % x\n"
@@ -438,17 +438,22 @@ msgid ""
 "lxc init ubuntu u1"
 msgstr ""
 
-#: lxc/remote.go:122
+#: lxc/remote.go:137
 #, c-format
 msgid "Invalid URL scheme \"%s\" in \"%s\""
 msgstr ""
 
+#: lxc/config.go:254
+#, fuzzy
+msgid "Invalid certificate"
+msgstr "Gérer la configuration.\n"
+
 #: lxc/init.go:30 lxc/init.go:35
 #, fuzzy
 msgid "Invalid configuration key"
 msgstr "Gérer la configuration.\n"
 
-#: lxc/file.go:190
+#: lxc/file.go:195
 #, c-format
 msgid "Invalid source %s"
 msgstr "Source invalide %s"
@@ -462,11 +467,15 @@ msgstr "Destination invalide %s"
 msgid "Ips:"
 msgstr ""
 
-#: lxc/image.go:156
+#: lxc/image.go:158
 msgid "Keep the image up to date after initial copy"
 msgstr ""
 
-#: lxc/main.go:35
+#: lxc/list.go:411
+msgid "LAST USED AT"
+msgstr ""
+
+#: lxc/main.go:27
 msgid "LXD socket not found; is LXD installed and running?"
 msgstr ""
 
@@ -497,7 +506,7 @@ msgid ""
 " lxc info [<remote>:]"
 msgstr ""
 
-#: lxc/list.go:67
+#: lxc/list.go:68
 msgid ""
 "Lists the available resources.\n"
 "\n"
@@ -517,11 +526,18 @@ msgid ""
 "* A regular expression matching a configuration item or its value. (e.g. "
 "volatile.eth0.hwaddr=00:16:3e:.*)\n"
 "\n"
-"Columns for table format are:\n"
+"The -c option takes a comma separated list of arguments that control\n"
+"which container attributes to output when displaying in table format.\n"
+"Column arguments are either pre-defined shorthand chars (see below),\n"
+"or (extended) config keys.  Commas between consecutive shorthand chars\n"
+"are optional.\n"
+"\n"
+"Pre-defined shorthand chars:\n"
 "* 4 - IPv4 address\n"
 "* 6 - IPv6 address\n"
 "* a - architecture\n"
 "* c - creation date\n"
+"* l - last used date\n"
 "* n - name\n"
 "* p - pid of container init process\n"
 "* P - profiles\n"
@@ -529,15 +545,29 @@ msgid ""
 "* S - number of snapshots\n"
 "* t - type (persistent or ephemeral)\n"
 "\n"
+"Config key syntax: key[:name][:maxWidth]\n"
+"* key      - The (extended) config key to display\n"
+"* name     - Name to display in the column header, defaults to the key\n"
+"             if not specified or if empty (to allow defining maxWidth\n"
+"             without a custom name, e.g. user.key::0)\n"
+"* maxWidth - Max width of the column (longer results are truncated).\n"
+"             -1 == unlimited\n"
+"              0 == width of column header\n"
+"             >0 == max width in chars\n"
+"             Default is -1 (unlimited)\n"
+"\n"
 "Default column layout: ns46tS\n"
-"Fast column layout: nsacPt"
+"Fast column layout: nsacPt\n"
+"\n"
+"Example: lxc list -c n,volatile.base_image:\"BASE IMAGE\":0,s46,volatile."
+"eth0.hwaddr:MAC\n"
 msgstr ""
 
 #: lxc/info.go:225
 msgid "Log:"
 msgstr ""
 
-#: lxc/image.go:154
+#: lxc/image.go:156
 msgid "Make image public"
 msgstr ""
 
@@ -563,16 +593,21 @@ msgid ""
 "             cat profile.yml | lxc profile edit <profile> # read from "
 "profile.yml\n"
 "\n"
-"lxc profile apply <container> <profiles>\n"
-"    Apply a comma-separated list of profiles to a container, in order.\n"
+"lxc profile assign <container> <profiles>\n"
+"    Assign a comma-separated list of profiles to a container, in order.\n"
 "    All profiles passed in this call (and only those) will be applied\n"
-"    to the specified container.\n"
-"    Example: lxc profile apply foo default,bar # Apply default and bar\n"
-"             lxc profile apply foo default # Only default is active\n"
-"             lxc profile apply '' # no profiles are applied anymore\n"
-"             lxc profile apply bar,default # Apply default second now\n"
-"lxc profile apply-add <container> <profile>\n"
-"lxc profile apply-remove <container> <profile>\n"
+"    to the specified container, i.e. it sets the list of profiles exactly "
+"to\n"
+"    those specified in this command. To add/remove a particular profile from "
+"a\n"
+"    container, use {add|remove} below.\n"
+"    Example: lxc profile assign foo default,bar # Apply default and bar\n"
+"             lxc profile assign foo default # Only default is active\n"
+"             lxc profile assign '' # no profiles are applied anymore\n"
+"             lxc profile assign bar,default # Apply default second now\n"
+"lxc profile add <container> <profile> # add a profile to a container\n"
+"lxc profile remove <container> <profile> # remove the profile from a "
+"container\n"
 "\n"
 "Devices:\n"
 "lxc profile device list <profile>                                   List "
@@ -686,7 +721,7 @@ msgid ""
 "Print the default remote."
 msgstr ""
 
-#: lxc/image.go:93
+#: lxc/image.go:95
 msgid ""
 "Manipulate container images.\n"
 "\n"
@@ -717,8 +752,8 @@ msgid ""
 "    The auto-update flag instructs the server to keep this image up to\n"
 "    date. It requires the source to be an alias and for it to be public.\n"
 "\n"
-"lxc image delete [remote:]<image>\n"
-"    Delete an image from the LXD image store.\n"
+"lxc image delete [remote:]<image> [remote:][<image>...]\n"
+"    Delete one or more images from the LXD image store.\n"
 "\n"
 "lxc image export [remote:]<image>\n"
 "    Export an image from the LXD image store into a distributable tarball.\n"
@@ -726,7 +761,7 @@ msgid ""
 "lxc image info [remote:]<image>\n"
 "    Print everything LXD knows about a given image.\n"
 "\n"
-"lxc image list [remote:] [filter]\n"
+"lxc image list [remote:] [filter] [--format table|json]\n"
 "    List images in the LXD image store. Filters may be of the\n"
 "    <key>=<value> form for property based filtering, or part of the image\n"
 "    hash or part of the image alias name.\n"
@@ -777,7 +812,7 @@ msgid ""
 "lxc monitor --type=logging"
 msgstr ""
 
-#: lxc/file.go:178
+#: lxc/file.go:183
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 "Plusieurs fichiers à télécharger mais la destination n'est pas un dossier"
@@ -794,15 +829,15 @@ msgid ""
 "    Rename a local container.\n"
 msgstr ""
 
-#: lxc/action.go:63
+#: lxc/action.go:64
 msgid "Must supply container name for: "
 msgstr ""
 
-#: lxc/list.go:380 lxc/remote.go:363
+#: lxc/list.go:412 lxc/remote.go:376
 msgid "NAME"
 msgstr ""
 
-#: lxc/remote.go:337 lxc/remote.go:342
+#: lxc/remote.go:350 lxc/remote.go:355
 msgid "NO"
 msgstr ""
 
@@ -811,33 +846,33 @@ msgstr ""
 msgid "Name: %s"
 msgstr ""
 
-#: lxc/image.go:157 lxc/publish.go:33
+#: lxc/image.go:159 lxc/publish.go:33
 msgid "New alias to define at target"
 msgstr ""
 
-#: lxc/config.go:281
+#: lxc/config.go:285
 #, fuzzy
 msgid "No certificate provided to add"
 msgstr "Un certificat n'a pas été fournis"
 
-#: lxc/config.go:304
+#: lxc/config.go:308
 msgid "No fingerprint specified."
 msgstr "Aucune empreinte n'a été spécifié."
 
-#: lxc/remote.go:107
+#: lxc/remote.go:122
 msgid "Only https URLs are supported for simplestreams"
 msgstr ""
 
-#: lxc/image.go:411
+#: lxc/image.go:420
 msgid "Only https:// is supported for remote image import."
 msgstr ""
 
-#: lxc/help.go:63 lxc/main.go:122
+#: lxc/help.go:63 lxc/main.go:108
 #, fuzzy
 msgid "Options:"
 msgstr "Opération %s"
 
-#: lxc/image.go:506
+#: lxc/image.go:524
 #, c-format
 msgid "Output is in %s"
 msgstr ""
@@ -846,23 +881,23 @@ msgstr ""
 msgid "Override the terminal mode (auto, interactive or non-interactive)"
 msgstr ""
 
-#: lxc/list.go:464
+#: lxc/list.go:556
 msgid "PERSISTENT"
 msgstr ""
 
-#: lxc/list.go:381
+#: lxc/list.go:413
 msgid "PID"
 msgstr ""
 
-#: lxc/list.go:382
+#: lxc/list.go:414
 msgid "PROFILES"
 msgstr ""
 
-#: lxc/remote.go:365
+#: lxc/remote.go:378
 msgid "PROTOCOL"
 msgstr ""
 
-#: lxc/image.go:606 lxc/remote.go:366
+#: lxc/image.go:626 lxc/remote.go:379
 msgid "PUBLIC"
 msgstr ""
 
@@ -884,7 +919,7 @@ msgstr "Dossier de configuration alternatif."
 msgid "Path to an alternate server directory."
 msgstr "Dossier de configuration alternatif."
 
-#: lxc/main.go:39
+#: lxc/main.go:31
 msgid "Permisson denied, are you in the lxd group?"
 msgstr ""
 
@@ -901,11 +936,11 @@ msgid ""
 "lxd help [--all]"
 msgstr "Explique comment utiliser LXD.\n"
 
-#: lxc/profile.go:216
+#: lxc/profile.go:218
 msgid "Press enter to open the editor again"
 msgstr ""
 
-#: lxc/config.go:501 lxc/config.go:566 lxc/image.go:688
+#: lxc/config.go:532 lxc/config.go:597 lxc/image.go:721
 msgid "Press enter to start the editor again"
 msgstr ""
 
@@ -934,22 +969,22 @@ msgstr "Montre le numéro de version de LXD.\n"
 msgid "Processes: %d"
 msgstr "Mauvaise URL pour le conteneur %s"
 
-#: lxc/profile.go:272
+#: lxc/profile.go:274
 #, fuzzy, c-format
 msgid "Profile %s added to %s"
 msgstr "Mauvaise URL pour le conteneur %s"
 
-#: lxc/profile.go:167
+#: lxc/profile.go:169
 #, c-format
 msgid "Profile %s created"
 msgstr ""
 
-#: lxc/profile.go:237
+#: lxc/profile.go:239
 #, c-format
 msgid "Profile %s deleted"
 msgstr ""
 
-#: lxc/profile.go:303
+#: lxc/profile.go:305
 #, c-format
 msgid "Profile %s removed from %s"
 msgstr ""
@@ -958,7 +993,7 @@ msgstr ""
 msgid "Profile to apply to the new container"
 msgstr ""
 
-#: lxc/profile.go:253
+#: lxc/profile.go:255
 #, c-format
 msgid "Profiles %s applied to %s"
 msgstr ""
@@ -968,7 +1003,7 @@ msgstr ""
 msgid "Profiles: %s"
 msgstr "Mauvaise URL pour le conteneur %s"
 
-#: lxc/image.go:343
+#: lxc/image.go:352
 msgid "Properties:"
 msgstr ""
 
@@ -976,7 +1011,7 @@ msgstr ""
 msgid "Public image server"
 msgstr ""
 
-#: lxc/image.go:331
+#: lxc/image.go:340
 #, c-format
 msgid "Public: %s"
 msgstr ""
@@ -1011,27 +1046,27 @@ msgstr ""
 msgid "Retrieving image: %s"
 msgstr ""
 
-#: lxc/image.go:609
+#: lxc/image.go:629
 msgid "SIZE"
 msgstr ""
 
-#: lxc/list.go:383
+#: lxc/list.go:415
 msgid "SNAPSHOTS"
 msgstr ""
 
-#: lxc/list.go:384
+#: lxc/list.go:416
 msgid "STATE"
 msgstr ""
 
-#: lxc/remote.go:367
+#: lxc/remote.go:380
 msgid "STATIC"
 msgstr ""
 
-#: lxc/remote.go:214
+#: lxc/remote.go:227
 msgid "Server certificate NACKed by user"
 msgstr "Le certificat serveur a été rejeté par l'utilisateur"
 
-#: lxc/remote.go:276
+#: lxc/remote.go:289
 msgid "Server doesn't trust us after adding our cert"
 msgstr "Identification refuse après l'ajout du certificat client"
 
@@ -1073,7 +1108,7 @@ msgstr "Affiche toutes les comandes (pas seulement les intéresantes)"
 msgid "Show the container's last 100 log lines?"
 msgstr ""
 
-#: lxc/image.go:329
+#: lxc/image.go:338
 #, c-format
 msgid "Size: %.2fMB"
 msgstr ""
@@ -1082,7 +1117,7 @@ msgstr ""
 msgid "Snapshots:"
 msgstr ""
 
-#: lxc/image.go:353
+#: lxc/image.go:362
 msgid "Source:"
 msgstr ""
 
@@ -1104,7 +1139,7 @@ msgstr ""
 msgid "Stopping container failed!"
 msgstr "L'arrêt du conteneur a échoué!"
 
-#: lxc/action.go:39
+#: lxc/action.go:40
 #, fuzzy
 msgid "Store the container state (only for stop)."
 msgstr "Force l'arrêt du conteneur."
@@ -1117,7 +1152,7 @@ msgstr ""
 msgid "Swap (peak)"
 msgstr ""
 
-#: lxc/list.go:385
+#: lxc/list.go:417
 msgid "TYPE"
 msgstr ""
 
@@ -1131,8 +1166,8 @@ msgid ""
 "restarted."
 msgstr ""
 
-#: lxc/config.go:645 lxc/config.go:657 lxc/config.go:690 lxc/config.go:708
-#: lxc/config.go:746 lxc/config.go:764
+#: lxc/config.go:676 lxc/config.go:688 lxc/config.go:721 lxc/config.go:739
+#: lxc/config.go:777 lxc/config.go:795
 #, fuzzy
 msgid "The device doesn't exist"
 msgstr "le serveur distant %s n'existe pas"
@@ -1150,20 +1185,20 @@ msgstr ""
 msgid "Time to wait for the container before killing it."
 msgstr "Temps d'attente avant de tuer le conteneur."
 
-#: lxc/image.go:332
+#: lxc/image.go:341
 msgid "Timestamps:"
 msgstr ""
 
-#: lxc/main.go:147
+#: lxc/main.go:133
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/image.go:402
+#: lxc/image.go:411
 #, c-format
 msgid "Transferring image: %d%%"
 msgstr ""
 
-#: lxc/action.go:93 lxc/launch.go:132
+#: lxc/action.go:94 lxc/launch.go:132
 #, c-format
 msgid "Try `lxc info --show-log %s` for more info"
 msgstr ""
@@ -1176,24 +1211,24 @@ msgstr ""
 msgid "Type: persistent"
 msgstr ""
 
-#: lxc/image.go:610
+#: lxc/image.go:630
 msgid "UPLOAD DATE"
 msgstr ""
 
-#: lxc/remote.go:364
+#: lxc/remote.go:377
 msgid "URL"
 msgstr ""
 
-#: lxc/remote.go:82
+#: lxc/remote.go:97
 msgid "Unable to read remote TLS certificate"
 msgstr ""
 
-#: lxc/image.go:337
+#: lxc/image.go:346
 #, c-format
 msgid "Uploaded: %s"
 msgstr ""
 
-#: lxc/main.go:122
+#: lxc/main.go:108
 #, fuzzy, c-format
 msgid "Usage: %s"
 msgstr ""
@@ -1232,11 +1267,11 @@ msgstr ""
 msgid "Whether to show the expanded configuration"
 msgstr ""
 
-#: lxc/remote.go:339 lxc/remote.go:344
+#: lxc/remote.go:352 lxc/remote.go:357
 msgid "YES"
 msgstr ""
 
-#: lxc/main.go:66
+#: lxc/main.go:52
 msgid "`lxc config profile` is deprecated, please use `lxc profile`"
 msgstr ""
 
@@ -1245,19 +1280,19 @@ msgstr ""
 msgid "bad number of things scanned from image, container or snapshot"
 msgstr "nombre de propriété invalide pour la ressource"
 
-#: lxc/action.go:89
+#: lxc/action.go:90
 msgid "bad result type from action"
 msgstr "mauvais type de réponse pour l'action!"
 
-#: lxc/copy.go:78
+#: lxc/copy.go:99
 msgid "can't copy to the same container name"
 msgstr ""
 
-#: lxc/remote.go:327
+#: lxc/remote.go:340
 msgid "can't remove the default remote"
 msgstr ""
 
-#: lxc/remote.go:353
+#: lxc/remote.go:366
 msgid "default"
 msgstr ""
 
@@ -1266,20 +1301,20 @@ msgstr ""
 msgid "didn't get any affected image, container or snapshot from server"
 msgstr "N'a pas pû obtenir de resource du serveur"
 
-#: lxc/image.go:323
+#: lxc/image.go:332
 msgid "disabled"
 msgstr ""
 
-#: lxc/image.go:325
+#: lxc/image.go:334
 msgid "enabled"
 msgstr ""
 
-#: lxc/main.go:25 lxc/main.go:159
+#: lxc/main.go:22 lxc/main.go:144
 #, fuzzy, c-format
 msgid "error: %v"
 msgstr "erreur: %v\n"
 
-#: lxc/help.go:40 lxc/main.go:117
+#: lxc/help.go:40 lxc/main.go:103
 #, fuzzy, c-format
 msgid "error: unknown command: %s"
 msgstr "erreur: comande inconnue: %s\n"
@@ -1288,40 +1323,40 @@ msgstr "erreur: comande inconnue: %s\n"
 msgid "got bad version"
 msgstr "reçu une version invalide"
 
-#: lxc/image.go:318 lxc/image.go:586
+#: lxc/image.go:327 lxc/image.go:606
 msgid "no"
 msgstr ""
 
-#: lxc/copy.go:101
+#: lxc/copy.go:122
 msgid "not all the profiles from the source exist on the target"
 msgstr ""
 
-#: lxc/remote.go:207
+#: lxc/remote.go:220
 #, fuzzy
 msgid "ok (y/n)?"
 msgstr "ok (y/n)?"
 
-#: lxc/main.go:266 lxc/main.go:270
+#: lxc/main.go:277 lxc/main.go:281
 #, c-format
 msgid "processing aliases failed %s\n"
 msgstr ""
 
-#: lxc/remote.go:389
+#: lxc/remote.go:402
 #, c-format
 msgid "remote %s already exists"
 msgstr "le serveur distant %s existe déjà"
 
-#: lxc/remote.go:319 lxc/remote.go:381 lxc/remote.go:416 lxc/remote.go:432
+#: lxc/remote.go:332 lxc/remote.go:394 lxc/remote.go:429 lxc/remote.go:445
 #, c-format
 msgid "remote %s doesn't exist"
 msgstr "le serveur distant %s n'existe pas"
 
-#: lxc/remote.go:302
+#: lxc/remote.go:315
 #, c-format
 msgid "remote %s exists as <%s>"
 msgstr "le serveur distant %s existe en tant que <%s>"
 
-#: lxc/remote.go:323 lxc/remote.go:385 lxc/remote.go:420
+#: lxc/remote.go:336 lxc/remote.go:398 lxc/remote.go:433
 #, c-format
 msgid "remote %s is static and cannot be modified"
 msgstr ""
@@ -1343,11 +1378,11 @@ msgstr ""
 msgid "unreachable return reached"
 msgstr "Un retour inacessible à été atteint"
 
-#: lxc/main.go:199
+#: lxc/main.go:209
 msgid "wrong number of subcommand arguments"
 msgstr "nombre d'argument incorrect pour la sous-comande"
 
-#: lxc/delete.go:45 lxc/image.go:320 lxc/image.go:590
+#: lxc/delete.go:45 lxc/image.go:329 lxc/image.go:610
 msgid "yes"
 msgstr ""
 
diff --git a/po/ja.po b/po/ja.po
index 4a65d63..bbd485e 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: 2016-04-25 14:47-0500\n"
+"POT-Creation-Date: 2016-06-24 08:22-0700\n"
 "PO-Revision-Date: 2016-04-26 14:31+0900\n"
 "Last-Translator: KATOH Yasufumi <karma at jazz.email.ne.jp>\n"
 "Language-Team: Japanese <lxd-ja-language-team at googlegroups.com>\n"
@@ -49,7 +49,7 @@ msgid ""
 "### Note that the name is shown but cannot be changed"
 msgstr ""
 
-#: lxc/image.go:83
+#: lxc/image.go:85
 msgid ""
 "### This is a yaml representation of the image properties.\n"
 "### Any line starting with a '# will be ignored.\n"
@@ -80,7 +80,7 @@ msgid ""
 "### Note that the name is shown but cannot be changed"
 msgstr ""
 
-#: lxc/image.go:583
+#: lxc/image.go:603
 #, c-format
 msgid "%s (%d more)"
 msgstr ""
@@ -89,19 +89,19 @@ msgstr ""
 msgid "'/' not allowed in snapshot name"
 msgstr "'/' はスナップショットの名前には使用できません。"
 
-#: lxc/profile.go:251
+#: lxc/profile.go:253
 msgid "(none)"
 msgstr ""
 
-#: lxc/image.go:604 lxc/image.go:633
+#: lxc/image.go:624 lxc/image.go:666
 msgid "ALIAS"
 msgstr ""
 
-#: lxc/image.go:608
+#: lxc/image.go:628
 msgid "ARCH"
 msgstr ""
 
-#: lxc/list.go:378
+#: lxc/list.go:409
 msgid "ARCHITECTURE"
 msgstr ""
 
@@ -109,12 +109,12 @@ msgstr ""
 msgid "Accept certificate"
 msgstr "証明書のフィンガープリントの確認なしで証明書を受け入れます"
 
-#: lxc/remote.go:256
+#: lxc/remote.go:269
 #, c-format
 msgid "Admin password for %s: "
 msgstr "%s の管理者パスワード: "
 
-#: lxc/image.go:347
+#: lxc/image.go:356
 msgid "Aliases:"
 msgstr "エイリアス:"
 
@@ -122,12 +122,12 @@ msgstr "エイリアス:"
 msgid "An environment variable of the form HOME=/home/foo"
 msgstr "環境変数を HOME=/home/foo の形式で指定します"
 
-#: lxc/image.go:330 lxc/info.go:90
+#: lxc/image.go:339 lxc/info.go:90
 #, c-format
 msgid "Architecture: %s"
 msgstr "アーキテクチャ: %s"
 
-#: lxc/image.go:351
+#: lxc/image.go:360
 #, c-format
 msgid "Auto update: %s"
 msgstr "自動更新: %s"
@@ -144,11 +144,11 @@ msgstr "受信バイト数"
 msgid "Bytes sent"
 msgstr "送信バイト数"
 
-#: lxc/config.go:270
+#: lxc/config.go:274
 msgid "COMMON NAME"
 msgstr ""
 
-#: lxc/list.go:379
+#: lxc/list.go:410
 msgid "CREATED AT"
 msgstr ""
 
@@ -162,11 +162,11 @@ msgstr "標準入力から読み込めません: %s"
 msgid "Can't unset key '%s', it's not currently set."
 msgstr "キー '%s' が指定されていないので削除できません。"
 
-#: lxc/profile.go:417
+#: lxc/profile.go:419
 msgid "Cannot provide container name to list"
 msgstr "コンテナ名を取得できません"
 
-#: lxc/remote.go:206
+#: lxc/remote.go:219
 #, c-format
 msgid "Certificate fingerprint: %x"
 msgstr "証明書のフィンガープリント: %x"
@@ -182,11 +182,11 @@ msgstr ""
 "\n"
 "lxc %s <name> [<name>...]"
 
-#: lxc/remote.go:279
+#: lxc/remote.go:292
 msgid "Client certificate stored at server: "
 msgstr "クライアント証明書がサーバに格納されました: "
 
-#: lxc/list.go:99 lxc/list.go:100
+#: lxc/list.go:121 lxc/list.go:122
 msgid "Columns"
 msgstr "カラムレイアウト"
 
@@ -194,12 +194,12 @@ msgstr "カラムレイアウト"
 msgid "Config key/value to apply to the new container"
 msgstr "新しいコンテナに適用するキー/値の設定"
 
-#: lxc/config.go:500 lxc/config.go:565 lxc/image.go:687 lxc/profile.go:215
+#: lxc/config.go:531 lxc/config.go:596 lxc/image.go:720 lxc/profile.go:217
 #, c-format
 msgid "Config parsing error: %s"
 msgstr "設定の構文エラー: %s"
 
-#: lxc/main.go:37
+#: lxc/main.go:29
 msgid "Connection refused; is LXD running?"
 msgstr "接続が拒否されました。LXDが実行されていますか?"
 
@@ -217,7 +217,7 @@ msgstr "コンテナ名: %s"
 msgid "Container published with fingerprint: %s"
 msgstr "コンテナは以下のフィンガープリントで publish されます: %s"
 
-#: lxc/image.go:155
+#: lxc/image.go:157
 msgid "Copy aliases from source"
 msgstr "ソースからエイリアスをコピーしました"
 
@@ -233,12 +233,12 @@ msgstr ""
 "lxc copy [remote:]<source container> [remote:]<destination container> [--"
 "ephemeral|e]"
 
-#: lxc/image.go:268
+#: lxc/image.go:271
 #, c-format
 msgid "Copying the image: %s"
 msgstr "イメージのコピー中: %s"
 
-#: lxc/remote.go:221
+#: lxc/remote.go:234
 msgid "Could not create server cert dir"
 msgstr "サーバ証明書格納用のディレクトリを作成できません。"
 
@@ -274,7 +274,7 @@ msgstr ""
 "例:\n"
 "lxc snapshot u1 snap0"
 
-#: lxc/image.go:335 lxc/info.go:92
+#: lxc/image.go:344 lxc/info.go:92
 #, c-format
 msgid "Created: %s"
 msgstr "作成日時: %s"
@@ -288,7 +288,7 @@ msgstr "%s を作成中"
 msgid "Creating the container"
 msgstr "コンテナを作成中"
 
-#: lxc/image.go:607 lxc/image.go:635
+#: lxc/image.go:627 lxc/image.go:668
 msgid "DESCRIPTION"
 msgstr ""
 
@@ -310,29 +310,29 @@ msgstr ""
 "付属するデータ (設定、スナップショット、...) と一緒にコンテナもしくはコンテ\n"
 "ナのスナップショットを消去します。"
 
-#: lxc/config.go:617
+#: lxc/config.go:648
 #, c-format
 msgid "Device %s added to %s"
 msgstr "デバイス %s が %s に追加されました"
 
-#: lxc/config.go:804
+#: lxc/config.go:835
 #, c-format
 msgid "Device %s removed from %s"
 msgstr "デバイス %s が %s から削除されました"
 
-#: lxc/list.go:462
+#: lxc/list.go:554
 msgid "EPHEMERAL"
 msgstr ""
 
-#: lxc/config.go:272
+#: lxc/config.go:276
 msgid "EXPIRY DATE"
 msgstr ""
 
-#: lxc/main.go:55
+#: lxc/main.go:41
 msgid "Enables debug mode."
 msgstr "デバッグモードを有効にします。"
 
-#: lxc/main.go:54
+#: lxc/main.go:40
 msgid "Enables verbose mode."
 msgstr "詳細モードを有効にします。"
 
@@ -367,24 +367,24 @@ msgstr ""
 "デフォルトのモードは non-interactive です。もし標準入出力が両方ともターミナ\n"
 "ルの場合は interactive モードが選択されます (標準エラー出力は無視されます)。"
 
-#: lxc/image.go:339
+#: lxc/image.go:348
 #, c-format
 msgid "Expires: %s"
 msgstr "失効日時: %s"
 
-#: lxc/image.go:341
+#: lxc/image.go:350
 msgid "Expires: never"
 msgstr "失効日時: 失効しない"
 
-#: lxc/config.go:269 lxc/image.go:605 lxc/image.go:634
+#: lxc/config.go:273 lxc/image.go:625 lxc/image.go:667
 msgid "FINGERPRINT"
 msgstr ""
 
-#: lxc/list.go:102
+#: lxc/list.go:124
 msgid "Fast mode (same as --columns=nsacPt"
 msgstr "Fast モード (--columns=nsacPt と同じ)"
 
-#: lxc/image.go:328
+#: lxc/image.go:337
 #, c-format
 msgid "Fingerprint: %s"
 msgstr "証明書のフィンガープリント: %s"
@@ -399,7 +399,7 @@ msgstr ""
 "\n"
 "lxc finger <remote>"
 
-#: lxc/action.go:37
+#: lxc/action.go:37 lxc/action.go:38
 msgid "Force the container to shutdown."
 msgstr "コンテナを強制シャットダウンします。"
 
@@ -407,48 +407,48 @@ msgstr "コンテナを強制シャットダウンします。"
 msgid "Force the removal of stopped containers."
 msgstr "停止したコンテナを強制的に削除します。"
 
-#: lxc/main.go:56
+#: lxc/main.go:42
 msgid "Force using the local unix socket."
 msgstr "強制的にローカルのUNIXソケットを使います。"
 
-#: lxc/list.go:101
+#: lxc/image.go:160 lxc/list.go:123
 msgid "Format"
 msgstr ""
 
-#: lxc/main.go:138
+#: lxc/remote.go:67
 msgid "Generating a client certificate. This may take a minute..."
 msgstr "クライアント証明書を生成します。1分ぐらいかかります..."
 
-#: lxc/list.go:376
+#: lxc/list.go:407
 msgid "IPV4"
 msgstr ""
 
-#: lxc/list.go:377
+#: lxc/list.go:408
 msgid "IPV6"
 msgstr ""
 
-#: lxc/config.go:271
+#: lxc/config.go:275
 msgid "ISSUE DATE"
 msgstr ""
 
-#: lxc/main.go:146
+#: lxc/main.go:132
 msgid ""
 "If this is your first time using LXD, you should also run: sudo lxd init"
 msgstr "初めて LXD を使う場合、sudo lxd init と実行する必要があります"
 
-#: lxc/main.go:57
+#: lxc/main.go:43
 msgid "Ignore aliases when determining what command to run."
 msgstr "どのコマンドを実行するか決める際にエイリアスを無視します。"
 
-#: lxc/action.go:40
+#: lxc/action.go:41
 msgid "Ignore the container state (only for start)."
 msgstr "コンテナの状態を無視します (startのみ)。"
 
-#: lxc/image.go:273
+#: lxc/image.go:276
 msgid "Image copied successfully!"
 msgstr "イメージのコピーが成功しました!"
 
-#: lxc/image.go:419
+#: lxc/image.go:428
 #, c-format
 msgid "Image imported with fingerprint: %s"
 msgstr "イメージは以下のフィンガープリントでインポートされました: %s"
@@ -481,16 +481,21 @@ msgstr ""
 "例:\n"
 "lxc init ubuntu u1"
 
-#: lxc/remote.go:122
+#: lxc/remote.go:137
 #, c-format
 msgid "Invalid URL scheme \"%s\" in \"%s\""
 msgstr "不正な URL スキーム \"%s\" (\"%s\" 内)"
 
+#: lxc/config.go:254
+#, fuzzy
+msgid "Invalid certificate"
+msgstr "証明書のフィンガープリントの確認なしで証明書を受け入れます"
+
 #: lxc/init.go:30 lxc/init.go:35
 msgid "Invalid configuration key"
 msgstr "正しくない設定項目 (key) です"
 
-#: lxc/file.go:190
+#: lxc/file.go:195
 #, c-format
 msgid "Invalid source %s"
 msgstr "不正なソース %s"
@@ -504,11 +509,15 @@ msgstr "不正な送り先 %s"
 msgid "Ips:"
 msgstr "IPアドレス:"
 
-#: lxc/image.go:156
+#: lxc/image.go:158
 msgid "Keep the image up to date after initial copy"
 msgstr "最初にコピーした後も常にイメージを最新の状態に保つ"
 
-#: lxc/main.go:35
+#: lxc/list.go:411
+msgid "LAST USED AT"
+msgstr ""
+
+#: lxc/main.go:27
 msgid "LXD socket not found; is LXD installed and running?"
 msgstr "LXD のソケットが見つかりません。LXD が実行されていますか?"
 
@@ -529,7 +538,8 @@ msgid ""
 msgstr ""
 "指定したイメージからコンテナを起動します。\n"
 "\n"
-"lxc launch [remote:]<image> [remote:][<name>] [--ephemeral|-e] [--profile|-p <profile>...] [--config|-c <key=value>...]\n"
+"lxc launch [remote:]<image> [remote:][<name>] [--ephemeral|-e] [--profile|-p "
+"<profile>...] [--config|-c <key=value>...]\n"
 "\n"
 "指定したイメージと名前を使ってコンテナを起動します。\n"
 "\n"
@@ -557,7 +567,8 @@ msgstr ""
 "サーバ情報:\n"
 " lxc info [<remote>:]"
 
-#: lxc/list.go:67
+#: lxc/list.go:68
+#, fuzzy
 msgid ""
 "Lists the available resources.\n"
 "\n"
@@ -577,11 +588,18 @@ msgid ""
 "* A regular expression matching a configuration item or its value. (e.g. "
 "volatile.eth0.hwaddr=00:16:3e:.*)\n"
 "\n"
-"Columns for table format are:\n"
+"The -c option takes a comma separated list of arguments that control\n"
+"which container attributes to output when displaying in table format.\n"
+"Column arguments are either pre-defined shorthand chars (see below),\n"
+"or (extended) config keys.  Commas between consecutive shorthand chars\n"
+"are optional.\n"
+"\n"
+"Pre-defined shorthand chars:\n"
 "* 4 - IPv4 address\n"
 "* 6 - IPv6 address\n"
 "* a - architecture\n"
 "* c - creation date\n"
+"* l - last used date\n"
 "* n - name\n"
 "* p - pid of container init process\n"
 "* P - profiles\n"
@@ -589,25 +607,43 @@ msgid ""
 "* S - number of snapshots\n"
 "* t - type (persistent or ephemeral)\n"
 "\n"
+"Config key syntax: key[:name][:maxWidth]\n"
+"* key      - The (extended) config key to display\n"
+"* name     - Name to display in the column header, defaults to the key\n"
+"             if not specified or if empty (to allow defining maxWidth\n"
+"             without a custom name, e.g. user.key::0)\n"
+"* maxWidth - Max width of the column (longer results are truncated).\n"
+"             -1 == unlimited\n"
+"              0 == width of column header\n"
+"             >0 == max width in chars\n"
+"             Default is -1 (unlimited)\n"
+"\n"
 "Default column layout: ns46tS\n"
-"Fast column layout: nsacPt"
+"Fast column layout: nsacPt\n"
+"\n"
+"Example: lxc list -c n,volatile.base_image:\"BASE IMAGE\":0,s46,volatile."
+"eth0.hwaddr:MAC\n"
 msgstr ""
 "利用可能なリソースを一覧表示します。\n"
 "\n"
 "lxc list [resource] [filters] [--format table|json] [-c columns] [--fast]\n"
 "\n"
 "フィルタの指定:\n"
-"* 単一の \"web\" のようなキーワードを指定すると、名前が \"web\" ではじまるコンテ\n"
+"* 単一の \"web\" のようなキーワードを指定すると、名前が \"web\" ではじまるコ"
+"ンテ\n"
 "  ナが一覧表示されます。\n"
 "* コンテナ名の正規表現 (例: .*web.*01$)\n"
-"* 設定項目のキーと値。キーの名前空間は一意に識別できる場合は短縮することがで\n"
+"* 設定項目のキーと値。キーの名前空間は一意に識別できる場合は短縮することが"
+"で\n"
 "  きます:\n"
-" * \"user.blah=abc\" は \"blah\" という user プロパティが \"abc\" に設定されている\n"
+" * \"user.blah=abc\" は \"blah\" という user プロパティが \"abc\" に設定され"
+"ている\n"
 "  コンテナをすべて一覧表示します。\n"
 " * \"u.blah=abc\" は上記と同じ意味になります。\n"
 " * \"security.privileged=1\" は特権コンテナをすべて一覧表示します。\n"
 " * \"s.privilaged=1\" は上記と同じ意味になります。\n"
-" * 設定項目もしくは値とマッチする正規表現 (例:volatile.eth0.hwaddr=00:16:3e:.*)\n"
+" * 設定項目もしくは値とマッチする正規表現 (例:volatile.eth0.hwaddr=00:16:3e:."
+"*)\n"
 "\n"
 "表のカラムの指定:\n"
 "* 4 - IPv4 アドレス\n"
@@ -628,7 +664,7 @@ msgstr ""
 msgid "Log:"
 msgstr "ログ:"
 
-#: lxc/image.go:154
+#: lxc/image.go:156
 msgid "Make image public"
 msgstr "イメージを public にする"
 
@@ -637,6 +673,7 @@ msgid "Make the image public"
 msgstr "イメージを public にする"
 
 #: lxc/profile.go:48
+#, fuzzy
 msgid ""
 "Manage configuration profiles.\n"
 "\n"
@@ -654,16 +691,21 @@ msgid ""
 "             cat profile.yml | lxc profile edit <profile> # read from "
 "profile.yml\n"
 "\n"
-"lxc profile apply <container> <profiles>\n"
-"    Apply a comma-separated list of profiles to a container, in order.\n"
+"lxc profile assign <container> <profiles>\n"
+"    Assign a comma-separated list of profiles to a container, in order.\n"
 "    All profiles passed in this call (and only those) will be applied\n"
-"    to the specified container.\n"
-"    Example: lxc profile apply foo default,bar # Apply default and bar\n"
-"             lxc profile apply foo default # Only default is active\n"
-"             lxc profile apply '' # no profiles are applied anymore\n"
-"             lxc profile apply bar,default # Apply default second now\n"
-"lxc profile apply-add <container> <profile>\n"
-"lxc profile apply-remove <container> <profile>\n"
+"    to the specified container, i.e. it sets the list of profiles exactly "
+"to\n"
+"    those specified in this command. To add/remove a particular profile from "
+"a\n"
+"    container, use {add|remove} below.\n"
+"    Example: lxc profile assign foo default,bar # Apply default and bar\n"
+"             lxc profile assign foo default # Only default is active\n"
+"             lxc profile assign '' # no profiles are applied anymore\n"
+"             lxc profile assign bar,default # Apply default second now\n"
+"lxc profile add <container> <profile> # add a profile to a container\n"
+"lxc profile remove <container> <profile> # remove the profile from a "
+"container\n"
 "\n"
 "Devices:\n"
 "lxc profile device list <profile>                                   List "
@@ -702,7 +744,8 @@ msgstr ""
 "lxc profile edit <profile>\n"
 "    プロファイルを編集します。外部エディタもしくはSTDINから読み込みます。\n"
 "    例: lxc profile edit <profile> # エディタの起動\n"
-"        cat profile.yml | lxc profile edit <profile> # profile.yml から読み込み\n"
+"        cat profile.yml | lxc profile edit <profile> # profile.yml から読み込"
+"み\n"
 "\n"
 "lxc profile apply <container> <profiles>\n"
 "    プロファイルのコンマ区切りのリストをコンテナに順番に適用します。\n"
@@ -727,7 +770,8 @@ msgstr ""
 "    デバイスプロパティを設定します\n"
 "lxc profile device unset <[remote:]profile> <name> <key>\n"
 "    デバイスプロパティを削除します\n"
-"lxc profile device add <profile name> <device name> <device type> [key=value]...\n"
+"lxc profile device add <profile name> <device name> <device type> "
+"[key=value]...\n"
 "    ディスクやNICのようなプロファイルデバイスを指定したプロファイルを使って\n"
 "    コンテナに追加します。"
 
@@ -905,7 +949,8 @@ msgstr ""
 "lxc remote get-default\n"
 "    デフォルトに設定されているリモートホストを表示します。"
 
-#: lxc/image.go:93
+#: lxc/image.go:95
+#, fuzzy
 msgid ""
 "Manipulate container images.\n"
 "\n"
@@ -936,8 +981,8 @@ msgid ""
 "    The auto-update flag instructs the server to keep this image up to\n"
 "    date. It requires the source to be an alias and for it to be public.\n"
 "\n"
-"lxc image delete [remote:]<image>\n"
-"    Delete an image from the LXD image store.\n"
+"lxc image delete [remote:]<image> [remote:][<image>...]\n"
+"    Delete one or more images from the LXD image store.\n"
 "\n"
 "lxc image export [remote:]<image>\n"
 "    Export an image from the LXD image store into a distributable tarball.\n"
@@ -945,7 +990,7 @@ msgid ""
 "lxc image info [remote:]<image>\n"
 "    Print everything LXD knows about a given image.\n"
 "\n"
-"lxc image list [remote:] [filter]\n"
+"lxc image list [remote:] [filter] [--format table|json]\n"
 "    List images in the LXD image store. Filters may be of the\n"
 "    <key>=<value> form for property based filtering, or part of the image\n"
 "    hash or part of the image alias name.\n"
@@ -983,11 +1028,14 @@ msgstr ""
 "る場合は) エイリアスで参照できます。\n"
 "\n"
 "\n"
-"lxc image import <tarball> [rootfs tarball|URL] [remote:] [--public] [--created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] [--alias=ALIAS].. [prop=value]\n"
+"lxc image import <tarball> [rootfs tarball|URL] [remote:] [--public] [--"
+"created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] [--"
+"alias=ALIAS].. [prop=value]\n"
 "    イメージの tarball (複数も可能) を LXD のイメージストアにインポートしま\n"
 "    す。\n"
 "\n"
-"lxc image copy [remote:]<image> <remote>: [--alias=ALIAS].. [--copy-aliases] [--public] [--auto-update]\n"
+"lxc image copy [remote:]<image> <remote>: [--alias=ALIAS].. [--copy-aliases] "
+"[--public] [--auto-update]\n"
 "    ネットワーク経由である LXD デーモンから他の LXD デーモンへイメージを\n"
 "    コピーします。\n"
 "\n"
@@ -1024,7 +1072,8 @@ msgstr ""
 "    エイリアスを削除します。\n"
 "\n"
 "lxc image alias list [remote:] [filter]\n"
-"    エイリアスを一覧表示します。イメージハッシュの一部やイメージのエイリアス\n"
+"    エイリアスを一覧表示します。イメージハッシュの一部やイメージのエイリア"
+"ス\n"
 "    名の一部をフィルタとして指定できます。\n"
 
 #: lxc/info.go:147
@@ -1065,7 +1114,7 @@ msgstr ""
 "例:\n"
 "lxc monitor --type=logging"
 
-#: lxc/file.go:178
+#: lxc/file.go:183
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 "ダウンロード対象のファイルが複数ありますが、コピー先がディレクトリではありま"
@@ -1091,15 +1140,15 @@ msgstr ""
 "lxc move <old name> <new name>\n"
 "    ローカルのコンテナをリネームします。\n"
 
-#: lxc/action.go:63
+#: lxc/action.go:64
 msgid "Must supply container name for: "
 msgstr "コンテナ名を指定する必要があります: "
 
-#: lxc/list.go:380 lxc/remote.go:363
+#: lxc/list.go:412 lxc/remote.go:376
 msgid "NAME"
 msgstr ""
 
-#: lxc/remote.go:337 lxc/remote.go:342
+#: lxc/remote.go:350 lxc/remote.go:355
 msgid "NO"
 msgstr ""
 
@@ -1108,31 +1157,31 @@ msgstr ""
 msgid "Name: %s"
 msgstr "コンテナ名: %s"
 
-#: lxc/image.go:157 lxc/publish.go:33
+#: lxc/image.go:159 lxc/publish.go:33
 msgid "New alias to define at target"
 msgstr "新しいエイリアスを定義する"
 
-#: lxc/config.go:281
+#: lxc/config.go:285
 msgid "No certificate provided to add"
 msgstr "追加すべき証明書が提供されていません"
 
-#: lxc/config.go:304
+#: lxc/config.go:308
 msgid "No fingerprint specified."
 msgstr "フィンガープリントが指定されていません。"
 
-#: lxc/remote.go:107
+#: lxc/remote.go:122
 msgid "Only https URLs are supported for simplestreams"
 msgstr "simplestreams は https の URL のみサポートします"
 
-#: lxc/image.go:411
+#: lxc/image.go:420
 msgid "Only https:// is supported for remote image import."
 msgstr "リモートイメージのインポートは https:// のみをサポートします。"
 
-#: lxc/help.go:63 lxc/main.go:122
+#: lxc/help.go:63 lxc/main.go:108
 msgid "Options:"
 msgstr "オプション:"
 
-#: lxc/image.go:506
+#: lxc/image.go:524
 #, c-format
 msgid "Output is in %s"
 msgstr "%s に出力されます"
@@ -1141,23 +1190,23 @@ msgstr "%s に出力されます"
 msgid "Override the terminal mode (auto, interactive or non-interactive)"
 msgstr "ターミナルモードを上書きします (auto, interactive, non-interactive)"
 
-#: lxc/list.go:464
+#: lxc/list.go:556
 msgid "PERSISTENT"
 msgstr ""
 
-#: lxc/list.go:381
+#: lxc/list.go:413
 msgid "PID"
 msgstr ""
 
-#: lxc/list.go:382
+#: lxc/list.go:414
 msgid "PROFILES"
 msgstr ""
 
-#: lxc/remote.go:365
+#: lxc/remote.go:378
 msgid "PROTOCOL"
 msgstr ""
 
-#: lxc/image.go:606 lxc/remote.go:366
+#: lxc/image.go:626 lxc/remote.go:379
 msgid "PUBLIC"
 msgstr ""
 
@@ -1177,7 +1226,7 @@ msgstr "別のクライアント用設定ディレクトリ"
 msgid "Path to an alternate server directory."
 msgstr "別のサーバ用設定ディレクトリ"
 
-#: lxc/main.go:39
+#: lxc/main.go:31
 msgid "Permisson denied, are you in the lxd group?"
 msgstr "アクセスが拒否されました。lxd グループに所属していますか?"
 
@@ -1196,11 +1245,11 @@ msgstr ""
 "\n"
 "lxd help [--all]"
 
-#: lxc/profile.go:216
+#: lxc/profile.go:218
 msgid "Press enter to open the editor again"
 msgstr "再度エディタを開くためには Enter キーを押します"
 
-#: lxc/config.go:501 lxc/config.go:566 lxc/image.go:688
+#: lxc/config.go:532 lxc/config.go:597 lxc/image.go:721
 msgid "Press enter to start the editor again"
 msgstr "再度エディタを起動するには Enter キーを押します"
 
@@ -1231,22 +1280,22 @@ msgstr ""
 msgid "Processes: %d"
 msgstr "プロセス数: %d"
 
-#: lxc/profile.go:272
+#: lxc/profile.go:274
 #, c-format
 msgid "Profile %s added to %s"
 msgstr "プロファイル %s が %s に追加されました"
 
-#: lxc/profile.go:167
+#: lxc/profile.go:169
 #, c-format
 msgid "Profile %s created"
 msgstr "プロファイル %s を作成しました"
 
-#: lxc/profile.go:237
+#: lxc/profile.go:239
 #, c-format
 msgid "Profile %s deleted"
 msgstr "プロファイル %s を削除しました"
 
-#: lxc/profile.go:303
+#: lxc/profile.go:305
 #, c-format
 msgid "Profile %s removed from %s"
 msgstr "プロファイル %s が %s から削除されました"
@@ -1255,7 +1304,7 @@ msgstr "プロファイル %s が %s から削除されました"
 msgid "Profile to apply to the new container"
 msgstr "新しいコンテナに適用するプロファイル"
 
-#: lxc/profile.go:253
+#: lxc/profile.go:255
 #, c-format
 msgid "Profiles %s applied to %s"
 msgstr "プロファイル %s が %s に追加されました"
@@ -1265,7 +1314,7 @@ msgstr "プロファイル %s が %s に追加されました"
 msgid "Profiles: %s"
 msgstr "プロファイル: %s"
 
-#: lxc/image.go:343
+#: lxc/image.go:352
 msgid "Properties:"
 msgstr "プロパティ:"
 
@@ -1273,7 +1322,7 @@ msgstr "プロパティ:"
 msgid "Public image server"
 msgstr "Public なイメージサーバとして設定します"
 
-#: lxc/image.go:331
+#: lxc/image.go:340
 #, c-format
 msgid "Public: %s"
 msgstr ""
@@ -1312,27 +1361,27 @@ msgstr "リソース:"
 msgid "Retrieving image: %s"
 msgstr "イメージの取得中: %s"
 
-#: lxc/image.go:609
+#: lxc/image.go:629
 msgid "SIZE"
 msgstr ""
 
-#: lxc/list.go:383
+#: lxc/list.go:415
 msgid "SNAPSHOTS"
 msgstr ""
 
-#: lxc/list.go:384
+#: lxc/list.go:416
 msgid "STATE"
 msgstr ""
 
-#: lxc/remote.go:367
+#: lxc/remote.go:380
 msgid "STATIC"
 msgstr ""
 
-#: lxc/remote.go:214
+#: lxc/remote.go:227
 msgid "Server certificate NACKed by user"
 msgstr "ユーザによりサーバ証明書が拒否されました"
 
-#: lxc/remote.go:276
+#: lxc/remote.go:289
 msgid "Server doesn't trust us after adding our cert"
 msgstr "サーバが我々の証明書を追加した後我々を信頼していません"
 
@@ -1384,7 +1433,7 @@ msgstr "全てコマンドを表示します (主なコマンドだけではな
 msgid "Show the container's last 100 log lines?"
 msgstr "コンテナログの最後の 100 行を表示しますか?"
 
-#: lxc/image.go:329
+#: lxc/image.go:338
 #, c-format
 msgid "Size: %.2fMB"
 msgstr "サイズ: %.2fMB"
@@ -1393,7 +1442,7 @@ msgstr "サイズ: %.2fMB"
 msgid "Snapshots:"
 msgstr "スナップショット:"
 
-#: lxc/image.go:353
+#: lxc/image.go:362
 msgid "Source:"
 msgstr "取得元:"
 
@@ -1415,7 +1464,7 @@ msgstr "実行中の場合、コンテナを停止します"
 msgid "Stopping container failed!"
 msgstr "コンテナの停止に失敗しました!"
 
-#: lxc/action.go:39
+#: lxc/action.go:40
 msgid "Store the container state (only for stop)."
 msgstr "コンテナの状態を保存します (stopのみ)。"
 
@@ -1427,7 +1476,7 @@ msgstr "Swap (現在値)"
 msgid "Swap (peak)"
 msgstr "Swap (ピーク)"
 
-#: lxc/list.go:385
+#: lxc/list.go:417
 msgid "TYPE"
 msgstr ""
 
@@ -1443,15 +1492,16 @@ msgstr ""
 "コンテナは現在実行中です。停止して、再起動するために --force を使用してくだ\n"
 "さい。"
 
-#: lxc/config.go:645 lxc/config.go:657 lxc/config.go:690 lxc/config.go:708
-#: lxc/config.go:746 lxc/config.go:764
+#: lxc/config.go:676 lxc/config.go:688 lxc/config.go:721 lxc/config.go:739
+#: lxc/config.go:777 lxc/config.go:795
 msgid "The device doesn't exist"
 msgstr "デバイスが存在しません"
 
 #: lxc/init.go:277
 #, c-format
 msgid "The local image '%s' couldn't be found, trying '%s:' instead."
-msgstr "ローカルイメージ '%s' が見つかりません。代わりに '%s:' を試してみてください。"
+msgstr ""
+"ローカルイメージ '%s' が見つかりません。代わりに '%s:' を試してみてください。"
 
 #: lxc/publish.go:62
 msgid "There is no \"image name\".  Did you want an alias?"
@@ -1464,22 +1514,23 @@ msgstr ""
 msgid "Time to wait for the container before killing it."
 msgstr "コンテナを強制停止するまでの時間"
 
-#: lxc/image.go:332
+#: lxc/image.go:341
 msgid "Timestamps:"
 msgstr "タイムスタンプ:"
 
-#: lxc/main.go:147
+#: lxc/main.go:133
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
-"初めてコンテナを起動するには、\"lxc launch ubuntu:16.04\" と実行してみてくだ\n"
+"初めてコンテナを起動するには、\"lxc launch ubuntu:16.04\" と実行してみてく"
+"だ\n"
 "さい。"
 
-#: lxc/image.go:402
+#: lxc/image.go:411
 #, c-format
 msgid "Transferring image: %d%%"
 msgstr "イメージを転送中: %d%%"
 
-#: lxc/action.go:93 lxc/launch.go:132
+#: lxc/action.go:94 lxc/launch.go:132
 #, c-format
 msgid "Try `lxc info --show-log %s` for more info"
 msgstr "更に情報を得るために `lxc info --show-log` を実行してみてください"
@@ -1492,24 +1543,24 @@ msgstr "タイプ: ephemeral"
 msgid "Type: persistent"
 msgstr "タイプ: persistent"
 
-#: lxc/image.go:610
+#: lxc/image.go:630
 msgid "UPLOAD DATE"
 msgstr ""
 
-#: lxc/remote.go:364
+#: lxc/remote.go:377
 msgid "URL"
 msgstr ""
 
-#: lxc/remote.go:82
+#: lxc/remote.go:97
 msgid "Unable to read remote TLS certificate"
 msgstr "リモートの TLS 証明書を読めません"
 
-#: lxc/image.go:337
+#: lxc/image.go:346
 #, c-format
 msgid "Uploaded: %s"
 msgstr "アップロード日時: %s"
 
-#: lxc/main.go:122
+#: lxc/main.go:108
 #, c-format
 msgid "Usage: %s"
 msgstr "使い方: %s"
@@ -1537,11 +1588,11 @@ msgstr "コンテナの稼動状態のスナップショットを取得するか
 msgid "Whether to show the expanded configuration"
 msgstr "拡張した設定を表示するかどうか"
 
-#: lxc/remote.go:339 lxc/remote.go:344
+#: lxc/remote.go:352 lxc/remote.go:357
 msgid "YES"
 msgstr ""
 
-#: lxc/main.go:66
+#: lxc/main.go:52
 msgid "`lxc config profile` is deprecated, please use `lxc profile`"
 msgstr "`lxc config profile` は廃止されました。`lxc profile` を使ってください"
 
@@ -1550,19 +1601,19 @@ msgid "bad number of things scanned from image, container or snapshot"
 msgstr ""
 "イメージ、コンテナ、スナップショットのいずれかからスキャンされた数が不正"
 
-#: lxc/action.go:89
+#: lxc/action.go:90
 msgid "bad result type from action"
 msgstr "アクションからの結果タイプが不正です"
 
-#: lxc/copy.go:78
+#: lxc/copy.go:99
 msgid "can't copy to the same container name"
 msgstr "同じコンテナ名へはコピーできません"
 
-#: lxc/remote.go:327
+#: lxc/remote.go:340
 msgid "can't remove the default remote"
 msgstr "デフォルトのリモートは削除できません"
 
-#: lxc/remote.go:353
+#: lxc/remote.go:366
 msgid "default"
 msgstr ""
 
@@ -1572,20 +1623,20 @@ msgstr ""
 "サーバから変更されたイメージ、コンテナ、スナップショットを取得できませんで\n"
 "した"
 
-#: lxc/image.go:323
+#: lxc/image.go:332
 msgid "disabled"
 msgstr "無効"
 
-#: lxc/image.go:325
+#: lxc/image.go:334
 msgid "enabled"
 msgstr "有効"
 
-#: lxc/main.go:25 lxc/main.go:159
+#: lxc/main.go:22 lxc/main.go:144
 #, c-format
 msgid "error: %v"
 msgstr "エラー: %v"
 
-#: lxc/help.go:40 lxc/main.go:117
+#: lxc/help.go:40 lxc/main.go:103
 #, c-format
 msgid "error: unknown command: %s"
 msgstr "エラー: 未知のコマンド: %s"
@@ -1594,39 +1645,39 @@ msgstr "エラー: 未知のコマンド: %s"
 msgid "got bad version"
 msgstr "不正なバージョンを得ました"
 
-#: lxc/image.go:318 lxc/image.go:586
+#: lxc/image.go:327 lxc/image.go:606
 msgid "no"
 msgstr ""
 
-#: lxc/copy.go:101
+#: lxc/copy.go:122
 msgid "not all the profiles from the source exist on the target"
 msgstr "コピー元の全てのプロファイルがターゲットに存在しません"
 
-#: lxc/remote.go:207
+#: lxc/remote.go:220
 msgid "ok (y/n)?"
 msgstr "ok (y/n)?"
 
-#: lxc/main.go:266 lxc/main.go:270
+#: lxc/main.go:277 lxc/main.go:281
 #, c-format
 msgid "processing aliases failed %s\n"
 msgstr "エイリアスの処理が失敗しました %s\n"
 
-#: lxc/remote.go:389
+#: lxc/remote.go:402
 #, c-format
 msgid "remote %s already exists"
 msgstr "リモート %s は既に存在します"
 
-#: lxc/remote.go:319 lxc/remote.go:381 lxc/remote.go:416 lxc/remote.go:432
+#: lxc/remote.go:332 lxc/remote.go:394 lxc/remote.go:429 lxc/remote.go:445
 #, c-format
 msgid "remote %s doesn't exist"
 msgstr "リモート %s は存在しません"
 
-#: lxc/remote.go:302
+#: lxc/remote.go:315
 #, c-format
 msgid "remote %s exists as <%s>"
 msgstr "リモート %s は <%s> として存在します"
 
-#: lxc/remote.go:323 lxc/remote.go:385 lxc/remote.go:420
+#: lxc/remote.go:336 lxc/remote.go:398 lxc/remote.go:433
 #, c-format
 msgid "remote %s is static and cannot be modified"
 msgstr "リモート %s は static ですので変更できません"
@@ -1648,11 +1699,11 @@ msgstr "%s に取得しました"
 msgid "unreachable return reached"
 msgstr "到達しないはずのreturnに到達しました"
 
-#: lxc/main.go:199
+#: lxc/main.go:209
 msgid "wrong number of subcommand arguments"
 msgstr "サブコマンドの引数の数が正しくありません"
 
-#: lxc/delete.go:45 lxc/image.go:320 lxc/image.go:590
+#: lxc/delete.go:45 lxc/image.go:329 lxc/image.go:610
 msgid "yes"
 msgstr ""
 
diff --git a/po/lxd.pot b/po/lxd.pot
index 471930f..8322a94 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: 2016-06-16 15:51-0400\n"
+        "POT-Creation-Date: 2016-06-24 08:22-0700\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"
@@ -98,7 +98,7 @@ msgstr  ""
 msgid   "ARCH"
 msgstr  ""
 
-#: lxc/list.go:379
+#: lxc/list.go:409
 msgid   "ARCHITECTURE"
 msgstr  ""
 
@@ -145,7 +145,7 @@ msgstr  ""
 msgid   "COMMON NAME"
 msgstr  ""
 
-#: lxc/list.go:380
+#: lxc/list.go:410
 msgid   "CREATED AT"
 msgstr  ""
 
@@ -179,7 +179,7 @@ msgstr  ""
 msgid   "Client certificate stored at server: "
 msgstr  ""
 
-#: lxc/list.go:100 lxc/list.go:101
+#: lxc/list.go:121 lxc/list.go:122
 msgid   "Columns"
 msgstr  ""
 
@@ -281,7 +281,7 @@ msgstr  ""
 msgid   "Device %s removed from %s"
 msgstr  ""
 
-#: lxc/list.go:464
+#: lxc/list.go:554
 msgid   "EPHEMERAL"
 msgstr  ""
 
@@ -330,7 +330,7 @@ msgstr  ""
 msgid   "FINGERPRINT"
 msgstr  ""
 
-#: lxc/list.go:103
+#: lxc/list.go:124
 msgid   "Fast mode (same as --columns=nsacPt"
 msgstr  ""
 
@@ -345,7 +345,7 @@ msgid   "Fingers the LXD instance to check if it is up and working.\n"
         "lxc finger <remote>"
 msgstr  ""
 
-#: lxc/action.go:37
+#: lxc/action.go:37 lxc/action.go:38
 msgid   "Force the container to shutdown."
 msgstr  ""
 
@@ -357,7 +357,7 @@ msgstr  ""
 msgid   "Force using the local unix socket."
 msgstr  ""
 
-#: lxc/image.go:160 lxc/list.go:102
+#: lxc/image.go:160 lxc/list.go:123
 msgid   "Format"
 msgstr  ""
 
@@ -365,11 +365,11 @@ msgstr  ""
 msgid   "Generating a client certificate. This may take a minute..."
 msgstr  ""
 
-#: lxc/list.go:377
+#: lxc/list.go:407
 msgid   "IPV4"
 msgstr  ""
 
-#: lxc/list.go:378
+#: lxc/list.go:408
 msgid   "IPV6"
 msgstr  ""
 
@@ -385,7 +385,7 @@ msgstr  ""
 msgid   "Ignore aliases when determining what command to run."
 msgstr  ""
 
-#: lxc/action.go:40
+#: lxc/action.go:41
 msgid   "Ignore the container state (only for start)."
 msgstr  ""
 
@@ -443,7 +443,7 @@ msgstr  ""
 msgid   "Keep the image up to date after initial copy"
 msgstr  ""
 
-#: lxc/list.go:381
+#: lxc/list.go:411
 msgid   "LAST USED AT"
 msgstr  ""
 
@@ -475,7 +475,7 @@ msgid   "List information on LXD servers and containers.\n"
         " lxc info [<remote>:]"
 msgstr  ""
 
-#: lxc/list.go:67
+#: lxc/list.go:68
 msgid   "Lists the available resources.\n"
         "\n"
         "lxc list [resource] [filters] [--format table|json] [-c columns] [--fast]\n"
@@ -490,7 +490,13 @@ msgid   "Lists the available resources.\n"
         " * \"s.privileged=1\" will do the same\n"
         "* A regular expression matching a configuration item or its value. (e.g. volatile.eth0.hwaddr=00:16:3e:.*)\n"
         "\n"
-        "Columns for table format are:\n"
+        "The -c option takes a comma separated list of arguments that control\n"
+        "which container attributes to output when displaying in table format.\n"
+        "Column arguments are either pre-defined shorthand chars (see below),\n"
+        "or (extended) config keys.  Commas between consecutive shorthand chars\n"
+        "are optional.\n"
+        "\n"
+        "Pre-defined shorthand chars:\n"
         "* 4 - IPv4 address\n"
         "* 6 - IPv6 address\n"
         "* a - architecture\n"
@@ -503,8 +509,21 @@ msgid   "Lists the available resources.\n"
         "* S - number of snapshots\n"
         "* t - type (persistent or ephemeral)\n"
         "\n"
+        "Config key syntax: key[:name][:maxWidth]\n"
+        "* key      - The (extended) config key to display\n"
+        "* name     - Name to display in the column header, defaults to the key\n"
+        "             if not specified or if empty (to allow defining maxWidth\n"
+        "             without a custom name, e.g. user.key::0)\n"
+        "* maxWidth - Max width of the column (longer results are truncated).\n"
+        "             -1 == unlimited\n"
+        "              0 == width of column header\n"
+        "             >0 == max width in chars\n"
+        "             Default is -1 (unlimited)\n"
+        "\n"
         "Default column layout: ns46tS\n"
-        "Fast column layout: nsacPt"
+        "Fast column layout: nsacPt\n"
+        "\n"
+        "Example: lxc list -c n,volatile.base_image:\"BASE IMAGE\":0,s46,volatile.eth0.hwaddr:MAC\n"
 msgstr  ""
 
 #: lxc/info.go:225
@@ -719,11 +738,11 @@ msgid   "Move containers within or in between lxd instances.\n"
         "    Rename a local container.\n"
 msgstr  ""
 
-#: lxc/action.go:63
+#: lxc/action.go:64
 msgid   "Must supply container name for: "
 msgstr  ""
 
-#: lxc/list.go:382 lxc/remote.go:376
+#: lxc/list.go:412 lxc/remote.go:376
 msgid   "NAME"
 msgstr  ""
 
@@ -769,15 +788,15 @@ msgstr  ""
 msgid   "Override the terminal mode (auto, interactive or non-interactive)"
 msgstr  ""
 
-#: lxc/list.go:466
+#: lxc/list.go:556
 msgid   "PERSISTENT"
 msgstr  ""
 
-#: lxc/list.go:383
+#: lxc/list.go:413
 msgid   "PID"
 msgstr  ""
 
-#: lxc/list.go:384
+#: lxc/list.go:414
 msgid   "PROFILES"
 msgstr  ""
 
@@ -930,11 +949,11 @@ msgstr  ""
 msgid   "SIZE"
 msgstr  ""
 
-#: lxc/list.go:385
+#: lxc/list.go:415
 msgid   "SNAPSHOTS"
 msgstr  ""
 
-#: lxc/list.go:386
+#: lxc/list.go:416
 msgid   "STATE"
 msgstr  ""
 
@@ -1018,7 +1037,7 @@ msgstr  ""
 msgid   "Stopping container failed!"
 msgstr  ""
 
-#: lxc/action.go:39
+#: lxc/action.go:40
 msgid   "Store the container state (only for stop)."
 msgstr  ""
 
@@ -1030,7 +1049,7 @@ msgstr  ""
 msgid   "Swap (peak)"
 msgstr  ""
 
-#: lxc/list.go:387
+#: lxc/list.go:417
 msgid   "TYPE"
 msgstr  ""
 
@@ -1072,7 +1091,7 @@ msgstr  ""
 msgid   "Transferring image: %d%%"
 msgstr  ""
 
-#: lxc/action.go:93 lxc/launch.go:132
+#: lxc/action.go:94 lxc/launch.go:132
 #, c-format
 msgid   "Try `lxc info --show-log %s` for more info"
 msgstr  ""
@@ -1139,7 +1158,7 @@ msgstr  ""
 msgid   "bad number of things scanned from image, container or snapshot"
 msgstr  ""
 
-#: lxc/action.go:89
+#: lxc/action.go:90
 msgid   "bad result type from action"
 msgstr  ""
 
diff --git a/shared/container.go b/shared/container.go
index 46fdb2f..bf997d1 100644
--- a/shared/container.go
+++ b/shared/container.go
@@ -1,6 +1,9 @@
 package shared
 
 import (
+	"fmt"
+	"strconv"
+	"strings"
 	"time"
 )
 
@@ -141,3 +144,116 @@ type ProfileConfig struct {
 	Description string            `json:"description"`
 	Devices     Devices           `json:"devices"`
 }
+
+func isInt64(value string) error {
+	if value == "" {
+		return nil
+	}
+
+	_, err := strconv.ParseInt(value, 10, 64)
+	if err != nil {
+		return fmt.Errorf("Invalid value for an integer: %s", value)
+	}
+
+	return nil
+}
+
+func isBool(value string) error {
+	if value == "" {
+		return nil
+	}
+
+	if !StringInSlice(strings.ToLower(value), []string{"true", "false", "yes", "no", "1", "0", "on", "off"}) {
+		return fmt.Errorf("Invalid value for a boolean: %s", value)
+	}
+
+	return nil
+}
+
+func isOneOf(value string, valid []string) error {
+	if value == "" {
+		return nil
+	}
+
+	if !StringInSlice(value, valid) {
+		return fmt.Errorf("Invalid value: %s (not one of %s)", value, valid)
+	}
+
+	return nil
+}
+
+func isAny(value string) error {
+	return nil
+}
+
+// KnownContainerConfigKeys maps all fully defined, well-known config keys
+// to an appropriate checker function, which validates whether or not a
+// given value is syntactically legal.
+var KnownContainerConfigKeys = map[string]func(value string) error{
+	"boot.autostart":             isBool,
+	"boot.autostart.delay":       isInt64,
+	"boot.autostart.priority":    isInt64,
+	"boot.host_shutdown_timeout": isInt64,
+
+	"limits.cpu":           isAny,
+	"limits.disk.priority": isInt64,
+	"limits.memory":        isAny,
+	"limits.memory.enforce": func(value string) error {
+		return isOneOf(value, []string{"soft", "hard"})
+	},
+	"limits.memory.swap":          isBool,
+	"limits.memory.swap.priority": isInt64,
+	"limits.network.priority":     isInt64,
+	"limits.processes":            isInt64,
+
+	"linux.kernel_modules": isAny,
+
+	"security.privileged":                 isBool,
+	"security.nesting":                    isBool,
+	"security.syscalls.blacklist_default": isBool,
+	"security.syscalls.blacklist_compat":  isBool,
+	"security.syscalls.blacklist":         isAny,
+	"security.syscalls.whitelist":         isAny,
+
+	// Caller is responsible for full validation of any raw.* value
+	"raw.apparmor": isAny,
+	"raw.lxc":      isAny,
+	"raw.seccomp":  isAny,
+
+	"volatile.apply_template":   isAny,
+	"volatile.base_image":       isAny,
+	"volatile.last_state.idmap": isAny,
+	"volatile.last_state.power": isAny,
+}
+
+// ConfigKeyChecker returns a function that will check whether or not
+// a provide value is valid for the associate config key.  Returns an
+// error if the key is not known.  The checker function only performs
+// syntactic checking of the value, semantic and usage checking must
+// be done by the caller.  User defined keys are always considered to
+// be valid, e.g. user.* and environment.* keys.
+func ConfigKeyChecker(key string) (func(value string) error, error) {
+	if f, ok := KnownContainerConfigKeys[key]; ok {
+		return f, nil
+	}
+
+	if strings.HasPrefix(key, "volatile.") {
+		if strings.HasSuffix(key, ".hwaddr") {
+			return isAny, nil
+		}
+
+		if strings.HasSuffix(key, ".name") {
+			return isAny, nil
+		}
+	}
+
+	if strings.HasPrefix(key, "environment.") {
+		return isAny, nil
+	}
+
+	if strings.HasPrefix(key, "user.") {
+		return isAny, nil
+	}
+
+	return nil, fmt.Errorf("Bad key: %s", key)
+}
diff --git a/shared/util.go b/shared/util.go
index ab6d061..b6539c2 100644
--- a/shared/util.go
+++ b/shared/util.go
@@ -704,6 +704,18 @@ func GetByteSizeString(input int64) string {
 	return fmt.Sprintf("%.2fEB", value)
 }
 
+// RemoveDuplicatesFromString removes all duplicates of the string 'sep'
+// from the specified string 's'.  Leading and trailing occurences of sep
+// are NOT removed (duplicate leading/trailing are).  Performs poorly if
+// there are multiple consecutive redundant separators.
+func RemoveDuplicatesFromString(s string, sep string) string {
+	dup := sep + sep
+	for s = strings.Replace(s, dup, sep, -1); strings.Contains(s, dup); s = strings.Replace(s, dup, sep, -1) {
+
+	}
+	return s
+}
+
 type TransferProgress struct {
 	io.Reader
 	percentage float64


More information about the lxc-devel mailing list