func (s *BootstrapSuite) TestSetConstraints(c *gc.C) { tcons := constraints.Value{Mem: uint64p(2048), CpuCores: uint64p(2)} _, cmd, err := s.initBootstrapCommand(c, nil, "--env-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId), "--constraints", tcons.String(), ) c.Assert(err, jc.ErrorIsNil) err = cmd.Run(nil) c.Assert(err, jc.ErrorIsNil) st, err := state.Open(testing.EnvironmentTag, &mongo.MongoInfo{ Info: mongo.Info{ Addrs: []string{gitjujutesting.MgoServer.Addr()}, CACert: testing.CACert, }, Password: testPasswordHash(), }, mongo.DefaultDialOpts(), environs.NewStatePolicy()) c.Assert(err, jc.ErrorIsNil) defer st.Close() cons, err := st.EnvironConstraints() c.Assert(err, jc.ErrorIsNil) c.Assert(cons, gc.DeepEquals, tcons) machines, err := st.AllMachines() c.Assert(err, jc.ErrorIsNil) c.Assert(machines, gc.HasLen, 1) cons, err = machines[0].Constraints() c.Assert(err, jc.ErrorIsNil) c.Assert(cons, gc.DeepEquals, tcons) }
// MatchingInstanceTypes returns all instance types matching constraints and available // in region, sorted by increasing region-specific cost (if known). func MatchingInstanceTypes(allInstanceTypes []InstanceType, region string, cons constraints.Value) ([]InstanceType, error) { var itypes []InstanceType // Rules used to select instance types: // - non memory constraints like cpu-cores etc are always honoured // - if no mem constraint specified and instance-type not specified, // try opinionated default with enough mem to run a server. // - if no matches and no mem constraint specified, try again and // return any matching instance with the largest memory origCons := cons if !cons.HasInstanceType() && cons.Mem == nil { minMem := uint64(minMemoryHeuristic) cons.Mem = &minMem } itypes = matchingTypesForConstraint(allInstanceTypes, cons) // No matches using opinionated default, so if no mem constraint specified, // look for matching instance with largest memory. if len(itypes) == 0 && cons.Mem != origCons.Mem { itypes = matchingTypesForConstraint(allInstanceTypes, origCons) if len(itypes) > 0 { sort.Sort(byMemory(itypes)) itypes = []InstanceType{itypes[len(itypes)-1]} } } // If we have matching instance types, we can return those, sorted by cost. if len(itypes) > 0 { sort.Sort(byCost(itypes)) return itypes, nil } // No luck, so report the error. return nil, fmt.Errorf("no instance types in %s matching constraints %q", region, origCons) }
func (i *importer) constraints(cons description.Constraints) constraints.Value { var result constraints.Value if cons == nil { return result } if arch := cons.Architecture(); arch != "" { result.Arch = &arch } if container := instance.ContainerType(cons.Container()); container != "" { result.Container = &container } if cores := cons.CpuCores(); cores != 0 { result.CpuCores = &cores } if power := cons.CpuPower(); power != 0 { result.CpuPower = &power } if inst := cons.InstanceType(); inst != "" { result.InstanceType = &inst } if mem := cons.Memory(); mem != 0 { result.Mem = &mem } if disk := cons.RootDisk(); disk != 0 { result.RootDisk = &disk } if spaces := cons.Spaces(); len(spaces) > 0 { result.Spaces = &spaces } if tags := cons.Tags(); len(tags) > 0 { result.Tags = &tags } return result }
// match returns true if itype can satisfy the supplied constraints. If so, // it also returns a copy of itype with any arches that do not match the // constraints filtered out. func (itype InstanceType) match(cons constraints.Value) (InstanceType, bool) { nothing := InstanceType{} if cons.Arch != nil { itype.Arches = filterArches(itype.Arches, []string{*cons.Arch}) } if itype.Deprecated && !cons.HasInstanceType() { return nothing, false } if cons.HasInstanceType() && itype.Name != *cons.InstanceType { return nothing, false } if len(itype.Arches) == 0 { return nothing, false } if cons.CpuCores != nil && itype.CpuCores < *cons.CpuCores { return nothing, false } if cons.CpuPower != nil && itype.CpuPower != nil && *itype.CpuPower < *cons.CpuPower { return nothing, false } if cons.Mem != nil && itype.Mem < *cons.Mem { return nothing, false } if cons.RootDisk != nil && itype.RootDisk > 0 && itype.RootDisk < *cons.RootDisk { return nothing, false } if cons.Tags != nil && len(*cons.Tags) > 0 && !tagsMatch(*cons.Tags, itype.Tags) { return nothing, false } return itype, true }
func (s *MigrationImportSuite) assertUnitsMigrated(c *gc.C, cons constraints.Value) { exported, pwd := s.Factory.MakeUnitReturningPassword(c, &factory.UnitParams{ Constraints: cons, }) err := exported.SetMeterStatus("GREEN", "some info") c.Assert(err, jc.ErrorIsNil) err = exported.SetWorkloadVersion("amethyst") c.Assert(err, jc.ErrorIsNil) err = s.State.SetAnnotations(exported, testAnnotations) c.Assert(err, jc.ErrorIsNil) s.primeStatusHistory(c, exported, status.Active, 5) s.primeStatusHistory(c, exported.Agent(), status.Idle, 5) _, newSt := s.importModel(c) importedApplications, err := newSt.AllApplications() c.Assert(err, jc.ErrorIsNil) c.Assert(importedApplications, gc.HasLen, 1) importedUnits, err := importedApplications[0].AllUnits() c.Assert(err, jc.ErrorIsNil) c.Assert(importedUnits, gc.HasLen, 1) imported := importedUnits[0] c.Assert(imported.UnitTag(), gc.Equals, exported.UnitTag()) c.Assert(imported.PasswordValid(pwd), jc.IsTrue) version, err := imported.WorkloadVersion() c.Assert(err, jc.ErrorIsNil) c.Assert(version, gc.Equals, "amethyst") exportedMachineId, err := exported.AssignedMachineId() c.Assert(err, jc.ErrorIsNil) importedMachineId, err := imported.AssignedMachineId() c.Assert(err, jc.ErrorIsNil) c.Assert(importedMachineId, gc.Equals, exportedMachineId) // Confirm machine Principals are set. exportedMachine, err := s.State.Machine(exportedMachineId) c.Assert(err, jc.ErrorIsNil) importedMachine, err := newSt.Machine(importedMachineId) c.Assert(err, jc.ErrorIsNil) s.AssertMachineEqual(c, importedMachine, exportedMachine) meterStatus, err := imported.GetMeterStatus() c.Assert(err, jc.ErrorIsNil) c.Assert(meterStatus, gc.Equals, state.MeterStatus{state.MeterGreen, "some info"}) s.assertAnnotations(c, newSt, imported) s.checkStatusHistory(c, exported, imported, 5) s.checkStatusHistory(c, exported.Agent(), imported.Agent(), 5) s.checkStatusHistory(c, exported.WorkloadVersionHistory(), imported.WorkloadVersionHistory(), 1) newCons, err := imported.Constraints() c.Assert(err, jc.ErrorIsNil) // Can't test the constraints directly, so go through the string repr. c.Assert(newCons.String(), gc.Equals, cons.String()) }
func (s *volumeSuite) TestBuildMAASVolumeParametersJustRootDisk(c *gc.C) { var cons constraints.Value rootSize := uint64(20000) cons.RootDisk = &rootSize vInfo, err := buildMAASVolumeParameters(nil, cons) c.Assert(err, jc.ErrorIsNil) c.Assert(vInfo, jc.DeepEquals, []volumeInfo{ {"root", 20, nil}, }) }
// PrecheckInstance verifies that the provided series and constraints // are valid for use in creating an instance in this environment. func (env *environ) PrecheckInstance(series string, cons constraints.Value, placement string) error { if _, err := env.parsePlacement(placement); err != nil { return errors.Trace(err) } if cons.HasInstanceType() { return errors.Errorf("LXD does not support instance types (got %q)", *cons.InstanceType) } return nil }
// PrecheckInstance verifies that the provided series and constraints // are valid for use in creating an instance in this environment. func (env *environ) PrecheckInstance(series string, cons constraints.Value, placement string) error { if _, err := env.parsePlacement(placement); err != nil { return errors.Trace(err) } if cons.HasInstanceType() { if !checkInstanceType(cons) { return errors.Errorf("invalid GCE instance type %q", *cons.InstanceType) } } return nil }
func (s *volumeSuite) TestBuildMAASVolumeParametersWithRootDisk(c *gc.C) { var cons constraints.Value rootSize := uint64(20000) cons.RootDisk = &rootSize vInfo, err := buildMAASVolumeParameters([]storage.VolumeParams{ {Tag: names.NewVolumeTag("1"), Size: 2000000}, }, cons) c.Assert(err, jc.ErrorIsNil) c.Assert(vInfo, jc.DeepEquals, []volumeInfo{ {"root", 20, nil}, //root disk {"1", 1954, nil}, }) }
func (s *MigrationExportSuite) assertMigrateApplications(c *gc.C, cons constraints.Value) { application := s.Factory.MakeApplication(c, &factory.ApplicationParams{ Settings: map[string]interface{}{ "foo": "bar", }, Constraints: cons, }) err := application.UpdateLeaderSettings(&goodToken{}, map[string]string{ "leader": "true", }) c.Assert(err, jc.ErrorIsNil) err = application.SetMetricCredentials([]byte("sekrit")) c.Assert(err, jc.ErrorIsNil) err = s.State.SetAnnotations(application, testAnnotations) c.Assert(err, jc.ErrorIsNil) s.primeStatusHistory(c, application, status.Active, addedHistoryCount) model, err := s.State.Export() c.Assert(err, jc.ErrorIsNil) applications := model.Applications() c.Assert(applications, gc.HasLen, 1) exported := applications[0] c.Assert(exported.Name(), gc.Equals, application.Name()) c.Assert(exported.Tag(), gc.Equals, application.ApplicationTag()) c.Assert(exported.Series(), gc.Equals, application.Series()) c.Assert(exported.Annotations(), jc.DeepEquals, testAnnotations) c.Assert(exported.Settings(), jc.DeepEquals, map[string]interface{}{ "foo": "bar", }) c.Assert(exported.LeadershipSettings(), jc.DeepEquals, map[string]interface{}{ "leader": "true", }) c.Assert(exported.MetricsCredentials(), jc.DeepEquals, []byte("sekrit")) constraints := exported.Constraints() c.Assert(constraints, gc.NotNil) c.Assert(constraints.Architecture(), gc.Equals, *cons.Arch) c.Assert(constraints.Memory(), gc.Equals, *cons.Mem) if cons.HasVirtType() { c.Assert(constraints.VirtType(), gc.Equals, *cons.VirtType) } history := exported.StatusHistory() c.Assert(history, gc.HasLen, expectedHistoryCount) s.checkStatusHistory(c, history[:addedHistoryCount], status.Active) }
// PrecheckInstance is defined on the state.Prechecker interface. func (env *joyentEnviron) PrecheckInstance(series string, cons constraints.Value, placement string) error { if placement != "" { return fmt.Errorf("unknown placement directive: %s", placement) } if !cons.HasInstanceType() { return nil } // Constraint has an instance-type constraint so let's see if it is valid. instanceTypes, err := env.listInstanceTypes() if err != nil { return err } for _, instanceType := range instanceTypes { if instanceType.Name == *cons.InstanceType { return nil } } return fmt.Errorf("invalid Joyent instance %q specified", *cons.InstanceType) }
func (s *MigrationExportSuite) assertMachinesMigrated(c *gc.C, cons constraints.Value) { // Add a machine with an LXC container. machine1 := s.Factory.MakeMachine(c, &factory.MachineParams{ Constraints: cons, }) nested := s.Factory.MakeMachineNested(c, machine1.Id(), nil) err := s.State.SetAnnotations(machine1, testAnnotations) c.Assert(err, jc.ErrorIsNil) s.primeStatusHistory(c, machine1, status.Started, addedHistoryCount) model, err := s.State.Export() c.Assert(err, jc.ErrorIsNil) machines := model.Machines() c.Assert(machines, gc.HasLen, 1) exported := machines[0] c.Assert(exported.Tag(), gc.Equals, machine1.MachineTag()) c.Assert(exported.Series(), gc.Equals, machine1.Series()) c.Assert(exported.Annotations(), jc.DeepEquals, testAnnotations) constraints := exported.Constraints() c.Assert(constraints, gc.NotNil) c.Assert(constraints.Architecture(), gc.Equals, *cons.Arch) c.Assert(constraints.Memory(), gc.Equals, *cons.Mem) if cons.HasVirtType() { c.Assert(constraints.VirtType(), gc.Equals, *cons.VirtType) } tools, err := machine1.AgentTools() c.Assert(err, jc.ErrorIsNil) exTools := exported.Tools() c.Assert(exTools, gc.NotNil) c.Assert(exTools.Version(), jc.DeepEquals, tools.Version) history := exported.StatusHistory() c.Assert(history, gc.HasLen, expectedHistoryCount) s.checkStatusHistory(c, history[:addedHistoryCount], status.Started) containers := exported.Containers() c.Assert(containers, gc.HasLen, 1) container := containers[0] c.Assert(container.Tag(), gc.Equals, nested.MachineTag()) }
func (context *statusContext) processService(service *state.Service) (status params.ServiceStatus) { serviceCharmURL, _ := service.CharmURL() status.Charm = serviceCharmURL.String() status.Exposed = service.IsExposed() status.Life = processLife(service) latestCharm, ok := context.latestCharms[*serviceCharmURL.WithRevision(-1)] if ok && latestCharm != serviceCharmURL.String() { status.CanUpgradeTo = latestCharm } var err error status.Relations, status.SubordinateTo, err = context.processServiceRelations(service) if err != nil { status.Err = err return } networks, err := service.Networks() if err != nil { status.Err = err return } var cons constraints.Value if service.IsPrincipal() { // Only principals can have constraints. cons, err = service.Constraints() if err != nil { status.Err = err return } } // TODO(dimitern): Drop support for this in a follow-up. if len(networks) > 0 || cons.HaveNetworks() { // Only the explicitly requested networks (using "juju deploy // <svc> --networks=...") will be enabled, and altough when // specified, networks constraints will be used for instance // selection, they won't be actually enabled. status.Networks = params.NetworksSpecification{ Enabled: networks, Disabled: append(cons.IncludeNetworks(), cons.ExcludeNetworks()...), } } if service.IsPrincipal() { status.Units = context.processUnits(context.units[service.Name()], serviceCharmURL.String()) serviceStatus, err := service.Status() if err != nil { status.Err = err return } status.Status.Status = params.Status(serviceStatus.Status) status.Status.Info = serviceStatus.Message status.Status.Data = serviceStatus.Data status.Status.Since = serviceStatus.Since status.MeterStatuses = context.processUnitMeterStatuses(context.units[service.Name()]) } return status }
func (s *BootstrapSuite) TestSetConstraints(c *gc.C) { bootstrapCons := constraints.Value{Mem: uint64p(4096), CpuCores: uint64p(4)} modelCons := constraints.Value{Mem: uint64p(2048), CpuCores: uint64p(2)} _, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlControllerModelConfig, "--hosted-model-config", s.b64yamlHostedModelConfig, "--instance-id", string(s.instanceId), "--bootstrap-constraints", bootstrapCons.String(), "--constraints", modelCons.String(), ) c.Assert(err, jc.ErrorIsNil) err = cmd.Run(nil) c.Assert(err, jc.ErrorIsNil) st, err := state.Open(testing.ModelTag, &mongo.MongoInfo{ Info: mongo.Info{ Addrs: []string{gitjujutesting.MgoServer.Addr()}, CACert: testing.CACert, }, Password: testPassword, }, mongotest.DialOpts(), environs.NewStatePolicy()) c.Assert(err, jc.ErrorIsNil) defer st.Close() cons, err := st.ModelConstraints() c.Assert(err, jc.ErrorIsNil) c.Assert(cons, gc.DeepEquals, modelCons) machines, err := st.AllMachines() c.Assert(err, jc.ErrorIsNil) c.Assert(machines, gc.HasLen, 1) cons, err = machines[0].Constraints() c.Assert(err, jc.ErrorIsNil) c.Assert(cons, gc.DeepEquals, bootstrapCons) }
// PrecheckInstance is defined on the state.Prechecker interface. func (e *Environ) PrecheckInstance(series string, cons constraints.Value, placement string) error { if placement != "" { if _, err := e.parsePlacement(placement); err != nil { return err } } if !cons.HasInstanceType() { return nil } // Constraint has an instance-type constraint so let's see if it is valid. novaClient := e.nova() flavors, err := novaClient.ListFlavorsDetail() if err != nil { return err } for _, flavor := range flavors { if flavor.Name == *cons.InstanceType { return nil } } return errors.Errorf("invalid Openstack flavour %q specified", *cons.InstanceType) }
func (s *constraintsSuite) TestConstraints(c *gc.C) { for i, t := range newConstraintTests { var cv constraints.Value if t.arch != nil { cv.Arch = &t.arch.v } if t.cores != nil { cv.CpuCores = &t.cores.v } if t.power != nil { cv.CpuPower = &t.power.v } if t.mem != nil { cv.Mem = &t.mem.v } if t.disk != nil { cv.RootDisk = &t.disk.v } v := newConstraints(t.bootstrap, cv, img) if !c.Check(*v, gc.Equals, t.expected) { c.Logf("test (%d): %+v", i, t) } } }