github.com/vmware/govmomi@v0.43.0/simulator/customization_spec_manager.go (about) 1 /* 2 Copyright (c) 2019-2024 VMware, Inc. All Rights Reserved. 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 simulator 18 19 import ( 20 "encoding/pem" 21 "fmt" 22 "sync/atomic" 23 "time" 24 25 "github.com/vmware/govmomi/simulator/internal" 26 "github.com/vmware/govmomi/vim25/methods" 27 "github.com/vmware/govmomi/vim25/mo" 28 "github.com/vmware/govmomi/vim25/soap" 29 "github.com/vmware/govmomi/vim25/types" 30 ) 31 32 var DefaultCustomizationSpec = []types.CustomizationSpecItem{ 33 { 34 Info: types.CustomizationSpecInfo{ 35 Name: "vcsim-linux", 36 Description: "", 37 Type: "Linux", 38 ChangeVersion: "1569965707", 39 LastUpdateTime: types.NewTime(time.Now()), 40 }, 41 Spec: types.CustomizationSpec{ 42 Options: &types.CustomizationLinuxOptions{}, 43 Identity: &types.CustomizationLinuxPrep{ 44 CustomizationIdentitySettings: types.CustomizationIdentitySettings{}, 45 HostName: &types.CustomizationVirtualMachineName{}, 46 Domain: "eng.vmware.com", 47 TimeZone: "Pacific/Apia", 48 HwClockUTC: types.NewBool(true), 49 }, 50 GlobalIPSettings: types.CustomizationGlobalIPSettings{ 51 DnsSuffixList: nil, 52 DnsServerList: []string{"127.0.1.1"}, 53 }, 54 NicSettingMap: []types.CustomizationAdapterMapping{ 55 { 56 MacAddress: "", 57 Adapter: types.CustomizationIPSettings{ 58 Ip: &types.CustomizationDhcpIpGenerator{}, 59 SubnetMask: "", 60 Gateway: nil, 61 IpV6Spec: (*types.CustomizationIPSettingsIpV6AddressSpec)(nil), 62 DnsServerList: nil, 63 DnsDomain: "", 64 PrimaryWINS: "", 65 SecondaryWINS: "", 66 NetBIOS: "", 67 }, 68 }, 69 }, 70 EncryptionKey: nil, 71 }, 72 }, 73 { 74 Info: types.CustomizationSpecInfo{ 75 Name: "vcsim-linux-static", 76 Description: "", 77 Type: "Linux", 78 ChangeVersion: "1569969598", 79 LastUpdateTime: types.NewTime(time.Now()), 80 }, 81 Spec: types.CustomizationSpec{ 82 Options: &types.CustomizationLinuxOptions{}, 83 Identity: &types.CustomizationLinuxPrep{ 84 CustomizationIdentitySettings: types.CustomizationIdentitySettings{}, 85 HostName: &types.CustomizationPrefixName{ 86 CustomizationName: types.CustomizationName{}, 87 Base: "vcsim", 88 }, 89 Domain: "eng.vmware.com", 90 TimeZone: "Africa/Cairo", 91 HwClockUTC: types.NewBool(true), 92 }, 93 GlobalIPSettings: types.CustomizationGlobalIPSettings{ 94 DnsSuffixList: nil, 95 DnsServerList: []string{"127.0.1.1"}, 96 }, 97 NicSettingMap: []types.CustomizationAdapterMapping{ 98 { 99 MacAddress: "", 100 Adapter: types.CustomizationIPSettings{ 101 Ip: &types.CustomizationUnknownIpGenerator{}, 102 SubnetMask: "255.255.255.0", 103 Gateway: []string{"10.0.0.1"}, 104 IpV6Spec: (*types.CustomizationIPSettingsIpV6AddressSpec)(nil), 105 DnsServerList: nil, 106 DnsDomain: "", 107 PrimaryWINS: "", 108 SecondaryWINS: "", 109 NetBIOS: "", 110 }, 111 }, 112 }, 113 EncryptionKey: nil, 114 }, 115 }, 116 { 117 Info: types.CustomizationSpecInfo{ 118 Name: "vcsim-windows-static", 119 Description: "", 120 Type: "Windows", 121 ChangeVersion: "1569978029", 122 LastUpdateTime: types.NewTime(time.Now()), 123 }, 124 Spec: types.CustomizationSpec{ 125 Options: &types.CustomizationWinOptions{ 126 CustomizationOptions: types.CustomizationOptions{}, 127 ChangeSID: true, 128 DeleteAccounts: false, 129 Reboot: "", 130 }, 131 Identity: &types.CustomizationSysprep{ 132 CustomizationIdentitySettings: types.CustomizationIdentitySettings{}, 133 GuiUnattended: types.CustomizationGuiUnattended{ 134 Password: (*types.CustomizationPassword)(nil), 135 TimeZone: 2, 136 AutoLogon: false, 137 AutoLogonCount: 1, 138 }, 139 UserData: types.CustomizationUserData{ 140 FullName: "vcsim", 141 OrgName: "VMware", 142 ComputerName: &types.CustomizationVirtualMachineName{}, 143 ProductId: "", 144 }, 145 GuiRunOnce: (*types.CustomizationGuiRunOnce)(nil), 146 Identification: types.CustomizationIdentification{ 147 JoinWorkgroup: "WORKGROUP", 148 JoinDomain: "", 149 DomainAdmin: "", 150 DomainAdminPassword: (*types.CustomizationPassword)(nil), 151 }, 152 LicenseFilePrintData: &types.CustomizationLicenseFilePrintData{ 153 AutoMode: "perServer", 154 AutoUsers: 5, 155 }, 156 }, 157 GlobalIPSettings: types.CustomizationGlobalIPSettings{}, 158 NicSettingMap: []types.CustomizationAdapterMapping{ 159 { 160 MacAddress: "", 161 Adapter: types.CustomizationIPSettings{ 162 Ip: &types.CustomizationUnknownIpGenerator{}, 163 SubnetMask: "255.255.255.0", 164 Gateway: []string{"10.0.0.1"}, 165 IpV6Spec: (*types.CustomizationIPSettingsIpV6AddressSpec)(nil), 166 DnsServerList: nil, 167 DnsDomain: "", 168 PrimaryWINS: "", 169 SecondaryWINS: "", 170 NetBIOS: "", 171 }, 172 }, 173 }, 174 EncryptionKey: nil, 175 }, 176 }, 177 { 178 Info: types.CustomizationSpecInfo{ 179 Name: "vcsim-windows-domain", 180 Description: "", 181 Type: "Windows", 182 ChangeVersion: "1569970234", 183 LastUpdateTime: types.NewTime(time.Now()), 184 }, 185 Spec: types.CustomizationSpec{ 186 Options: &types.CustomizationWinOptions{ 187 CustomizationOptions: types.CustomizationOptions{}, 188 ChangeSID: true, 189 DeleteAccounts: false, 190 Reboot: "", 191 }, 192 Identity: &types.CustomizationSysprep{ 193 CustomizationIdentitySettings: types.CustomizationIdentitySettings{}, 194 GuiUnattended: types.CustomizationGuiUnattended{ 195 Password: &types.CustomizationPassword{ 196 Value: "3Gs...==", 197 PlainText: false, 198 }, 199 TimeZone: 15, 200 AutoLogon: false, 201 AutoLogonCount: 1, 202 }, 203 UserData: types.CustomizationUserData{ 204 FullName: "dougm", 205 OrgName: "VMware", 206 ComputerName: &types.CustomizationVirtualMachineName{}, 207 ProductId: "", 208 }, 209 GuiRunOnce: (*types.CustomizationGuiRunOnce)(nil), 210 Identification: types.CustomizationIdentification{ 211 JoinWorkgroup: "", 212 JoinDomain: "DOMAIN", 213 DomainAdmin: "vcsim", 214 DomainAdminPassword: &types.CustomizationPassword{ 215 Value: "H3g...==", 216 PlainText: false, 217 }, 218 }, 219 LicenseFilePrintData: &types.CustomizationLicenseFilePrintData{ 220 AutoMode: "perServer", 221 AutoUsers: 5, 222 }, 223 }, 224 GlobalIPSettings: types.CustomizationGlobalIPSettings{}, 225 NicSettingMap: []types.CustomizationAdapterMapping{ 226 { 227 MacAddress: "", 228 Adapter: types.CustomizationIPSettings{ 229 Ip: &types.CustomizationUnknownIpGenerator{}, 230 SubnetMask: "255.255.255.0", 231 Gateway: []string{"10.0.0.1"}, 232 IpV6Spec: (*types.CustomizationIPSettingsIpV6AddressSpec)(nil), 233 DnsServerList: nil, 234 DnsDomain: "", 235 PrimaryWINS: "", 236 SecondaryWINS: "", 237 NetBIOS: "", 238 }, 239 }, 240 }, 241 EncryptionKey: nil, 242 }, 243 }, 244 } 245 246 type CustomizationSpecManager struct { 247 mo.CustomizationSpecManager 248 249 items []types.CustomizationSpecItem 250 } 251 252 func (m *CustomizationSpecManager) init(r *Registry) { 253 m.items = DefaultCustomizationSpec 254 255 // Real VC is different DN, X509v3 extensions, etc. 256 // This is still useful for testing []byte of DER encoded cert over SOAP 257 if len(m.EncryptionKey) == 0 { 258 block, _ := pem.Decode(internal.LocalhostCert) 259 m.EncryptionKey = block.Bytes 260 } 261 } 262 263 var customizeNameCounter uint64 264 265 func customizeName(vm *VirtualMachine, base types.BaseCustomizationName) string { 266 n := atomic.AddUint64(&customizeNameCounter, 1) 267 268 switch name := base.(type) { 269 case *types.CustomizationPrefixName: 270 return fmt.Sprintf("%s-%d", name.Base, n) 271 case *types.CustomizationCustomName: 272 return fmt.Sprintf("%s-%d", name.Argument, n) 273 case *types.CustomizationFixedName: 274 return name.Name 275 case *types.CustomizationUnknownName: 276 return "" 277 case *types.CustomizationVirtualMachineName: 278 return fmt.Sprintf("%s-%d", vm.Name, n) 279 default: 280 return "" 281 } 282 } 283 284 func (m *CustomizationSpecManager) DoesCustomizationSpecExist(ctx *Context, req *types.DoesCustomizationSpecExist) soap.HasFault { 285 exists := false 286 287 for _, item := range m.items { 288 if item.Info.Name == req.Name { 289 exists = true 290 break 291 } 292 } 293 294 return &methods.DoesCustomizationSpecExistBody{ 295 Res: &types.DoesCustomizationSpecExistResponse{ 296 Returnval: exists, 297 }, 298 } 299 } 300 301 func (m *CustomizationSpecManager) GetCustomizationSpec(ctx *Context, req *types.GetCustomizationSpec) soap.HasFault { 302 body := new(methods.GetCustomizationSpecBody) 303 304 for _, item := range m.items { 305 if item.Info.Name == req.Name { 306 body.Res = &types.GetCustomizationSpecResponse{ 307 Returnval: item, 308 } 309 return body 310 } 311 } 312 313 body.Fault_ = Fault("", new(types.NotFound)) 314 315 return body 316 } 317 318 func (m *CustomizationSpecManager) CreateCustomizationSpec(ctx *Context, req *types.CreateCustomizationSpec) soap.HasFault { 319 body := new(methods.CreateCustomizationSpecBody) 320 321 for _, item := range m.items { 322 if item.Info.Name == req.Item.Info.Name { 323 body.Fault_ = Fault("", &types.AlreadyExists{Name: req.Item.Info.Name}) 324 return body 325 } 326 } 327 328 m.items = append(m.items, req.Item) 329 body.Res = new(types.CreateCustomizationSpecResponse) 330 331 return body 332 } 333 334 func (m *CustomizationSpecManager) OverwriteCustomizationSpec(ctx *Context, req *types.OverwriteCustomizationSpec) soap.HasFault { 335 body := new(methods.OverwriteCustomizationSpecBody) 336 337 for i, item := range m.items { 338 if item.Info.Name == req.Item.Info.Name { 339 m.items[i] = req.Item 340 body.Res = new(types.OverwriteCustomizationSpecResponse) 341 return body 342 } 343 } 344 345 body.Fault_ = Fault("", new(types.NotFound)) 346 347 return body 348 } 349 350 func (m *CustomizationSpecManager) Get() mo.Reference { 351 clone := *m 352 353 for i := range clone.items { 354 clone.Info = append(clone.Info, clone.items[i].Info) 355 } 356 357 return &clone 358 }