package network import ( "errors" "fmt" "strings" kapi "k8s.io/kubernetes/pkg/api" kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" kcontainer "k8s.io/kubernetes/pkg/kubelet/container" kexec "k8s.io/kubernetes/pkg/util/exec" "github.com/openshift/origin/pkg/diagnostics/networkpod/util" "github.com/openshift/origin/pkg/diagnostics/types" ) const ( CheckNodeNetworkName = "CheckNodeNetwork" ) // CheckNodeNetwork is a Diagnostic to check that pods in the cluster can access its own node type CheckNodeNetwork struct { KubeClient *kclientset.Clientset } // Name is part of the Diagnostic interface and just returns name. func (d CheckNodeNetwork) Name() string { return CheckNodeNetworkName } // Description is part of the Diagnostic interface and just returns the diagnostic description. func (d CheckNodeNetwork) Description() string { return "Check that pods in the cluster can access its own node." } // CanRun is part of the Diagnostic interface; it determines if the conditions are right to run this diagnostic. func (d CheckNodeNetwork) CanRun() (bool, error) { if d.KubeClient == nil { return false, errors.New("must have kube client") } return true, nil } // Check is part of the Diagnostic interface; it runs the actual diagnostic logic func (d CheckNodeNetwork) Check() types.DiagnosticResult { r := types.NewDiagnosticResult(CheckNodeNetworkName) _, localIP, err := util.GetLocalNode(d.KubeClient) if err != nil { r.Error("DNodeNet1001", err, err.Error()) return r } localPods, _, err := util.GetLocalAndNonLocalDiagnosticPods(d.KubeClient) if err != nil { r.Error("DNodeNet1002", err, fmt.Sprintf("Getting local and nonlocal pods failed. Error: %s", err)) return r } for _, pod := range localPods { checkNodeConnection(&pod, localIP, r) } return r } func checkNodeConnection(pod *kapi.Pod, nodeIP string, r types.DiagnosticResult) { if len(pod.Status.ContainerStatuses) == 0 { err := fmt.Errorf("ContainerID not found for pod %q", util.PrintPod(pod)) r.Error("DNodeNet1003", err, err.Error()) return } kexecer := kexec.New() containerID := kcontainer.ParseContainerID(pod.Status.ContainerStatuses[0].ContainerID).ID pid, err := kexecer.Command("docker", "inspect", "-f", "{{.State.Pid}}", containerID).CombinedOutput() if err != nil { r.Error("DNodeNet1004", err, fmt.Sprintf("Fetching pid for pod %q, container %q failed. Error: %s", util.PrintPod(pod), containerID, err)) return } if _, err := kexecer.Command("nsenter", "-n", "-t", strings.Trim(fmt.Sprintf("%s", pid), "\n"), "--", "ping", "-c1", "-W2", nodeIP).CombinedOutput(); err != nil { r.Error("DNodeNet1005", err, fmt.Sprintf("Connectivity from pod %q to node %q failed. Error: %s", util.PrintPod(pod), nodeIP, err)) } }