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"
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.
220
224
return errors.Annotatef(err, "cannot create leadership lease client")
226
st.leadershipClient = leadershipClient
222
227
logger.Infof("starting leadership lease manager")
223
228
leadershipManager, err := lease.NewManager(lease.ManagerConfig{
224
229
Secretary: leadershipSecretary{},
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(),
602
605
return errors.Trace(err)
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)
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)
846
if err := validateCharmVersion(ch); err != nil {
847
return nil, errors.Trace(err)
843
850
query := charms.FindId(curl.String()).Select(bson.D{{"placeholder", 1}})
845
852
buildTxn := func(attempt int) ([]txn.Op, error) {
861
868
return nil, errors.Trace(err)
871
type hasMeta interface {
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)
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")
1195
if err := validateCharmVersion(args.Charm); err != nil {
1196
return nil, errors.Trace(err)
1173
1199
if exists, err := isNotDead(st, servicesC, args.Name); err != nil {
1174
1200
return nil, errors.Trace(err)
1175
1201
} else if exists {
1220
1246
supportedSeries = args.Charm.Meta().Series
1222
seriesOS, err := series.GetOSFromSeries(args.Series)
1224
return nil, errors.Trace(err)
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)
1232
supportedOperatingSystems[os] = true
1234
if !supportedOperatingSystems[seriesOS] {
1235
return nil, errors.NewNotSupported(errors.Errorf(
1236
"series %q (OS %q) not supported by charm",
1237
args.Series, seriesOS,
1253
supportedOperatingSystems := make(map[os.OSType]bool)
1254
for _, supportedSeries := range supportedSeries {
1255
os, err := series.GetOSFromSeries(supportedSeries)
1257
return nil, errors.Trace(err)
1259
supportedOperatingSystems[os] = true
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, ", "),
1301
1329
// TODO(fwereade): this violates the spec. Should be "waiting".
1302
1330
// Implemented like this to be consistent with incorrect add-unit
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
2258
2288
// configured to run a controller and to have a vote
2259
2289
// in peer election.
2260
2290
VotingMachineIds []string
2292
// MongoSpaceName is the space that contains all Mongo servers.
2293
MongoSpaceName string
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
2303
type MongoSpaceStates string
2306
MongoSpaceUnknown MongoSpaceStates = ""
2307
MongoSpaceValid MongoSpaceStates = "valid"
2308
MongoSpaceInvalid MongoSpaceStates = "invalid"
2309
MongoSpaceUnsupported MongoSpaceStates = "unsupported"
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),
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()
2434
return network.SpaceName(""), errors.Trace(err)
2436
return network.SpaceName(controllerInfo.MongoSpaceName), nil
2437
} else if err != nil {
2438
return network.SpaceName(""), errors.Trace(err)
2440
return mongoSpaceName, nil
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 {
2448
if mongoSpaceState != MongoSpaceUnknown &&
2449
mongoSpaceState != MongoSpaceValid &&
2450
mongoSpaceState != MongoSpaceInvalid &&
2451
mongoSpaceState != MongoSpaceUnsupported {
2452
return errors.NotValidf("mongoSpaceState: %s", mongoSpaceState)
2455
err := st.setMongoSpaceState(mongoSpaceState)
2457
return errors.Trace(err)
2462
func (st *State) setMongoSpaceName(mongoSpaceName network.SpaceName) error {
2466
Assert: bson.D{{"mongo-space-state", string(MongoSpaceUnknown)}},
2470
{"mongo-space-name", string(mongoSpaceName)},
2471
{"mongo-space-state", MongoSpaceValid},
2476
return st.runTransaction(ops)
2479
func (st *State) setMongoSpaceState(mongoSpaceState MongoSpaceStates) error {
2483
Update: bson.D{{"$set", bson.D{{"mongo-space-state", mongoSpaceState}}}},
2486
return st.runTransaction(ops)
2374
2489
var tagPrefix = map[byte]string{
2375
2490
'm': names.MachineTagKind + "-",
2376
2491
's': names.ServiceTagKind + "-",