Windows: Minimal docker top implementation

Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
John Howard 2016-03-20 15:58:23 -07:00
parent 9ea7e082ef
commit 52237787fa
7 changed files with 92 additions and 7 deletions

View file

@ -1,12 +1,32 @@
package daemon
import (
"fmt"
"errors"
"strconv"
"github.com/docker/engine-api/types"
)
// ContainerTop is not supported on Windows and returns an error.
func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) {
return nil, fmt.Errorf("Top is not supported on Windows")
// ContainerTop is a minimal implementation on Windows currently.
// TODO Windows: This needs more work, but needs platform API support.
// All we can currently return (particularly in the case of Hyper-V containers)
// is a PID and the command.
func (daemon *Daemon) ContainerTop(containerID string, psArgs string) (*types.ContainerProcessList, error) {
// It's really not an equivalent to linux 'ps' on Windows
if psArgs != "" {
return nil, errors.New("Windows does not support arguments to top")
}
s, err := daemon.containerd.Summary(containerID)
if err != nil {
return nil, err
}
procList := &types.ContainerProcessList{}
for _, v := range s {
procList.Titles = append(procList.Titles, strconv.Itoa(int(v.Pid))+" "+v.Command)
}
return procList, nil
}

View file

@ -299,6 +299,12 @@ func (clnt *client) GetPidsForContainer(containerID string) ([]int, error) {
return pids, nil
}
// Summary returns a summary of the processes running in a container.
// This is a no-op on Linux.
func (clnt *client) Summary(containerID string) ([]Summary, error) {
return nil, nil
}
func (clnt *client) getContainerdContainer(containerID string) (*containerd.Container, error) {
resp, err := clnt.remote.apiClient.State(context.Background(), &containerd.StateRequest{Id: containerID})
if err != nil {

View file

@ -303,6 +303,7 @@ func (clnt *client) Create(containerID string, spec Spec, options ...CreateOptio
client: clnt,
friendlyName: InitFriendlyName,
},
commandLine: strings.Join(spec.Process.Args, " "),
},
processes: make(map[string]*process),
},
@ -396,6 +397,7 @@ func (clnt *client) AddProcess(containerID, processFriendlyName string, procToAd
client: clnt,
systemPid: pid,
},
commandLine: createProcessParms.CommandLine,
}
// Make sure the lock is not held while calling back into the daemon
@ -508,9 +510,53 @@ func (clnt *client) Restore(containerID string, unusedOnWindows ...CreateOption)
})
}
// GetPidsForContainers is not implemented on Windows.
// GetPidsForContainer returns a list of process IDs running in a container.
// Although implemented, this is not used in Windows.
func (clnt *client) GetPidsForContainer(containerID string) ([]int, error) {
return nil, errors.New("GetPidsForContainer: GetPidsForContainer() not implemented")
var pids []int
clnt.lock(containerID)
defer clnt.unlock(containerID)
cont, err := clnt.getContainer(containerID)
if err != nil {
return nil, err
}
// Add the first process
pids = append(pids, int(cont.containerCommon.systemPid))
// And add all the exec'd processes
for _, p := range cont.processes {
pids = append(pids, int(p.processCommon.systemPid))
}
return pids, nil
}
// Summary returns a summary of the processes running in a container.
// This is present in Windows to support docker top. In linux, the
// engine shells out to ps to get process information. On Windows, as
// the containers could be Hyper-V containers, they would not be
// visible on the container host. However, libcontainerd does have
// that information.
func (clnt *client) Summary(containerID string) ([]Summary, error) {
var s []Summary
clnt.lock(containerID)
defer clnt.unlock(containerID)
cont, err := clnt.getContainer(containerID)
if err != nil {
return nil, err
}
// Add the first process
s = append(s, Summary{
Pid: cont.containerCommon.systemPid,
Command: cont.ociSpec.Process.Args[0]})
// And add all the exec'd processes
for _, p := range cont.processes {
s = append(s, Summary{
Pid: p.processCommon.systemPid,
Command: p.commandLine})
}
return s, nil
}
// UpdateResources updates resources for a running container.

View file

@ -8,7 +8,10 @@ import (
type process struct {
processCommon
// Platform specific fields are below here. There are none presently on Windows.
// Platform specific fields are below here.
// commandLine is to support returning summary information for docker top
commandLine string
}
func openReaderFromPipe(p io.ReadCloser) io.Reader {

View file

@ -42,6 +42,7 @@ type Client interface {
Restore(containerID string, options ...CreateOption) error
Stats(containerID string) (*Stats, error)
GetPidsForContainer(containerID string) ([]int, error)
Summary(containerID string) ([]Summary, error)
UpdateResources(containerID string, resources Resources) error
}

View file

@ -36,6 +36,9 @@ type Process struct {
// Stats contains a stats properties from containerd.
type Stats containerd.StatsResponse
// Summary container a container summary from containerd
type Summary struct{}
// User specifies linux specific user and group information for the container's
// main process.
type User specs.User

View file

@ -11,6 +11,12 @@ type Process windowsoci.Process
// User specifies user information for the containers main process.
type User windowsoci.User
// Summary container a container summary from containerd
type Summary struct {
Pid uint32
Command string
}
// Stats contains a stats properties from containerd.
type Stats struct{}