[lxc-devel] [lxd/master] *: Add lifecycle events to events API

monstermunchkin on Github lxc-bot at linuxcontainers.org
Thu Mar 22 11:36:46 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 373 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180322/a46d30c8/attachment.bin>
-------------- next part --------------
From 6c21fa2b8c3142a06ec3bd157d5aeffeb76a1f25 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Thu, 22 Mar 2018 12:18:59 +0100
Subject: [PATCH] *: Add lifecycle events to events API

Resolves #4322

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 doc/api-extensions.md |  3 +++
 doc/rest-api.md       |  3 ++-
 lxc/monitor.go        |  3 +++
 lxd/container.go      |  6 ++++++
 lxd/container_lxc.go  | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 lxd/events.go         | 11 ++++++++++-
 shared/api/event.go   |  7 +++++++
 shared/version/api.go |  1 +
 8 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 04c8b9219..a8573d0a7 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -443,3 +443,6 @@ The following existing endpoints have been modified:
  * `DELETE /1.0/storage-pool/<pool>/volumes/<type>/<name>` accepts a new target query parameter
  * `POST /1.0/networks` accepts a new target query parameter
  * `GET /1.0/networks/<name>` accepts a new target query parameter
+
+## lifecycle
+This adds a new `lifecycle` message type to the events API.
diff --git a/doc/rest-api.md b/doc/rest-api.md
index 97cc5146f..6f5e541ed 100644
--- a/doc/rest-api.md
+++ b/doc/rest-api.md
@@ -1392,6 +1392,7 @@ The notification types are:
 
  * operation (notification about creation, updates and termination of all background operations)
  * logging (every log entry from the server)
+ * lifecycle (container lifecycle events)
 
 This never returns. Each notification is sent as a separate JSON dict:
 
@@ -1628,7 +1629,7 @@ GET the image as a guest, passing the secret token.
  * Authentication: trusted
  * Operation: async
  * Return: Background operation or standard error
- 
+
 This creates an operation to refresh the specified image from its origin.
 
 ## `/1.0/images/<fingerprint>/secret`
diff --git a/lxc/monitor.go b/lxc/monitor.go
index 318b42a92..c3996d84d 100644
--- a/lxc/monitor.go
+++ b/lxc/monitor.go
@@ -61,6 +61,9 @@ lxc monitor --type=logging
 
 lxc monitor --pretty --type=logging --loglevel=info
     Show a pretty log of messages with info level or higher.
