~rogpeppe/juju-core/azure

« back to all changes in this revision

Viewing changes to environs/bootstrap.go

[r=gz] Check correct info attr in cloudinit.apiHostAddrs

Fixes a copy/paste error in cloudinit.MachineConfig to agent.Conf
conversion helper function. No test as the only codepath that uses
this goes through verifyConfig which already asserts both StateInfo
and APIInfo are not nil, so not possible to write a failing test
using exposed functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012, 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package environs
 
5
 
 
6
import (
 
7
        "fmt"
 
8
 
 
9
        "launchpad.net/juju-core/agent"
 
10
        "launchpad.net/juju-core/constraints"
 
11
        "launchpad.net/juju-core/environs/config"
 
12
        "launchpad.net/juju-core/errors"
 
13
        "launchpad.net/juju-core/state"
 
14
        "launchpad.net/juju-core/utils"
 
15
        "launchpad.net/juju-core/version"
 
16
)
 
17
 
 
18
// Bootstrap bootstraps the given environment. The supplied constraints are
 
19
// used to provision the instance, and are also set within the bootstrapped
 
20
// environment.
 
21
func Bootstrap(environ Environ, cons constraints.Value) error {
 
22
        cfg := environ.Config()
 
23
        if secret := cfg.AdminSecret(); secret == "" {
 
24
                return fmt.Errorf("environment configuration has no admin-secret")
 
25
        }
 
26
        if authKeys := cfg.AuthorizedKeys(); authKeys == "" {
 
27
                // Apparently this can never happen, so it's not tested. But, one day,
 
28
                // Config will act differently (it's pretty crazy that, AFAICT, the
 
29
                // authorized-keys are optional config settings... but it's impossible
 
30
                // to actually *create* a config without them)... and when it does,
 
31
                // we'll be here to catch this problem early.
 
32
                return fmt.Errorf("environment configuration has no authorized-keys")
 
33
        }
 
34
        if _, hasCACert := cfg.CACert(); !hasCACert {
 
35
                return fmt.Errorf("environment configuration has no ca-cert")
 
36
        }
 
37
        if _, hasCAKey := cfg.CAPrivateKey(); !hasCAKey {
 
38
                return fmt.Errorf("environment configuration has no ca-private-key")
 
39
        }
 
40
        return environ.Bootstrap(cons)
 
41
}
 
42
 
 
43
// VerifyBootstrapInit does the common initial check inside bootstrap to
 
44
// confirm that the environment isn't already running, and that the storage
 
45
// works.
 
46
func VerifyBootstrapInit(env Environ, shortAttempt utils.AttemptStrategy) error {
 
47
        var err error
 
48
 
 
49
        // If the state file exists, it might actually have just been
 
50
        // removed by Destroy, and eventual consistency has not caught
 
51
        // up yet, so we retry to verify if that is happening.
 
52
        for a := shortAttempt.Start(); a.Next(); {
 
53
                if _, err = LoadState(env.Storage()); err != nil {
 
54
                        break
 
55
                }
 
56
        }
 
57
        if err == nil {
 
58
                return fmt.Errorf("environment is already bootstrapped")
 
59
        }
 
60
        if !errors.IsNotFoundError(err) {
 
61
                return fmt.Errorf("cannot query old bootstrap state: %v", err)
 
62
        }
 
63
 
 
64
        return VerifyStorage(env.Storage())
 
65
}
 
66
 
 
67
// BootstrapUsers creates the initial admin user for the database, and sets
 
68
// the initial password.
 
69
func BootstrapUsers(st *state.State, cfg *config.Config, passwordHash string) error {
 
70
        logger.Debugf("adding admin user")
 
71
        // Set up initial authentication.
 
72
        u, err := st.AddUser("admin", "")
 
73
        if err != nil {
 
74
                return err
 
75
        }
 
76
 
 
77
        // Note that at bootstrap time, the password is set to
 
78
        // the hash of its actual value. The first time a client
 
79
        // connects to mongo, it changes the mongo password
 
80
        // to the original password.
 
81
        logger.Debugf("setting password hash for admin user")
 
82
        if err := u.SetPasswordHash(passwordHash); err != nil {
 
83
                return err
 
84
        }
 
85
        if err := st.SetAdminMongoPassword(passwordHash); err != nil {
 
86
                return err
 
87
        }
 
88
        return nil
 
89
 
 
90
}
 
91
 
 
92
// ConfigureBootstrapMachine adds the initial machine into state.  As a part
 
93
// of this process the environmental constraints are saved as constraints used
 
94
// when bootstrapping are considered constraints for the entire environment.
 
95
func ConfigureBootstrapMachine(
 
96
        st *state.State,
 
97
        cfg *config.Config,
 
98
        cons constraints.Value,
 
99
        datadir string,
 
100
        jobs []state.MachineJob,
 
101
) error {
 
102
        logger.Debugf("setting environment constraints")
 
103
        if err := st.SetEnvironConstraints(cons); err != nil {
 
104
                return err
 
105
        }
 
106
 
 
107
        logger.Debugf("configure bootstrap machine")
 
108
        provider, err := Provider(cfg.Type())
 
109
        if err != nil {
 
110
                return err
 
111
        }
 
112
        instanceId, err := provider.InstanceId()
 
113
        if err != nil {
 
114
                return err
 
115
        }
 
116
 
 
117
        logger.Debugf("create bootstrap machine in state")
 
118
        m, err := st.InjectMachine(version.Current.Series, cons, instanceId, jobs...)
 
119
        if err != nil {
 
120
                return err
 
121
        }
 
122
        // Read the machine agent's password and change it to
 
123
        // a new password (other agents will change their password
 
124
        // via the API connection).
 
125
        logger.Debugf("create new random password for machine %v", m.Id())
 
126
        mconf, err := agent.ReadConf(datadir, m.Tag())
 
127
        if err != nil {
 
128
                return err
 
129
        }
 
130
        newPassword, err := utils.RandomPassword()
 
131
        if err != nil {
 
132
                return err
 
133
        }
 
134
        mconf.StateInfo.Password = newPassword
 
135
        mconf.APIInfo.Password = newPassword
 
136
        mconf.OldPassword = ""
 
137
 
 
138
        if err := mconf.Write(); err != nil {
 
139
                return err
 
140
        }
 
141
        if err := m.SetMongoPassword(newPassword); err != nil {
 
142
                return err
 
143
        }
 
144
        if err := m.SetPassword(newPassword); err != nil {
 
145
                return err
 
146
        }
 
147
        return nil
 
148
}