1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
package server
import (
"context"
"errors"
"fmt"
"time"
"github.com/spf13/cobra"
"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/cmd/cmpl"
"github.com/hetznercloud/cli/internal/hcapi2"
"github.com/hetznercloud/cli/internal/state"
"github.com/hetznercloud/hcloud-go/v2/hcloud"
)
var ShutdownCommand = base.Cmd{
BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
const description = "Shuts down a Server gracefully by sending an ACPI shutdown request. " +
"The Server operating system must support ACPI and react to the request, " +
"otherwise the Server will not shut down. Use the --wait flag to wait for the " +
"server to shut down before returning."
cmd := &cobra.Command{
Use: "shutdown [FLAGS] SERVER",
Short: "Shutdown a server",
Long: description,
Args: cobra.ExactArgs(1),
ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)),
TraverseChildren: true,
DisableFlagsInUseLine: true,
}
cmd.Flags().Bool("wait", false, "Wait for the server to shut down before exiting")
cmd.Flags().Duration("wait-timeout", 30*time.Second, "Timeout for waiting for off state after shutdown")
return cmd
},
Run: func(ctx context.Context, client hcapi2.Client, waiter state.ActionWaiter, cmd *cobra.Command, args []string) error {
wait, _ := cmd.Flags().GetBool("wait")
timeout, _ := cmd.Flags().GetDuration("wait-timeout")
idOrName := args[0]
server, _, err := client.Server().Get(ctx, idOrName)
if err != nil {
return err
}
if server == nil {
return fmt.Errorf("server not found: %s", idOrName)
}
action, _, err := client.Server().Shutdown(ctx, server)
if err != nil {
return err
}
if err := waiter.ActionProgress(ctx, action); err != nil {
return err
}
fmt.Printf("Sent shutdown signal to server %d\n", server.ID)
if wait {
start := time.Now()
errCh := make(chan error)
interval, _ := cmd.Flags().GetDuration("poll-interval")
if interval < time.Second {
interval = time.Second
}
go func() {
defer close(errCh)
ticker := time.NewTicker(interval)
defer ticker.Stop()
for server.Status != hcloud.ServerStatusOff {
if now := <-ticker.C; now.Sub(start) >= timeout {
errCh <- errors.New("failed to shut down server")
return
}
server, _, err = client.Server().GetByID(ctx, server.ID)
if err != nil {
errCh <- err
return
}
}
errCh <- nil
}()
if err := state.DisplayProgressCircle(errCh, "Waiting for server to shut down"); err != nil {
return err
}
fmt.Printf("Server %d shut down\n", server.ID)
}
return nil
},
}
|