|
| 1 | +package vsphere |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "fmt" |
| 6 | + "path" |
| 7 | + |
| 8 | + "github.com/openshift/installer/pkg/asset" |
| 9 | + "github.com/openshift/installer/pkg/asset/installconfig" |
| 10 | + "github.com/openshift/installer/pkg/types/vsphere" |
| 11 | + vsphereplatform "github.com/openshift/installer/pkg/types/vsphere" |
| 12 | + "github.com/vmware/govmomi/object" |
| 13 | + "github.com/vmware/govmomi/vapi/tags" |
| 14 | + "sigs.k8s.io/cluster-api-provider-vsphere/pkg/session" |
| 15 | +) |
| 16 | + |
| 17 | +func (a *VCenterContexts) cacheNetworkNames(ctx context.Context, failureDomain vsphere.FailureDomain, session *session.Session, server string) error { |
| 18 | + |
| 19 | + finder := session.Finder |
| 20 | + clusterPath := failureDomain.Topology.ComputeCluster |
| 21 | + |
| 22 | + clusterRef, err := finder.ClusterComputeResource(ctx, clusterPath) |
| 23 | + if err != nil { |
| 24 | + return fmt.Errorf("unable to retrieve compute cluster: %v", err) |
| 25 | + } |
| 26 | + |
| 27 | + pools, err := finder.ResourcePoolList(ctx, clusterRef.InventoryPath) |
| 28 | + if err != nil { |
| 29 | + return fmt.Errorf("unable to retrieve resource pools relative to compute cluster: %v", err) |
| 30 | + } |
| 31 | + |
| 32 | + for _, network := range failureDomain.Topology.Networks { |
| 33 | + clusterMap, present := a.VCenters[server].ClusterNetworkMap[clusterPath] |
| 34 | + if !present { |
| 35 | + clusterMap = NetworkNameMap{ |
| 36 | + Cluster: clusterPath, |
| 37 | + NetworkNames: map[string]string{}, |
| 38 | + ResourcePools: map[string]*object.ResourcePool{}, |
| 39 | + } |
| 40 | + for _, pool := range pools { |
| 41 | + clusterMap.ResourcePools[path.Clean(pool.InventoryPath)] = pool |
| 42 | + } |
| 43 | + |
| 44 | + a.VCenters[server].ClusterNetworkMap[clusterPath] = clusterMap |
| 45 | + } |
| 46 | + |
| 47 | + networkName := path.Join(clusterRef.InventoryPath, network) |
| 48 | + clusterMap.NetworkNames[network] = networkName |
| 49 | + |
| 50 | + } |
| 51 | + |
| 52 | + return nil |
| 53 | +} |
| 54 | + |
| 55 | +func (a *VCenterContexts) createClusterTagID(ctx context.Context, session *session.Session, clusterId string, server string) error { |
| 56 | + tagManager := session.TagManager |
| 57 | + categories, err := tagManager.GetCategories(ctx) |
| 58 | + if err != nil { |
| 59 | + return fmt.Errorf("unable to get tag categories: %v", err) |
| 60 | + } |
| 61 | + |
| 62 | + var clusterTagCategory *tags.Category |
| 63 | + clusterTagCategoryName := fmt.Sprintf("openshift-%s", clusterId) |
| 64 | + tagCategoryId := "" |
| 65 | + |
| 66 | + for _, category := range categories { |
| 67 | + if category.Name == clusterTagCategoryName { |
| 68 | + clusterTagCategory = &category |
| 69 | + tagCategoryId = category.ID |
| 70 | + break |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + if clusterTagCategory == nil { |
| 75 | + clusterTagCategory = &tags.Category{ |
| 76 | + Name: clusterTagCategoryName, |
| 77 | + Description: "Added by openshift-install do not remove", |
| 78 | + Cardinality: "SINGLE", |
| 79 | + AssociableTypes: []string{ |
| 80 | + "urn:vim25:VirtualMachine", |
| 81 | + "urn:vim25:ResourcePool", |
| 82 | + "urn:vim25:Folder", |
| 83 | + "urn:vim25:Datastore", |
| 84 | + "urn:vim25:StoragePod", |
| 85 | + }, |
| 86 | + } |
| 87 | + tagCategoryId, err = tagManager.CreateCategory(ctx, clusterTagCategory) |
| 88 | + if err != nil { |
| 89 | + return fmt.Errorf("unable to create tag category: %v", err) |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + var categoryTag *tags.Tag |
| 94 | + tagId := "" |
| 95 | + |
| 96 | + categoryTags, err := tagManager.GetTagsForCategory(ctx, tagCategoryId) |
| 97 | + if err != nil { |
| 98 | + return fmt.Errorf("unable to get tags for category: %v", err) |
| 99 | + } |
| 100 | + for _, tag := range categoryTags { |
| 101 | + if tag.Name == clusterId { |
| 102 | + categoryTag = &tag |
| 103 | + tagId = tag.ID |
| 104 | + break |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + if categoryTag == nil { |
| 109 | + categoryTag = &tags.Tag{ |
| 110 | + Description: "Added by openshift-install do not remove", |
| 111 | + Name: clusterId, |
| 112 | + CategoryID: tagCategoryId, |
| 113 | + } |
| 114 | + tagId, err = tagManager.CreateTag(ctx, categoryTag) |
| 115 | + if err != nil { |
| 116 | + return fmt.Errorf("unable to create tag: %v", err) |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + vCenterContext := a.VCenters[server] |
| 121 | + vCenterContext.TagID = tagId |
| 122 | + a.VCenters[server] = vCenterContext |
| 123 | + |
| 124 | + return nil |
| 125 | +} |
| 126 | + |
| 127 | +type NetworkNameMap struct { |
| 128 | + Cluster string |
| 129 | + ResourcePools map[string]*object.ResourcePool |
| 130 | + NetworkNames map[string]string |
| 131 | +} |
| 132 | + |
| 133 | +// VCenterContext maintains context of known vCenters to be used in CAPI manifest reconciliation. |
| 134 | +type VCenterContext struct { |
| 135 | + VCenter string |
| 136 | + TagID string |
| 137 | + Datacenters []string |
| 138 | + ClusterNetworkMap map[string]NetworkNameMap |
| 139 | +} |
| 140 | + |
| 141 | +type VCenterContexts struct { |
| 142 | + VCenters map[string]VCenterContext |
| 143 | +} |
| 144 | + |
| 145 | +var ( |
| 146 | + _ asset.Asset = (*VCenterContexts)(nil) |
| 147 | +) |
| 148 | + |
| 149 | +func (a *VCenterContexts) Generate(parents asset.Parents) error { |
| 150 | + ctx := context.TODO() |
| 151 | + |
| 152 | + a.VCenters = map[string]VCenterContext{} |
| 153 | + |
| 154 | + ic := &installconfig.InstallConfig{} |
| 155 | + clusterID := &installconfig.ClusterID{} |
| 156 | + parents.Get( |
| 157 | + ic, |
| 158 | + clusterID, |
| 159 | + ) |
| 160 | + |
| 161 | + if ic.Config.Platform.Name() != vsphereplatform.Name { |
| 162 | + return nil |
| 163 | + } |
| 164 | + |
| 165 | + installConfig := ic.Config |
| 166 | + |
| 167 | + for _, vcenter := range installConfig.VSphere.VCenters { |
| 168 | + server := vcenter.Server |
| 169 | + params := session.NewParams().WithServer(server).WithUserInfo(vcenter.Username, vcenter.Password) |
| 170 | + tempConnection, err := session.GetOrCreate(ctx, params) |
| 171 | + if err != nil { |
| 172 | + return fmt.Errorf("unable to create session: %v", err) |
| 173 | + } |
| 174 | + |
| 175 | + defer tempConnection.CloseIdleConnections() |
| 176 | + |
| 177 | + a.VCenters[server] = VCenterContext{ |
| 178 | + VCenter: server, |
| 179 | + Datacenters: vcenter.Datacenters, |
| 180 | + ClusterNetworkMap: map[string]NetworkNameMap{}, |
| 181 | + } |
| 182 | + |
| 183 | + if err = a.createClusterTagID(ctx, tempConnection, clusterID.InfraID, server); err != nil { |
| 184 | + return fmt.Errorf("unable to create cluster tag ID: %v", err) |
| 185 | + } |
| 186 | + |
| 187 | + for _, failureDomain := range installConfig.VSphere.FailureDomains { |
| 188 | + if failureDomain.Server != server { |
| 189 | + continue |
| 190 | + } |
| 191 | + if err = a.cacheNetworkNames(ctx, failureDomain, tempConnection, server); err != nil { |
| 192 | + return fmt.Errorf("unable to retrieve network names: %v", err) |
| 193 | + } |
| 194 | + } |
| 195 | + } |
| 196 | + return nil |
| 197 | +} |
| 198 | + |
| 199 | +func (a *VCenterContexts) Dependencies() []asset.Asset { |
| 200 | + return []asset.Asset{ |
| 201 | + &installconfig.InstallConfig{}, |
| 202 | + &installconfig.ClusterID{}, |
| 203 | + } |
| 204 | +} |
| 205 | + |
| 206 | +func (a *VCenterContexts) Name() string { |
| 207 | + return "vCenter Context" |
| 208 | +} |
0 commit comments