~james-page/ubuntu/saucy/juju-core/1.16.5

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/provider/dummy/environs.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-09-03 14:22:22 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20130903142222-9mes2r8wqr0bs7lp
Tags: 1.13.3-0ubuntu1
New upstream point release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
139
139
        storage       *storage
146
146
// environ represents a client's connection to a given environment's
147
147
// state.
148
148
type environ struct {
149
 
        state        *environState
 
149
        name         string
150
150
        ecfgMutex    sync.Mutex
151
151
        ecfgUnlocked *environConfig
152
152
}
204
204
        }
205
205
}
206
206
 
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)
210
 
}
211
 
 
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 {
237
 
        if e.state == nil {
238
 
                return nil
239
 
        }
240
 
        return e.state.apiState
 
232
        return e.state().apiState
241
233
}
242
234
 
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{
248
 
                name:         name,
249
 
                ops:          ops,
250
 
                insts:        make(map[instance.Id]*dummyInstance),
251
 
                globalPorts:  make(map[instance.Port]bool),
252
 
                firewallMode: fwmode,
 
240
                name:        name,
 
241
                ops:         ops,
 
242
                insts:       make(map[instance.Id]*dummyInstance),
 
243
                globalPorts: make(map[instance.Port]bool),
253
244
        }
254
245
        s.storage = newStorage(s, "/"+name+"/private")
255
246
        s.publicStorage = newStorage(s, "/"+name+"/public")
355
346
        return cfg.Apply(validated)
356
347
}
357
348
 
 
349
func (e *environ) state() *environState {
 
350
        p := &providerInstance
 
351
        p.mu.Lock()
 
352
        defer p.mu.Unlock()
 
353
        if state := p.state[e.name]; state != nil {
 
354
                return state
 
355
        }
 
356
        panic(fmt.Errorf("environment %q is not prepared", e.name))
 
357
}
 
358
 
358
359
func (p *environProvider) Open(cfg *config.Config) (environs.Environ, error) {
359
360
        p.mu.Lock()
360
361
        defer p.mu.Unlock()
 
362
        ecfg, err := p.newConfig(cfg)
 
363
        if err != nil {
 
364
                return nil, err
 
365
        }
 
366
        env := &environ{
 
367
                name:         ecfg.Name(),
 
368
                ecfgUnlocked: ecfg,
 
369
        }
 
370
        if err := env.checkBroken("Open"); err != nil {
 
371
                return nil, err
 
372
        }
 
373
        return env, nil
 
374
}
 
375
 
 
376
func (p *environProvider) Prepare(cfg *config.Config) (environs.Environ, error) {
 
377
        ecfg, err := p.newConfig(cfg)
 
378
        if err != nil {
 
379
                return nil, err
 
380
        }
 
381
        p.mu.Lock()
361
382
        name := cfg.Name()
362
 
        ecfg, err := p.newConfig(cfg)
363
 
        if err != nil {
364
 
                return nil, err
365
 
        }
366
383
        state := p.state[name]
367
384
        if state == nil {
368
385
                if ecfg.stateServer() && len(p.state) != 0 {
373
390
                        }
374
391
                        panic(fmt.Errorf("cannot share a state between two dummy environs; old %q; new %q", old, name))
375
392
                }
376
 
                state = newState(name, p.ops, ecfg.FirewallMode())
 
393
                state = newState(name, p.ops)
377
394
                p.state[name] = state
378
395
        }
379
 
        env := &environ{
380
 
                state:        state,
381
 
                ecfgUnlocked: ecfg,
382
 
        }
383
 
        if err := env.checkBroken("Open"); err != nil {
384
 
                return nil, err
385
 
        }
386
 
        return env, nil
 
396
        // TODO(rog) add an attribute to the configuration which is required for Open?
 
397
        p.mu.Unlock()
 
398
        return p.Open(cfg)
387
399
}
388
400
 
389
401
func (*environProvider) SecretAttrs(cfg *config.Config) (map[string]interface{}, error) {
434
446
}
435
447
 
436
448
func (e *environ) Name() string {
437
 
        return e.state.name
 
449
        return e.name
438
450
}
439
451
 
440
452
// GetImageBaseURLs returns a list of URLs which are used to search for simplestreams image metadata.
466
478
                return fmt.Errorf("cannot make bootstrap config: %v", err)
467
479
        }
468
480
 
469
 
        e.state.mu.Lock()
470
 
        defer e.state.mu.Unlock()
