[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