github.com/sacloud/iaas-api-go@v1.12.0/helper/query/referenced.go (about)

     1  // Copyright 2016-2022 The sacloud/iaas-api-go Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package query
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  
    21  	"github.com/sacloud/iaas-api-go"
    22  	"github.com/sacloud/iaas-api-go/types"
    23  )
    24  
    25  // IsPrivateHostReferenced 指定の専有ホストが利用されている場合trueを返す
    26  func IsPrivateHostReferenced(ctx context.Context, caller iaas.APICaller, zone string, privateHostID types.ID) (bool, error) {
    27  	return checkReferenced(ctx, caller, []string{zone}, privateHostID, []referenceFindFunc{
    28  		findServerByPrivateHostID,
    29  	})
    30  }
    31  
    32  // WaitWhilePrivateHostIsReferenced 指定の専有ホストが利用されている間待ち合わせる
    33  func WaitWhilePrivateHostIsReferenced(ctx context.Context, caller iaas.APICaller, zone string, privateHostID types.ID, option CheckReferencedOption) error {
    34  	return waitWhileReferenced(ctx, option, func() (bool, error) {
    35  		return IsPrivateHostReferenced(ctx, caller, zone, privateHostID)
    36  	})
    37  }
    38  
    39  // IsPacketFilterReferenced 指定のパケットフィルタが利用されている場合trueを返す
    40  func IsPacketFilterReferenced(ctx context.Context, caller iaas.APICaller, zone string, packetFilterID types.ID) (bool, error) {
    41  	return checkReferenced(ctx, caller, []string{zone}, packetFilterID, []referenceFindFunc{
    42  		findServerByPacketFilterID,
    43  	})
    44  }
    45  
    46  // WaitWhilePacketFilterIsReferenced 指定のパケットフィルタが利用されている間待ち合わせる
    47  func WaitWhilePacketFilterIsReferenced(ctx context.Context, caller iaas.APICaller, zone string, packetFilterID types.ID, option CheckReferencedOption) error {
    48  	return waitWhileReferenced(ctx, option, func() (bool, error) {
    49  		return IsPacketFilterReferenced(ctx, caller, zone, packetFilterID)
    50  	})
    51  }
    52  
    53  // IsSIMReferenced 指定のSIMが利用されている場合trueを返す
    54  func IsSIMReferenced(ctx context.Context, caller iaas.APICaller, zones []string, simID types.ID) (bool, error) {
    55  	return checkReferenced(ctx, caller, zones, simID, []referenceFindFunc{
    56  		findMobileGatewayBySIMID,
    57  	})
    58  }
    59  
    60  // WaitWhileSIMIsReferenced 指定のSIMが利用されている間待ち合わせる
    61  func WaitWhileSIMIsReferenced(ctx context.Context, caller iaas.APICaller, zones []string, simID types.ID, option CheckReferencedOption) error {
    62  	return waitWhileReferenced(ctx, option, func() (bool, error) {
    63  		return IsSIMReferenced(ctx, caller, zones, simID)
    64  	})
    65  }
    66  
    67  // IsBridgeReferenced 指定のブリッジが利用されている場合trueを返す
    68  func IsBridgeReferenced(ctx context.Context, caller iaas.APICaller, zones []string, bridgeID types.ID) (bool, error) {
    69  	return checkReferenced(ctx, caller, zones, bridgeID, []referenceFindFunc{
    70  		findSwitchByBridgeID,
    71  	})
    72  }
    73  
    74  // WaitWhileBridgeIsReferenced 指定のSIMが利用されている間待ち合わせる
    75  func WaitWhileBridgeIsReferenced(ctx context.Context, caller iaas.APICaller, zones []string, bridgeID types.ID, option CheckReferencedOption) error {
    76  	return waitWhileReferenced(ctx, option, func() (bool, error) {
    77  		return IsBridgeReferenced(ctx, caller, zones, bridgeID)
    78  	})
    79  }
    80  
    81  // IsCDROMReferenced 指定のCD-ROM(ISOイメージ)が利用されている場合trueを返す
    82  func IsCDROMReferenced(ctx context.Context, caller iaas.APICaller, zone string, cdromID types.ID) (bool, error) {
    83  	return checkReferenced(ctx, caller, []string{zone}, cdromID, []referenceFindFunc{
    84  		findServerByCDROMID,
    85  	})
    86  }
    87  
    88  // WaitWhileCDROMIsReferenced 指定のCD-ROM(ISOイメージ)が利用されている間待ち合わせる
    89  func WaitWhileCDROMIsReferenced(ctx context.Context, caller iaas.APICaller, zone string, cdromID types.ID, option CheckReferencedOption) error {
    90  	return waitWhileReferenced(ctx, option, func() (bool, error) {
    91  		return IsCDROMReferenced(ctx, caller, zone, cdromID)
    92  	})
    93  }
    94  
    95  // IsDiskReferenced 指定のディスクが利用されている場合trueを返す
    96  func IsDiskReferenced(ctx context.Context, caller iaas.APICaller, zone string, diskID types.ID) (bool, error) {
    97  	return checkReferenced(ctx, caller, []string{zone}, diskID, []referenceFindFunc{
    98  		findServerByDiskID,
    99  	})
   100  }
   101  
   102  // WaitWhileDiskIsReferenced 指定のディスクが利用されている間待ち合わせる
   103  func WaitWhileDiskIsReferenced(ctx context.Context, caller iaas.APICaller, zone string, diskID types.ID, option CheckReferencedOption) error {
   104  	return waitWhileReferenced(ctx, option, func() (bool, error) {
   105  		return IsDiskReferenced(ctx, caller, zone, diskID)
   106  	})
   107  }
   108  
   109  // IsSwitchReferenced 指定のスイッチが利用されている場合trueを返す
   110  //
   111  // ハイブリッド接続情報が残っている場合にも参照されているものとみなしtrueを返す
   112  func IsSwitchReferenced(ctx context.Context, caller iaas.APICaller, zone string, switchID types.ID) (bool, error) {
   113  	return checkReferenced(ctx, caller, []string{zone}, switchID, []referenceFindFunc{
   114  		switchHasHybridConnection,
   115  		findServerBySwitchID,
   116  		findLoadBalancerBySwitchID,
   117  		findVPCRouterBySwitchID,
   118  		findDatabaseBySwitchID,
   119  		findNFSBySwitchID,
   120  		findMobileGatewayBySwitchID,
   121  	})
   122  }
   123  
   124  // WaitWhileSwitchIsReferenced 指定のディスクが利用されている間待ち合わせる
   125  func WaitWhileSwitchIsReferenced(ctx context.Context, caller iaas.APICaller, zone string, switchID types.ID, option CheckReferencedOption) error {
   126  	return waitWhileReferenced(ctx, option, func() (bool, error) {
   127  		return IsSwitchReferenced(ctx, caller, zone, switchID)
   128  	})
   129  }
   130  
   131  type referenceFindFunc func(context.Context, iaas.APICaller, string, types.ID) (bool, error)
   132  
   133  func checkReferenced(ctx context.Context, caller iaas.APICaller, zones []string, id types.ID, finder []referenceFindFunc) (bool, error) {
   134  	if len(zones) == 0 {
   135  		zones = iaas.SakuraCloudZones
   136  	}
   137  
   138  	for _, zone := range zones {
   139  		for _, f := range finder {
   140  			exists, err := f(ctx, caller, zone, id)
   141  			if exists || err != nil {
   142  				return exists, err
   143  			}
   144  		}
   145  	}
   146  	return false, nil
   147  }
   148  
   149  func switchHasHybridConnection(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   150  	swOp := iaas.NewSwitchOp(caller)
   151  	sw, err := swOp.Read(ctx, zone, id)
   152  	if err != nil {
   153  		return false, fmt.Errorf("reading switch is failed: %s", err)
   154  	}
   155  	return !sw.HybridConnectionID.IsEmpty(), nil
   156  }
   157  
   158  func findServerBySwitchID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   159  	swOp := iaas.NewSwitchOp(caller)
   160  
   161  	searched, err := swOp.GetServers(ctx, zone, id)
   162  	if err != nil {
   163  		return false, fmt.Errorf("finding server is failed: %s", err)
   164  	}
   165  	return searched.Count != 0, nil
   166  }
   167  
   168  func findServerByPrivateHostID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   169  	serverOp := iaas.NewServerOp(caller)
   170  
   171  	searched, err := serverOp.Find(ctx, zone, &iaas.FindCondition{})
   172  	if err != nil {
   173  		return false, fmt.Errorf("finding Server is failed: %s", err)
   174  	}
   175  
   176  	for _, s := range searched.Servers {
   177  		if s.PrivateHostID == id {
   178  			return true, nil
   179  		}
   180  	}
   181  	return false, nil
   182  }
   183  
   184  func findServerByPacketFilterID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   185  	serverOp := iaas.NewServerOp(caller)
   186  
   187  	searched, err := serverOp.Find(ctx, zone, &iaas.FindCondition{})
   188  	if err != nil {
   189  		return false, fmt.Errorf("finding Server is failed: %s", err)
   190  	}
   191  
   192  	for _, s := range searched.Servers {
   193  		for _, iface := range s.Interfaces {
   194  			if iface.PacketFilterID == id {
   195  				return true, nil
   196  			}
   197  		}
   198  	}
   199  	return false, nil
   200  }
   201  
   202  func findServerByCDROMID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   203  	serverOp := iaas.NewServerOp(caller)
   204  
   205  	searched, err := serverOp.Find(ctx, zone, &iaas.FindCondition{})
   206  	if err != nil {
   207  		return false, fmt.Errorf("finding Server is failed: %s", err)
   208  	}
   209  
   210  	for _, server := range searched.Servers {
   211  		if server.CDROMID == id {
   212  			return true, nil
   213  		}
   214  	}
   215  	return false, nil
   216  }
   217  
   218  func findServerByDiskID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   219  	serverOp := iaas.NewServerOp(caller)
   220  
   221  	searched, err := serverOp.Find(ctx, zone, &iaas.FindCondition{})
   222  	if err != nil {
   223  		return false, fmt.Errorf("finding Server is failed: %s", err)
   224  	}
   225  
   226  	for _, server := range searched.Servers {
   227  		for _, disk := range server.Disks {
   228  			if disk.ID == id {
   229  				return true, nil
   230  			}
   231  		}
   232  	}
   233  	return false, nil
   234  }
   235  
   236  func findSwitchByBridgeID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   237  	swOp := iaas.NewSwitchOp(caller)
   238  
   239  	searched, err := swOp.Find(ctx, zone, &iaas.FindCondition{})
   240  	if err != nil {
   241  		return false, fmt.Errorf("finding Switch is failed: %s", err)
   242  	}
   243  
   244  	for _, sw := range searched.Switches {
   245  		if sw.BridgeID == id {
   246  			return true, nil
   247  		}
   248  	}
   249  	return false, nil
   250  }
   251  
   252  func findMobileGatewayBySIMID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   253  	mgwOp := iaas.NewMobileGatewayOp(caller)
   254  
   255  	searched, err := mgwOp.Find(ctx, zone, &iaas.FindCondition{})
   256  	if err != nil {
   257  		return false, fmt.Errorf("finding MobileGateway is failed: %s", err)
   258  	}
   259  
   260  	for _, mgw := range searched.MobileGateways {
   261  		sims, err := mgwOp.ListSIM(ctx, zone, mgw.ID)
   262  		if err != nil {
   263  			if iaas.IsNotFoundError(err) {
   264  				return false, nil
   265  			}
   266  			return false, fmt.Errorf("finding SIMs is failed: %s", err)
   267  		}
   268  		for _, sim := range sims {
   269  			if sim.ResourceID == id.String() {
   270  				return true, nil
   271  			}
   272  		}
   273  	}
   274  	return false, nil
   275  }
   276  
   277  func findVPCRouterBySwitchID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   278  	vrOp := iaas.NewVPCRouterOp(caller)
   279  
   280  	searched, err := vrOp.Find(ctx, zone, &iaas.FindCondition{})
   281  	if err != nil {
   282  		return false, fmt.Errorf("finding VPCRouter is failed: %s", err)
   283  	}
   284  
   285  	for _, vpcRouter := range searched.VPCRouters {
   286  		for _, iface := range vpcRouter.Interfaces {
   287  			if iface.SwitchScope != types.Scopes.Shared && iface.SwitchID == id {
   288  				return true, nil
   289  			}
   290  		}
   291  	}
   292  	return false, nil
   293  }
   294  
   295  func findLoadBalancerBySwitchID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   296  	lbOp := iaas.NewLoadBalancerOp(caller)
   297  
   298  	searched, err := lbOp.Find(ctx, zone, &iaas.FindCondition{})
   299  	if err != nil {
   300  		return false, fmt.Errorf("finding LoadBalancer is failed: %s", err)
   301  	}
   302  
   303  	for _, lb := range searched.LoadBalancers {
   304  		for _, iface := range lb.Interfaces {
   305  			if iface.SwitchScope != types.Scopes.Shared && iface.SwitchID == id {
   306  				return true, nil
   307  			}
   308  		}
   309  	}
   310  	return false, nil
   311  }
   312  
   313  func findDatabaseBySwitchID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   314  	dbOp := iaas.NewDatabaseOp(caller)
   315  
   316  	searched, err := dbOp.Find(ctx, zone, &iaas.FindCondition{})
   317  	if err != nil {
   318  		return false, fmt.Errorf("finding Database is failed: %s", err)
   319  	}
   320  
   321  	for _, db := range searched.Databases {
   322  		for _, iface := range db.Interfaces {
   323  			if iface.SwitchScope != types.Scopes.Shared && iface.SwitchID == id {
   324  				return true, nil
   325  			}
   326  		}
   327  	}
   328  	return false, nil
   329  }
   330  
   331  func findNFSBySwitchID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   332  	nfsOp := iaas.NewNFSOp(caller)
   333  
   334  	searched, err := nfsOp.Find(ctx, zone, &iaas.FindCondition{})
   335  	if err != nil {
   336  		return false, fmt.Errorf("finding NFS is failed: %s", err)
   337  	}
   338  
   339  	for _, nfs := range searched.NFS {
   340  		for _, iface := range nfs.Interfaces {
   341  			if iface.SwitchScope != types.Scopes.Shared && iface.SwitchID == id {
   342  				return true, nil
   343  			}
   344  		}
   345  	}
   346  	return false, nil
   347  }
   348  
   349  func findMobileGatewayBySwitchID(ctx context.Context, caller iaas.APICaller, zone string, id types.ID) (bool, error) {
   350  	mgwOp := iaas.NewMobileGatewayOp(caller)
   351  
   352  	searched, err := mgwOp.Find(ctx, zone, &iaas.FindCondition{})
   353  	if err != nil {
   354  		return false, fmt.Errorf("finding MobileGateway is failed: %s", err)
   355  	}
   356  
   357  	for _, mgw := range searched.MobileGateways {
   358  		for _, iface := range mgw.Interfaces {
   359  			if iface.SwitchScope != types.Scopes.Shared && iface.SwitchID == id {
   360  				return true, nil
   361  			}
   362  		}
   363  	}
   364  	return false, nil
   365  }