471
 
        if e.state.bootstrapped {
 
481
        estate := e.state()
 
482
        estate.mu.Lock()
 
483
        defer estate.mu.Unlock()
 
484
        if estate.bootstrapped {
472
485
                return fmt.Errorf("environment is already bootstrapped")
473
486
        }
474
487
        if e.ecfg().stateServer() {
490
503
                if err != nil {
491
504
                        panic(err)
492
505
                }
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))
494
507
                if err != nil {
495
508
                        panic(err)
496
509
                }
497
 
                e.state.apiState = st
 
510
                estate.apiState = st
498
511
        }
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}
501
514
        return nil
502
515
}
503
516
 
504
517
func (e *environ) StateInfo() (*state.Info, *api.Info, error) {
505
 
        e.state.mu.Lock()
506
 
        defer e.state.mu.Unlock()
 
518
        estate := e.state()
 
519
        estate.mu.Lock()
 
520
        defer estate.mu.Unlock()
507
521
        if err := e.checkBroken("StateInfo"); err != nil {
508
522
                return nil, nil, err
509
523
        }
510
524
        if !e.ecfg().stateServer() {
511
525
                return nil, nil, errors.New("dummy environment has no state configured")
512
526
        }
513
 
        if !e.state.bootstrapped {
 
527
        if !estate.bootstrapped {
514
528
                return nil, nil, errors.New("dummy environment not bootstrapped")
515
529
        }
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),
519
533
        }, nil
520
534
}
533
547
        }
534
548
        e.ecfgMutex.Lock()
535
549
        e.ecfgUnlocked = ecfg
536
 
        e.state.firewallMode = ecfg.FirewallMode()
537
550
        e.ecfgMutex.Unlock()
538
551
        return nil
539
552
}
543
556
        if err := e.checkBroken("Destroy"); err != nil {
544
557
                return err
545
558
        }
546
 
        e.state.mu.Lock()
547
 
        defer e.state.mu.Unlock()
548
 
        e.state.ops <- OpDestroy{Env: e.state.name}
549
 
        e.state.destroy()
 
559
        estate := e.state()
 
560
        estate.mu.Lock()
 
561
        defer estate.mu.Unlock()
 
562
        estate.ops <- OpDestroy{Env: estate.name}
 
563
        estate.destroy()
550
564
        return nil
551
565
}
552
566
 
560
574
        if err := e.checkBroken("StartInstance"); err != nil {
561
575
                return nil, nil, err
562
576
        }
563
 
        e.state.mu.Lock()
564
 
        defer e.state.mu.Unlock()
 
577
        estate := e.state()
 
578
        estate.mu.Lock()
 
579
        defer estate.mu.Unlock()
565
580
        if machineConfig.MachineNonce == "" {
566
581
                return nil, nil, fmt.Errorf("cannot start instance: missing machine nonce")
567
582
        }
577
592
        log.Infof("environs/dummy: would pick tools from %s", possibleTools)
578
593
        series := possibleTools.OneSeries()
579
594
        i := &dummyInstance{
580
 
                state:     e.state,
581
 
                id:        instance.Id(fmt.Sprintf("%s-%d", e.state.name, e.state.maxId)),
582
 
                ports:     make(map[instance.Port]bool),
583
 
                machineId: machineId,
584
 
                series:    series,
 
595
                id:           instance.Id(fmt.Sprintf("%s-%d", e.name, estate.maxId)),
 
596
                ports:        make(map[instance.Port]bool),
 
597
                machineId:    machineId,
 
598
                series:       series,
 
599
                firewallMode: e.Config().FirewallMode(),
 
600
                state:        estate,
585
601
        }
586
602
        var hc *instance.HardwareCharacteristics
587
603
        // To match current system capability, only provide hardware characteristics for
614
630
                        hc.CpuCores = &cores
615
631
                }
616
632
        }
617
 
        e.state.insts[i.id] = i
618
 
        e.state.maxId++
619
 
        e.state.ops <- OpStartInstance{
620
 
                Env:          e.state.name,
 
633
        estate.insts[i.id] = i
 
634
        estate.maxId++
 
635
        estate.ops <- OpStartInstance{
 
636
                Env:          e.name,
621
637
                MachineId:    machineId,
622
638
                MachineNonce: machineConfig.MachineNonce,
623
639
                Constraints:  cons,
634
650
        if err := e.checkBroken("StopInstance"); err != nil {
635
651
                return err
636
652
        }
637
 
        e.state.mu.Lock()
638
 
        defer e.state.mu.Unlock()
 
653
        estate := e.state()
 
654
        estate.mu.Lock()
 
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)
641
658
        }
