[lxc-devel] [lxd/master] Store and show time when container was last started

ctrlrsf on Github lxc-bot at linuxcontainers.org
Mon Jun 6 13:39:56 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 3733 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160606/40f85715/attachment.bin>
-------------- next part --------------
From 6bb9b925fd3eb6f49020944a2060577dd272b79b Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:27:33 -0400
Subject: [PATCH 01/14] Add last_used_at field to rest-api documentation

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 doc/rest-api.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/rest-api.md b/doc/rest-api.md
index 4f50f90..a1390cc 100644
--- a/doc/rest-api.md
+++ b/doc/rest-api.md
@@ -546,6 +546,7 @@ Output:
                 "type": "disk"
             }
         },
+        "last_used_at": "2016-02-16T01:05:05Z",
         "name": "my-container",
         "profiles": [
             "default"

From 22e53578e375dc3d54bc9b0ff54cc22ba3d1173b Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:28:25 -0400
Subject: [PATCH 02/14] Add container_last_used_at extension to api_extensions
 list

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/api_1.0.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index adde9eb..438d11e 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -55,6 +55,7 @@ func api10Get(d *Daemon, r *http.Request) Response {
 		 *  - New HTTPs authentication mechanisms or protocols
 		 */
 		"api_extensions": []string{
+			"container_last_used_at",
 			"storage_zfs_remove_snapshots",
 			"container_host_shutdown_timeout",
 			"container_syscall_filtering",

From ec6e301956b1860d41d8c5405d9394b84c952f00 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:30:09 -0400
Subject: [PATCH 03/14] Add last_use_date column to containers table

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/db.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lxd/db.go b/lxd/db.go
index 17fc137..fa4389e 100644
--- a/lxd/db.go
+++ b/lxd/db.go
@@ -60,6 +60,7 @@ CREATE TABLE IF NOT EXISTS containers (
     ephemeral INTEGER NOT NULL DEFAULT 0,
     stateful INTEGER NOT NULL DEFAULT 0,
     creation_date DATETIME,
+    last_use_date DATETIME,
     UNIQUE (name)
 );
 CREATE TABLE IF NOT EXISTS containers_config (

From ed2a7917f5e03f7a4912180e319ce6cf55d64367 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:30:47 -0400
Subject: [PATCH 04/14] Add new db update to add last_use_date column

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/db_update.go | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lxd/db_update.go b/lxd/db_update.go
index 73ec867..c87047e 100644
--- a/lxd/db_update.go
+++ b/lxd/db_update.go
@@ -17,6 +17,14 @@ import (
 	log "gopkg.in/inconshreveable/log15.v2"
 )
 
+func dbUpdateFromV32(db *sql.DB) error {
+	stmt := `
+ALTER TABLE containers ADD COLUMN last_use_date DATETIME;
+INSERT INTO schema (version, updated_at) VALUES (?, strftime("%s"));`
+	_, err := db.Exec(stmt, 33)
+	return err
+}
+
 func dbUpdateFromV31(db *sql.DB) error {
 	stmt := `
 CREATE TABLE IF NOT EXISTS patches (
@@ -1093,6 +1101,12 @@ func dbUpdate(d *Daemon, prevVersion int) error {
 			return err
 		}
 	}
+	if prevVersion < 33 {
+		err = dbUpdateFromV32(db)
+		if err != nil {
+			return err
+		}
+	}
 
 	return nil
 }

From f222e2b5154b2af82294e919a021b187bbf4d513 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:34:52 -0400
Subject: [PATCH 05/14] Bump DB current version to 33

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/db.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxd/db.go b/lxd/db.go
index fa4389e..616dc32 100644
--- a/lxd/db.go
+++ b/lxd/db.go
@@ -34,7 +34,7 @@ type Profile struct {
 // Profiles will contain a list of all Profiles.
 type Profiles []Profile
 
-const DB_CURRENT_VERSION int = 32
+const DB_CURRENT_VERSION int = 33
 
 // CURRENT_SCHEMA contains the current SQLite SQL Schema.
 const CURRENT_SCHEMA string = `

From 8456602dea26eb0cd0ebe35787201b000b706580 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:36:52 -0400
Subject: [PATCH 06/14] Add LastUsedDate field to containerArgs struct

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/container.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lxd/container.go b/lxd/container.go
index f93fe29..d30792a 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -358,6 +358,7 @@ type containerArgs struct {
 	BaseImage    string
 	Config       map[string]string
 	CreationDate time.Time
+	LastUsedDate time.Time
 	Ctype        containerType
 	Devices      shared.Devices
 	Ephemeral    bool
@@ -420,6 +421,7 @@ type container interface {
 	Name() string
 	Architecture() int
 	CreationDate() time.Time
+	LastUsedDate() time.Time
 	ExpandedConfig() map[string]string
 	ExpandedDevices() shared.Devices
 	LocalConfig() map[string]string

From d7def43dd8c2790a6f436ddd0cb760889ba85d84 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:38:33 -0400
Subject: [PATCH 07/14] Also get and set last_use_date column from containers
 DB

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/db_containers.go | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/lxd/db_containers.go b/lxd/db_containers.go
index 28ce6f0..84dabd3 100644
--- a/lxd/db_containers.go
+++ b/lxd/db_containers.go
@@ -62,14 +62,16 @@ func dbContainerId(db *sql.DB, name string) (int, error) {
 }
 
 func dbContainerGet(db *sql.DB, name string) (containerArgs, error) {
+	var used *time.Time // Hold the db-returned time
+
 	args := containerArgs{}
 	args.Name = name
 
 	ephemInt := -1
 	statefulInt := -1
-	q := "SELECT id, architecture, type, ephemeral, stateful, creation_date FROM containers WHERE name=?"
+	q := "SELECT id, architecture, type, ephemeral, stateful, creation_date, last_use_date FROM containers WHERE name=?"
 	arg1 := []interface{}{name}
-	arg2 := []interface{}{&args.Id, &args.Architecture, &args.Ctype, &ephemInt, &statefulInt, &args.CreationDate}
+	arg2 := []interface{}{&args.Id, &args.Architecture, &args.Ctype, &ephemInt, &statefulInt, &args.CreationDate, &used}
 	err := dbQueryRowScan(db, q, arg1, arg2)
 	if err != nil {
 		return args, err
@@ -87,6 +89,12 @@ func dbContainerGet(db *sql.DB, name string) (containerArgs, error) {
 		args.Stateful = true
 	}
 
+	if used != nil {
+		args.LastUsedDate = *used
+	} else {
+		args.LastUsedDate = time.Unix(0, 0).UTC()
+	}
+
 	config, err := dbContainerConfig(db, args.Id)
 	if err != nil {
 		return args, err
@@ -135,15 +143,16 @@ func dbContainerCreate(db *sql.DB, args containerArgs) (int, error) {
 	}
 
 	args.CreationDate = time.Now().UTC()
+	args.LastUsedDate = time.Unix(0, 0).UTC()
 
-	str := fmt.Sprintf("INSERT INTO containers (name, architecture, type, ephemeral, creation_date, stateful) VALUES (?, ?, ?, ?, ?, ?)")
+	str := fmt.Sprintf("INSERT INTO containers (name, architecture, type, ephemeral, creation_date, last_use_date, stateful) VALUES (?, ?, ?, ?, ?, ?, ?)")
 	stmt, err := tx.Prepare(str)
 	if err != nil {
 		tx.Rollback()
 		return 0, err
 	}
 	defer stmt.Close()
-	result, err := stmt.Exec(args.Name, args.Architecture, args.Ctype, ephemInt, args.CreationDate.Unix(), statefulInt)
+	result, err := stmt.Exec(args.Name, args.Architecture, args.Ctype, ephemInt, args.CreationDate.Unix(), args.LastUsedDate.Unix(), statefulInt)
 	if err != nil {
 		tx.Rollback()
 		return 0, err

From 9d03f180c37389e6ee63c432f8e8c222ae5fb74c Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:45:20 -0400
Subject: [PATCH 08/14] Add DB function that updates last_use_date column

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/db_containers.go | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lxd/db_containers.go b/lxd/db_containers.go
index 84dabd3..3c244a4 100644
--- a/lxd/db_containers.go
+++ b/lxd/db_containers.go
@@ -380,6 +380,12 @@ func dbContainerUpdate(tx *sql.Tx, id int, architecture int, ephemeral bool) err
 	return nil
 }
 
+func dbContainerLastUsedUpdate(db *sql.DB, id int, date time.Time) error {
+	stmt := `UPDATE containers SET last_use_date=? WHERE id=?`
+	_, err := dbExec(db, stmt, date, id)
+	return err
+}
+
 func dbContainerGetSnapshots(db *sql.DB, name string) ([]string, error) {
 	result := []string{}
 

From 33be38575fcd30d85b5a6d866cbbcb2621b1e1d9 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:47:02 -0400
Subject: [PATCH 09/14] Update last use date when container is started

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxd/container_lxc.go | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index ccaa637..2623174 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -99,6 +99,7 @@ func containerLXCCreate(d *Daemon, args containerArgs) (container, error) {
 		cType:        args.Ctype,
 		stateful:     args.Stateful,
 		creationDate: args.CreationDate,
+		lastUsedDate: args.LastUsedDate,
 		profiles:     args.Profiles,
 		localConfig:  args.Config,
 		localDevices: args.Devices,
@@ -196,6 +197,7 @@ func containerLXCLoad(d *Daemon, args containerArgs) (container, error) {
 		architecture: args.Architecture,
 		cType:        args.Ctype,
 		creationDate: args.CreationDate,
+		lastUsedDate: args.LastUsedDate,
 		profiles:     args.Profiles,
 		localConfig:  args.Config,
 		localDevices: args.Devices,
@@ -223,6 +225,7 @@ type containerLXC struct {
 	architecture int
 	cType        containerType
 	creationDate time.Time
+	lastUsedDate time.Time
 	ephemeral    bool
 	id           int
 	name         string
@@ -1131,6 +1134,12 @@ func (c *containerLXC) startCommon() (string, error) {
 		return "", err
 	}
 
+	// Update time container was last started
+	err = dbContainerLastUsedUpdate(c.daemon.db, c.id, time.Now().UTC())
+	if err != nil {
+		fmt.Printf("Error updating last used: %v", err)
+	}
+
 	return configPath, nil
 }
 
@@ -1622,6 +1631,7 @@ func (c *containerLXC) Render() (interface{}, error) {
 			Ephemeral:       c.ephemeral,
 			ExpandedConfig:  c.expandedConfig,
 			ExpandedDevices: c.expandedDevices,
+			LastUsedDate:    c.lastUsedDate,
 			Name:            c.name,
 			Profiles:        c.profiles,
 			Stateful:        c.stateful,
@@ -1642,6 +1652,7 @@ func (c *containerLXC) Render() (interface{}, error) {
 			Ephemeral:       c.ephemeral,
 			ExpandedConfig:  c.expandedConfig,
 			ExpandedDevices: c.expandedDevices,
+			LastUsedDate:    c.lastUsedDate,
 			Name:            c.name,
 			Profiles:        c.profiles,
 			Status:          statusCode.String(),
@@ -4453,6 +4464,9 @@ func (c *containerLXC) Architecture() int {
 func (c *containerLXC) CreationDate() time.Time {
 	return c.creationDate
 }
+func (c *containerLXC) LastUsedDate() time.Time {
+	return c.lastUsedDate
+}
 func (c *containerLXC) ExpandedConfig() map[string]string {
 	return c.expandedConfig
 }

From 8eb869c11a399dc4b026dad3e88e8889b3a0c02d Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:48:00 -0400
Subject: [PATCH 10/14] Add LastUsedDate to ContainerInfo and SnapshotInfo
 structs

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 shared/container.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/shared/container.go b/shared/container.go
index bc919c2..46fdb2f 100644
--- a/shared/container.go
+++ b/shared/container.go
@@ -62,6 +62,7 @@ type SnapshotInfo struct {
 	Ephemeral       bool              `json:"ephemeral"`
 	ExpandedConfig  map[string]string `json:"expanded_config"`
 	ExpandedDevices Devices           `json:"expanded_devices"`
+	LastUsedDate    time.Time         `json:"last_used_at"`
 	Name            string            `json:"name"`
 	Profiles        []string          `json:"profiles"`
 	Stateful        bool              `json:"stateful"`
@@ -75,6 +76,7 @@ type ContainerInfo struct {
 	Ephemeral       bool              `json:"ephemeral"`
 	ExpandedConfig  map[string]string `json:"expanded_config"`
 	ExpandedDevices Devices           `json:"expanded_devices"`
+	LastUsedDate    time.Time         `json:"last_used_at"`
 	Name            string            `json:"name"`
 	Profiles        []string          `json:"profiles"`
 	Stateful        bool              `json:"stateful"`

From 689aa4b69f47079585ca0cf1ace0d4d5f2b6eb92 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:48:42 -0400
Subject: [PATCH 11/14] Add Last Used At column to lxc list command

This column is not displayed by default but can be added to
output with custom table format key 'l'.

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxc/list.go | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/lxc/list.go b/lxc/list.go
index e0e809f..e9d4f32 100644
--- a/lxc/list.go
+++ b/lxc/list.go
@@ -84,6 +84,7 @@ Columns for table format are:
 * 6 - IPv6 address
 * a - architecture
 * c - creation date
+* l - last used date
 * n - name
 * p - pid of container init process
 * P - profiles
@@ -377,6 +378,7 @@ func (c *listCmd) run(config *lxd.Config, args []string) error {
 		'6': column{i18n.G("IPV6"), c.IP6ColumnData, true, false},
 		'a': column{i18n.G("ARCHITECTURE"), c.ArchitectureColumnData, false, false},
 		'c': column{i18n.G("CREATED AT"), c.CreatedColumnData, false, false},
+		'l': column{i18n.G("LAST USED AT"), c.LastUsedColumnData, false, false},
 		'n': column{i18n.G("NAME"), c.nameColumnData, false, false},
 		'p': column{i18n.G("PID"), c.PIDColumnData, true, false},
 		'P': column{i18n.G("PROFILES"), c.ProfilesColumnData, false, false},
@@ -498,3 +500,13 @@ func (c *listCmd) CreatedColumnData(cInfo shared.ContainerInfo, cState *shared.C
 
 	return ""
 }
+
+func (c *listCmd) LastUsedColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string {
+	layout := "2006/01/02 15:04 UTC"
+
+	if cInfo.LastUsedDate.UTC().Unix() != 0 {
+		return cInfo.LastUsedDate.UTC().Format(layout)
+	}
+
+	return ""
+}

From 37164867de993233fda9e146090416d1be259ad5 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:51:58 -0400
Subject: [PATCH 12/14] Update i18n

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 po/lxd.pot | 41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/po/lxd.pot b/po/lxd.pot
index c80ab8f..ca7072a 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-03 07:27-0700\n"
+        "POT-Creation-Date: 2016-06-05 01:51-0400\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:378
+#: lxc/list.go:379
 msgid   "ARCHITECTURE"
 msgstr  ""
 
@@ -145,7 +145,7 @@ msgstr  ""
 msgid   "COMMON NAME"
 msgstr  ""
 
-#: lxc/list.go:379
+#: lxc/list.go:380
 msgid   "CREATED AT"
 msgstr  ""
 
@@ -179,7 +179,7 @@ msgstr  ""
 msgid   "Client certificate stored at server: "
 msgstr  ""
 
-#: lxc/list.go:99 lxc/list.go:100
+#: lxc/list.go:100 lxc/list.go:101
 msgid   "Columns"
 msgstr  ""
 
@@ -281,7 +281,7 @@ msgstr  ""
 msgid   "Device %s removed from %s"
 msgstr  ""
 
-#: lxc/list.go:462
+#: lxc/list.go:464
 msgid   "EPHEMERAL"
 msgstr  ""
 
@@ -330,7 +330,7 @@ msgstr  ""
 msgid   "FINGERPRINT"
 msgstr  ""
 
-#: lxc/list.go:102
+#: lxc/list.go:103
 msgid   "Fast mode (same as --columns=nsacPt"
 msgstr  ""
 
@@ -357,7 +357,7 @@ msgstr  ""
 msgid   "Force using the local unix socket."
 msgstr  ""
 
-#: lxc/image.go:160 lxc/list.go:101
+#: lxc/image.go:160 lxc/list.go:102
 msgid   "Format"
 msgstr  ""
 
@@ -365,11 +365,11 @@ msgstr  ""
 msgid   "Generating a client certificate. This may take a minute..."
 msgstr  ""
 
-#: lxc/list.go:376
+#: lxc/list.go:377
 msgid   "IPV4"
 msgstr  ""
 
-#: lxc/list.go:377
+#: lxc/list.go:378
 msgid   "IPV6"
 msgstr  ""
 
@@ -421,7 +421,7 @@ msgstr  ""
 msgid   "Invalid configuration key"
 msgstr  ""
 
-#: lxc/file.go:190
+#: lxc/file.go:195
 #, c-format
 msgid   "Invalid source %s"
 msgstr  ""
@@ -439,6 +439,10 @@ msgstr  ""
 msgid   "Keep the image up to date after initial copy"
 msgstr  ""
 
+#: lxc/list.go:381
+msgid   "LAST USED AT"
+msgstr  ""
+
 #: lxc/main.go:27
 msgid   "LXD socket not found; is LXD installed and running?"
 msgstr  ""
@@ -487,6 +491,7 @@ msgid   "Lists the available resources.\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"
@@ -696,7 +701,7 @@ msgid   "Monitor activity on the LXD server.\n"
         "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  ""
 
@@ -714,7 +719,7 @@ msgstr  ""
 msgid   "Must supply container name for: "
 msgstr  ""
 
-#: lxc/list.go:380 lxc/remote.go:363
+#: lxc/list.go:382 lxc/remote.go:363
 msgid   "NAME"
 msgstr  ""
 
@@ -760,15 +765,15 @@ msgstr  ""
 msgid   "Override the terminal mode (auto, interactive or non-interactive)"
 msgstr  ""
 
-#: lxc/list.go:464
+#: lxc/list.go:466
 msgid   "PERSISTENT"
 msgstr  ""
 
-#: lxc/list.go:381
+#: lxc/list.go:383
 msgid   "PID"
 msgstr  ""
 
-#: lxc/list.go:382
+#: lxc/list.go:384
 msgid   "PROFILES"
 msgstr  ""
 
@@ -921,11 +926,11 @@ msgstr  ""
 msgid   "SIZE"
 msgstr  ""
 
-#: lxc/list.go:383
+#: lxc/list.go:385
 msgid   "SNAPSHOTS"
 msgstr  ""
 
-#: lxc/list.go:384
+#: lxc/list.go:386
 msgid   "STATE"
 msgstr  ""
 
@@ -1021,7 +1026,7 @@ msgstr  ""
 msgid   "Swap (peak)"
 msgstr  ""
 
-#: lxc/list.go:385
+#: lxc/list.go:387
 msgid   "TYPE"
 msgstr  ""
 

From de0bfc8d962d019c9652308d888b916d33f815e4 Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Sun, 5 Jun 2016 01:52:25 -0400
Subject: [PATCH 13/14] Add test to verify last_used_at field is working
 properly

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 test/suites/basic.sh | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/test/suites/basic.sh b/test/suites/basic.sh
index 41516d5..1000eba 100644
--- a/test/suites/basic.sh
+++ b/test/suites/basic.sh
@@ -202,6 +202,12 @@ test_basic_usage() {
     false
   fi
 
+  # Test last_used_at field is working properly
+  lxc init testimage last-used-at-test
+  lxc list last-used-at-test  --format json | jq -r '.[].last_used_at' | grep '1970-01-01T00:00:00Z'
+  lxc start last-used-at-test
+  lxc list last-used-at-test  --format json | jq -r '.[].last_used_at' | grep -v '1970-01-01T00:00:00Z'
+
   # check that we can set the environment
   lxc exec foo pwd | grep /root
   lxc exec --env BEST_BAND=meshuggah foo env | grep meshuggah

From 31d1e81e09bb401f453971fd504473eb8e3d4dee Mon Sep 17 00:00:00 2001
From: Rene Fragoso <ctrlrsf at gmail.com>
Date: Mon, 6 Jun 2016 08:42:35 -0400
Subject: [PATCH 14/14] Don't show last used at column for remotes running old
 lxd

Prior versions of lxd will not include a last_used_at field in their
JSON response. When the lxd client unmarshalls the JSON response from
an older remote, the LastUsedDate field will be left at its zero
value. Here we check if the LastUsedDate is this zero value so we don't
show the "last used at" column.

Signed-off-by: Rene Fragoso <ctrlrsf at gmail.com>
---
 lxc/list.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lxc/list.go b/lxc/list.go
index e9d4f32..12afac8 100644
--- a/lxc/list.go
+++ b/lxc/list.go
@@ -504,7 +504,7 @@ func (c *listCmd) CreatedColumnData(cInfo shared.ContainerInfo, cState *shared.C
 func (c *listCmd) LastUsedColumnData(cInfo shared.ContainerInfo, cState *shared.ContainerState, cSnaps []shared.SnapshotInfo) string {
 	layout := "2006/01/02 15:04 UTC"
 
-	if cInfo.LastUsedDate.UTC().Unix() != 0 {
+	if !cInfo.LastUsedDate.IsZero() && cInfo.LastUsedDate.UTC().Unix() != 0 {
 		return cInfo.LastUsedDate.UTC().Format(layout)
 	}
 


More information about the lxc-devel mailing list