~james-page/ubuntu/saucy/juju-core/1.16.5

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/cmd/juju/destroymachine.go

  • Committer: James Page
  • Date: 2014-02-07 14:01:51 UTC
  • mfrom: (1.1.13)
  • Revision ID: james.page@canonical.com-20140207140151-h9fontlwzytbqbfz
* New upstream stable point release:
  - core: Add destroy-machine --force option to allow forced termination
    of machines that are unresponsive (LP: #1089291).
  - core: Fix problem with dying services with no service units
    attached not completing destruction (LP: #1233457).
  - regression: Add API calls to allow clients < 1.16.4 to
    communicate with >= 1.16.4 environments (LP: #1253643).
  - regression: Fix juju set-env functionality with MAAS environments
    (LP: #1256179).
  - core: Fix issue with yaml parsing in juju get command (LP: #1227952).
  - core: Limit effect of juju destroy-environment to the environment
    actually being destroyed (LP: #1257481).
  - core: Add 'safe-mode' feature to provisioner to support operations
    such as backup/restore of juju environments (LP: #1254729).
  - core: Fix juju set operation for boolean config attributes
    (LP: #1254938).
  - core: Add update-bootstrap plugin to allow bootstrap machine
    address to be updated to a new bootstrap node in the event of
    a bootstrap node failure (LP: #1254579):
    + d/rules: Build and install juju-update-bootstrap plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
import (
7
7
        "fmt"
 
8
        "strings"
 
9
 
 
10
        "launchpad.net/gnuflag"
8
11
 
9
12
        "launchpad.net/juju-core/cmd"
 
13
        "launchpad.net/juju-core/errors"
10
14
        "launchpad.net/juju-core/juju"
11
15
        "launchpad.net/juju-core/names"
 
16
        "launchpad.net/juju-core/rpc"
 
17
        "launchpad.net/juju-core/state"
12
18
)
13
19
 
14
20
// DestroyMachineCommand causes an existing machine to be destroyed.
15
21
type DestroyMachineCommand struct {
16
22
        cmd.EnvCommandBase
17
23
        MachineIds []string
 
24
        Force      bool
18
25
}
19
26
 
 
27
const destroyMachineDoc = `
 
28
Machines that are responsible for the environment cannot be destroyed. Machines
 
29
running units or containers can only be destroyed with the --force flag; doing
 
30
so will also destroy all those units and containers without giving them any
 
31
opportunity to shut down cleanly.
 
32
`
 
33
 
20
34
func (c *DestroyMachineCommand) Info() *cmd.Info {
21
35
        return &cmd.Info{
22
36
                Name:    "destroy-machine",
23
37
                Args:    "<machine> ...",
24
38
                Purpose: "destroy machines",
25
 
                Doc:     "Machines that have assigned units, or are responsible for the environment, cannot be destroyed.",
 
39
                Doc:     destroyMachineDoc,
26
40
                Aliases: []string{"terminate-machine"},
27
41
        }
28
42
}
29
43
 
 
44
func (c *DestroyMachineCommand) SetFlags(f *gnuflag.FlagSet) {
 
45
        c.EnvCommandBase.SetFlags(f)
 
46
        f.BoolVar(&c.Force, "force", false, "completely remove machine and all dependencies")
 
47
}
 
48
 
30
49
func (c *DestroyMachineCommand) Init(args []string) error {
31
50
        if len(args) == 0 {
32
51
                return fmt.Errorf("no machines specified")
40
59
        return nil
41
60
}
42
61
 
43
 
func (c *DestroyMachineCommand) Run(_ *cmd.Context) error {
 
62
// destroyMachines destroys the machines with the specified ids.
 
63
// This is copied from the 1.16.3 code to enable compatibility. It should be
 
64
// removed when we release a version that goes via the API only (whatever is
 
65
// after 1.18)
 
66
func destroyMachines(st *state.State, ids ...string) (err error) {
 
67
        var errs []string
 
68
        for _, id := range ids {
 
69
                machine, err := st.Machine(id)
 
70
                switch {
 
71
                case errors.IsNotFoundError(err):
 
72
                        err = fmt.Errorf("machine %s does not exist", id)
 
73
                case err != nil:
 
74
                case machine.Life() != state.Alive:
 
75
                        continue
 
76
                default:
 
77
                        err = machine.Destroy()
 
78
                }
 
79
                if err != nil {
 
80
                        errs = append(errs, err.Error())
 
81
                }
 
82
        }
 
83
        if len(errs) == 0 {
 
84
                return nil
 
85
        }
 
86
        msg := "some machines were not destroyed"
 
87
        if len(errs) == len(ids) {
 
88
                msg = "no machines were destroyed"
 
89
        }
 
90
        return fmt.Errorf("%s: %s", msg, strings.Join(errs, "; "))
 
91
}
 
92
 
 
93
func (c *DestroyMachineCommand) run1dot16() error {
 
94
        if c.Force {
 
95
                return fmt.Errorf("destroy-machine --force is not supported in Juju servers older than 1.16.4")
 
96
        }
44
97
        conn, err := juju.NewConnFromName(c.EnvName)
45
98
        if err != nil {
46
99
                return err
47
100
        }
48
101
        defer conn.Close()
49
 
        return conn.State.DestroyMachines(c.MachineIds...)
 
102
        return destroyMachines(conn.State, c.MachineIds...)
 
103
}
 
104
 
 
105
func (c *DestroyMachineCommand) Run(_ *cmd.Context) error {
 
106
        apiclient, err := juju.NewAPIClientFromName(c.EnvName)
 
107
        if err != nil {
 
108
                return err
 
109
        }
 
110
        defer apiclient.Close()
 
111
        if c.Force {
 
112
                err = apiclient.ForceDestroyMachines(c.MachineIds...)
 
113
        } else {
 
114
                err = apiclient.DestroyMachines(c.MachineIds...)
 
115
        }
 
116
        // Juju 1.16.3 and older did not have DestroyMachines as an API command.
 
117
        if rpc.IsNoSuchRequest(err) {
 
118
                logger.Infof("DestroyMachines not supported by the API server, " +
 
119
                        "falling back to <=1.16.3 compatibility")
 
120
                return c.run1dot16()
 
121
        }
 
122
        return err
50
123
}