github.com/openshift/installer@v1.4.17/pkg/destroy/powervs/power-instance.go (about) 1 package powervs 2 3 import ( 4 "context" 5 "fmt" 6 "math" 7 "strings" 8 "time" 9 10 "k8s.io/apimachinery/pkg/util/wait" 11 ) 12 13 const ( 14 powerInstanceTypeName = "powerInstance" 15 ) 16 17 // listPowerInstances lists instances in the power server. 18 func (o *ClusterUninstaller) listPowerInstances() (cloudResources, error) { 19 o.Logger.Debugf("Listing virtual Power service instances (%s)", o.InfraID) 20 21 if o.instanceClient == nil { 22 o.Logger.Infof("Skipping deleting Power service instances because no service instance was found") 23 result := []cloudResource{} 24 return cloudResources{}.insert(result...), nil 25 } 26 27 instances, err := o.instanceClient.GetAll() 28 if err != nil { 29 o.Logger.Warnf("Error instanceClient.GetAll: %v", err) 30 return nil, err 31 } 32 33 var foundOne = false 34 35 result := []cloudResource{} 36 for _, instance := range instances.PvmInstances { 37 // https://github.com/IBM-Cloud/power-go-client/blob/master/power/models/p_vm_instance.go 38 if strings.Contains(*instance.ServerName, o.InfraID) { 39 foundOne = true 40 o.Logger.Debugf("listPowerInstances: FOUND: %s, %s, %s", *instance.PvmInstanceID, *instance.ServerName, *instance.Status) 41 result = append(result, cloudResource{ 42 key: *instance.PvmInstanceID, 43 name: *instance.ServerName, 44 status: *instance.Status, 45 typeName: powerInstanceTypeName, 46 id: *instance.PvmInstanceID, 47 }) 48 } 49 } 50 if !foundOne { 51 o.Logger.Debugf("listPowerInstances: NO matching virtual instance against: %s", o.InfraID) 52 for _, instance := range instances.PvmInstances { 53 o.Logger.Debugf("listPowerInstances: only found virtual instance: %s", *instance.ServerName) 54 } 55 } 56 57 return cloudResources{}.insert(result...), nil 58 } 59 60 // destroyPowerInstance deletes a given instance. 61 func (o *ClusterUninstaller) destroyPowerInstance(item cloudResource) error { 62 var err error 63 64 _, err = o.instanceClient.Get(item.id) 65 if err != nil { 66 o.deletePendingItems(item.typeName, []cloudResource{item}) 67 o.Logger.Infof("Deleted Power Instance %q (%q)", item.name, item.status) 68 return nil 69 } 70 71 o.Logger.Debugf("Deleting Power instance %q", item.name) 72 73 err = o.instanceClient.Delete(item.id) 74 if err != nil { 75 o.Logger.Infof("Error: o.instanceClient.Delete: %q", err) 76 return err 77 } 78 79 o.deletePendingItems(item.typeName, []cloudResource{item}) 80 o.Logger.Infof("Deleted Power Instance %q (%q)", item.name, item.status) 81 82 return nil 83 } 84 85 // destroyPowerInstances searches for Power instances that have a name that starts with 86 // the cluster's infra ID. 87 func (o *ClusterUninstaller) destroyPowerInstances() error { 88 firstPassList, err := o.listPowerInstances() 89 if err != nil { 90 return err 91 } 92 93 if len(firstPassList.list()) == 0 { 94 return nil 95 } 96 97 items := o.insertPendingItems(powerInstanceTypeName, firstPassList.list()) 98 99 ctx, cancel := o.contextWithTimeout() 100 defer cancel() 101 102 for _, item := range items { 103 select { 104 case <-ctx.Done(): 105 o.Logger.Debugf("destroyPowerInstances: case <-ctx.Done()") 106 return o.Context.Err() // we're cancelled, abort 107 default: 108 } 109 110 backoff := wait.Backoff{ 111 Duration: 15 * time.Second, 112 Factor: 1.1, 113 Cap: leftInContext(ctx), 114 Steps: math.MaxInt32} 115 err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) { 116 err2 := o.destroyPowerInstance(item) 117 if err2 == nil { 118 return true, err2 119 } 120 o.errorTracker.suppressWarning(item.key, err2, o.Logger) 121 return false, err2 122 }) 123 if err != nil { 124 o.Logger.Fatal("destroyPowerInstances: ExponentialBackoffWithContext (destroy) returns ", err) 125 } 126 } 127 128 if items = o.getPendingItems(powerInstanceTypeName); len(items) > 0 { 129 for _, item := range items { 130 o.Logger.Debugf("destroyPowerInstances: found %s in pending items", item.name) 131 } 132 return fmt.Errorf("destroyPowerInstances: %d undeleted items pending", len(items)) 133 } 134 135 backoff := wait.Backoff{ 136 Duration: 15 * time.Second, 137 Factor: 1.1, 138 Cap: leftInContext(ctx), 139 Steps: math.MaxInt32} 140 err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) { 141 secondPassList, err2 := o.listPowerInstances() 142 if err2 != nil { 143 return false, err2 144 } 145 if len(secondPassList) == 0 { 146 // We finally don't see any remaining instances! 147 return true, nil 148 } 149 for _, item := range secondPassList { 150 o.Logger.Debugf("destroyPowerInstances: found %s in second pass", item.name) 151 } 152 return false, nil 153 }) 154 if err != nil { 155 o.Logger.Fatal("destroyPowerInstances: ExponentialBackoffWithContext (list) returns ", err) 156 } 157 158 return nil 159 }