Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(91)

Side by Side Diff: environs/openstack/provider.go

Issue 10250044: Implement container lifecycle watcher (Closed)
Patch Set: Implement container lifecycle watcher Created 11 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « environs/openstack/local_test.go ('k') | environs/openstack/provider_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012, 2013 Canonical Ltd. 1 // Copyright 2012, 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 // Stub provider for OpenStack, using goose will be implemented here 4 // Stub provider for OpenStack, using goose will be implemented here
5 5
6 package openstack 6 package openstack
7 7
8 import ( 8 import (
9 "encoding/json" 9 "encoding/json"
10 "errors" 10 "errors"
11 "fmt" 11 "fmt"
12 "io/ioutil" 12 "io/ioutil"
13 "launchpad.net/goose/client" 13 "launchpad.net/goose/client"
14 gooseerrors "launchpad.net/goose/errors" 14 gooseerrors "launchpad.net/goose/errors"
15 "launchpad.net/goose/identity" 15 "launchpad.net/goose/identity"
16 "launchpad.net/goose/nova" 16 "launchpad.net/goose/nova"
17 "launchpad.net/goose/swift" 17 "launchpad.net/goose/swift"
18 "launchpad.net/juju-core/constraints" 18 "launchpad.net/juju-core/constraints"
19 "launchpad.net/juju-core/environs" 19 "launchpad.net/juju-core/environs"
20 "launchpad.net/juju-core/environs/cloudinit" 20 "launchpad.net/juju-core/environs/cloudinit"
21 "launchpad.net/juju-core/environs/config" 21 "launchpad.net/juju-core/environs/config"
22 "launchpad.net/juju-core/environs/imagemetadata" 22 "launchpad.net/juju-core/environs/imagemetadata"
23 "launchpad.net/juju-core/environs/instances" 23 "launchpad.net/juju-core/environs/instances"
24 "launchpad.net/juju-core/environs/tools" 24 "launchpad.net/juju-core/environs/tools"
25 coreerrors "launchpad.net/juju-core/errors" 25 coreerrors "launchpad.net/juju-core/errors"
26 "launchpad.net/juju-core/instance"
26 "launchpad.net/juju-core/log" 27 "launchpad.net/juju-core/log"
27 "launchpad.net/juju-core/state" 28 "launchpad.net/juju-core/state"
28 "launchpad.net/juju-core/state/api" 29 "launchpad.net/juju-core/state/api"
29 "launchpad.net/juju-core/state/api/params" 30 "launchpad.net/juju-core/state/api/params"
30 "launchpad.net/juju-core/utils" 31 "launchpad.net/juju-core/utils"
31 "net/http" 32 "net/http"
32 "strconv" 33 "strconv"
33 "strings" 34 "strings"
34 "sync" 35 "sync"
35 "time" 36 "time"
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 novaUnlocked *nova.Client 264 novaUnlocked *nova.Client
264 storageUnlocked environs.Storage 265 storageUnlocked environs.Storage
265 publicStorageUnlocked environs.StorageReader // optional. 266 publicStorageUnlocked environs.StorageReader // optional.
266 // An ordered list of paths in which to find the simplestreams index fil es used to 267 // An ordered list of paths in which to find the simplestreams index fil es used to
267 // look up image ids. 268 // look up image ids.
268 imageBaseURLs []string 269 imageBaseURLs []string
269 } 270 }
270 271
271 var _ environs.Environ = (*environ)(nil) 272 var _ environs.Environ = (*environ)(nil)
272 273
273 type instance struct { 274 type openstackInstance struct {
274 e *environ 275 e *environ
275 *nova.ServerDetail 276 *nova.ServerDetail
276 address string 277 address string
277 } 278 }
278 279
279 func (inst *instance) String() string { 280 func (inst *openstackInstance) String() string {
280 return inst.ServerDetail.Id 281 return inst.ServerDetail.Id
281 } 282 }
282 283
283 var _ environs.Instance = (*instance)(nil) 284 var _ instance.Instance = (*openstackInstance)(nil)
284 285
285 func (inst *instance) Id() state.InstanceId { 286 func (inst *openstackInstance) Id() state.InstanceId {
286 return state.InstanceId(inst.ServerDetail.Id) 287 return state.InstanceId(inst.ServerDetail.Id)
287 } 288 }
288 289
289 // instanceAddress processes a map of networks to lists of IP 290 // instanceAddress processes a map of networks to lists of IP
290 // addresses, as returned by Nova.GetServer(), extracting the proper 291 // addresses, as returned by Nova.GetServer(), extracting the proper
291 // public (or private, if public is not available) IPv4 address, and 292 // public (or private, if public is not available) IPv4 address, and
292 // returning it, or an error. 293 // returning it, or an error.
293 func instanceAddress(addresses map[string][]nova.IPAddress) (string, error) { 294 func instanceAddress(addresses map[string][]nova.IPAddress) (string, error) {
294 var private, public, privateNet string 295 var private, public, privateNet string
295 for network, ips := range addresses { 296 for network, ips := range addresses {
(...skipping 16 matching lines...) Expand all
312 public = prv[1].Address 313 public = prv[1].Address
313 } 314 }
314 } 315 }
315 // Juju assumes it always needs a public address and loops waiting for o ne. 316 // Juju assumes it always needs a public address and loops waiting for o ne.
316 // In fact a private address is generally fine provided it can be sshed to. 317 // In fact a private address is generally fine provided it can be sshed to.
317 // (ported from py-juju/providers/openstack) 318 // (ported from py-juju/providers/openstack)
318 if public == "" && private != "" { 319 if public == "" && private != "" {
319 public = private 320 public = private
320 } 321 }
321 if public == "" { 322 if public == "" {
322 » » return "", environs.ErrNoDNSName 323 » » return "", instance.ErrNoDNSName
323 } 324 }
324 return public, nil 325 return public, nil
325 } 326 }
326 327
327 func (inst *instance) DNSName() (string, error) { 328 func (inst *openstackInstance) DNSName() (string, error) {
328 if inst.address != "" { 329 if inst.address != "" {
329 return inst.address, nil 330 return inst.address, nil
330 } 331 }
331 // Fetch the instance information again, in case 332 // Fetch the instance information again, in case
332 // the addresses have become available. 333 // the addresses have become available.
333 server, err := inst.e.nova().GetServer(string(inst.Id())) 334 server, err := inst.e.nova().GetServer(string(inst.Id()))
334 if err != nil { 335 if err != nil {
335 return "", err 336 return "", err
336 } 337 }
337 inst.address, err = instanceAddress(server.Addresses) 338 inst.address, err = instanceAddress(server.Addresses)
338 if err != nil { 339 if err != nil {
339 return "", err 340 return "", err
340 } 341 }
341 return inst.address, nil 342 return inst.address, nil
342 } 343 }
343 344
344 func (inst *instance) WaitDNSName() (string, error) { 345 func (inst *openstackInstance) WaitDNSName() (string, error) {
345 for a := longAttempt.Start(); a.Next(); { 346 for a := longAttempt.Start(); a.Next(); {
346 addr, err := inst.DNSName() 347 addr, err := inst.DNSName()
347 » » if err == nil || err != environs.ErrNoDNSName { 348 » » if err == nil || err != instance.ErrNoDNSName {
348 return addr, err 349 return addr, err
349 } 350 }
350 } 351 }
351 return "", fmt.Errorf("timed out trying to get DNS address for %v", inst .Id()) 352 return "", fmt.Errorf("timed out trying to get DNS address for %v", inst .Id())
352 } 353 }
353 354
354 // TODO: following 30 lines nearly verbatim from environs/ec2 355 // TODO: following 30 lines nearly verbatim from environs/ec2
355 356
356 func (inst *instance) OpenPorts(machineId string, ports []params.Port) error { 357 func (inst *openstackInstance) OpenPorts(machineId string, ports []params.Port) error {
357 if inst.e.Config().FirewallMode() != config.FwInstance { 358 if inst.e.Config().FirewallMode() != config.FwInstance {
358 return fmt.Errorf("invalid firewall mode for opening ports on in stance: %q", 359 return fmt.Errorf("invalid firewall mode for opening ports on in stance: %q",
359 inst.e.Config().FirewallMode()) 360 inst.e.Config().FirewallMode())
360 } 361 }
361 name := inst.e.machineGroupName(machineId) 362 name := inst.e.machineGroupName(machineId)
362 if err := inst.e.openPortsInGroup(name, ports); err != nil { 363 if err := inst.e.openPortsInGroup(name, ports); err != nil {
363 return err 364 return err
364 } 365 }
365 log.Infof("environs/openstack: opened ports in security group %s: %v", n ame, ports) 366 log.Infof("environs/openstack: opened ports in security group %s: %v", n ame, ports)
366 return nil 367 return nil
367 } 368 }
368 369
369 func (inst *instance) ClosePorts(machineId string, ports []params.Port) error { 370 func (inst *openstackInstance) ClosePorts(machineId string, ports []params.Port) error {
370 if inst.e.Config().FirewallMode() != config.FwInstance { 371 if inst.e.Config().FirewallMode() != config.FwInstance {
371 return fmt.Errorf("invalid firewall mode for closing ports on in stance: %q", 372 return fmt.Errorf("invalid firewall mode for closing ports on in stance: %q",
372 inst.e.Config().FirewallMode()) 373 inst.e.Config().FirewallMode())
373 } 374 }
374 name := inst.e.machineGroupName(machineId) 375 name := inst.e.machineGroupName(machineId)
375 if err := inst.e.closePortsInGroup(name, ports); err != nil { 376 if err := inst.e.closePortsInGroup(name, ports); err != nil {
376 return err 377 return err
377 } 378 }
378 log.Infof("environs/openstack: closed ports in security group %s: %v", n ame, ports) 379 log.Infof("environs/openstack: closed ports in security group %s: %v", n ame, ports)
379 return nil 380 return nil
380 } 381 }
381 382
382 func (inst *instance) Ports(machineId string) ([]params.Port, error) { 383 func (inst *openstackInstance) Ports(machineId string) ([]params.Port, error) {
383 if inst.e.Config().FirewallMode() != config.FwInstance { 384 if inst.e.Config().FirewallMode() != config.FwInstance {
384 return nil, fmt.Errorf("invalid firewall mode for retrieving por ts from instance: %q", 385 return nil, fmt.Errorf("invalid firewall mode for retrieving por ts from instance: %q",
385 inst.e.Config().FirewallMode()) 386 inst.e.Config().FirewallMode())
386 } 387 }
387 name := inst.e.machineGroupName(machineId) 388 name := inst.e.machineGroupName(machineId)
388 return inst.e.portsInGroup(name) 389 return inst.e.portsInGroup(name)
389 } 390 }
390 391
391 func (e *environ) ecfg() *environConfig { 392 func (e *environ) ecfg() *environConfig {
392 e.ecfgMutex.Lock() 393 e.ecfgMutex.Lock()
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 }) 501 })
501 if err != nil { 502 if err != nil {
502 return fmt.Errorf("cannot start bootstrap instance: %v", err) 503 return fmt.Errorf("cannot start bootstrap instance: %v", err)
503 } 504 }
504 err = e.saveState(&bootstrapState{ 505 err = e.saveState(&bootstrapState{
505 StateInstances: []state.InstanceId{inst.Id()}, 506 StateInstances: []state.InstanceId{inst.Id()},
506 }) 507 })
507 if err != nil { 508 if err != nil {
508 // ignore error on StopInstance because the previous error is 509 // ignore error on StopInstance because the previous error is
509 // more important. 510 // more important.
510 » » e.StopInstances([]environs.Instance{inst}) 511 » » e.StopInstances([]instance.Instance{inst})
511 return fmt.Errorf("cannot save state: %v", err) 512 return fmt.Errorf("cannot save state: %v", err)
512 } 513 }
513 // TODO make safe in the case of racing Bootstraps 514 // TODO make safe in the case of racing Bootstraps
514 // If two Bootstraps are called concurrently, there's 515 // If two Bootstraps are called concurrently, there's
515 // no way to use Swift to make sure that only one succeeds. 516 // no way to use Swift to make sure that only one succeeds.
516 // Perhaps consider using SimpleDB for state storage 517 // Perhaps consider using SimpleDB for state storage
517 // which would enable that possibility. 518 // which would enable that possibility.
518 519
519 return nil 520 return nil
520 } 521 }
(...skipping 17 matching lines...) Expand all
538 insts, err := e.Instances(st.StateInstances) 539 insts, err := e.Instances(st.StateInstances)
539 if err != nil && err != environs.ErrPartialInstances { 540 if err != nil && err != environs.ErrPartialInstances {
540 log.Debugf("error getting state instance: %v", err.Error ()) 541 log.Debugf("error getting state instance: %v", err.Error ())
541 return nil, nil, err 542 return nil, nil, err
542 } 543 }
543 log.Debugf("started processing instances: %#v", insts) 544 log.Debugf("started processing instances: %#v", insts)
544 for _, inst := range insts { 545 for _, inst := range insts {
545 if inst == nil { 546 if inst == nil {
546 continue 547 continue
547 } 548 }
548 » » » name, err := inst.(*instance).DNSName() 549 » » » name, err := inst.(*openstackInstance).DNSName()
549 if err != nil { 550 if err != nil {
550 continue 551 continue
551 } 552 }
552 if name != "" { 553 if name != "" {
553 statePortSuffix := fmt.Sprintf(":%d", config.Sta tePort()) 554 statePortSuffix := fmt.Sprintf(":%d", config.Sta tePort())
554 apiPortSuffix := fmt.Sprintf(":%d", config.APIPo rt()) 555 apiPortSuffix := fmt.Sprintf(":%d", config.APIPo rt())
555 stateAddrs = append(stateAddrs, name+statePortSu ffix) 556 stateAddrs = append(stateAddrs, name+statePortSu ffix)
556 apiAddrs = append(apiAddrs, name+apiPortSuffix) 557 apiAddrs = append(apiAddrs, name+apiPortSuffix)
557 } 558 }
558 } 559 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 productStreamsURL, err := e.client.MakeServiceURL("product-streams", nil ) 651 productStreamsURL, err := e.client.MakeServiceURL("product-streams", nil )
651 if err == nil { 652 if err == nil {
652 e.imageBaseURLs = append(e.imageBaseURLs, productStreamsURL) 653 e.imageBaseURLs = append(e.imageBaseURLs, productStreamsURL)
653 } 654 }
654 // Add the default simplestreams base URL. 655 // Add the default simplestreams base URL.
655 e.imageBaseURLs = append(e.imageBaseURLs, imagemetadata.DefaultBaseURL) 656 e.imageBaseURLs = append(e.imageBaseURLs, imagemetadata.DefaultBaseURL)
656 657
657 return e.imageBaseURLs, nil 658 return e.imageBaseURLs, nil
658 } 659 }
659 660
660 func (e *environ) StartInstance(machineId, machineNonce string, series string, c ons constraints.Value, info *state.Info, apiInfo *api.Info) (environs.Instance, error) { 661 func (e *environ) StartInstance(machineId, machineNonce string, series string, c ons constraints.Value, info *state.Info, apiInfo *api.Info) (instance.Instance, error) {
661 possibleTools, err := environs.FindInstanceTools(e, series, cons) 662 possibleTools, err := environs.FindInstanceTools(e, series, cons)
662 if err != nil { 663 if err != nil {
663 return nil, err 664 return nil, err
664 } 665 }
665 return e.startInstance(&startInstanceParams{ 666 return e.startInstance(&startInstanceParams{
666 machineId: machineId, 667 machineId: machineId,
667 machineNonce: machineNonce, 668 machineNonce: machineNonce,
668 series: series, 669 series: series,
669 constraints: cons, 670 constraints: cons,
670 info: info, 671 info: info,
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 err = e.nova().AddServerFloatingIP(serverId, fip.IP) 761 err = e.nova().AddServerFloatingIP(serverId, fip.IP)
761 if err == nil { 762 if err == nil {
762 return nil 763 return nil
763 } 764 }
764 } 765 }
765 return err 766 return err
766 } 767 }
767 768
768 // startInstance is the internal version of StartInstance, used by Bootstrap 769 // startInstance is the internal version of StartInstance, used by Bootstrap
769 // as well as via StartInstance itself. 770 // as well as via StartInstance itself.
770 func (e *environ) startInstance(scfg *startInstanceParams) (environs.Instance, e rror) { 771 func (e *environ) startInstance(scfg *startInstanceParams) (instance.Instance, e rror) {
771 series := scfg.possibleTools.Series() 772 series := scfg.possibleTools.Series()
772 if len(series) != 1 { 773 if len(series) != 1 {
773 return nil, fmt.Errorf("expected single series, got %v", series) 774 return nil, fmt.Errorf("expected single series, got %v", series)
774 } 775 }
775 if series[0] != scfg.series { 776 if series[0] != scfg.series {
776 return nil, fmt.Errorf("tools mismatch: expected series %v, got %v", series, series[0]) 777 return nil, fmt.Errorf("tools mismatch: expected series %v, got %v", series, series[0])
777 } 778 }
778 arches := scfg.possibleTools.Arches() 779 arches := scfg.possibleTools.Arches()
779 spec, err := findInstanceSpec(e, &instances.InstanceConstraint{ 780 spec, err := findInstanceSpec(e, &instances.InstanceConstraint{
780 Region: e.ecfg().region(), 781 Region: e.ecfg().region(),
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 break 826 break
826 } 827 }
827 } 828 }
828 if err != nil { 829 if err != nil {
829 return nil, fmt.Errorf("cannot run instance: %v", err) 830 return nil, fmt.Errorf("cannot run instance: %v", err)
830 } 831 }
831 detail, err := e.nova().GetServer(server.Id) 832 detail, err := e.nova().GetServer(server.Id)
832 if err != nil { 833 if err != nil {
833 return nil, fmt.Errorf("cannot get started instance: %v", err) 834 return nil, fmt.Errorf("cannot get started instance: %v", err)
834 } 835 }
835 » inst := &instance{e, detail, ""} 836 » inst := &openstackInstance{e, detail, ""}
836 log.Infof("environs/openstack: started instance %q", inst.Id()) 837 log.Infof("environs/openstack: started instance %q", inst.Id())
837 if scfg.withPublicIP { 838 if scfg.withPublicIP {
838 if err := e.assignPublicIP(publicIP, string(inst.Id())); err != nil { 839 if err := e.assignPublicIP(publicIP, string(inst.Id())); err != nil {
839 if err := e.terminateInstances([]state.InstanceId{inst.I d()}); err != nil { 840 if err := e.terminateInstances([]state.InstanceId{inst.I d()}); err != nil {
840 // ignore the failure at this stage, just log it 841 // ignore the failure at this stage, just log it
841 log.Debugf("environs/openstack: failed to termin ate instance %q: %v", inst.Id(), err) 842 log.Debugf("environs/openstack: failed to termin ate instance %q: %v", inst.Id(), err)
842 } 843 }
843 return nil, fmt.Errorf("cannot assign public address %s to instance %q: %v", publicIP.IP, inst.Id(), err) 844 return nil, fmt.Errorf("cannot assign public address %s to instance %q: %v", publicIP.IP, inst.Id(), err)
844 } 845 }
845 log.Infof("environs/openstack: assigned public IP %s to %q", pub licIP.IP, inst.Id()) 846 log.Infof("environs/openstack: assigned public IP %s to %q", pub licIP.IP, inst.Id())
846 } 847 }
847 return inst, nil 848 return inst, nil
848 } 849 }
849 850
850 func (e *environ) StopInstances(insts []environs.Instance) error { 851 func (e *environ) StopInstances(insts []instance.Instance) error {
851 ids := make([]state.InstanceId, len(insts)) 852 ids := make([]state.InstanceId, len(insts))
852 for i, inst := range insts { 853 for i, inst := range insts {
853 » » instanceValue, ok := inst.(*instance) 854 » » instanceValue, ok := inst.(*openstackInstance)
854 if !ok { 855 if !ok {
855 » » » return errors.New("Incompatible environs.Instance suppli ed") 856 » » » return errors.New("Incompatible instance.Instance suppli ed")
856 } 857 }
857 ids[i] = instanceValue.Id() 858 ids[i] = instanceValue.Id()
858 } 859 }
859 log.Debugf("environs/openstack: terminating instances %v", ids) 860 log.Debugf("environs/openstack: terminating instances %v", ids)
860 return e.terminateInstances(ids) 861 return e.terminateInstances(ids)
861 } 862 }
862 863
863 // collectInstances tries to get information on each instance id in ids. 864 // collectInstances tries to get information on each instance id in ids.
864 // It fills the slots in the given map for known servers with status 865 // It fills the slots in the given map for known servers with status
865 // either ACTIVE or BUILD. Returns a list of missing ids. 866 // either ACTIVE or BUILD. Returns a list of missing ids.
866 func (e *environ) collectInstances(ids []state.InstanceId, out map[state.Instanc eId]environs.Instance) []state.InstanceId { 867 func (e *environ) collectInstances(ids []state.InstanceId, out map[state.Instanc eId]instance.Instance) []state.InstanceId {
867 var err error 868 var err error
868 serversById := make(map[string]nova.ServerDetail) 869 serversById := make(map[string]nova.ServerDetail)
869 if len(ids) == 1 { 870 if len(ids) == 1 {
870 // most common case - single instance 871 // most common case - single instance
871 var server *nova.ServerDetail 872 var server *nova.ServerDetail
872 server, err = e.nova().GetServer(string(ids[0])) 873 server, err = e.nova().GetServer(string(ids[0]))
873 if server != nil { 874 if server != nil {
874 serversById[server.Id] = *server 875 serversById[server.Id] = *server
875 } 876 }
876 } else { 877 } else {
877 var servers []nova.ServerDetail 878 var servers []nova.ServerDetail
878 servers, err = e.nova().ListServersDetail(e.machinesFilter()) 879 servers, err = e.nova().ListServersDetail(e.machinesFilter())
879 for _, server := range servers { 880 for _, server := range servers {
880 serversById[server.Id] = server 881 serversById[server.Id] = server
881 } 882 }
882 } 883 }
883 if err != nil { 884 if err != nil {
884 return ids 885 return ids
885 } 886 }
886 var missing []state.InstanceId 887 var missing []state.InstanceId
887 for _, id := range ids { 888 for _, id := range ids {
888 if server, found := serversById[string(id)]; found { 889 if server, found := serversById[string(id)]; found {
889 if server.Status == nova.StatusActive || server.Status = = nova.StatusBuild { 890 if server.Status == nova.StatusActive || server.Status = = nova.StatusBuild {
890 » » » » out[id] = &instance{e, &server, ""} 891 » » » » out[id] = &openstackInstance{e, &server, ""}
891 } 892 }
892 continue 893 continue
893 } 894 }
894 missing = append(missing, id) 895 missing = append(missing, id)
895 } 896 }
896 return missing 897 return missing
897 } 898 }
898 899
899 func (e *environ) Instances(ids []state.InstanceId) ([]environs.Instance, error) { 900 func (e *environ) Instances(ids []state.InstanceId) ([]instance.Instance, error) {
900 if len(ids) == 0 { 901 if len(ids) == 0 {
901 return nil, nil 902 return nil, nil
902 } 903 }
903 missing := ids 904 missing := ids
904 » found := make(map[state.InstanceId]environs.Instance) 905 » found := make(map[state.InstanceId]instance.Instance)
905 // Make a series of requests to cope with eventual consistency. 906 // Make a series of requests to cope with eventual consistency.
906 // Each request will attempt to add more instances to the requested 907 // Each request will attempt to add more instances to the requested
907 // set. 908 // set.
908 for a := shortAttempt.Start(); a.Next(); { 909 for a := shortAttempt.Start(); a.Next(); {
909 if missing = e.collectInstances(missing, found); len(missing) == 0 { 910 if missing = e.collectInstances(missing, found); len(missing) == 0 {
910 break 911 break
911 } 912 }
912 } 913 }
913 if len(found) == 0 { 914 if len(found) == 0 {
914 return nil, environs.ErrNoInstances 915 return nil, environs.ErrNoInstances
915 } 916 }
916 » insts := make([]environs.Instance, len(ids)) 917 » insts := make([]instance.Instance, len(ids))
917 var err error 918 var err error
918 for i, id := range ids { 919 for i, id := range ids {
919 if inst := found[id]; inst != nil { 920 if inst := found[id]; inst != nil {
920 insts[i] = inst 921 insts[i] = inst
921 } else { 922 } else {
922 err = environs.ErrPartialInstances 923 err = environs.ErrPartialInstances
923 } 924 }
924 } 925 }
925 return insts, err 926 return insts, err
926 } 927 }
927 928
928 func (e *environ) AllInstances() (insts []environs.Instance, err error) { 929 func (e *environ) AllInstances() (insts []instance.Instance, err error) {
929 servers, err := e.nova().ListServersDetail(e.machinesFilter()) 930 servers, err := e.nova().ListServersDetail(e.machinesFilter())
930 if err != nil { 931 if err != nil {
931 return nil, err 932 return nil, err
932 } 933 }
933 for _, server := range servers { 934 for _, server := range servers {
934 if server.Status == nova.StatusActive || server.Status == nova.S tatusBuild { 935 if server.Status == nova.StatusActive || server.Status == nova.S tatusBuild {
935 var s = server 936 var s = server
936 » » » insts = append(insts, &instance{e, &s, ""}) 937 » » » insts = append(insts, &openstackInstance{e, &s, ""})
937 } 938 }
938 } 939 }
939 return insts, err 940 return insts, err
940 } 941 }
941 942
942 func (e *environ) Destroy(ensureInsts []environs.Instance) error { 943 func (e *environ) Destroy(ensureInsts []instance.Instance) error {
943 log.Infof("environs/openstack: destroying environment %q", e.name) 944 log.Infof("environs/openstack: destroying environment %q", e.name)
944 insts, err := e.AllInstances() 945 insts, err := e.AllInstances()
945 if err != nil { 946 if err != nil {
946 return fmt.Errorf("cannot get instances: %v", err) 947 return fmt.Errorf("cannot get instances: %v", err)
947 } 948 }
948 found := make(map[state.InstanceId]bool) 949 found := make(map[state.InstanceId]bool)
949 var ids []state.InstanceId 950 var ids []state.InstanceId
950 for _, inst := range insts { 951 for _, inst := range insts {
951 ids = append(ids, inst.Id()) 952 ids = append(ids, inst.Id())
952 found[inst.Id()] = true 953 found[inst.Id()] = true
953 } 954 }
954 955
955 // Add any instances we've been told about but haven't yet shown 956 // Add any instances we've been told about but haven't yet shown
956 // up in the instance list. 957 // up in the instance list.
957 for _, inst := range ensureInsts { 958 for _, inst := range ensureInsts {
958 » » id := state.InstanceId(inst.(*instance).Id()) 959 » » id := state.InstanceId(inst.(*openstackInstance).Id())
959 if !found[id] { 960 if !found[id] {
960 ids = append(ids, id) 961 ids = append(ids, id)
961 found[id] = true 962 found[id] = true
962 } 963 }
963 } 964 }
964 err = e.terminateInstances(ids) 965 err = e.terminateInstances(ids)
965 if err != nil { 966 if err != nil {
966 return err 967 return err
967 } 968 }
968 969
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
1196 if gooseerrors.IsNotFound(err) { 1197 if gooseerrors.IsNotFound(err) {
1197 err = nil 1198 err = nil
1198 } 1199 }
1199 if err != nil && firstErr == nil { 1200 if err != nil && firstErr == nil {
1200 log.Debugf("environs/openstack: error terminating instan ce %q: %v", id, err) 1201 log.Debugf("environs/openstack: error terminating instan ce %q: %v", id, err)
1201 firstErr = err 1202 firstErr = err
1202 } 1203 }
1203 } 1204 }
1204 return firstErr 1205 return firstErr
1205 } 1206 }
OLDNEW
« no previous file with comments | « environs/openstack/local_test.go ('k') | environs/openstack/provider_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b