+
+lxc monitor --type=lifecycle
+	Only show lifecycle events.
 `)
 }
 
diff --git a/lxd/container.go b/lxd/container.go
index d1890e1a2..9af69ed1c 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -795,6 +795,12 @@ func containerCreateAsSnapshot(s *state.State, args db.ContainerArgs, sourceCont
 		os.RemoveAll(sourceContainer.StatePath())
 	}
 
+	SendLifecycleEvent("container-snapshot-created",
+		fmt.Sprintf("/1.0/containers/%s", sourceContainer.Name()),
+		map[string]interface{}{
+			"snapshot_name": args.Name,
+		})
+
 	return c, nil
 }
 
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 2b850da3e..b244ccc72 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -439,6 +439,8 @@ func containerLXCCreate(s *state.State, args db.ContainerArgs) (container, error
 	networkUpdateStatic(s, "")
 
 	logger.Info("Created container", ctxMap)
+	SendLifecycleEvent("container-created",
+		fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
 
 	return c, nil
 }
@@ -2386,6 +2388,8 @@ func (c *containerLXC) Start(stateful bool) error {
 	c.restartProxyDevices()
 
 	logger.Info("Started container", ctxMap)
+	SendLifecycleEvent("container-started",
+		fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
 
 	return nil
 }
@@ -2550,6 +2554,8 @@ func (c *containerLXC) Stop(stateful bool) error {
 
 		op.Done(nil)
 		logger.Info("Stopped container", ctxMap)
+		SendLifecycleEvent("container-stopped",
+			fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
 		return nil
 	} else if shared.PathExists(c.StatePath()) {
 		os.RemoveAll(c.StatePath())
@@ -2595,6 +2601,9 @@ func (c *containerLXC) Stop(stateful bool) error {
 	}
 
 	logger.Info("Stopped container", ctxMap)
+	SendLifecycleEvent("container-stopped",
+		fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
+
 	return nil
 }
 
@@ -2642,6 +2651,8 @@ func (c *containerLXC) Shutdown(timeout time.Duration) error {
 	}
 
 	logger.Info("Shut down container", ctxMap)
+	SendLifecycleEvent("container-shutdown",
+		fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
 
 	return nil
 }
@@ -2786,6 +2797,8 @@ func (c *containerLXC) Freeze() error {
 	}
 
 	logger.Info("Froze container", ctxMap)
+	SendLifecycleEvent("container-paused",
+		fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
 
 	return err
 }
@@ -2821,6 +2834,8 @@ func (c *containerLXC) Unfreeze() error {
 	}
 
 	logger.Info("Unfroze container", ctxMap)
+	SendLifecycleEvent("container-resumed",
+		fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
 
 	return err
 }
@@ -3087,6 +3102,9 @@ func (c *containerLXC) Restore(sourceContainer container, stateful bool) error {
 		return nil
 	}
 
+	SendLifecycleEvent("container-snapshot-restored",
+		fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
+
 	// Restart the container
 	if wasRunning {
 		logger.Info("Restored container", ctxMap)
@@ -3206,6 +3224,14 @@ func (c *containerLXC) Delete() error {
 
 	logger.Info("Deleted container", ctxMap)
 
+	if c.IsSnapshot() {
+		SendLifecycleEvent("container-snapshot-deleted",
+			fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
+	} else {
+		SendLifecycleEvent("container-deleted",
+			fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
+	}
+
 	return nil
 }
 
@@ -3326,6 +3352,14 @@ func (c *containerLXC) Rename(newName string) error {
 
 	logger.Info("Renamed container", ctxMap)
 
+	if c.IsSnapshot() {
+		SendLifecycleEvent("container-snapshot-renamed",
+			fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
+	} else {
+		SendLifecycleEvent("container-renamed",
+			fmt.Sprintf("/1.0/containers/%s", c.name), ctxMap)
+	}
+
 	return nil
 }
 
@@ -4565,6 +4599,20 @@ func (c *containerLXC) Update(args db.ContainerArgs, userRequested bool) error {
 	// Success, update the closure to mark that the changes should be kept.
 	undoChanges = false
 
+	SendLifecycleEvent("container-updated",
+		fmt.Sprintf("/1.0/containers/%s", c.name), log.Ctx{"name": c.name,
+			"created":         c.creationDate,
+			"ephemeral":       c.ephemeral,
+			"used":            c.lastUsedDate,
+			"description":     c.description,
+			"architecture":    c.architecture,
+			"expandedConfig":  c.expandedConfig,
+			"expandedDevices": c.expandedDevices,
+			"localConfig":     c.localConfig,
+			"localDevices":    c.localDevices,
+			"profiles":        c.profiles,
+		})
+
 	return nil
 }
 
diff --git a/lxd/events.go b/lxd/events.go
index b1f782657..484b36896 100644
--- a/lxd/events.go
+++ b/lxd/events.go
@@ -44,6 +44,15 @@ func (h eventsHandler) Log(r *log.Record) error {
 	return nil
 }
 
+func SendLifecycleEvent(action, source string,
+	context map[string]interface{}) error {
+	eventSend("lifecycle", api.EventLifecycle{
+		Action:  action,
+		Source:  source,
+		Context: context})
+	return nil
+}
+
 var eventsLock sync.Mutex
 var eventListeners map[string]*eventListener = make(map[string]*eventListener)
 
@@ -76,7 +85,7 @@ func (r *eventsServe) String() string {
 func eventsSocket(r *http.Request, w http.ResponseWriter) error {
 	typeStr := r.FormValue("type")
 	if typeStr == "" {
-		typeStr = "logging,operation"
+		typeStr = "logging,operation,lifecycle"
 	}
 
 	c, err := shared.WebsocketUpgrader.Upgrade(w, r, nil)
diff --git a/shared/api/event.go b/shared/api/event.go
index 8d755a535..f72b5005e 100644
--- a/shared/api/event.go
+++ b/shared/api/event.go
@@ -18,3 +18,10 @@ type EventLogging struct {
 	Level   string            `yaml:"level" json:"level"`
 	Context map[string]string `yaml:"context" json:"context"`
 }
+
+// EventLifecycle represets a lifecycle type event entry
+type EventLifecycle struct {
+	Action  string                 `yaml:"action" json:"action"`
+	Source  string                 `yaml:"source" json:"source"`
+	Context map[string]interface{} `yaml:"context" json:"context"`
+}
diff --git a/shared/version/api.go b/shared/version/api.go
index 6cc82bbd7..009f166c0 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -99,6 +99,7 @@ var APIExtensions = []string{
 	"storage_api_local_volume_handling",
 	"operation_description",
 	"clustering",
+	"event_lifecycle",
 }
 
 // APIExtensionsCount returns the number of available API extensions.


More information about the lxc-devel mailing list