github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/providers/openstack/list_instances.go (about) 1 package openstack 2 3 import ( 4 "github.com/sirupsen/logrus" 5 "github.com/emc-advanced-dev/pkg/errors" 6 "github.com/solo-io/unik/pkg/types" 7 "github.com/rackspace/gophercloud" 8 "github.com/rackspace/gophercloud/openstack/compute/v2/servers" 9 "github.com/rackspace/gophercloud/pagination" 10 "strings" 11 ) 12 13 func (p *OpenstackProvider) ListInstances() ([]*types.Instance, error) { 14 // Return immediately if no instance is managed by unik. 15 managedInstances := p.state.GetInstances() 16 if len(managedInstances) < 1 { 17 return []*types.Instance{}, nil 18 } 19 20 clientNova, err := p.newClientNova() 21 if err != nil { 22 return nil, err 23 } 24 25 instList, err := fetchInstances(clientNova, managedInstances) 26 27 // Update state. 28 if err := p.state.ModifyInstances(func(instances map[string]*types.Instance) error { 29 // Clear everything. 30 for k := range instances { 31 delete(instances, k) 32 } 33 34 // Add fetched instances. 35 for _, inst := range instList { 36 instances[inst.Id] = inst 37 } 38 return nil 39 }); err != nil { 40 return nil, errors.New("failed to modify instance map in state", err) 41 } 42 43 return instList, nil 44 } 45 46 // fetchInstances fetches a list of instances runnign on OpenStack and returns a list of 47 // those that are managed by unik. 48 func fetchInstances(clientNova *gophercloud.ServiceClient, managedInstances map[string]*types.Instance) ([]*types.Instance, error) { 49 var result []*types.Instance = make([]*types.Instance, 0) 50 51 pagerServers := servers.List(clientNova, servers.ListOpts{}) 52 pagerServers.EachPage(func(page pagination.Page) (bool, error) { 53 serverList, err := servers.ExtractServers(page) 54 if err != nil { 55 return false, err 56 } 57 58 for _, s := range serverList { 59 // Filter out instances that unik is not aware of. 60 instance, ok := managedInstances[s.ID] 61 if !ok { 62 continue 63 } 64 65 // Interpret instance state and filter out instance with bad state. 66 if state := parseInstanceState(s.Status); state == types.InstanceState_Terminated { 67 continue 68 } else { 69 instance.State = state 70 } 71 72 // Update fields. 73 instance.Name = s.Name 74 instance.IpAddress = s.AccessIPv4 75 76 result = append(result, instance) 77 } 78 79 return true, nil 80 }) 81 return result, nil 82 } 83 84 func parseInstanceState(serverState string) types.InstanceState { 85 // http://docs.openstack.org/developer/nova/vmstates.html#vm-states-and-possible-commands 86 switch strings.ToLower(serverState) { 87 case "active", "rescued": 88 return types.InstanceState_Running 89 case "building": 90 return types.InstanceState_Pending 91 case "paused": 92 return types.InstanceState_Paused 93 case "suspended": 94 return types.InstanceState_Suspended 95 case "shutoff", "stopped", "soft_deleted": 96 return types.InstanceState_Stopped 97 case "hard_deleted": 98 return types.InstanceState_Terminated 99 case "error": 100 return types.InstanceState_Error 101 } 102 103 logrus.WithFields(logrus.Fields{ 104 "serverState": serverState, 105 }).Infof("Received unknown instance state") 106 107 return types.InstanceState_Unknown 108 }