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 }