diff --git a/cmd/kubeadm/app/cmd/cmd.go b/cmd/kubeadm/app/cmd/cmd.go index 25dd8fd8bf..8826cd38c0 100644 --- a/cmd/kubeadm/app/cmd/cmd.go +++ b/cmd/kubeadm/app/cmd/cmd.go @@ -80,6 +80,7 @@ func NewKubeadmCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob cmds.AddCommand(NewCmdInit(out)) cmds.AddCommand(NewCmdJoin(out)) + cmds.AddCommand(NewCmdReset(out)) cmds.AddCommand(NewCmdVersion(out)) return cmds diff --git a/cmd/kubeadm/app/cmd/reset.go b/cmd/kubeadm/app/cmd/reset.go new file mode 100644 index 0000000000..15d11e0b6e --- /dev/null +++ b/cmd/kubeadm/app/cmd/reset.go @@ -0,0 +1,96 @@ +/* +Copyright 2014 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 cmd + +import ( + "fmt" + "io" + "os" + "os/exec" + + "github.com/spf13/cobra" + + "k8s.io/kubernetes/cmd/kubeadm/app/preflight" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/util/initsystem" +) + +func NewCmdReset(out io.Writer) *cobra.Command { + var skipPreFlight bool + cmd := &cobra.Command{ + Use: "reset", + Short: "Revert the actions kubeadm init or join made to the machine", + Run: func(cmd *cobra.Command, args []string) { + err := RunReset(out, cmd, skipPreFlight) + cmdutil.CheckErr(err) + }, + } + + cmd.PersistentFlags().BoolVar( + &skipPreFlight, "skip-preflight-checks", false, + "skip preflight checks normally run before modifying the system", + ) + + return cmd +} + +func RunReset(out io.Writer, cmd *cobra.Command, skipPreFlight bool) error { + if !skipPreFlight { + fmt.Println("Running pre-flight checks") + err := preflight.RunResetCheck() + if err != nil { + return &preflight.PreFlightError{Msg: err.Error()} + } + } else { + fmt.Println("Skipping pre-flight checks") + } + + serviceToStop := "kubelet" + initSystem, err := initsystem.GetInitSystem() + if err != nil { + fmt.Printf("%v", err) + } else { + fmt.Printf("Stopping the %s service...\n", serviceToStop) + initSystem.ServiceStop(serviceToStop) + } + + fmt.Printf("Unmounting directories in /var/lib/kubelet...\n") + // Don't check for errors here, since umount will return a non-zero exit code if there is no directories to umount + exec.Command("sh", "-c", "cat /proc/mounts | awk '{print $2}' | grep '/var/lib/kubelet' | xargs umount").Run() + + dirsToRemove := []string{"/var/lib/kubelet", "/var/lib/etcd", "/etc/kubernetes"} + fmt.Printf("Deleting the stateful directories: %v\n", dirsToRemove) + for _, dir := range dirsToRemove { + err := os.RemoveAll(dir) + if err != nil { + fmt.Printf("failed to remove directory: [%v]\n", err) + } + } + + dockerCheck := preflight.ServiceCheck{Service: "docker"} + if warnings, errors := dockerCheck.Check(); len(warnings) == 0 && len(errors) == 0 { + + fmt.Println("Stopping all running docker containers...") + if err := exec.Command("sh", "-c", "docker ps | grep 'k8s_' | awk '{print $1}' | xargs docker rm --force --volumes").Run(); err != nil { + fmt.Println("failed to stop the running containers") + } + } else { + fmt.Println("docker doesn't seem to be running, skipping the removal of kubernetes containers") + } + + return nil +} diff --git a/cmd/kubeadm/app/preflight/checks.go b/cmd/kubeadm/app/preflight/checks.go index 748d8ecfb8..4435a7787a 100644 --- a/cmd/kubeadm/app/preflight/checks.go +++ b/cmd/kubeadm/app/preflight/checks.go @@ -45,32 +45,32 @@ type PreFlightCheck interface { // detect a supported init system however, all checks are skipped and a warning is // returned. type ServiceCheck struct { - service string + Service string } func (sc ServiceCheck) Check() (warnings, errors []error) { - initSystem := initsystem.GetInitSystem() - if initSystem == nil { - return []error{fmt.Errorf("no supported init system detected, skipping service checks for %s", sc.service)}, nil + initSystem, err := initsystem.GetInitSystem() + if err != nil { + return []error{err}, nil } warnings = []error{} - if !initSystem.ServiceExists(sc.service) { - warnings = append(warnings, fmt.Errorf("%s service does not exist", sc.service)) + if !initSystem.ServiceExists(sc.Service) { + warnings = append(warnings, fmt.Errorf("%s service does not exist", sc.Service)) return warnings, nil } - if !initSystem.ServiceIsEnabled(sc.service) { + if !initSystem.ServiceIsEnabled(sc.Service) { warnings = append(warnings, fmt.Errorf("%s service is not enabled, please run 'systemctl enable %s.service'", - sc.service, sc.service)) + sc.Service, sc.Service)) } - if !initSystem.ServiceIsActive(sc.service) { + if !initSystem.ServiceIsActive(sc.Service) { errors = append(errors, fmt.Errorf("%s service is not active, please run 'systemctl start %s.service'", - sc.service, sc.service)) + sc.Service, sc.Service)) } return warnings, errors @@ -160,8 +160,8 @@ func RunInitMasterChecks() error { // TODO: Some of these ports should come from kubeadm config eventually: checks := []PreFlightCheck{ IsRootCheck{root: true}, - ServiceCheck{service: "kubelet"}, - ServiceCheck{service: "docker"}, + ServiceCheck{Service: "kubelet"}, + ServiceCheck{Service: "docker"}, PortOpenCheck{port: 443}, PortOpenCheck{port: 2379}, PortOpenCheck{port: 8080}, @@ -189,12 +189,9 @@ func RunJoinNodeChecks() error { // TODO: Some of these ports should come from kubeadm config eventually: checks := []PreFlightCheck{ IsRootCheck{root: true}, - ServiceCheck{service: "docker"}, - ServiceCheck{service: "kubelet"}, - PortOpenCheck{port: 8080}, + ServiceCheck{Service: "docker"}, + ServiceCheck{Service: "kubelet"}, PortOpenCheck{port: 10250}, - PortOpenCheck{port: 10251}, - PortOpenCheck{port: 10252}, DirAvailableCheck{path: "/etc/kubernetes"}, DirAvailableCheck{path: "/var/lib/kubelet"}, InPathCheck{executable: "ebtables", mandatory: true}, @@ -211,6 +208,14 @@ func RunJoinNodeChecks() error { return runChecks(checks) } +func RunResetCheck() error { + checks := []PreFlightCheck{ + IsRootCheck{root: true}, + } + + return runChecks(checks) +} + // runChecks runs each check, displays it's warnings/errors, and once all // are processed will exit if any errors occurred. func runChecks(checks []PreFlightCheck) error { diff --git a/pkg/util/initsystem/initsystem.go b/pkg/util/initsystem/initsystem.go index 43ea818eb9..435cf57ad3 100644 --- a/pkg/util/initsystem/initsystem.go +++ b/pkg/util/initsystem/initsystem.go @@ -17,11 +17,18 @@ limitations under the License. package initsystem import ( + "fmt" "os/exec" "strings" ) type InitSystem interface { + // ServiceStart tries to start a specific service + ServiceStart(service string) error + + // ServiceStop tries to stop a specific service + ServiceStop(service string) error + // ServiceExists ensures the service is defined for this init system. ServiceExists(service string) bool @@ -34,6 +41,18 @@ type InitSystem interface { type SystemdInitSystem struct{} +func (sysd SystemdInitSystem) ServiceStart(service string) error { + args := []string{"start", service} + _, err := exec.Command("systemctl", args...).Output() + return err +} + +func (sysd SystemdInitSystem) ServiceStop(service string) error { + args := []string{"stop", service} + _, err := exec.Command("systemctl", args...).Output() + return err +} + func (sysd SystemdInitSystem) ServiceExists(service string) bool { args := []string{"status", service} outBytes, _ := exec.Command("systemctl", args...).Output() @@ -70,11 +89,11 @@ func (sysd SystemdInitSystem) ServiceIsActive(service string) bool { // getInitSystem returns an InitSystem for the current system, or nil // if we cannot detect a supported init system for pre-flight checks. // This indicates we will skip init system checks, not an error. -func GetInitSystem() InitSystem { +func GetInitSystem() (InitSystem, error) { // Assume existence of systemctl in path implies this is a systemd system: _, err := exec.LookPath("systemctl") if err == nil { - return &SystemdInitSystem{} + return &SystemdInitSystem{}, nil } - return nil + return nil, fmt.Errorf("no supported init system detected, skipping checking for services") }