~rogpeppe/juju-core/azure

« back to all changes in this revision

Viewing changes to environs/bootstrap.go

  • Committer: Roger Peppe
  • Date: 2011-12-15 18:54:31 UTC
  • mfrom: (19.5.4 go-juju-ec2-operations)
  • mto: This revision was merged to the branch mainline in revision 30.
  • Revision ID: roger.peppe@canonical.com-20111215185431-tjuxi6bmg1mswcwg
renameĀ environ->environs

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
 
}