Trace all processes in a container.

This commit is contained in:
Tom Wilkie
2015-09-17 10:46:28 +00:00
committed by Tom Wilkie
parent 38e7c7c560
commit 3e4b3ad0eb
5 changed files with 87 additions and 12 deletions

View File

@@ -46,13 +46,8 @@ def ignore_error(f):
@app.route('/')
def hello():
counter_future = pool.submit(do_redis)
search_future = pool.submit(do_search)
qotd_future = pool.submit(do_qotd)
result = 'Hello World! I have been seen %s times.' % ignore_error(counter_future.result)
result += ignore_error(search_future.result)
result += ignore_error(qotd_future.result)
return result
qotd_msg = do_qotd()
return qotd_msg
if __name__ == "__main__":
logging.basicConfig(format='%(asctime)s %(levelname)s %(filename)s:%(lineno)d - %(message)s', level=logging.INFO)

View File

@@ -11,6 +11,7 @@ import (
dockerClient "github.com/fsouza/go-dockerclient"
"github.com/weaveworks/scope/probe/docker"
"github.com/weaveworks/scope/probe/process"
)
func respondWith(w http.ResponseWriter, code int, response interface{}) {
@@ -23,10 +24,30 @@ func respondWith(w http.ResponseWriter, code int, response interface{}) {
}
}
func (t *tracer) pidsForContainer(id string) ([]int, error) {
var container docker.Container
t.docker.WalkContainers(func(c docker.Container) {
if c.ID() == id {
container = c
}
})
if container == nil {
return []int{}, fmt.Errorf("Not Found")
}
pidTree, err := process.NewTree(process.NewWalker("/proc"))
if err != nil {
return []int{}, err
}
return pidTree.GetChildren(container.PID())
}
func (t *tracer) http(port int) {
router := mux.NewRouter()
router.Methods("GET").Path("/containers").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
router.Methods("GET").Path("/container").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
containers := []*dockerClient.Container{}
t.docker.WalkContainers(func(container docker.Container) {
containers = append(containers, container.Container())
@@ -35,6 +56,34 @@ func (t *tracer) http(port int) {
respondWith(w, http.StatusOK, containers)
})
router.Methods("POST").Path("/container/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
children, err := t.pidsForContainer(id)
if err != nil {
respondWith(w, http.StatusBadRequest, err.Error())
return
}
for _, pid := range children {
t.ptrace.TraceProcess(pid)
}
w.WriteHeader(204)
})
router.Methods("DELETE").Path("/container/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := mux.Vars(r)["id"]
children, err := t.pidsForContainer(id)
if err != nil {
respondWith(w, http.StatusBadRequest, err.Error())
return
}
for _, pid := range children {
t.ptrace.StopTracing(pid)
}
w.WriteHeader(204)
})
router.Methods("GET").Path("/pid").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
respondWith(w, http.StatusOK, t.ptrace.AttachedPIDs())
})
@@ -61,6 +110,8 @@ func (t *tracer) http(port int) {
w.WriteHeader(204)
})
router.Methods("GET").Path("/traces").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
respondWith(w, http.StatusOK, t.store.Traces())
})

View File

@@ -13,6 +13,7 @@ const (
READ = 0
WRITE = 1
CLOSE = 3
STAT = 4
MMAP = 9
MPROTECT = 10
MADVISE = 28
@@ -96,7 +97,7 @@ func (t *thread) syscallStopped() {
t.handleIO(&t.callRegs, &t.resultRegs)
// we can ignore these syscalls
case SETROBUSTLIST, GETID, MMAP, MPROTECT, MADVISE, SOCKET, CLONE:
case SETROBUSTLIST, GETID, MMAP, MPROTECT, MADVISE, SOCKET, CLONE, STAT:
return
default:

View File

@@ -60,7 +60,7 @@
}
function updateContainers() {
$.get("/containers").done(function (data) {
$.get("/container").done(function (data) {
data.sort(function (a, b) {
if (a.Name > b.Name) {
return 1;
@@ -99,14 +99,14 @@
$("body").on("click", "div.mainview button.start", function() {
var id = $(this).parent().data("containerId")
var container = containersByID[id]
$.post(sprintf("/pid/%d", container.State.Pid))
$.post(sprintf("/container/%s", container.Id))
})
$("body").on("click", "div.mainview button.stop", function() {
var id = $(this).parent().data("containerId")
var container = containersByID[id]
$.ajax({
url: sprintf("/pid/%d", container.State.Pid),
url: sprintf("/container/%s", container.Id),
type: 'DELETE',
});
})

View File

@@ -7,6 +7,7 @@ import (
// Tree represents all processes on the machine.
type Tree interface {
GetParent(pid int) (int, error)
GetChildren(pid int) ([]int, error)
}
type tree struct {
@@ -32,3 +33,30 @@ func (pt *tree) GetParent(pid int) (int, error) {
return proc.PPID, nil
}
// GetChildren
func (pt *tree) GetChildren(pid int) ([]int, error) {
_, ok := pt.processes[pid]
if !ok {
return []int{}, fmt.Errorf("PID %d not found", pid)
}
var isChild func(id int) bool
isChild = func(id int) bool {
p, ok := pt.processes[id]
if !ok || p.PPID == 0 {
return false
} else if p.PPID == pid {
return true
}
return isChild(p.PPID)
}
children := []int{pid}
for id, _ := range pt.processes {
if isChild(id) {
children = append(children, id)
}
}
return children, nil
}