Skip to content

Commit 0481a93

Browse files
Merge pull request openshift#7931 from jcpowermac/OCPBUGS-22410
OCPBUGS-22410: vsphere-fix convert if only provided name
2 parents 9c5e54d + baf76f9 commit 0481a93

File tree

3 files changed

+346
-123
lines changed

3 files changed

+346
-123
lines changed

pkg/asset/installconfig/vsphere/mock/vsphere_sim.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func StartSimulator(setVersionToSupported bool) (*simulator.Server, error) {
4545
}
4646

4747
model.Folder = 1
48-
model.Datacenter = 2
48+
model.Datacenter = 5
4949
model.OpaqueNetwork = 1
5050
err := model.Create()
5151
if err != nil {

pkg/types/vsphere/conversion/installconfig.go

Lines changed: 160 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package conversion
22

33
import (
4-
"fmt"
5-
"strings"
4+
"context"
5+
"errors"
6+
"net/url"
7+
"path"
8+
"time"
69

710
"github.com/sirupsen/logrus"
11+
"github.com/vmware/govmomi"
12+
"github.com/vmware/govmomi/find"
13+
"github.com/vmware/govmomi/vim25/soap"
814

915
"github.com/openshift/installer/pkg/types"
1016
"github.com/openshift/installer/pkg/types/vsphere"
@@ -21,11 +27,59 @@ const (
2127
GeneratedFailureDomainZone string = "generated-zone"
2228
)
2329

24-
// ConvertInstallConfig modifies a given platform spec for the new requirements.
25-
func ConvertInstallConfig(config *types.InstallConfig) error {
26-
platform := config.Platform.VSphere
30+
// GetFinder connects to vCenter via SOAP and returns the Finder object if the SOAP
31+
// connection is successful. If the connection fails it returns nil.
32+
// Errors are mostly ignored to support AI and agent installers.
33+
func GetFinder(server, username, password string) (*find.Finder, error) {
34+
var finder *find.Finder
35+
36+
if server != "" && password != "" && username != "" {
37+
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
38+
defer cancel()
39+
u, err := soap.ParseURL(server)
40+
if err != nil {
41+
return nil, err
42+
}
43+
u.User = url.UserPassword(username, password)
44+
45+
client, err := govmomi.NewClient(ctx, u, false)
46+
if err != nil {
47+
// If bogus authentication is provided in the scenario of AI or assisted
48+
// just provide warning message. If this is IPI or UPI validation will
49+
// catch and halt on incorrect authentication.
50+
localLogger.Warnf("unable to log into vCenter %s, %v", server, err)
51+
return nil, nil
52+
}
53+
finder = find.NewFinder(client.Client, true)
54+
}
55+
56+
return finder, nil
57+
}
58+
59+
func findViaPathOrName(finder *find.Finder, objectPath, objectFindPath string) (string, error) {
60+
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
61+
defer cancel()
2762

28-
// Scenario: IPI or 4.12 Zonal IPI w/o vcenters defined
63+
elements, err := finder.ManagedObjectListChildren(ctx, objectFindPath)
64+
if err != nil {
65+
return "", err
66+
}
67+
68+
for _, e := range elements {
69+
if e.Path == objectPath {
70+
return objectPath, nil
71+
}
72+
73+
if path.Base(e.Path) == path.Base(objectPath) {
74+
return e.Path, nil
75+
}
76+
}
77+
return "", errors.New("unable to find object")
78+
}
79+
80+
// fixNoVCentersScenario this function creates the VCenters slice
81+
// with existing legacy vcenter authentication and configuration.
82+
func fixNoVCentersScenario(platform *vsphere.Platform) {
2983
if len(platform.VCenters) == 0 {
3084
createVCenters(platform)
3185

@@ -44,23 +98,40 @@ func ConvertInstallConfig(config *types.InstallConfig) error {
4498
}
4599
}
46100
}
101+
}
47102

48-
// Scenario: Fields are not paths
103+
func fixTechPreviewZonalFailureDomainsScenario(platform *vsphere.Platform, finder *find.Finder) error {
49104
if len(platform.FailureDomains) > 0 {
105+
var err error
106+
50107
for i := range platform.FailureDomains {
51-
platform.FailureDomains[i].Topology.ComputeCluster = setComputeClusterPath(platform.FailureDomains[i].Topology.ComputeCluster,
52-
platform.FailureDomains[i].Topology.Datacenter)
108+
computeCluster := platform.FailureDomains[i].Topology.ComputeCluster
109+
datastore := platform.FailureDomains[i].Topology.Datastore
110+
folder := platform.FailureDomains[i].Topology.Folder
111+
datacenter := platform.FailureDomains[i].Topology.Datacenter
53112

54-
platform.FailureDomains[i].Topology.Datastore = setDatastorePath(platform.FailureDomains[i].Topology.Datastore,
55-
platform.FailureDomains[i].Topology.Datacenter)
113+
platform.FailureDomains[i].Topology.ComputeCluster, err = SetObjectPath(finder, "host", computeCluster, datacenter)
114+
if err != nil {
115+
return err
116+
}
117+
118+
platform.FailureDomains[i].Topology.Datastore, err = SetObjectPath(finder, "datastore", datastore, datacenter)
119+
if err != nil {
120+
return err
121+
}
56122

57-
platform.FailureDomains[i].Topology.Folder = setFolderPath(platform.FailureDomains[i].Topology.Folder,
58-
platform.FailureDomains[i].Topology.Datacenter)
123+
platform.FailureDomains[i].Topology.Folder, err = SetObjectPath(finder, "vm", folder, datacenter)
124+
if err != nil {
125+
return err
126+
}
59127
}
60128
}
129+
return nil
130+
}
61131

62-
// Scenario: legacy UPI or IPI
132+
func fixLegacyPlatformScenario(platform *vsphere.Platform, finder *find.Finder) error {
63133
if len(platform.FailureDomains) == 0 {
134+
var err error
64135
localLogger.Warn("vsphere topology fields are now deprecated; please use failureDomains")
65136

66137
platform.FailureDomains = make([]vsphere.FailureDomain, 1)
@@ -71,38 +142,92 @@ func ConvertInstallConfig(config *types.InstallConfig) error {
71142

72143
platform.FailureDomains[0].Topology.Datacenter = platform.DeprecatedDatacenter
73144
platform.FailureDomains[0].Topology.ResourcePool = platform.DeprecatedResourcePool
74-
platform.FailureDomains[0].Topology.ComputeCluster = setComputeClusterPath(platform.DeprecatedCluster, platform.DeprecatedDatacenter)
75145
platform.FailureDomains[0].Topology.Networks = make([]string, 1)
76146
platform.FailureDomains[0].Topology.Networks[0] = platform.DeprecatedNetwork
77-
platform.FailureDomains[0].Topology.Datastore = setDatastorePath(platform.DeprecatedDefaultDatastore, platform.DeprecatedDatacenter)
78-
platform.FailureDomains[0].Topology.Folder = setFolderPath(platform.DeprecatedFolder, platform.DeprecatedDatacenter)
79-
}
80147

81-
return nil
82-
}
148+
platform.FailureDomains[0].Topology.ComputeCluster, err = SetObjectPath(finder, "host", platform.DeprecatedCluster, platform.DeprecatedDatacenter)
149+
if err != nil {
150+
return err
151+
}
83152

84-
func setComputeClusterPath(cluster, datacenter string) string {
85-
if cluster != "" && !strings.HasPrefix(cluster, "/") {
86-
localLogger.Warnf("computeCluster as a non-path is now deprecated; please use the form: /%s/host/%s", datacenter, cluster)
87-
return fmt.Sprintf("/%s/host/%s", datacenter, cluster)
153+
platform.FailureDomains[0].Topology.Datastore, err = SetObjectPath(finder, "datastore", platform.DeprecatedDefaultDatastore, platform.DeprecatedDatacenter)
154+
if err != nil {
155+
return err
156+
}
157+
158+
platform.FailureDomains[0].Topology.Folder, err = SetObjectPath(finder, "vm", platform.DeprecatedFolder, platform.DeprecatedDatacenter)
159+
if err != nil {
160+
return err
161+
}
88162
}
89-
return cluster
163+
return nil
90164
}
91165

92-
func setDatastorePath(datastore, datacenter string) string {
93-
if datastore != "" && !strings.HasPrefix(datastore, "/") {
94-
localLogger.Warnf("datastore as a non-path is now deprecated; please use the form: /%s/datastore/%s", datacenter, datastore)
95-
return fmt.Sprintf("/%s/datastore/%s", datacenter, datastore)
166+
// ConvertInstallConfig modifies a given platform spec for the new requirements.
167+
func ConvertInstallConfig(config *types.InstallConfig) error {
168+
platform := config.Platform.VSphere
169+
170+
fixNoVCentersScenario(platform)
171+
finder, err := GetFinder(platform.VCenters[0].Server, platform.VCenters[0].Username, platform.VCenters[0].Password)
172+
if err != nil {
173+
return err
174+
}
175+
err = fixTechPreviewZonalFailureDomainsScenario(platform, finder)
176+
if err != nil {
177+
return err
178+
}
179+
err = fixLegacyPlatformScenario(platform, finder)
180+
if err != nil {
181+
return err
96182
}
97-
return datastore
183+
184+
return nil
98185
}
99186

100-
func setFolderPath(folder, datacenter string) string {
101-
if folder != "" && !strings.HasPrefix(folder, "/") {
102-
localLogger.Warnf("folder as a non-path is now deprecated; please use the form: /%s/vm/%s", datacenter, folder)
103-
return fmt.Sprintf("/%s/vm/%s", datacenter, folder)
187+
// SetObjectPath based on the pathType will either determine the path for the type via
188+
// a simple join of the datacenter, pathType and objectPath if finder is nil
189+
// or via a connection to vCenter find of all child objects under the
190+
// datacenter and pathType.
191+
// pathType must only be "host", "vm", or "datastore".
192+
func SetObjectPath(finder *find.Finder, pathType, objectPath, datacenter string) (string, error) {
193+
if objectPath != "" && !path.IsAbs(objectPath) {
194+
var joinedObjectPath string
195+
var joinedObjectFindPath string
196+
var paramName string
197+
198+
switch pathType {
199+
case "host":
200+
paramName = "computeCluster"
201+
case "vm":
202+
paramName = "folder"
203+
case "datastore":
204+
paramName = "datastore"
205+
default:
206+
return "", errors.New("pathType can only be host, datastore or vm")
207+
}
208+
209+
joinedObjectFindPath = path.Join("/", datacenter, pathType, "...")
210+
joinedObjectPath = path.Join("/", datacenter, pathType, objectPath)
211+
212+
if finder == nil {
213+
localLogger.Warnf("%s as a non-path is now deprecated; please use the joined form: %s", paramName, joinedObjectPath)
214+
return joinedObjectPath, nil
215+
}
216+
217+
newObjectPath, err := findViaPathOrName(finder, joinedObjectPath, joinedObjectFindPath)
218+
if err != nil {
219+
return "", err
220+
}
221+
222+
if objectPath != newObjectPath {
223+
localLogger.Debugf("%s path changed from %s to %s", paramName, objectPath, newObjectPath)
224+
}
225+
localLogger.Warnf("%s as a non-path is now deprecated; please use the discovered form: %s", paramName, newObjectPath)
226+
227+
return newObjectPath, nil
104228
}
105-
return folder
229+
230+
return objectPath, nil
106231
}
107232

108233
func createVCenters(platform *vsphere.Platform) {

0 commit comments

Comments
 (0)