github.com/openshift/installer@v1.4.17/pkg/destroy/powervs/dhcp.go (about)

     1  package powervs
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/IBM-Cloud/power-go-client/power/models"
    11  	"k8s.io/apimachinery/pkg/util/wait"
    12  )
    13  
    14  const (
    15  	dhcpTypeName = "dhcp"
    16  )
    17  
    18  // listDHCPNetworks lists previously found DHCP networks in found instances in the vpc.
    19  func (o *ClusterUninstaller) listDHCPNetworks() (cloudResources, error) {
    20  	// https://github.com/IBM-Cloud/power-go-client/blob/v1.0.88/power/models/d_h_c_p_servers.go#L19
    21  	var dhcpServers models.DHCPServers
    22  	// https://github.com/IBM-Cloud/power-go-client/blob/v1.0.88/power/models/d_h_c_p_server.go#L18-L31
    23  	var dhcpServer *models.DHCPServer
    24  	var err error
    25  
    26  	o.Logger.Debugf("Listing DHCP networks")
    27  
    28  	if o.dhcpClient == nil {
    29  		o.Logger.Infof("Skipping deleting DHCP servers because no service instance was found")
    30  		result := []cloudResource{}
    31  		return cloudResources{}.insert(result...), nil
    32  	}
    33  
    34  	dhcpServers, err = o.dhcpClient.GetAll()
    35  	if err != nil {
    36  		o.Logger.Fatalf("Failed to list DHCP servers: %v", err)
    37  	}
    38  
    39  	var foundOne = false
    40  
    41  	result := []cloudResource{}
    42  	for _, dhcpServer = range dhcpServers {
    43  		if dhcpServer.Network == nil {
    44  			o.Logger.Debugf("listDHCPNetworks: DHCP has empty Network: %s", *dhcpServer.ID)
    45  			continue
    46  		}
    47  		if dhcpServer.Network.Name == nil {
    48  			// https://github.com/IBM-Cloud/power-go-client/blob/master/power/models/p_vm_instance.go#L22
    49  			var instance *models.PVMInstance
    50  
    51  			o.Logger.Debugf("listDHCPNetworks: DHCP has empty Network.Name: %s", *dhcpServer.ID)
    52  
    53  			instance, err = o.instanceClient.Get(*dhcpServer.ID)
    54  			o.Logger.Debugf("listDHCPNetworks: Getting instance %s %v", *dhcpServer.ID, err)
    55  			if err != nil {
    56  				continue
    57  			}
    58  
    59  			if instance.Status == nil {
    60  				continue
    61  			}
    62  			// If there is a backing DHCP VM and it has a status, then check for an ERROR state
    63  			o.Logger.Debugf("listDHCPNetworks: instance.Status: %s", *instance.Status)
    64  			if *instance.Status != "ERROR" {
    65  				continue
    66  			}
    67  
    68  			foundOne = true
    69  			result = append(result, cloudResource{
    70  				key:      *dhcpServer.ID,
    71  				name:     *dhcpServer.ID,
    72  				status:   "VM",
    73  				typeName: dhcpTypeName,
    74  				id:       *dhcpServer.ID,
    75  			})
    76  			continue
    77  		}
    78  
    79  		if strings.Contains(*dhcpServer.Network.Name, o.InfraID) {
    80  			o.Logger.Debugf("listDHCPNetworks: FOUND: %s (%s)", *dhcpServer.Network.Name, *dhcpServer.ID)
    81  			foundOne = true
    82  			result = append(result, cloudResource{
    83  				key:      *dhcpServer.ID,
    84  				name:     *dhcpServer.Network.Name,
    85  				status:   "DHCP",
    86  				typeName: dhcpTypeName,
    87  				id:       *dhcpServer.ID,
    88  			})
    89  		}
    90  	}
    91  	if !foundOne {
    92  		o.Logger.Debugf("listDHCPNetworks: NO matching DHCP network found in:")
    93  		for _, dhcpServer = range dhcpServers {
    94  			if dhcpServer.Network == nil {
    95  				continue
    96  			}
    97  			if dhcpServer.Network.Name == nil {
    98  				continue
    99  			}
   100  			o.Logger.Debugf("listDHCPNetworks: only found DHCP: %s", *dhcpServer.Network.Name)
   101  		}
   102  	}
   103  
   104  	return cloudResources{}.insert(result...), nil
   105  }
   106  
   107  func (o *ClusterUninstaller) destroyDHCPNetwork(item cloudResource) error {
   108  	var err error
   109  
   110  	_, err = o.dhcpClient.Get(item.id)
   111  	if err != nil {
   112  		o.deletePendingItems(item.typeName, []cloudResource{item})
   113  		o.Logger.Infof("Deleted DHCP Network %q", item.name)
   114  		return nil
   115  	}
   116  
   117  	o.Logger.Debugf("Deleting DHCP network %q", item.name)
   118  
   119  	err = o.dhcpClient.Delete(item.id)
   120  	if err != nil {
   121  		o.Logger.Infof("Error: o.dhcpClient.Delete: %q", err)
   122  		return err
   123  	}
   124  
   125  	o.deletePendingItems(item.typeName, []cloudResource{item})
   126  	o.Logger.Infof("Deleted DHCP Network %q", item.name)
   127  
   128  	return nil
   129  }
   130  
   131  func (o *ClusterUninstaller) destroyDHCPVM(item cloudResource) error {
   132  	var err error
   133  
   134  	_, err = o.instanceClient.Get(item.id)
   135  	if err != nil {
   136  		o.deletePendingItems(item.typeName, []cloudResource{item})
   137  		o.Logger.Infof("Deleted DHCP VM %q", item.name)
   138  		return nil
   139  	}
   140  
   141  	o.Logger.Debugf("Deleting DHCP VM %q", item.name)
   142  
   143  	err = o.instanceClient.Delete(item.id)
   144  	if err != nil {
   145  		o.Logger.Infof("Error: DHCP o.instanceClient.Delete: %q", err)
   146  		return err
   147  	}
   148  
   149  	o.deletePendingItems(item.typeName, []cloudResource{item})
   150  	o.Logger.Infof("Deleted DHCP VM %q", item.name)
   151  
   152  	return nil
   153  }
   154  
   155  // destroyDHCPNetworks searches for DHCP networks that are in a previous list
   156  // the cluster's infra ID.
   157  func (o *ClusterUninstaller) destroyDHCPNetworks() error {
   158  	firstPassList, err := o.listDHCPNetworks()
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	if len(firstPassList.list()) == 0 {
   164  		return nil
   165  	}
   166  
   167  	items := o.insertPendingItems(dhcpTypeName, firstPassList.list())
   168  
   169  	ctx, cancel := o.contextWithTimeout()
   170  	defer cancel()
   171  
   172  	for _, item := range items {
   173  		select {
   174  		case <-ctx.Done():
   175  			o.Logger.Debugf("destroyDHCPNetworks: case <-ctx.Done()")
   176  			return o.Context.Err() // we're cancelled, abort
   177  		default:
   178  		}
   179  
   180  		backoff := wait.Backoff{
   181  			Duration: 15 * time.Second,
   182  			Factor:   1.1,
   183  			Cap:      leftInContext(ctx),
   184  			Steps:    math.MaxInt32}
   185  		err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) {
   186  			var err2 error
   187  
   188  			switch item.status {
   189  			case "DHCP":
   190  				err2 = o.destroyDHCPNetwork(item)
   191  			case "VM":
   192  				err2 = o.destroyDHCPVM(item)
   193  			default:
   194  				err2 = fmt.Errorf("unknown DHCP item status %s", item.status)
   195  				return true, err2
   196  			}
   197  			if err2 == nil {
   198  				return true, err2
   199  			}
   200  			o.errorTracker.suppressWarning(item.key, err2, o.Logger)
   201  			return false, err2
   202  		})
   203  		if err != nil {
   204  			o.Logger.Fatal("destroyDHCPNetworks: ExponentialBackoffWithContext (destroy) returns ", err)
   205  		}
   206  	}
   207  
   208  	if items = o.getPendingItems(dhcpTypeName); len(items) > 0 {
   209  		for _, item := range items {
   210  			o.Logger.Debugf("destroyDHCPNetworks: found %s in pending items", item.name)
   211  		}
   212  		return fmt.Errorf("destroyDHCPNetworks: %d undeleted items pending", len(items))
   213  	}
   214  
   215  	backoff := wait.Backoff{
   216  		Duration: 15 * time.Second,
   217  		Factor:   1.1,
   218  		Cap:      leftInContext(ctx),
   219  		Steps:    math.MaxInt32}
   220  	err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) {
   221  		secondPassList, err2 := o.listDHCPNetworks()
   222  		if err2 != nil {
   223  			return false, err2
   224  		}
   225  		if len(secondPassList) == 0 {
   226  			// We finally don't see any remaining instances!
   227  			return true, nil
   228  		}
   229  		for _, item := range secondPassList {
   230  			o.Logger.Debugf("destroyDHCPNetworks: found %s in second pass", item.name)
   231  		}
   232  		return false, nil
   233  	})
   234  	if err != nil {
   235  		o.Logger.Fatal("destroyDHCPNetworks: ExponentialBackoffWithContext (list) returns ", err)
   236  	}
   237  
   238  	return nil
   239  }