42
42
"launchpad.net/juju-core/instance"
43
43
"launchpad.net/juju-core/log"
44
44
"launchpad.net/juju-core/names"
45
"launchpad.net/juju-core/provider"
45
46
"launchpad.net/juju-core/schema"
46
47
"launchpad.net/juju-core/state"
47
48
"launchpad.net/juju-core/state/api"
133
134
maxId int // maximum instance id allocated so far.
134
135
insts map[instance.Id]*dummyInstance
135
136
globalPorts map[instance.Port]bool
136
firewallMode config.FirewallMode
137
137
bootstrapped bool
138
138
storageDelay time.Duration
207
// ResetPublicStorage clears the contents of the specified environment's public storage.
208
func ResetPublicStorage(e environs.Environ) {
209
e.(*environ).state.publicStorage.files = make(map[string][]byte)
212
207
func (state *environState) destroy() {
213
208
state.storage.files = make(map[string][]byte)
214
209
if !state.bootstrapped {
234
229
// This is so code in the test suite can trigger Syncs, etc that the API server
235
230
// will see, which will then trigger API watchers, etc.
236
231
func (e *environ) GetStateInAPIServer() *state.State {
240
return e.state.apiState
232
return e.state().apiState
243
235
// newState creates the state for a new environment with the
244
236
// given name and starts an http server listening for
245
237
// storage requests.
246
func newState(name string, ops chan<- Operation, fwmode config.FirewallMode) *environState {
238
func newState(name string, ops chan<- Operation) *environState {
247
239
s := &environState{
250
insts: make(map[instance.Id]*dummyInstance),
251
globalPorts: make(map[instance.Port]bool),
252
firewallMode: fwmode,
242
insts: make(map[instance.Id]*dummyInstance),
243
globalPorts: make(map[instance.Port]bool),
254
245
s.storage = newStorage(s, "/"+name+"/private")
255
246
s.publicStorage = newStorage(s, "/"+name+"/public")
355
346
return cfg.Apply(validated)
349
func (e *environ) state() *environState {
350
p := &providerInstance
353
if state := p.state[e.name]; state != nil {
356
panic(fmt.Errorf("environment %q is not prepared", e.name))
358
359
func (p *environProvider) Open(cfg *config.Config) (environs.Environ, error) {
360
361
defer p.mu.Unlock()
362
ecfg, err := p.newConfig(cfg)
370
if err := env.checkBroken("Open"); err != nil {
376
func (p *environProvider) Prepare(cfg *config.Config) (environs.Environ, error) {
377
ecfg, err := p.newConfig(cfg)
361
382
name := cfg.Name()
362
ecfg, err := p.newConfig(cfg)
366
383
state := p.state[name]
367
384
if state == nil {
368
385
if ecfg.stateServer() && len(p.state) != 0 {
374
391
panic(fmt.Errorf("cannot share a state between two dummy environs; old %q; new %q", old, name))
376
state = newState(name, p.ops, ecfg.FirewallMode())
393
state = newState(name, p.ops)
377
394
p.state[name] = state
383
if err := env.checkBroken("Open"); err != nil {
396
// TODO(rog) add an attribute to the configuration which is required for Open?
389
401
func (*environProvider) SecretAttrs(cfg *config.Config) (map[string]interface{}, error) {
466
478
return fmt.Errorf("cannot make bootstrap config: %v", err)
470
defer e.state.mu.Unlock()
471
if e.state.bootstrapped {
483
defer estate.mu.Unlock()
484
if estate.bootstrapped {
472
485
return fmt.Errorf("environment is already bootstrapped")
474
487
if e.ecfg().stateServer() {
493
e.state.apiServer, err = apiserver.NewServer(st, "localhost:0", []byte(testing.ServerCert), []byte(testing.ServerKey))
506
estate.apiServer, err = apiserver.NewServer(st, "localhost:0", []byte(testing.ServerCert), []byte(testing.ServerKey))
497
e.state.apiState = st
499
e.state.bootstrapped = true
500
e.state.ops <- OpBootstrap{Env: e.state.name, Constraints: cons}
512
estate.bootstrapped = true
513
estate.ops <- OpBootstrap{Env: e.name, Constraints: cons}
504
517
func (e *environ) StateInfo() (*state.Info, *api.Info, error) {
506
defer e.state.mu.Unlock()
520
defer estate.mu.Unlock()
507
521
if err := e.checkBroken("StateInfo"); err != nil {
508
522
return nil, nil, err
510
524
if !e.ecfg().stateServer() {
511
525
return nil, nil, errors.New("dummy environment has no state configured")
513
if !e.state.bootstrapped {
527
if !estate.bootstrapped {
514
528
return nil, nil, errors.New("dummy environment not bootstrapped")
516
530
return stateInfo(), &api.Info{
517
Addrs: []string{e.state.apiServer.Addr()},
531
Addrs: []string{estate.apiServer.Addr()},
518
532
CACert: []byte(testing.CACert),
560
574
if err := e.checkBroken("StartInstance"); err != nil {
561
575
return nil, nil, err
564
defer e.state.mu.Unlock()
579
defer estate.mu.Unlock()
565
580
if machineConfig.MachineNonce == "" {
566
581
return nil, nil, fmt.Errorf("cannot start instance: missing machine nonce")
577
592
log.Infof("environs/dummy: would pick tools from %s", possibleTools)
578
593
series := possibleTools.OneSeries()
579
594
i := &dummyInstance{
581
id: instance.Id(fmt.Sprintf("%s-%d", e.state.name, e.state.maxId)),
582
ports: make(map[instance.Port]bool),
583
machineId: machineId,
595
id: instance.Id(fmt.Sprintf("%s-%d", e.name, estate.maxId)),
596
ports: make(map[instance.Port]bool),
597
machineId: machineId,
599
firewallMode: e.Config().FirewallMode(),
586
602
var hc *instance.HardwareCharacteristics
587
603
// To match current system capability, only provide hardware characteristics for
634
650
if err := e.checkBroken("StopInstance"); err != nil {
638
defer e.state.mu.Unlock()
655
defer estate.mu.Unlock()
639
656
for _, i := range is {
640
delete(e.state.insts, i.(*dummyInstance).id)
657
delete(estate.insts, i.(*dummyInstance).id)
642
e.state.ops <- OpStopInstances{
659
estate.ops <- OpStopInstances{
679
697
var insts []instance.Instance
681
defer e.state.mu.Unlock()
682
for _, v := range e.state.insts {
700
defer estate.mu.Unlock()
701
for _, v := range estate.insts {
683
702
insts = append(insts, v)
685
704
return insts, nil
688
707
func (e *environ) OpenPorts(ports []instance.Port) error {
690
defer e.state.mu.Unlock()
691
if e.state.firewallMode != config.FwGlobal {
692
return fmt.Errorf("invalid firewall mode for opening ports on environment: %q",
693
e.state.firewallMode)
708
if mode := e.ecfg().FirewallMode(); mode != config.FwGlobal {
709
return fmt.Errorf("invalid firewall mode %q for opening ports on environment", mode)
713
defer estate.mu.Unlock()
695
714
for _, p := range ports {
696
e.state.globalPorts[p] = true
715
estate.globalPorts[p] = true
701
720
func (e *environ) ClosePorts(ports []instance.Port) error {
703
defer e.state.mu.Unlock()
704
if e.state.firewallMode != config.FwGlobal {
705
return fmt.Errorf("invalid firewall mode for closing ports on environment: %q",
706
e.state.firewallMode)
721
if mode := e.ecfg().FirewallMode(); mode != config.FwGlobal {
722
return fmt.Errorf("invalid firewall mode %q for closing ports on environment", mode)
726
defer estate.mu.Unlock()
708
727
for _, p := range ports {
709
delete(e.state.globalPorts, p)
728
delete(estate.globalPorts, p)
714
733
func (e *environ) Ports() (ports []instance.Port, err error) {
716
defer e.state.mu.Unlock()
717
if e.state.firewallMode != config.FwGlobal {
718
return nil, fmt.Errorf("invalid firewall mode for retrieving ports from environment: %q",
719
e.state.firewallMode)
734
if mode := e.ecfg().FirewallMode(); mode != config.FwGlobal {
735
return nil, fmt.Errorf("invalid firewall mode %q for retrieving ports from environment", mode)
721
for p := range e.state.globalPorts {
739
defer estate.mu.Unlock()
740
for p := range estate.globalPorts {
722
741
ports = append(ports, p)
724
743
state.SortPorts(ports)
732
751
type dummyInstance struct {
734
ports map[instance.Port]bool
753
ports map[instance.Port]bool
757
firewallMode config.FirewallMode
740
760
func (inst *dummyInstance) Id() instance.Id {
758
778
func (inst *dummyInstance) WaitDNSName() (string, error) {
759
return environs.WaitDNSName(inst)
779
return provider.WaitDNSName(inst)
762
782
func (inst *dummyInstance) OpenPorts(machineId string, ports []instance.Port) error {
764
784
log.Infof("environs/dummy: openPorts %s, %#v", machineId, ports)
765
if inst.state.firewallMode != config.FwInstance {
766
return fmt.Errorf("invalid firewall mode for opening ports on instance: %q",
767
inst.state.firewallMode)
785
if inst.firewallMode != config.FwInstance {
786
return fmt.Errorf("invalid firewall mode %q for opening ports on instance",
769
789
if inst.machineId != machineId {
770
790
panic(fmt.Errorf("OpenPorts with mismatched machine id, expected %q got %q", inst.machineId, machineId))
786
806
func (inst *dummyInstance) ClosePorts(machineId string, ports []instance.Port) error {
788
if inst.state.firewallMode != config.FwInstance {
789
return fmt.Errorf("invalid firewall mode for closing ports on instance: %q",
790
inst.state.firewallMode)
808
if inst.firewallMode != config.FwInstance {
809
return fmt.Errorf("invalid firewall mode %q for closing ports on instance",
792
812
if inst.machineId != machineId {
793
813
panic(fmt.Errorf("ClosePorts with mismatched machine id, expected %s got %s", inst.machineId, machineId))
809
829
func (inst *dummyInstance) Ports(machineId string) (ports []instance.Port, err error) {
811
if inst.state.firewallMode != config.FwInstance {
812
return nil, fmt.Errorf("invalid firewall mode for retrieving ports from instance: %q",
813
inst.state.firewallMode)
831
if inst.firewallMode != config.FwInstance {
832
return nil, fmt.Errorf("invalid firewall mode %q for retrieving ports from instance",
815
835
if inst.machineId != machineId {
816
836
panic(fmt.Errorf("Ports with mismatched machine id, expected %q got %q", inst.machineId, machineId))