From 3048ff7e643f1b428f88ceba08f06b0bacdddfa7 Mon Sep 17 00:00:00 2001 From: Michael Wan Date: Sun, 15 Apr 2018 13:03:14 -0400 Subject: [PATCH] feature: add snapshotter info in container json Signed-off-by: Michael Wan --- apis/server/container_bridge.go | 21 ++++---- apis/swagger.yml | 16 ++++++ apis/types/container_json.go | 29 +++++++++++ apis/types/graph_driver_data.go | 2 +- apis/types/snapshotter_data.go | 88 +++++++++++++++++++++++++++++++++ ctrd/interface.go | 4 ++ ctrd/snapshot.go | 15 ++++++ daemon/mgr/container.go | 34 +++++++++++++ daemon/mgr/container_types.go | 5 ++ 9 files changed, 202 insertions(+), 12 deletions(-) create mode 100644 apis/types/snapshotter_data.go diff --git a/apis/server/container_bridge.go b/apis/server/container_bridge.go index c83592d7e..0491713b5 100644 --- a/apis/server/container_bridge.go +++ b/apis/server/container_bridge.go @@ -315,18 +315,17 @@ func (s *Server) getContainer(ctx context.Context, rw http.ResponseWriter, req * } container := types.ContainerJSON{ - ID: meta.ID, - Name: meta.Name, - Image: meta.Config.Image, - Created: meta.Created, - State: meta.State, - Config: meta.Config, - HostConfig: meta.HostConfig, + ID: meta.ID, + Name: meta.Name, + Image: meta.Config.Image, + Created: meta.Created, + State: meta.State, + Config: meta.Config, + HostConfig: meta.HostConfig, + Snapshotter: meta.Snapshotter, GraphDriver: &types.GraphDriverData{ - Name: "overlay2", - Data: map[string]string{ - "BaseFS": meta.BaseFS, - }, + Name: meta.Snapshotter.Name, + Data: meta.Snapshotter.Data, }, } diff --git a/apis/swagger.yml b/apis/swagger.yml index 1ac305c3b..ec9dedd4e 100644 --- a/apis/swagger.yml +++ b/apis/swagger.yml @@ -2808,6 +2808,8 @@ definitions: x-nullable: true Config: $ref: "#/definitions/ContainerConfig" + Snapshotter: + $ref: "#/definitions/SnapshotterData" GraphDriver: $ref: "#/definitions/GraphDriverData" Mounts: @@ -2902,6 +2904,20 @@ definitions: type: "string" enum: ["created", "running", "stopped", "paused", "restarting", "removing", "exited", "dead"] + SnapshotterData: + description: "Information about a container's snapshotter." + type: "object" + required: [Name, Data] + properties: + Name: + type: "string" + x-nullable: false + Data: + type: "object" + x-nullable: false + additionalProperties: + type: "string" + GraphDriverData: description: "Information about a container's graph driver." type: "object" diff --git a/apis/types/container_json.go b/apis/types/container_json.go index bf11aca4b..20671e588 100644 --- a/apis/types/container_json.go +++ b/apis/types/container_json.go @@ -88,6 +88,9 @@ type ContainerJSON struct { // The size of files that have been created or changed by this container. SizeRw *int64 `json:"SizeRw,omitempty"` + // snapshotter + Snapshotter *SnapshotterData `json:"Snapshotter,omitempty"` + // The state of the container. State *ContainerState `json:"State,omitempty"` } @@ -138,6 +141,8 @@ type ContainerJSON struct { /* polymorph ContainerJSON SizeRw false */ +/* polymorph ContainerJSON Snapshotter false */ + /* polymorph ContainerJSON State false */ // Validate validates this container JSON @@ -169,6 +174,11 @@ func (m *ContainerJSON) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateSnapshotter(formats); err != nil { + // prop + res = append(res, err) + } + if err := m.validateState(formats); err != nil { // prop res = append(res, err) @@ -255,6 +265,25 @@ func (m *ContainerJSON) validateNetworkSettings(formats strfmt.Registry) error { return nil } +func (m *ContainerJSON) validateSnapshotter(formats strfmt.Registry) error { + + if swag.IsZero(m.Snapshotter) { // not required + return nil + } + + if m.Snapshotter != nil { + + if err := m.Snapshotter.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Snapshotter") + } + return err + } + } + + return nil +} + func (m *ContainerJSON) validateState(formats strfmt.Registry) error { if swag.IsZero(m.State) { // not required diff --git a/apis/types/graph_driver_data.go b/apis/types/graph_driver_data.go index a37f92a82..4c0143707 100644 --- a/apis/types/graph_driver_data.go +++ b/apis/types/graph_driver_data.go @@ -13,7 +13,7 @@ import ( "github.com/go-openapi/validate" ) -// GraphDriverData Information about a container's graph driver. +// GraphDriverData Information about a container's snapshotter. // swagger:model GraphDriverData type GraphDriverData struct { diff --git a/apis/types/snapshotter_data.go b/apis/types/snapshotter_data.go new file mode 100644 index 000000000..2ed25394f --- /dev/null +++ b/apis/types/snapshotter_data.go @@ -0,0 +1,88 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package types + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + strfmt "github.com/go-openapi/strfmt" + + "github.com/go-openapi/errors" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// SnapshotterData Information about a container's snapshotter. +// swagger:model SnapshotterData + +type SnapshotterData struct { + + // data + // Required: true + Data map[string]string `json:"Data"` + + // name + // Required: true + Name string `json:"Name"` +} + +/* polymorph SnapshotterData Data false */ + +/* polymorph SnapshotterData Name false */ + +// Validate validates this snapshotter data +func (m *SnapshotterData) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateData(formats); err != nil { + // prop + res = append(res, err) + } + + if err := m.validateName(formats); err != nil { + // prop + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *SnapshotterData) validateData(formats strfmt.Registry) error { + + if swag.IsZero(m.Data) { // not required + return nil + } + + return nil +} + +func (m *SnapshotterData) validateName(formats strfmt.Registry) error { + + if err := validate.RequiredString("Name", "body", string(m.Name)); err != nil { + return err + } + + return nil +} + +// MarshalBinary interface implementation +func (m *SnapshotterData) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *SnapshotterData) UnmarshalBinary(b []byte) error { + var res SnapshotterData + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/ctrd/interface.go b/ctrd/interface.go index 0e296527d..a7c7198a9 100644 --- a/ctrd/interface.go +++ b/ctrd/interface.go @@ -9,6 +9,7 @@ import ( "github.com/alibaba/pouch/pkg/jsonstream" "github.com/containerd/containerd" + "github.com/containerd/containerd/mount" "github.com/containerd/containerd/snapshots" "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -73,4 +74,7 @@ type SnapshotAPIClient interface { GetSnapshot(ctx context.Context, id string) (snapshots.Info, error) // RemoveSnapshot removes the snapshot by id. RemoveSnapshot(ctx context.Context, id string) error + // GetMounts returns the mounts for the active snapshot transaction identified + // by key. + GetMounts(ctx context.Context, id string) ([]mount.Mount, error) } diff --git a/ctrd/snapshot.go b/ctrd/snapshot.go index 56eb2757b..36de1f4af 100644 --- a/ctrd/snapshot.go +++ b/ctrd/snapshot.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/mount" "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/snapshots" "github.com/opencontainers/image-spec/identity" @@ -62,3 +63,17 @@ func (c *Client) RemoveSnapshot(ctx context.Context, id string) error { return service.Remove(ctx, id) } + +// GetMounts returns the mounts for the active snapshot transaction identified +// by key. +func (c *Client) GetMounts(ctx context.Context, id string) ([]mount.Mount, error) { + wrapperCli, err := c.Get(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get a containerd grpc client: %v", err) + } + + service := wrapperCli.client.SnapshotService(defaultSnapshotterName) + defer service.Close() + + return service.Mounts(ctx, id) +} diff --git a/daemon/mgr/container.go b/daemon/mgr/container.go index 60f23ff60..e25f32ae2 100644 --- a/daemon/mgr/container.go +++ b/daemon/mgr/container.go @@ -409,6 +409,20 @@ func (mgr *ContainerManager) Create(ctx context.Context, name string, config *ty return nil, err } + // Get snapshot UpperDir + var upperDir string + mounts, err := mgr.Client.GetMounts(ctx, id) + if err != nil { + return nil, err + } else if len(mounts) != 1 { + return nil, fmt.Errorf("failed to get snapshot %s mounts: not equals one", id) + } + for _, opt := range mounts[0].Options { + if strings.HasPrefix(opt, "upperdir=") { + upperDir = strings.TrimPrefix(opt, "upperdir=") + } + } + // set lxcfs binds if config.HostConfig.EnableLxcfs && lxcfs.IsLxcfsEnabled { config.HostConfig.Binds = append(config.HostConfig.Binds, lxcfs.LxcfsParentDir+":/var/lib/lxc:shared") @@ -470,6 +484,17 @@ func (mgr *ContainerManager) Create(ctx context.Context, name string, config *ty return nil, err } + // set snapshotter for container + // TODO(ziren): now we only support overlayfs + meta.Snapshotter = &types.SnapshotterData{ + Name: "overlayfs", + Data: map[string]string{}, + } + + if upperDir != "" { + meta.Snapshotter.Data["UpperDir"] = upperDir + } + container := &Container{ meta: meta, } @@ -627,6 +652,9 @@ func (mgr *ContainerManager) createContainerdContainer(ctx context.Context, c *C } c.meta.State.Pid = int64(pid) c.meta.State.ExitCode = 0 + + // set Snapshot MergedDir + c.meta.Snapshotter.Data["MergedDir"] = c.meta.BaseFS } else { c.meta.State.FinishedAt = time.Now().UTC().Format(utils.TimeLayout) c.meta.State.Error = err.Error() @@ -1261,6 +1289,12 @@ func (mgr *ContainerManager) markStoppedAndRelease(c *Container, m *ctrd.Message } } + // unset Snapshot MergedDir. Stop a container will + // delete the containerd container, the merged dir + // will also be deleted, so we should unset the + // container's MergedDir. + c.meta.Snapshotter.Data["MergedDir"] = "" + // update meta if err := c.Write(mgr.Store); err != nil { logrus.Errorf("failed to update meta: %v", err) diff --git a/daemon/mgr/container_types.go b/daemon/mgr/container_types.go index d056eff16..f5adf6e96 100644 --- a/daemon/mgr/container_types.go +++ b/daemon/mgr/container_types.go @@ -104,6 +104,11 @@ type ContainerMeta struct { // exec ids ExecIds string `json:"ExecIDs,omitempty"` + // Snapshotter, GraphDriver is same, keep both + // just for compatibility + // snapshotter informations of container + Snapshotter *types.SnapshotterData `json:"Snapshotter,omitempty"` + // graph driver GraphDriver *types.GraphDriverData `json:"GraphDriver,omitempty"`