提交 5411b3b2 编写于 作者: P Priya Wadhwa

Add code for daemonizing on windows and add integration test

上级 8daf7ea3
// +build windows
/*
Copyright 2020 The Kubernetes Authors All rights reserved.
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 schedule
import (
"fmt"
"time"
"github.com/pkg/errors"
"k8s.io/klog/v2"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/sysinit"
)
func killExisting(profiles []string) error {
for _, profile := range profiles {
klog.Infof("trying to kill existing schedule stop for profile %s...", profile)
api, err := machine.NewAPIClient()
if err != nil {
return errors.Wrapf(err, "getting api client for profile %s", profile)
}
h, err := api.Load(profile)
if err != nil {
return errors.Wrap(err, "Error loading existing host. Please try running [minikube delete], then run [minikube start] again.")
}
runner, err := machine.CommandRunner(h)
if err != nil {
return errors.Wrap(err, "getting command runner")
}
// restart scheduled stop service in container
sysManger := sysinit.New(runner)
if err := sysManger.Stop(constants.ScheduledStopSystemdService); err != nil {
return errors.Wrapf(err, "stopping schedule-stop service for profile %s", profile)
}
}
return nil
}
func killWithin(profiles []string, duration time.Duration) error {
for _, profile := range profiles {
if err := startSystemdService(profile, duration); err != nil {
return errors.Wrapf(err, "implementing scheduled stop for %s", profile)
}
}
return nil
}
func startSystemdService(profile string, duration time.Duration) error {
// get ssh runner
klog.Infof("starting systemd service for profile %s...", profile)
api, err := machine.NewAPIClient()
if err != nil {
return errors.Wrapf(err, "getting api client for profile %s", profile)
}
h, err := api.Load(profile)
if err != nil {
return errors.Wrap(err, "Error loading existing host. Please try running [minikube delete], then run [minikube start] again.")
}
runner, err := machine.CommandRunner(h)
if err != nil {
return errors.Wrap(err, "getting command runner")
}
// update environment file to include duration
if err := runner.Copy(environmentFile(duration)); err != nil {
return errors.Wrap(err, "copying scheduled stop env file")
}
// restart scheduled stop service in container
sysManger := sysinit.New(runner)
return sysManger.Restart(constants.ScheduledStopSystemdService)
}
func environmentFile(duration time.Duration) assets.CopyableFile {
contents := []byte(fmt.Sprintf("SLEEP=%v", duration.Seconds()))
return assets.NewMemoryAssetTarget(contents, constants.ScheduledStopEnvFile, "0644")
}
......@@ -22,14 +22,82 @@ import (
"fmt"
"time"
"fmt"
"time"
"github.com/pkg/errors"
"k8s.io/klog/v2"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/machine"
"k8s.io/minikube/pkg/minikube/sysinit"
)
// KillExisting will kill existing scheduled stops
func KillExisting(profiles []string) {
klog.Errorf("not yet implemented for windows")
for _, profile := range profiles {
if err := killExisting(profile); err != nil {
klog.Errorf("error terminating scheduled stop for profile %s: %v", profile, err)
}
}
}
func killExisting(profile string) error {
klog.Infof("trying to kill existing schedule stop for profile %s...", profile)
api, err := machine.NewAPIClient()
if err != nil {
return errors.Wrapf(err, "getting api client for profile %s", profile)
}
h, err := api.Load(profile)
if err != nil {
return errors.Wrap(err, "Error loading existing host. Please try running [minikube delete], then run [minikube start] again.")
}
runner, err := machine.CommandRunner(h)
if err != nil {
return errors.Wrap(err, "getting command runner")
}
// restart scheduled stop service in container
sysManger := sysinit.New(runner)
if err := sysManger.Stop(constants.ScheduledStopSystemdService); err != nil {
return errors.Wrapf(err, "stopping schedule-stop service for profile %s", profile)
}
return nil
}
func daemonize(profiles []string, duration time.Duration) error {
return fmt.Errorf("not yet implemented for windows")
for _, profile := range profiles {
if err := startSystemdService(profile, duration); err != nil {
return errors.Wrapf(err, "implementing scheduled stop for %s", profile)
}
}
return nil
}
func startSystemdService(profile string, duration time.Duration) error {
// get ssh runner
klog.Infof("starting systemd service for profile %s...", profile)
api, err := machine.NewAPIClient()
if err != nil {
return errors.Wrapf(err, "getting api client for profile %s", profile)
}
h, err := api.Load(profile)
if err != nil {
return errors.Wrap(err, "Error loading existing host. Please try running [minikube delete], then run [minikube start] again.")
}
runner, err := machine.CommandRunner(h)
if err != nil {
return errors.Wrap(err, "getting command runner")
}
// update environment file to include duration
if err := runner.Copy(environmentFile(duration)); err != nil {
return errors.Wrap(err, "copying scheduled stop env file")
}
// restart scheduled stop service in container
sysManger := sysinit.New(runner)
return sysManger.Restart(constants.ScheduledStopSystemdService)
}
func environmentFile(duration time.Duration) assets.CopyableFile {
contents := []byte(fmt.Sprintf("SLEEP=%v", duration.Seconds()))
return assets.NewMemoryAssetTarget(contents, constants.ScheduledStopEnvFile, "0644")
}
......@@ -24,19 +24,61 @@ import (
"io/ioutil"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"syscall"
"testing"
"time"
"github.com/docker/machine/libmachine/state"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/util/retry"
)
func TestScheduledStop(t *testing.T) {
func TestScheduledStopWindows(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("test only runs on windows")
}
if NoneDriver() {
t.Skip("--schedule does not apply to none driver ")
t.Skip("--schedule does not work with the none driver")
}
if !KicDriver() {
t.Skip("currently only works with container-based drivers on windows")
}
profile := UniqueProfileName("scheduled-stop")
ctx, cancel := context.WithTimeout(context.Background(), Minutes(5))
defer CleanupWithLogs(t, profile, cancel)
startMinikube(ctx, t, profile)
// schedule a stop for 5m from now
scheduledStopMinikube(ctx, t, profile, "5m")
// make sure the systemd service is running
rr, err := Run(t, exec.CommandContext(ctx, Target(), []string{"ssh", "-p", profile, "--", "sudo", "systemctl", "show", constants.ScheduledStopSystemdService, "--no-page"}...))
if err != nil {
t.Fatalf("getting minikube-scheduled-stop status: %v\n%s", err, rr.Output())
}
if !strings.Contains(rr.Output(), "ActiveState=active") {
t.Fatalf("minikube-scheduled-stop is not running: %v", rr.Output())
}
// reschedule stop for 5 seconds from now
scheduledStopMinikube(ctx, t, profile, "5s")
// sleep for 5 seconds
time.Sleep(5 * time.Second)
// make sure minikube status is "Stopped"
ensureMinikubeStatusStopped(ctx, t, profile)
}
func TestScheduledStopUnix(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("test only runs on unix")
}
if NoneDriver() {
t.Skip("--schedule does not work with the none driver")
}
profile := UniqueProfileName("scheduled-stop")
ctx, cancel := context.WithTimeout(context.Background(), Minutes(5))
......@@ -56,17 +98,8 @@ func TestScheduledStop(t *testing.T) {
t.Fatalf("process %v running but should have been killed on reschedule of stop", pid)
}
checkPID(t, profile)
// wait allotted time to make sure minikube status is "Stopped"
checkStatus := func() error {
got := Status(ctx, t, Target(), profile, "Host", profile)
if got != state.Stopped.String() {
return fmt.Errorf("expected post-stop host status to be -%q- but got *%q*", state.Stopped, got)
}
return nil
}
if err := retry.Expo(checkStatus, time.Second, 30*time.Second); err != nil {
t.Fatalf("error %v", err)
}
// make sure minikube status is "Stopped"
ensureMinikubeStatusStopped(ctx, t, profile)
}
func startMinikube(ctx context.Context, t *testing.T, profile string) {
......@@ -114,3 +147,16 @@ func processRunning(t *testing.T, pid string) bool {
t.Log("signal error was: ", err)
return err == nil
}
func ensureMinikubeStatusStopped(ctx context.Context, t *testing.T, profile string) {
checkStatus := func() error {
got := Status(ctx, t, Target(), profile, "Host", profile)
if got != state.Stopped.String() {
return fmt.Errorf("expected post-stop host status to be -%q- but got *%q*", state.Stopped, got)
}
return nil
}
if err := retry.Expo(checkStatus, time.Second, 30*time.Second); err != nil {
t.Fatalf("error %v", err)
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册