~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/state/state.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
        "github.com/juju/utils/os"
25
25
        "github.com/juju/utils/series"
26
26
        "github.com/juju/utils/set"
 
27
        "github.com/juju/version"
27
28
        "gopkg.in/juju/charm.v6-unstable"
28
29
        "gopkg.in/mgo.v2"
29
30
        "gopkg.in/mgo.v2/bson"
31
32
 
32
33
        "github.com/juju/juju/apiserver/params"
33
34
        "github.com/juju/juju/constraints"
 
35
        corelease "github.com/juju/juju/core/lease"
34
36
        "github.com/juju/juju/environs/config"
35
37
        "github.com/juju/juju/instance"
36
38
        "github.com/juju/juju/mongo"
39
41
        statelease "github.com/juju/juju/state/lease"
40
42
        "github.com/juju/juju/state/presence"
41
43
        "github.com/juju/juju/state/watcher"
42
 
        "github.com/juju/juju/version"
 
44
        "github.com/juju/juju/status"
 
45
        jujuversion "github.com/juju/juju/version"
43
46
        "github.com/juju/juju/worker/lease"
44
47
)
45
48
 
81
84
        pwatcher *presence.Watcher
82
85
        // leadershipManager keeps track of units' service leadership leases
83
86
        // within this environment.
 
87
        leadershipClient  corelease.Client
84
88
        leadershipManager *lease.Manager
85
89
        // singularManager keeps track of which controller machine is responsible
86
90
        // for managing this state's environment.
219
223
        if err != nil {
220
224
                return errors.Annotatef(err, "cannot create leadership lease client")
221
225
        }
 
226
        st.leadershipClient = leadershipClient
222
227
        logger.Infof("starting leadership lease manager")
