From 379e5aac5795fd4fc7b33a808fa1f3936e790434 Mon Sep 17 00:00:00 2001 From: Rohit Jnagal Date: Wed, 13 May 2015 21:49:29 +0000 Subject: [PATCH] Add manager methods to get docker status and images. This is only meant to populate /docker UI page. --- container/docker/handler.go | 24 ++++++++ manager/manager.go | 109 ++++++++++++++++++++++++++++++++++++ manager/manager_mock.go | 10 ++++ 3 files changed, 143 insertions(+) diff --git a/container/docker/handler.go b/container/docker/handler.go index a6c7ec87..2e3f8cf4 100644 --- a/container/docker/handler.go +++ b/container/docker/handler.go @@ -340,3 +340,27 @@ func (self *dockerContainerHandler) StopWatchingSubcontainers() error { func (self *dockerContainerHandler) Exists() bool { return containerLibcontainer.Exists(*dockerRootDir, *dockerRunDir, self.id) } + +func DockerInfo() (map[string]string, error) { + client, err := docker.NewClient(*ArgDockerEndpoint) + if err != nil { + return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err) + } + info, err := client.Info() + if err != nil { + return nil, err + } + return info.Map(), nil +} + +func DockerImages() ([]docker.APIImages, error) { + client, err := docker.NewClient(*ArgDockerEndpoint) + if err != nil { + return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err) + } + images, err := client.ListImages(docker.ListImagesOptions{All: false}) + if err != nil { + return nil, err + } + return images, nil +} diff --git a/manager/manager.go b/manager/manager.go index c1a83212..f2092e4a 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -100,6 +100,12 @@ type Manager interface { GetPastEvents(request *events.Request) ([]*info.Event, error) CloseEventChannel(watch_id int) + + // Get status information about docker. + DockerInfo() (DockerStatus, error) + + // Get details about interesting docker images. + DockerImages() ([]DockerImage, error) } // New takes a memory storage and returns a new manager. @@ -157,6 +163,8 @@ func New(memoryStorage *memory.InMemoryStorage, sysfs sysfs.SysFs) (Manager, err glog.Errorf("Registration of the raw container factory failed: %v", err) } + newManager.DockerInfo() + newManager.DockerImages() return newManager, nil } @@ -1021,3 +1029,104 @@ func parseEventsStoragePolicy() events.StoragePolicy { return policy } + +type DockerStatus struct { + Version string `json:"version"` + KernelVersion string `json:"kernel_version"` + OS string `json:"os"` + Hostname string `json:"hostname"` + RootDir string `json:"root_dir"` + Driver string `json:"driver"` + DriverStatus map[string]string `json:"driver_status"` + ExecDriver string `json:"exec_driver"` + NumImages int `json:"num_images"` + NumContainers int `json:"num_containers"` +} + +type DockerImage struct { + ID string `json:"id"` + RepoTags []string `json:"repo_tags"` // repository name and tags. + Created int64 `json:"created"` // unix time since creation. + VirtualSize int64 `json:"virtual_size"` + Size int64 `json:"size"` +} + +func (m *manager) DockerImages() ([]DockerImage, error) { + images, err := docker.DockerImages() + if err != nil { + return nil, err + } + out := []DockerImage{} + const unknownTag = ":" + for _, image := range images { + if len(image.RepoTags) == 1 && image.RepoTags[0] == unknownTag { + // images with repo or tags are uninteresting. + continue + } + di := DockerImage{ + ID: image.ID, + RepoTags: image.RepoTags, + Created: image.Created, + VirtualSize: image.VirtualSize, + Size: image.Size, + } + out = append(out, di) + } + return out, nil +} + +func (m *manager) DockerInfo() (DockerStatus, error) { + info, err := docker.DockerInfo() + if err != nil { + return DockerStatus{}, err + } + out := DockerStatus{} + out.Version = m.versionInfo.DockerVersion + if val, ok := info["KernelVersion"]; ok { + out.KernelVersion = val + } + if val, ok := info["OperatingSystem"]; ok { + out.OS = val + } + if val, ok := info["Name"]; ok { + out.Hostname = val + } + if val, ok := info["DockerRootDir"]; ok { + out.RootDir = val + } + if val, ok := info["Driver"]; ok { + out.Driver = val + } + if val, ok := info["ExecutionDriver"]; ok { + out.ExecDriver = val + } + if val, ok := info["Images"]; ok { + n, err := strconv.Atoi(val) + if err == nil { + out.NumImages = n + } + } + if val, ok := info["Containers"]; ok { + n, err := strconv.Atoi(val) + if err == nil { + out.NumContainers = n + } + } + // cut, trim, cut - Example format: + // DriverStatus=[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirperm1 Supported","false"]] + if val, ok := info["DriverStatus"]; ok { + out.DriverStatus = make(map[string]string) + val = strings.TrimPrefix(val, "[[") + val = strings.TrimSuffix(val, "]]") + vals := strings.Split(val, "],[") + for _, v := range vals { + kv := strings.Split(v, "\",\"") + if len(kv) != 2 { + continue + } else { + out.DriverStatus[strings.Trim(kv[0], "\"")] = strings.Trim(kv[1], "\"") + } + } + } + return out, nil +} diff --git a/manager/manager_mock.go b/manager/manager_mock.go index bcc872d9..75204118 100644 --- a/manager/manager_mock.go +++ b/manager/manager_mock.go @@ -104,3 +104,13 @@ func (c *ManagerMock) GetProcessList(name string, options v2.RequestOptions) ([] args := c.Called() return args.Get(0).([]v2.ProcessInfo), args.Error(1) } + +func (c *ManagerMock) DockerInfo() (DockerStatus, error) { + args := c.Called() + return args.Get(0).(DockerStatus), args.Error(1) +} + +func (c *ManagerMock) DockerImages() ([]DockerImage, error) { + args := c.Called() + return args.Get(0).([]DockerImage), args.Error(1) +}