Example #1
0
func (bm *BaseMachine) HandleStart(ctx context.Context) error {
	origState := bm.State()
	currentState := origState

	bm.PushEvent("Checking machine state", 10, machinestate.Starting)

	realState, meta, err := bm.machine.Info(ctx)
	if err != nil {
		return err
	}

	defer func() {
		bm.Log.Debug("exit: origState=%s, currentState=%s, err=%v", origState, currentState, err)

		if err != nil && origState != currentState {
			modelhelper.ChangeMachineState(bm.ObjectId, "Machine is marked as "+origState.String(), origState)
		}
	}()

	bm.Log.Debug("origState=%s, currentState=%s, realState=%s", origState, currentState, realState)

	if !realState.In(machinestate.Running, machinestate.Starting) {
		currentState = machinestate.Starting

		bm.PushEvent("Starting machine", 25, currentState)

		err = modelhelper.ChangeMachineState(bm.ObjectId, "Machine is starting", currentState)
		if err != nil {
			return err
		}

		meta, err = bm.machine.Start(ctx)
		if err != nil {
			return stack.NewEventerError(err)
		}
	}

	bm.PushEvent("Checking remote machine", 75, currentState)

	dialState, err := bm.WaitKlientReady(0)
	if err != nil {
		bm.Log.Debug("waiting for klient failed with error: %s", err)

		currentState = machinestate.Stopped

		return stack.NewEventerError(err)
	}

	currentState = machinestate.Running

	if err := bm.updateMachine(dialState, meta, currentState); err != nil {
		return fmt.Errorf("failed to update machine: %s", err)
	}

	return nil
}
Example #2
0
func (bm *BaseMachine) HandleStop(ctx context.Context) error {
	origState := bm.State()
	currentState := origState

	bm.PushEvent("Checking machine state", 10, machinestate.Stopping)

	realState, meta, err := bm.machine.Info(ctx)
	if err != nil {
		return err
	}

	defer func() {
		bm.Log.Debug("stop exit: origState=%s, currentState=%s, err=%v", origState, currentState, err)

		if err != nil && origState != currentState {
			modelhelper.ChangeMachineState(bm.ObjectId, "Machine is marked as "+origState.String(), origState)
		}
	}()

	bm.Log.Debug("stop origState=%s, currentState=%s, realState=%s", origState, currentState, realState)

	if !realState.In(machinestate.Stopping, machinestate.Stopped) {
		currentState = machinestate.Stopping

		bm.PushEvent("Stopping machine", 25, currentState)

		err = modelhelper.ChangeMachineState(bm.ObjectId, "Machine is stopping", currentState)
		if err != nil {
			return err
		}

		meta, err = bm.machine.Stop(ctx)
		if err != nil {
			return stack.NewEventerError(err)
		}

		currentState = machinestate.Stopped
	}

	if err := bm.updateMachine(nil, meta, currentState); err != nil {
		return fmt.Errorf("failed to update machine: %s", err)
	}

	return nil
}
Example #3
0
func (bm *BaseMachine) HandleInfo(ctx context.Context) (*stack.InfoResponse, error) {
	var state *DialState

	origState := bm.State()

	currentState, meta, err := bm.machine.Info(ctx)
	if err != nil {
		return nil, err
	}

	defer func() {
		if currentState == origState {
			currentState = 0
		}

		if meta != nil || state != nil {
			bm.updateMachine(state, meta, currentState)
		} else if currentState != 0 {
			modelhelper.ChangeMachineState(bm.ObjectId, "Machine is marked as "+currentState.String(), currentState)
		}
	}()

	bm.Log.Debug("origState=%s, currentState=%s", origState, currentState)
	if currentState.InProgress() {
		return &stack.InfoResponse{
			State: currentState,
		}, nil
	}

	if origState == currentState && currentState != machinestate.Running {
		return &stack.InfoResponse{
			State: origState,
		}, nil
	}

	if alwaysOn, ok := bm.Meta["alwaysOn"].(bool); ok && alwaysOn && currentState == machinestate.Running {
		// We do not test klient connection when machine is always-on.
		// Most likely we assume that kloud/queue is going to start/restart
		// the vm if klient connectivity fails.
		return &stack.InfoResponse{
			State: currentState,
		}, nil
	}

	if state, err = bm.WaitKlientReady(10 * time.Second); err == nil {
		currentState = machinestate.Running
	} else {
		bm.Log.Debug("klient connection test failed %q: %s", bm.Label, err)
	}

	return &stack.InfoResponse{
		State: currentState,
	}, nil
}