forked from openshift/assisted-service
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MGMT-15902: Trigger reboots for node event when day2 node moves to do…
…ne (openshift#5648) This is done for kube api client only when spoke kubeconfig is available. The implementation is done using debug command (as in oc command). The number of reboots are counted by 'last reboot' linux command.
- Loading branch information
1 parent
e6fc5f3
commit 652202c
Showing
6 changed files
with
202 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package oc | ||
|
||
import ( | ||
"io" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/go-errors/errors" | ||
"github.com/openshift/assisted-service/pkg/executer" | ||
"golang.org/x/net/context" | ||
) | ||
|
||
type Debug interface { | ||
RebootsForNode(nodeName string) (int, error) | ||
} | ||
|
||
type debug struct { | ||
kubeconfig []byte | ||
exec executer.Executer | ||
} | ||
|
||
func NewDebug(kubeconfig []byte) Debug { | ||
return &debug{ | ||
kubeconfig: kubeconfig, | ||
exec: &executer.CommonExecuter{}, | ||
} | ||
} | ||
|
||
func NewDebugWithExecuter(kubeconfig []byte, exec executer.Executer) Debug { | ||
return &debug{ | ||
kubeconfig: kubeconfig, | ||
exec: exec, | ||
} | ||
} | ||
|
||
func (d *debug) kubeconfigFile() (string, error) { | ||
var n int | ||
|
||
f, err := os.CreateTemp("", "kubeconfig") | ||
if err != nil { | ||
return "", err | ||
} | ||
defer f.Close() | ||
numWritten := 0 | ||
for n, err = f.Write(d.kubeconfig[numWritten:]); err == io.ErrShortWrite; n, err = f.Write(d.kubeconfig[numWritten:]) { | ||
numWritten += n | ||
} | ||
if err != nil { | ||
return "", err | ||
} | ||
return f.Name(), nil | ||
} | ||
|
||
func (d *debug) runDebug(entity string, args ...string) (string, string, error) { | ||
kubeconfigFname, err := d.kubeconfigFile() | ||
if err != nil { | ||
return "", "", err | ||
} | ||
defer func() { | ||
_ = os.RemoveAll(kubeconfigFname) | ||
}() | ||
execArgs := append([]string{ | ||
"debug", | ||
"--kubeconfig", | ||
kubeconfigFname, | ||
entity, | ||
"--", | ||
}, args...) | ||
execCtx, cancel := context.WithTimeout(context.TODO(), 2*time.Minute) | ||
defer cancel() | ||
out, errOut, exitCode := d.exec.ExecuteWithContext(execCtx, "oc", execArgs...) | ||
if exitCode != 0 { | ||
return "", "", errors.Errorf("oc debug failed to execute with code %d: %s", exitCode, errOut) | ||
} | ||
return out, errOut, nil | ||
} | ||
|
||
func (d *debug) RebootsForNode(nodeName string) (int, error) { | ||
out, _, err := d.runDebug("node/"+nodeName, | ||
"chroot", | ||
"/host", | ||
"last", | ||
"reboot") | ||
if err != nil { | ||
return 0, err | ||
} | ||
lines := strings.Split(out, "\n") | ||
numReboots := 0 | ||
for _, line := range lines { | ||
if strings.HasPrefix(line, "reboot ") { | ||
numReboots++ | ||
} | ||
} | ||
return numReboots, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package oc | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/golang/mock/gomock" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"github.com/openshift/assisted-service/pkg/executer" | ||
) | ||
|
||
var _ = Describe("oc debug", func() { | ||
const ( | ||
kubeconfig = "kubeconfig" | ||
nodeName = "node1" | ||
) | ||
var ( | ||
ctrl *gomock.Controller | ||
execMock *executer.MockExecuter | ||
d Debug | ||
) | ||
|
||
BeforeEach(func() { | ||
ctrl = gomock.NewController(GinkgoT()) | ||
execMock = executer.NewMockExecuter(ctrl) | ||
d = NewDebugWithExecuter([]byte(kubeconfig), execMock) | ||
}) | ||
expectOk := func(ret string) { | ||
execMock.EXPECT().ExecuteWithContext(gomock.Any(), | ||
"oc", | ||
"debug", | ||
"--kubeconfig", | ||
gomock.Any(), | ||
fmt.Sprintf("node/%s", nodeName), | ||
"--", | ||
"chroot", | ||
"/host", | ||
"last", | ||
"reboot").Return(ret, "", 0) | ||
} | ||
It("1 reboot", func() { | ||
expectOk("reboot system boot 4.18.0-372.9.1.e Tue Mar 7 04:13 still running\n") | ||
numReboots, err := d.RebootsForNode(nodeName) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(numReboots).To(Equal(1)) | ||
}) | ||
It("2 reboot", func() { | ||
expectOk("reboot system boot 4.18.0-372.9.1.e Tue Mar 7 04:13 still running\nreboot system boot 4.18.0-372.9.1.e Sun Mar 5 07:29 - 09:11 (2+01:41)\n") | ||
numReboots, err := d.RebootsForNode(nodeName) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(numReboots).To(Equal(2)) | ||
}) | ||
It("with error", func() { | ||
execMock.EXPECT().ExecuteWithContext(gomock.Any(), | ||
"oc", | ||
"debug", | ||
"--kubeconfig", | ||
gomock.Any(), | ||
fmt.Sprintf("node/%s", nodeName), | ||
"--", | ||
"chroot", | ||
"/host", | ||
"last", | ||
"reboot").Return("", "This is an error", -1) | ||
_, err := d.RebootsForNode(nodeName) | ||
Expect(err).To(HaveOccurred()) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters