@@ -562,6 +562,15 @@ func (s *VPCClusterScope) SetResourceStatus(resourceType infrav1beta2.ResourceTy
562
562
return
563
563
}
564
564
s .IBMVPCCluster .Status .Image .Set (* resource )
565
+ case infrav1beta2 .ResourceTypeDedicatedHost :
566
+ if s .IBMVPCCluster .Status .DedicatedHosts == nil {
567
+ s .IBMVPCCluster .Status .DedicatedHosts = make (map [string ]* infrav1beta2.ResourceStatus )
568
+ }
569
+ if dHost , ok := s .IBMVPCCluster .Status .DedicatedHosts [* resource .Name ]; ok {
570
+ dHost .Set (* resource )
571
+ } else {
572
+ s .IBMVPCCluster .Status .DedicatedHosts [* resource .Name ] = resource
573
+ }
565
574
case infrav1beta2 .ResourceTypeControlPlaneSubnet :
566
575
if s .NetworkStatus () == nil {
567
576
s .IBMVPCCluster .Status .Network = & infrav1beta2.VPCNetworkStatus {}
@@ -907,6 +916,104 @@ func (s *VPCClusterScope) buildCOSObjectHRef() (*string, error) {
907
916
return ptr .To (href ), nil
908
917
}
909
918
919
+ // ReconcileDedicatedHosts reconciles the VPC Dedicated Hosts, if defined.
920
+ func (s * VPCClusterScope ) ReconcileDedicatedHosts () (bool , error ) {
921
+ if len (s .IBMVPCCluster .Spec .DedicatedHosts ) == 0 {
922
+ s .V (3 ).Info ("no dedicated hosts to reconcile" )
923
+ return false , nil
924
+ }
925
+
926
+ requeue := false
927
+ for _ , dHost := range s .IBMVPCCluster .Spec .DedicatedHosts {
928
+ var dHostDetails * vpcv1.DedicatedHost
929
+ var err error
930
+ switch {
931
+ // Attempt lookup of Dedicated Host by ID, if provided. A defined ID expects the Dedicated Host to exist.
932
+ case dHost .ID != nil :
933
+ dHostDetails , _ , err = s .VPCClient .GetDedicatedHost (& vpcv1.GetDedicatedHostOptions {
934
+ ID : dHost .ID ,
935
+ })
936
+ if err != nil {
937
+ return false , fmt .Errorf ("error looking up existing dedicated host by id %s: %w" , * dHost .ID , err )
938
+ } else if dHostDetails == nil {
939
+ return false , fmt .Errorf ("error unable to retrieve existing dedicated host by id %s" , * dHost .ID )
940
+ }
941
+ s .V (3 ).Info ("found dedicated host by id" , "id" , * dHost .ID )
942
+ // Attempt lookup of Dedicated Host by Name, if provided. A defined name could be for an existing Dedicated Host, or if not found and a profile provided, create a new Dedicated Host.
943
+ case dHost .Name != nil :
944
+ dHostDetails , err = s .VPCClient .GetDedicatedHostByName (* dHost .Name )
945
+ switch {
946
+ case err != nil :
947
+ return false , fmt .Errorf ("error looking up dedicated host by name %s: %w" , * dHost .Name , err )
948
+ case dHostDetails == nil && dHost .Profile != nil :
949
+ // If Dedicated Host not found by name and a profile is defined, try to create a new Dedicated Host.
950
+ dHostDetails , _ , err = s .createDedicatedHost (dHost )
951
+ if err != nil {
952
+ return false , fmt .Errorf ("error creating dedicated host %s: %w" , * dHost .Name , err )
953
+ } else if dHostDetails == nil {
954
+ return false , fmt .Errorf ("error failed to create dedicated host %s" , * dHost .Name )
955
+ }
956
+ s .V (3 ).Info ("created dedicated host" , "name" , * dHost .Name )
957
+ // Flag for requeue after creating a new Dedicated Host.
958
+ requeue = true
959
+ // Update Status with the new Dedicated Host now and move on to next Dedicated Host to reconcile.
960
+ s .SetResourceStatus (infrav1beta2 .ResourceTypeDedicatedHost , & infrav1beta2.ResourceStatus {
961
+ ID : * dHostDetails .ID ,
962
+ Name : dHost .Name ,
963
+ Ready : false ,
964
+ })
965
+ continue
966
+ case dHostDetails == nil :
967
+ return false , fmt .Errorf ("error unable to retrieve existing dedicated host by name %s" , * dHost .Name )
968
+ default :
969
+ s .V (3 ).Info ("found dedicated host by name" , "name" , * dHost .Name )
970
+ }
971
+ default :
972
+ return false , fmt .Errorf ("error cannot reconcile dedicated host without id and name" )
973
+ }
974
+ // Determine whether the Dedicated Host is ready and available for provisioning VSI's.
975
+ dHostReady := * dHostDetails .State == vpcv1 .DedicatedHostStateAvailableConst && * dHostDetails .Provisionable
976
+ // Update Dedicated Host Status.
977
+ s .SetResourceStatus (infrav1beta2 .ResourceTypeDedicatedHost , & infrav1beta2.ResourceStatus {
978
+ ID : * dHostDetails .ID ,
979
+ Name : dHostDetails .Name ,
980
+ Ready : dHostReady ,
981
+ })
982
+ // If the Dedicated Host is not ready, flag for requeue.
983
+ if ! dHostReady {
984
+ requeue = true
985
+ }
986
+ }
987
+
988
+ return requeue , nil
989
+ }
990
+
991
+ // createDedicatedHost will create a new Dedicated Host as defined by the VPCDedicatedHost.
992
+ func (s * VPCClusterScope ) createDedicatedHost (dHost infrav1beta2.VPCDedicatedHost ) (* vpcv1.DedicatedHost , * core.DetailedResponse , error ) {
993
+ // Collect Resource Group ID for Dedicated Host creation options.
994
+ resourceGroupID , err := s .GetResourceGroupID ()
995
+ if err != nil {
996
+ return nil , nil , fmt .Errorf ("error retrieving resource group id for dedicated host creation %s: %w" , * dHost .Name , err )
997
+ }
998
+ dHostOptions := & vpcv1.CreateDedicatedHostOptions {
999
+ // NOTE(cjschaef): Currently only support creating a new Dedicated Host by Zone, not by Dedicated Host Group.
1000
+ DedicatedHostPrototype : & vpcv1.DedicatedHostPrototypeDedicatedHostByZone {
1001
+ Name : dHost .Name ,
1002
+ Profile : & vpcv1.DedicatedHostProfileIdentityByName {
1003
+ Name : dHost .Profile ,
1004
+ },
1005
+ ResourceGroup : & vpcv1.ResourceGroupIdentityByID {
1006
+ ID : ptr .To (resourceGroupID ),
1007
+ },
1008
+ Zone : & vpcv1.ZoneIdentityByName {
1009
+ Name : ptr .To (dHost .Zone ),
1010
+ },
1011
+ },
1012
+ }
1013
+
1014
+ return s .VPCClient .CreateDedicatedHost (dHostOptions )
1015
+ }
1016
+
910
1017
// ReconcileSubnets reconciles the VPC Subnet(s).
911
1018
// For Subnets, we collect all of the required subnets, for each Plane, and reconcile them individually. Requeing if one is missing or just created. Reconciliation is attempted on all subnets each loop, to prevent single subnet creation per reconciliation loop.
912
1019
func (s * VPCClusterScope ) ReconcileSubnets () (bool , error ) {
0 commit comments