223
228
        leadershipManager, err := lease.NewManager(lease.ManagerConfig{
224
229
                Secretary: leadershipSecretary{},
350
355
        return st.session
351
356
}
352
357
 
353
 
type closeFunc func()
354
 
 
355
358
func (st *State) Watch() *Multiwatcher {
356
359
        st.mu.Lock()
357
360
        if st.allManager == nil {
478
481
// running the current version). If this is a hosted model, newVersion
479
482
// cannot be higher than the controller version.
480
483
func (st *State) SetModelAgentVersion(newVersion version.Number) (err error) {
481
 
        if newVersion.Compare(version.Current) > 0 && !st.IsController() {
 
484
        if newVersion.Compare(jujuversion.Current) > 0 && !st.IsController() {
482
485
                return errors.Errorf("a hosted model cannot have a higher version than the server model: %s > %s",
483
486
                        newVersion.String(),
484
 
                        version.Current,
 
487
                        jujuversion.Current,
485
488
                )
486
489
        }
487
490
 
602
605
        return errors.Trace(err)
603
606
}
604
607
 
605
 
// EnvironConstraints returns the current model constraints.
 
608
// ModelConstraints returns the current model constraints.
606
609
func (st *State) ModelConstraints() (constraints.Value, error) {
607
610
        cons, err := readConstraints(st, modelGlobalKey)
608
611
        return cons, errors.Trace(err)
609
612
}
610
613
 
611
 
// SetEnvironConstraints replaces the current model constraints.
 
614
// SetModelConstraints replaces the current model constraints.
612
615
func (st *State) SetModelConstraints(cons constraints.Value) error {
613
616
        unsupported, err := st.validateConstraints(cons)
614
617
        if len(unsupported) > 0 {
840
843
        charms, closer := st.getCollection(charmsC)
841
844
        defer closer()
842
845
 
 
846
        if err := validateCharmVersion(ch); err != nil {
 
847
                return nil, errors.Trace(err)
 
848
        }
 
849
 
843
850
        query := charms.FindId(curl.String()).Select(bson.D{{"placeholder", 1}})
844
851
 
845
852
        buildTxn := func(attempt int) ([]txn.Op, error) {
861
868
        return nil, errors.Trace(err)
862
869
}
863
870
 
 
871
type hasMeta interface {
 
872
        Meta() *charm.Meta
 
873
}
 
874
 
 
875
func validateCharmVersion(ch hasMeta) error {
 
876
        minver := ch.Meta().MinJujuVersion
 
877
        if minver != version.Zero {
 
878
                if minver.Compare(jujuversion.Current) > 0 {
 
879
                        return errors.Errorf("Charm's min version (%s) is higher than this juju environment's version (%s)", minver, jujuversion.Current)
 
880
                }
 
881
        }
 
882
        return nil
 
883
}
 
884
 
864
885
// AllCharms returns all charms in state.
865
886
func (st *State) AllCharms() ([]*Charm, error) {
866
887
        charmsCollection, closer := st.getCollection(charmsC)
1170
1191
        if args.Charm == nil {
1171
1192
                return nil, errors.Errorf("charm is nil")
1172
1193
        }
 
1194
 
 
1195
        if err := validateCharmVersion(args.Charm); err != nil {
 
1196
                return nil, errors.Trace(err)
 
1197
        }
 
1198
 
1173
1199
        if exists, err := isNotDead(st, servicesC, args.Name); err != nil {
1174
1200
                return nil, errors.Trace(err)
1175
1201
        } else if exists {
1219
1245
                } else {
1220
1246
                        supportedSeries = args.Charm.Meta().Series
1221
1247
                }
1222
 
                seriesOS, err := series.GetOSFromSeries(args.Series)
1223
 
                if err != nil {
1224
 
                        return nil, errors.Trace(err)
1225
 
                }
1226
 
                supportedOperatingSystems := make(map[os.OSType]bool)
1227
 
                for _, supportedSeries := range supportedSeries {
1228
 
                        os, err := series.GetOSFromSeries(supportedSeries)
 
1248
                if len(supportedSeries) > 0 {
 
1249
                        seriesOS, err := series.GetOSFromSeries(args.Series)
1229
1250
                        if err != nil {
1230
1251
                                return nil, errors.Trace(err)
1231
1252
                        }
1232
 
                        supportedOperatingSystems[os] = true
1233
 
                }
1234
 
                if !supportedOperatingSystems[seriesOS] {
1235
 
                        return nil, errors.NewNotSupported(errors.Errorf(
1236
 
                                "series %q (OS %q) not supported by charm",
1237
 
                                args.Series, seriesOS,
1238
 
                        ), "")
 
1253
                        supportedOperatingSystems := make(map[os.OSType]bool)
 
1254
                        for _, supportedSeries := range supportedSeries {
 
1255
                                os, err := series.GetOSFromSeries(supportedSeries)
 
1256
                                if err != nil {
 
1257
                                        return nil, errors.Trace(err)
 
1258
                                }
 
1259
                                supportedOperatingSystems[os] = true
 
1260
                        }
 
1261
                        if !supportedOperatingSystems[seriesOS] {
 
1262
                                return nil, errors.NewNotSupported(errors.Errorf(
 
1263
                                        "series %q (OS %q) not supported by charm, supported series are %q",
 
1264
                                        args.Series, seriesOS, strings.Join(supportedSeries, ", "),
 
1265
                                ), "")
 
1266
                        }
1239
1267
                }
1240
1268
        }
1241
1269
 
1301
1329
                // TODO(fwereade): this violates the spec. Should be "waiting".
1302
1330
                // Implemented like this to be consistent with incorrect add-unit
1303
1331
                // behaviour.
1304
 
                Status:     StatusUnknown,
 
1332
                Status:     status.StatusUnknown,
1305
1333
                StatusInfo: MessageWaitForAgentInit,
1306
1334
                Updated:    time.Now().UnixNano(),
1307
1335
                // This exists to preserve questionable unit-aggregation behaviour
2239
2267
        ModelUUID        string `bson:"model-uuid"`
2240
2268
        MachineIds       []string
2241
2269
        VotingMachineIds []string
 
2270
        MongoSpaceName   string `bson:"mongo-space-name"`
 
2271
        MongoSpaceState  string `bson:"mongo-space-state"`
2242
2272
}
2243
2273
 
2244
2274
// ControllerInfo holds information about currently
2258
2288
        // configured to run a controller and to have a vote
2259
2289
        // in peer election.
2260
2290
        VotingMachineIds []string
 
2291
 
 
2292
        // MongoSpaceName is the space that contains all Mongo servers.
 
2293
        MongoSpaceName string
 
2294
 
 
2295
        // MongoSpaceState records the state of the mongo space selection state machine. Valid states are:
 
2296
        // * We haven't looked for a Mongo space yet (MongoSpaceUnknown)
 
2297
        // * We have looked for a Mongo space, but we didn't find one (MongoSpaceInvalid)
 
2298
        // * We have looked for and found a Mongo space (MongoSpaceValid)
 
2299
        // * We didn't try to find a Mongo space because the provider doesn't support spaces (MongoSpaceUnsupported)
 
2300
        MongoSpaceState MongoSpaceStates
2261
2301
}
2262
2302
 
 
2303
type MongoSpaceStates string
 
2304
 
 
2305
const (
 
2306
        MongoSpaceUnknown     MongoSpaceStates = ""
 
2307
        MongoSpaceValid       MongoSpaceStates = "valid"
 
2308
        MongoSpaceInvalid     MongoSpaceStates = "invalid"
 
2309
        MongoSpaceUnsupported MongoSpaceStates = "unsupported"
 
2310
)
 
2311
 
2263
2312
// ControllerInfo returns information about
2264
2313
// the currently configured controller machines.
2265
2314
func (st *State) ControllerInfo() (*ControllerInfo, error) {
2309
2358
                ModelTag:         names.NewModelTag(doc.ModelUUID),
2310
2359
                MachineIds:       doc.MachineIds,
2311
2360
                VotingMachineIds: doc.VotingMachineIds,
 
2361
                MongoSpaceName:   doc.MongoSpaceName,
 
2362
                MongoSpaceState:  MongoSpaceStates(doc.MongoSpaceState),
2312
2363
        }, nil
2313
2364
}
2314
2365
 
2371
2422
        return nil
2372
2423
}
2373
2424
 
 
2425
// SetOrGetMongoSpaceName attempts to set the Mongo space or, if that fails, look
 
2426
// up the current Mongo space. Either way, it always returns what is in the
 
2427
// database by the end of the call.
 
2428
func (st *State) SetOrGetMongoSpaceName(mongoSpaceName network.SpaceName) (network.SpaceName, error) {
 
2429
        err := st.setMongoSpaceName(mongoSpaceName)
 
2430
        if err == txn.ErrAborted {
 
2431
                // Failed to set the new space name. Return what is already stored in state.
 
2432
                controllerInfo, err := st.ControllerInfo()
 
2433
                if err != nil {
 
2434
                        return network.SpaceName(""), errors.Trace(err)
 
2435
                }
 
2436
                return network.SpaceName(controllerInfo.MongoSpaceName), nil
 
2437
        } else if err != nil {
 
2438
                return network.SpaceName(""), errors.Trace(err)
 
2439
        }
 
2440
        return mongoSpaceName, nil
 
2441
}
 
2442
 
 
2443
// SetMongoSpaceState attempts to set the Mongo space state or, if that fails, look
 
2444
// up the current Mongo state. Either way, it always returns what is in the
 
2445
// database by the end of the call.
 
2446
func (st *State) SetMongoSpaceState(mongoSpaceState MongoSpaceStates) error {
 
2447
 
 
2448
        if mongoSpaceState != MongoSpaceUnknown &&
 
2449
                mongoSpaceState != MongoSpaceValid &&
 
2450
                mongoSpaceState != MongoSpaceInvalid &&
 
2451
                mongoSpaceState != MongoSpaceUnsupported {
 
2452
                return errors.NotValidf("mongoSpaceState: %s", mongoSpaceState)
 
2453
        }
 
2454
 
 
2455
        err := st.setMongoSpaceState(mongoSpaceState)
 
2456
        if err != nil {
 
2457
                return errors.Trace(err)
 
2458
        }
 
2459
        return nil
 
2460
}
 
2461
 
 
2462
func (st *State) setMongoSpaceName(mongoSpaceName network.SpaceName) error {
 
2463
        ops := []txn.Op{{
 
2464
                C:      controllersC,
 
2465
                Id:     modelGlobalKey,
 
2466
                Assert: bson.D{{"mongo-space-state", string(MongoSpaceUnknown)}},
 
2467
                Update: bson.D{{
 
2468
                        "$set",
 
2469
                        bson.D{
 
2470
                                {"mongo-space-name", string(mongoSpaceName)},
 
2471
                                {"mongo-space-state", MongoSpaceValid},
 
2472
                        },
 
2473
                }},
 
2474
        }}
 
2475
 
 
2476
        return st.runTransaction(ops)
 
2477
}
 
2478
 
 
2479
func (st *State) setMongoSpaceState(mongoSpaceState MongoSpaceStates) error {
 
2480
        ops := []txn.Op{{
 
2481
                C:      controllersC,
 
2482
                Id:     modelGlobalKey,
 
2483
                Update: bson.D{{"$set", bson.D{{"mongo-space-state", mongoSpaceState}}}},
 
2484
        }}
 
2485
 
 
2486
        return st.runTransaction(ops)
 
2487
}
 
2488
 
2374
2489
var tagPrefix = map[byte]string{
2375
2490
        'm': names.MachineTagKind + "-",
2376
2491
        's': names.ServiceTagKind + "-",