k8s.io/kubernetes@v1.29.3/test/e2e/storage/vsphere/config.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package vsphere 18 19 import ( 20 "errors" 21 "fmt" 22 "io" 23 "os" 24 25 "gopkg.in/gcfg.v1" 26 "k8s.io/kubernetes/test/e2e/framework" 27 ) 28 29 const ( 30 vSphereConfFileEnvVar = "VSPHERE_CONF_FILE" 31 ) 32 33 var ( 34 confFileLocation = os.Getenv(vSphereConfFileEnvVar) 35 ) 36 37 // Config represents vSphere configuration 38 type Config struct { 39 Username string 40 Password string 41 Hostname string 42 Port string 43 Datacenters string 44 RoundTripperCount uint 45 DefaultDatastore string 46 Folder string 47 } 48 49 // ConfigFile represents the content of vsphere.conf file. 50 // Users specify the configuration of one or more vSphere instances in vsphere.conf where 51 // the Kubernetes master and worker nodes are running. 52 type ConfigFile struct { 53 Global struct { 54 // vCenter username. 55 User string `gcfg:"user"` 56 // vCenter password in clear text. 57 Password string `gcfg:"password"` 58 // vCenter port. 59 VCenterPort string `gcfg:"port"` 60 // True if vCenter uses self-signed cert. 61 InsecureFlag bool `gcfg:"insecure-flag"` 62 // Datacenter in which VMs are located. 63 Datacenters string `gcfg:"datacenters"` 64 // Soap round tripper count (retries = RoundTripper - 1) 65 RoundTripperCount uint `gcfg:"soap-roundtrip-count"` 66 } 67 68 VirtualCenter map[string]*Config 69 70 Network struct { 71 // PublicNetwork is name of the network the VMs are joined to. 72 PublicNetwork string `gcfg:"public-network"` 73 } 74 75 Disk struct { 76 // SCSIControllerType defines SCSI controller to be used. 77 SCSIControllerType string `dcfg:"scsicontrollertype"` 78 } 79 80 // Endpoint used to create volumes 81 Workspace struct { 82 VCenterIP string `gcfg:"server"` 83 Datacenter string `gcfg:"datacenter"` 84 Folder string `gcfg:"folder"` 85 DefaultDatastore string `gcfg:"default-datastore"` 86 ResourcePoolPath string `gcfg:"resourcepool-path"` 87 } 88 // Tag categories and tags which correspond to "built-in node labels: zones and region" 89 Labels struct { 90 Zone string `gcfg:"zone"` 91 Region string `gcfg:"region"` 92 } 93 } 94 95 // GetVSphereInstances parses vsphere.conf and returns VSphere instances 96 func GetVSphereInstances() (map[string]*VSphere, error) { 97 cfg, err := getConfig() 98 if err != nil { 99 return nil, err 100 } 101 return populateInstanceMap(cfg) 102 } 103 104 func getConfig() (*ConfigFile, error) { 105 if confFileLocation == "" { 106 if framework.TestContext.CloudConfig.ConfigFile == "" { 107 return nil, fmt.Errorf("env variable 'VSPHERE_CONF_FILE' is not set, and no config-file specified") 108 } 109 confFileLocation = framework.TestContext.CloudConfig.ConfigFile 110 } 111 confFile, err := os.Open(confFileLocation) 112 if err != nil { 113 return nil, err 114 } 115 defer confFile.Close() 116 cfg, err := readConfig(confFile) 117 if err != nil { 118 return nil, err 119 } 120 return &cfg, nil 121 } 122 123 // readConfig parses vSphere cloud config file into ConfigFile. 124 func readConfig(config io.Reader) (ConfigFile, error) { 125 if config == nil { 126 err := fmt.Errorf("no vSphere cloud provider config file given") 127 return ConfigFile{}, err 128 } 129 130 var cfg ConfigFile 131 err := gcfg.ReadInto(&cfg, config) 132 return cfg, err 133 } 134 135 func populateInstanceMap(cfg *ConfigFile) (map[string]*VSphere, error) { 136 vsphereInstances := make(map[string]*VSphere) 137 138 if cfg.Workspace.VCenterIP == "" || cfg.Workspace.DefaultDatastore == "" || cfg.Workspace.Folder == "" || cfg.Workspace.Datacenter == "" { 139 msg := fmt.Sprintf("All fields in workspace are mandatory."+ 140 " vsphere.conf does not have the workspace specified correctly. cfg.Workspace: %+v", cfg.Workspace) 141 framework.Logf(msg) 142 return nil, errors.New(msg) 143 } 144 for vcServer, vcConfig := range cfg.VirtualCenter { 145 framework.Logf("Initializing vc server %s", vcServer) 146 if vcServer == "" { 147 framework.Logf("vsphere.conf does not have the VirtualCenter IP address specified") 148 return nil, errors.New("vsphere.conf does not have the VirtualCenter IP address specified") 149 } 150 vcConfig.Hostname = vcServer 151 152 if vcConfig.Username == "" { 153 vcConfig.Username = cfg.Global.User 154 } 155 if vcConfig.Password == "" { 156 vcConfig.Password = cfg.Global.Password 157 } 158 if vcConfig.Username == "" { 159 msg := fmt.Sprintf("vcConfig.Username is empty for vc %s!", vcServer) 160 framework.Logf(msg) 161 return nil, errors.New(msg) 162 } 163 if vcConfig.Password == "" { 164 msg := fmt.Sprintf("vcConfig.Password is empty for vc %s!", vcServer) 165 framework.Logf(msg) 166 return nil, errors.New(msg) 167 } 168 if vcConfig.Port == "" { 169 vcConfig.Port = cfg.Global.VCenterPort 170 } 171 if vcConfig.Datacenters == "" && cfg.Global.Datacenters != "" { 172 vcConfig.Datacenters = cfg.Global.Datacenters 173 } 174 if vcConfig.RoundTripperCount == 0 { 175 vcConfig.RoundTripperCount = cfg.Global.RoundTripperCount 176 } 177 178 vcConfig.DefaultDatastore = cfg.Workspace.DefaultDatastore 179 vcConfig.Folder = cfg.Workspace.Folder 180 181 vsphereIns := VSphere{ 182 Config: vcConfig, 183 } 184 vsphereInstances[vcServer] = &vsphereIns 185 } 186 187 framework.Logf("vSphere instances: %v", vsphereInstances) 188 return vsphereInstances, nil 189 }