642
 
        e.state.ops <- OpStopInstances{
643
 
                Env:       e.state.name,
 
659
        estate.ops <- OpStopInstances{
 
660
                Env:       e.name,
644
661
                Instances: is,
645
662
        }
646
663
        return nil
654
671
        if len(ids) == 0 {
655
672
                return nil, nil
656
673
        }
657
 
        e.state.mu.Lock()
658
 
        defer e.state.mu.Unlock()
 
674
        estate := e.state()
 
675
        estate.mu.Lock()
 
676
        defer estate.mu.Unlock()
659
677
        notFound := 0
660
678
        for _, id := range ids {
661
 
                inst := e.state.insts[id]
 
679
                inst := estate.insts[id]
662
680
                if inst == nil {
663
681
                        err = environs.ErrPartialInstances
664
682
                        notFound++
677
695
                return nil, err
678
696
        }
679
697
        var insts []instance.Instance
680
 
        e.state.mu.Lock()
681
 
        defer e.state.mu.Unlock()
682
 
        for _, v := range e.state.insts {
 
698
        estate := e.state()
 
699
        estate.mu.Lock()
 
700
        defer estate.mu.Unlock()
 
701
        for _, v := range estate.insts {
683
702
                insts = append(insts, v)
684
703
        }
685
704
        return insts, nil
686
705
}
687
706
 
688
707
func (e *environ) OpenPorts(ports []instance.Port) error {
689
 
        e.state.mu.Lock()
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)
694
710
        }
 
711
        estate := e.state()
 
712
        estate.mu.Lock()
 
713
        defer estate.mu.Unlock()
695
714
        for _, p := range ports {
696
 
                e.state.globalPorts[p] = true
 
715
                estate.globalPorts[p] = true
697
716
        }
698
717
        return nil
699
718
}
700
719
 
701
720
func (e *environ) ClosePorts(ports []instance.Port) error {
702
 
        e.state.mu.Lock()
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)
707
723
        }
 
724
        estate := e.state()
 
725
        estate.mu.Lock()
 
726
        defer estate.mu.Unlock()
708
727
        for _, p := range ports {
709
 
                delete(e.state.globalPorts, p)
 
728
                delete(estate.globalPorts, p)
710
729
        }
711
730
        return nil
712
731
}
713
732
 
714
733
func (e *environ) Ports() (ports []instance.Port, err error) {
715
 
        e.state.mu.Lock()
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)
720
736
        }
721
 
        for p := range e.state.globalPorts {
 
737
        estate := e.state()
 
738
        estate.mu.Lock()
 
739
        defer estate.mu.Unlock()
 
740
        for p := range estate.globalPorts {
722
741
                ports = append(ports, p)
723
742
        }
724
743
        state.SortPorts(ports)
730
749
}
731
750
 
732
751
type dummyInstance struct {
733
 
        state     *environState
734
 
        ports     map[instance.Port]bool
735
 
        id        instance.Id
736
 
        machineId string
737
 
        series    string
 
752
        state        *environState
 
753
        ports        map[instance.Port]bool
 
754
        id           instance.Id
 
755
        machineId    string
 
756
        series       string
 
757
        firewallMode config.FirewallMode
738
758
}
739
759
 
740
760
func (inst *dummyInstance) Id() instance.Id {
756
776
}
757
777
 
758
778
func (inst *dummyInstance) WaitDNSName() (string, error) {
759
 
        return environs.WaitDNSName(inst)
 
779
        return provider.WaitDNSName(inst)
760
780
}
761
781
 
762
782
func (inst *dummyInstance) OpenPorts(machineId string, ports []instance.Port) error {
763
783
        defer delay()
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",
 
787
                        inst.firewallMode)
768
788
        }
769
789
        if inst.machineId != machineId {
770
790
                panic(fmt.Errorf("OpenPorts with mismatched machine id, expected %q got %q", inst.machineId, machineId))
785
805
 
786
806
func (inst *dummyInstance) ClosePorts(machineId string, ports []instance.Port) error {
787
807
        defer delay()
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",
 
810
                        inst.firewallMode)
791
811
        }
792
812
        if inst.machineId != machineId {
793
813
                panic(fmt.Errorf("ClosePorts with mismatched machine id, expected %s got %s", inst.machineId, machineId))
808
828
 
809
829
func (inst *dummyInstance) Ports(machineId string) (ports []instance.Port, err error) {
810
830
        defer delay()
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",
 
833
                        inst.firewallMode)
814
834
        }
815
835
        if inst.machineId != machineId {
816
836
                panic(fmt.Errorf("Ports with mismatched machine id, expected %q got %q", inst.machineId, machineId))