Commit 55c52328 authored by Random-Liu's avatar Random-Liu

Add Status implementation.

parent fc10a25a
...@@ -81,6 +81,8 @@ type RuntimeService interface { ...@@ -81,6 +81,8 @@ type RuntimeService interface {
// UpdateRuntimeConfig updates runtime configuration if specified // UpdateRuntimeConfig updates runtime configuration if specified
UpdateRuntimeConfig(runtimeConfig *runtimeApi.RuntimeConfig) error UpdateRuntimeConfig(runtimeConfig *runtimeApi.RuntimeConfig) error
// Status returns the status of the runtime.
Status() (*runtimeApi.RuntimeStatus, error)
} }
// ImageManagerService interface should be implemented by a container image // ImageManagerService interface should be implemented by a container image
......
...@@ -50,6 +50,7 @@ type FakeRuntimeService struct { ...@@ -50,6 +50,7 @@ type FakeRuntimeService struct {
Called []string Called []string
FakeStatus *runtimeApi.RuntimeStatus
Containers map[string]*FakeContainer Containers map[string]*FakeContainer
Sandboxes map[string]*FakePodSandbox Sandboxes map[string]*FakePodSandbox
} }
...@@ -109,6 +110,15 @@ func (r *FakeRuntimeService) Version(apiVersion string) (*runtimeApi.VersionResp ...@@ -109,6 +110,15 @@ func (r *FakeRuntimeService) Version(apiVersion string) (*runtimeApi.VersionResp
}, nil }, nil
} }
func (r *FakeRuntimeService) Status() (*runtimeApi.RuntimeStatus, error) {
r.Lock()
defer r.Unlock()
r.Called = append(r.Called, "Status")
return r.FakeStatus, nil
}
func (r *FakeRuntimeService) RunPodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) { func (r *FakeRuntimeService) RunPodSandbox(config *runtimeApi.PodSandboxConfig) (string, error) {
r.Lock() r.Lock()
defer r.Unlock() defer r.Unlock()
......
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package runtime
// This file contains all constants defined in CRI.
// Required runtime condition type.
const (
// RuntimeReady means the runtime is up and ready to accept basic containers.
RuntimeReady = "RuntimeReady"
// NetworkReady means the runtime network is up and ready to accept containers which require network.
NetworkReady = "NetworkReady"
)
...@@ -21,6 +21,8 @@ import ( ...@@ -21,6 +21,8 @@ import (
"io" "io"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/golang/protobuf/proto"
"k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/apis/componentconfig"
internalApi "k8s.io/kubernetes/pkg/kubelet/api" internalApi "k8s.io/kubernetes/pkg/kubelet/api"
runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime" runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
...@@ -222,3 +224,24 @@ type dockerNetworkHost struct { ...@@ -222,3 +224,24 @@ type dockerNetworkHost struct {
func (ds *dockerService) Start() error { func (ds *dockerService) Start() error {
return ds.containerManager.Start() return ds.containerManager.Start()
} }
// Status returns the status of the runtime.
// TODO(random-liu): Set network condition accordingly here.
func (ds *dockerService) Status() (*runtimeApi.RuntimeStatus, error) {
runtimeReady := &runtimeApi.RuntimeCondition{
Type: proto.String(runtimeApi.RuntimeReady),
Status: proto.Bool(true),
}
networkReady := &runtimeApi.RuntimeCondition{
Type: proto.String(runtimeApi.NetworkReady),
Status: proto.Bool(true),
}
conditions := []*runtimeApi.RuntimeCondition{runtimeReady, networkReady}
_, err := ds.client.Version()
if err != nil {
runtimeReady.Status = proto.Bool(false)
runtimeReady.Reason = proto.String("DockerDaemonNotReady")
runtimeReady.Message = proto.String(fmt.Sprintf("docker: failed to get docker version: %v", err))
}
return &runtimeApi.RuntimeStatus{Conditions: conditions}, nil
}
...@@ -17,10 +17,14 @@ limitations under the License. ...@@ -17,10 +17,14 @@ limitations under the License.
package dockershim package dockershim
import ( import (
"github.com/golang/mock/gomock" "errors"
"testing" "testing"
"time" "time"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing" containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
"k8s.io/kubernetes/pkg/kubelet/dockertools" "k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/pkg/kubelet/network" "k8s.io/kubernetes/pkg/kubelet/network"
...@@ -39,3 +43,37 @@ func newTestDockerService() (*dockerService, *dockertools.FakeDockerClient, *clo ...@@ -39,3 +43,37 @@ func newTestDockerService() (*dockerService, *dockertools.FakeDockerClient, *clo
c := dockertools.NewFakeDockerClientWithClock(fakeClock) c := dockertools.NewFakeDockerClientWithClock(fakeClock)
return &dockerService{client: c, os: &containertest.FakeOS{}, networkPlugin: &network.NoopNetworkPlugin{}}, c, fakeClock return &dockerService{client: c, os: &containertest.FakeOS{}, networkPlugin: &network.NoopNetworkPlugin{}}, c, fakeClock
} }
// TestStatus tests the runtime status logic.
func TestStatus(t *testing.T) {
ds, fDocker, _ := newTestDockerService()
assertStatus := func(expected map[string]bool, status *runtimeApi.RuntimeStatus) {
conditions := status.GetConditions()
assert.Equal(t, len(expected), len(conditions))
for k, v := range expected {
for _, c := range conditions {
if k == c.GetType() {
assert.Equal(t, v, c.GetStatus())
}
}
}
}
// Should report ready status if version returns no error.
status, err := ds.Status()
assert.NoError(t, err)
assertStatus(map[string]bool{
runtimeApi.RuntimeReady: true,
runtimeApi.NetworkReady: true,
}, status)
// Should not report ready status if version returns error.
fDocker.InjectError("version", errors.New("test error"))
status, err = ds.Status()
assert.NoError(t, err)
assertStatus(map[string]bool{
runtimeApi.RuntimeReady: false,
runtimeApi.NetworkReady: true,
}, status)
}
...@@ -52,7 +52,11 @@ func (d *dockerService) Version(ctx context.Context, r *runtimeApi.VersionReques ...@@ -52,7 +52,11 @@ func (d *dockerService) Version(ctx context.Context, r *runtimeApi.VersionReques
} }
func (d *dockerService) Status(ctx context.Context, r *runtimeApi.StatusRequest) (*runtimeApi.StatusResponse, error) { func (d *dockerService) Status(ctx context.Context, r *runtimeApi.StatusRequest) (*runtimeApi.StatusResponse, error) {
return nil, fmt.Errorf("not implemented") status, err := d.runtimeService.Status()
if err != nil {
return nil, err
}
return &runtimeApi.StatusResponse{Status: status}, nil
} }
func (d *dockerService) RunPodSandbox(ctx context.Context, r *runtimeApi.RunPodSandboxRequest) (*runtimeApi.RunPodSandboxResponse, error) { func (d *dockerService) RunPodSandbox(ctx context.Context, r *runtimeApi.RunPodSandboxRequest) (*runtimeApi.RunPodSandboxResponse, error) {
......
...@@ -216,3 +216,14 @@ func buildFullContainerLogsPath(podUID types.UID, containerName string, restartC ...@@ -216,3 +216,14 @@ func buildFullContainerLogsPath(podUID types.UID, containerName string, restartC
func buildPodLogsDirectory(podUID types.UID) string { func buildPodLogsDirectory(podUID types.UID) string {
return filepath.Join(podLogsRootDirectory, string(podUID)) return filepath.Join(podLogsRootDirectory, string(podUID))
} }
// getRuntimeCondition gets specified runtime condition from the runtime status.
func getRuntimeCondition(status *runtimeApi.RuntimeStatus, t string) *runtimeApi.RuntimeCondition {
conditions := status.GetConditions()
for _, condition := range conditions {
if condition.GetType() == t {
return condition
}
}
return nil
}
...@@ -68,6 +68,15 @@ func (in instrumentedRuntimeService) Version(apiVersion string) (*runtimeApi.Ver ...@@ -68,6 +68,15 @@ func (in instrumentedRuntimeService) Version(apiVersion string) (*runtimeApi.Ver
return out, err return out, err
} }
func (in instrumentedRuntimeService) Status() (*runtimeApi.RuntimeStatus, error) {
const operation = "status"
defer recordOperation(operation, time.Now())
out, err := in.service.Status()
recordError(operation, err)
return out, err
}
func (in instrumentedRuntimeService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) { func (in instrumentedRuntimeService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) {
const operation = "create_container" const operation = "create_container"
defer recordOperation(operation, time.Now()) defer recordOperation(operation, time.Now())
......
...@@ -269,13 +269,23 @@ func (m *kubeGenericRuntimeManager) APIVersion() (kubecontainer.Version, error) ...@@ -269,13 +269,23 @@ func (m *kubeGenericRuntimeManager) APIVersion() (kubecontainer.Version, error)
} }
// Status returns error if the runtime is unhealthy; nil otherwise. // Status returns error if the runtime is unhealthy; nil otherwise.
// TODO(random-liu): Change the Status in runtime interface to return runtime status.
// TODO(random-liu): Add unit test for this function after addressing the TODO above.
func (m *kubeGenericRuntimeManager) Status() error { func (m *kubeGenericRuntimeManager) Status() error {
_, err := m.runtimeService.Version(kubeRuntimeAPIVersion) status, err := m.runtimeService.Status()
if err != nil { if err != nil {
glog.Errorf("Checkout remote runtime status failed: %v", err) return fmt.Errorf("failed to checkout runtime status: %v", err)
return err }
networkReady := getRuntimeCondition(status, runtimeApi.NetworkReady)
if networkReady == nil || !networkReady.GetStatus() {
return fmt.Errorf("runtime network not ready: reason: %q, message: %q",
networkReady.GetReason(), networkReady.GetMessage())
}
runtimeReady := getRuntimeCondition(status, runtimeApi.RuntimeReady)
if runtimeReady == nil || !runtimeReady.GetStatus() {
return fmt.Errorf("runtime not ready: reason: %q, message: %q",
runtimeReady.GetReason(), runtimeReady.GetMessage())
} }
return nil return nil
} }
......
...@@ -339,3 +339,17 @@ func (r *RemoteRuntimeService) UpdateRuntimeConfig(runtimeConfig *runtimeApi.Run ...@@ -339,3 +339,17 @@ func (r *RemoteRuntimeService) UpdateRuntimeConfig(runtimeConfig *runtimeApi.Run
return nil return nil
} }
// Status returns the status of the runtime.
func (r *RemoteRuntimeService) Status() (*runtimeApi.RuntimeStatus, error) {
ctx, cancel := getContextWithTimeout(r.timeout)
defer cancel()
resp, err := r.runtimeClient.Status(ctx, &runtimeApi.StatusRequest{})
if err != nil {
glog.Errorf("Status from runtime service failed: %v", err)
return nil, err
}
return resp.Status, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment