diff options
Diffstat (limited to 'pkg/api/server')
-rw-r--r-- | pkg/api/server/register_images.go | 32 | ||||
-rw-r--r-- | pkg/api/server/register_pods.go | 29 | ||||
-rw-r--r-- | pkg/api/server/server.go | 44 |
3 files changed, 92 insertions, 13 deletions
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 6cc6f0cfa..f59dca6f5 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -822,6 +822,38 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/import"), s.APIHandler(libpod.ImagesImport)).Methods(http.MethodPost) + // swagger:operation GET /libpod/images/remove libpod libpodImagesRemove + // --- + // tags: + // - images + // summary: Remove one or more images from the storage. + // description: Remove one or more images from the storage. + // parameters: + // - in: query + // name: images + // description: Images IDs or names to remove. + // type: array + // items: + // type: string + // - in: query + // name: all + // description: Remove all images. + // type: boolean + // default: true + // - in: query + // name: force + // description: Force image removal (including containers using the images). + // type: boolean + // produces: + // - application/json + // responses: + // 200: + // $ref: "#/responses/DocsLibpodImagesRemoveResponse" + // 400: + // $ref: "#/responses/BadParamError" + // 500: + // $ref: '#/responses/InternalError' + r.Handle(VersionedPath("/libpod/images/remove"), s.APIHandler(libpod.ImagesRemove)).Methods(http.MethodGet) // swagger:operation POST /libpod/images/pull libpod libpodImagesPull // --- // tags: diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go index 63060af41..4156dd86b 100644 --- a/pkg/api/server/register_pods.go +++ b/pkg/api/server/register_pods.go @@ -286,9 +286,36 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // 200: // $ref: "#/responses/DocsPodTopResponse" // 404: - // $ref: "#/responses/NoSuchContainer" + // $ref: "#/responses/NoSuchPod" // 500: // $ref: "#/responses/InternalError" r.Handle(VersionedPath("/libpod/pods/{name}/top"), s.APIHandler(libpod.PodTop)).Methods(http.MethodGet) + // swagger:operation GET /libpod/pods/stats pods statsPod + // --- + // tags: + // - pods + // summary: Get stats for one or more pods + // description: Display a live stream of resource usage statistics for the containers in one or more pods + // parameters: + // - in: query + // name: all + // description: Provide statistics for all running pods. + // type: boolean + // - in: query + // name: namesOrIDs + // description: Names or IDs of pods. + // type: array + // items: + // type: string + // produces: + // - application/json + // responses: + // 200: + // $ref: "#/responses/DocsPodTopResponse" + // 404: + // $ref: "#/responses/NoSuchPod" + // 500: + // $ref: "#/responses/InternalError" + r.Handle(VersionedPath("/libpod/pods/stats"), s.APIHandler(libpod.PodStats)).Methods(http.MethodGet) return nil } diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index 5f1a86183..ce2d152e0 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -8,6 +8,7 @@ import ( "os" "os/signal" "runtime" + goRuntime "runtime" "strings" "sync" "syscall" @@ -30,6 +31,7 @@ type APIServer struct { net.Listener // mux for routing HTTP API calls to libpod routines context.CancelFunc // Stop APIServer idleTracker *IdleTracker // Track connections to support idle shutdown + pprof *http.Server // Sidecar http server for providing performance data } // Number of seconds to wait for next request, if exceeded shutdown server @@ -51,7 +53,7 @@ func NewServerWithSettings(runtime *libpod.Runtime, duration time.Duration, list func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Listener) (*APIServer, error) { // If listener not provided try socket activation protocol if listener == nil { - if _, found := os.LookupEnv("LISTEN_FDS"); !found { + if _, found := os.LookupEnv("LISTEN_PID"); !found { return nil, errors.Errorf("Cannot create API Server, no listener provided and socket activation protocol is not active.") } @@ -125,7 +127,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li if err != nil { methods = []string{"<N/A>"} } - logrus.Debugf("Methods: %s Path: %s", strings.Join(methods, ", "), path) + logrus.Debugf("Methods: %6s Path: %s", strings.Join(methods, ", "), path) return nil }) } @@ -145,6 +147,20 @@ func (s *APIServer) Serve() error { _ = s.Shutdown() }() + if logrus.IsLevelEnabled(logrus.DebugLevel) { + go func() { + pprofMux := mux.NewRouter() + pprofMux.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux) + goRuntime.SetMutexProfileFraction(1) + goRuntime.SetBlockProfileRate(1) + s.pprof = &http.Server{Addr: "localhost:8888", Handler: pprofMux} + err := s.pprof.ListenAndServe() + if err != nil && err != http.ErrServerClosed { + logrus.Warn("Profiler Service failed: " + err.Error()) + } + }() + } + go func() { err := s.Server.Serve(s.Listener) if err != nil && err != http.ErrServerClosed { @@ -166,25 +182,29 @@ func (s *APIServer) Serve() error { // Shutdown is a clean shutdown waiting on existing clients func (s *APIServer) Shutdown() error { + if s.idleTracker.Duration == UnlimitedServiceDuration { + logrus.Debug("APIServer.Shutdown ignored as Duration is UnlimitedService.") + return nil + } + + // Gracefully shutdown server(s), duration of wait same as idle window + // TODO: Should we really wait the idle window for shutdown? + ctx, cancel := context.WithTimeout(context.Background(), s.idleTracker.Duration) + defer cancel() + if logrus.IsLevelEnabled(logrus.DebugLevel) { _, file, line, _ := runtime.Caller(1) logrus.Debugf("APIServer.Shutdown by %s:%d, %d/%d connection(s)", file, line, s.idleTracker.ActiveConnections(), s.idleTracker.TotalConnections()) + if err := s.pprof.Shutdown(ctx); err != nil { + logrus.Warn("Failed to cleanly shutdown pprof Server: " + err.Error()) + } } - // Duration == 0 flags no auto-shutdown of the server - if s.idleTracker.Duration == 0 { - logrus.Debug("APIServer.Shutdown ignored as Duration == 0") - return nil - } - - // Gracefully shutdown server, duration of wait same as idle window - ctx, cancel := context.WithTimeout(context.Background(), s.idleTracker.Duration) - defer cancel() go func() { err := s.Server.Shutdown(ctx) if err != nil && err != context.Canceled && err != http.ErrServerClosed { - logrus.Errorf("Failed to cleanly shutdown APIServer: %s", err.Error()) + logrus.Error("Failed to cleanly shutdown APIServer: " + err.Error()) } }() <-ctx.Done() |