I am making a script where I read a CSV-file with parameters to deploy multiple VMs. Now I've added functionality to get it to do sysprep with the help of OSCustomizationSpec and when I tested it was working fine. After that I made some minor modifications, such as added "-ResourcePool" and some other things I can't quite remember unfortunately. Or at least I thought they were minor changes that should affect anything negatively, but when I now run it I get error "A specified parameter was not correct". I found this thread saying it was a bug in older version but that should've been fixed. I tried the workaround but I do get the same error still. The script runs fine when I remove the "-OSCustomizationSpec" parameter, but there seems to be nothing wrong with the file as I can manually deploy VMs with the OSCust file from the GUI and with the same templates. And as I said, it worked fine earlier when I used that parameter. Any ideas on which "parameter" that is incorrect?
PSVersion: 4.0
PowerCLI Version: VMware vSphere PowerCLI 5.5 Release 2 build 1671586
The script throws error:
New-VM : 2014-07-14 10:13:13 New-VM The operation for the entity "Template" failed with the following message: "A specified parameter was not correct. spec.identity.userData.computerName"
At script.ps1:141 char:6
+ New-VM -Template $Template `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-VM], InvalidArgument
+ FullyQualifiedErrorId : Client20_TaskServiceImpl_CheckServerSideTaskUpdates_OperationFailed,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewVM
And in the GUI:
Task: Clone virtual machine
Status: A specified parameter was not correct. spec.identity.userData.computerName
Below is the part of the script regarding New-VM and OSCust:
New-OSCustomizationSpec -Name "PowerCLI" `
-AdminPassword "password" `
-AutoLogonCount 0 `
-ChangeSID:$True `
-Confirm:$False `
-DeleteAccounts:$False `
-Description "Only for use with PowerCLI." `
-FullName $Customer `
-LicenseMode "NotSpecified" `
-NamingScheme "Fixed" `
-NamingPrefix $VMName `
-OrgName $Customer `
-OSType "Windows" `
-TimeZone 110 `
-Type "Persistent" `
-Workgroup "WORKGROUP" | Out-Null
New-VM -Template $Template `
-Name $VMName `
-VMHost $VMHost `
-Datastore $Datastore `
-Location $Folder `
-ResourcePool $ResourcePool `
-OSCustomizationSpec PowerCLI | Out-Null
Damn I'm stupid, I do believe it is Monday today! :smileyangry:
Just like you figured, it has something to do with the computer name.
"spec.identity.userData.computerName"
Or more specifically "-NamingPrefix $row.Name". Since this is the NETBIOS name which may only contain letters, numbers and hyphens.
As previously stated I'm stupid. I had $row.Name defined as "nickey_test01", and underscore isn't an allowed character. This explains why the script worked earlier when I created customer VM's. Guess I'll have to build in more checks in the script, to idiot proof it.
Cheers for the help Luc.
The Template parameter expects a String with the name of the template, or a Template object (as returned by Get-Template).
According to the error the value you pass is neither of these.
How did you populate the $Template variable ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc for the quick reply as usual.
I too figured it might have something to do with that, but when I try fetching the template manually it works fine...
Here is how the script populates $Template:
$Filename = ".\NewVM.csv"
foreach($row in Import-Csv $Filename -UseCulture){
(...)
$Template = Get-Template -Name $row.Template
## And some more variables related to the Template
$ViewTemplate = Get-View -id $Template.id
$TemplateCPU = $ViewTemplate.config.hardware.numcpu
$TemplateMem = ($ViewTemplate.config.hardware.memorymb / 1024)
$TemplateOS = $ViewTemplate.config.guestid
$DiskSize = Get-HardDisk -Template $Template | Select-Object -ExpandProperty CapacityGB | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$ResourcePool = Get-Cluster $row.Cluster | Get-ResourcePool $row.ResourcePool
(...)
}
When running just the above code and not the rest of the script PowerCLI fetches all the parameters correctly and finds the Template.
I suspect you might be overwriting the content of the $Template variable somewhere.
You could display the content of the $Template variable just before you do the New-VM.
And perhaps also check the type.
Write-Output $Template
$Template.GetType()
$Template | Get-Member
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
It only gives me output for 1 template:
## Write-Output $Template
Name
----
WIN2012_R2_STD_template
## $Template.GetType()
Module : VMware.VimAutomation.ViCore.Impl.dll
Assembly : VMware.VimAutomation.ViCore.Impl, Version=5.5.0.0, Culture=neutral, PublicKeyToken=null
TypeHandle : System.RuntimeTypeHandle
DeclaringMethod :
BaseType : VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl
UnderlyingSystemType : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
FullName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
AssemblyQualifiedName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl, VMware.VimAutomation.ViCore.Impl, Version=5.5.0.0, Culture=neutral, PublicKeyToken=null
Namespace : VMware.VimAutomation.ViCore.Impl.V1.Inventory
GUID : bdfb3c64-a617-3970-850f-f51d784bee4e
IsEnum : False
GenericParameterAttributes :
IsSecurityCritical : False
IsSecuritySafeCritical : False
IsSecurityTransparent : True
IsGenericTypeDefinition : False
IsGenericParameter : False
GenericParameterPosition :
IsGenericType : False
IsConstructedGenericType : False
ContainsGenericParameters : False
StructLayoutAttribute : System.Runtime.InteropServices.StructLayoutAttribute
Name : TemplateImpl
MemberType : TypeInfo
DeclaringType :
ReflectedType :
MetadataToken : 33554721
GenericTypeParameters : {}
DeclaredConstructors : {Void .cctor(), Void .ctor(System.String), Void .c
tor(System.String, System.String), Void .ctor(Syst
em.String, System.String, System.String, System.St
ring, System.String[], VMware.VimAutomation.ViCore
.Impl.V1.VimClient, System.Collections.Generic.Dic
tionary`2[System.String,System.String], VMware.Vim
.VirtualMachine)}
DeclaredEvents : {}
DeclaredFields : {_isInitialized, _hostId, _folderId, _datastoreIdList...}
DeclaredMembers : {VMware.VimAutomation.ViCore.Impl.V1.Inventory.Tem
plateImpl Create(VMware.Vim.ManagedObjectReference
, VMware.VimAutomation.ViCore.Impl.V1.VimClient, S
ystem.Collections.Generic.Dictionary`2[System.Stri
ng,System.Object], System.Collections.Generic.Dict
ionary`2[System.String,System.String], System.Obje
ct), VMware.VimAutomation.ViCore.Impl.V1.ManagedCl
assInfo get_ClassInfo(), System.String VMware.VimA
utomation.ViCore.Interop.V1.Inventory.TemplateInte
rop.get_HostId(), System.String get_FolderId()...}
DeclaredMethods : {VMware.VimAutomation.ViCore.Impl.V1.Inventory.Tem
plateImpl Create(VMware.Vim.ManagedObjectReference
, VMware.VimAutomation.ViCore.Impl.V1.VimClient, S
ystem.Collections.Generic.Dictionary`2[System.Stri
ng,System.Object], System.Collections.Generic.Dict
ionary`2[System.String,System.String], System.Obje
ct), VMware.VimAutomation.ViCore.Impl.V1.ManagedCl
assInfo get_ClassInfo(), System.String VMware.VimA
utomation.ViCore.Interop.V1.Inventory.TemplateInte
rop.get_HostId(), System.String get_FolderId()...}
DeclaredNestedTypes : {}
DeclaredProperties : {VMware.VimAutomation.ViCore.Impl.V1.ManagedClassI
nfo ClassInfo, System.String VMware.VimAutomation.
ViCore.Interop.V1.Inventory.TemplateInterop.HostId
, System.String FolderId, System.String[] Datastor
eIdList}
ImplementedInterfaces : {VMware.VimAutomation.Sdk.Types.V1.VIObject, VMwar
e.VimAutomation.Sdk.Types.V1.VIObjectCore, VMware.
VimAutomation.Sdk.Types.V1.NamedObject, VMware.Vim
Automation.ViCore.Interop.V1.VIObjectInterop...}
TypeInitializer : Void .cctor()
IsNested : False
Attributes : AutoLayout, AnsiClass, Class, Public
IsVisible : True
IsNotPublic : False
IsPublic : True
IsNestedPublic : False
IsNestedPrivate : False
IsNestedFamily : False
IsNestedAssembly : False
IsNestedFamANDAssem : False
IsNestedFamORAssem : False
IsAutoLayout : True
IsLayoutSequential : False
IsExplicitLayout : False
IsClass : True
IsInterface : False
IsValueType : False
IsAbstract : False
IsSealed : False
IsSpecialName : False
IsImport : False
IsSerializable : False
IsAnsiClass : True
IsUnicodeClass : False
IsAutoClass : False
IsArray : False
IsByRef : False
IsPointer : False
IsPrimitive : False
IsCOMObject : False
HasElementType : False
IsContextful : False
IsMarshalByRef : False
GenericTypeArguments : {}
CustomAttributes : {}
## $Template | Get-Member
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : ConvertToVersion
MemberType : Method
Definition : T VersionedObjectInterop.ConvertToVersion[T]()
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : Equals
MemberType : Method
Definition : bool Equals(System.Object obj)
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : GetHashCode
MemberType : Method
Definition : int GetHashCode()
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : GetType
MemberType : Method
Definition : type GetType()
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : IsConvertableTo
MemberType : Method
Definition : bool VersionedObjectInterop.IsConvertableTo(type type)
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : LockUpdates
MemberType : Method
Definition : void ExtensionData.LockUpdates()
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : ToString
MemberType : Method
Definition : string ToString()
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : UnlockUpdates
MemberType : Method
Definition : void ExtensionData.UnlockUpdates()
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : Client
MemberType : Property
Definition : VMware.VimAutomation.ViCore.Interop.V1.VIAutomation Client {get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : CustomFields
MemberType : Property
Definition : System.Collections.Generic.IDictionary[string,string] CustomFields
{get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : DatastoreIdList
MemberType : Property
Definition : string[] DatastoreIdList {get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : ExtensionData
MemberType : Property
Definition : System.Object ExtensionData {get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : FolderId
MemberType : Property
Definition : string FolderId {get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : HostId
MemberType : Property
Definition : string HostId {get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : Id
MemberType : Property
Definition : string Id {get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : Name
MemberType : Property
Definition : string Name {get;}
TypeName : VMware.VimAutomation.ViCore.Impl.V1.Inventory.TemplateImpl
Name : Uid
MemberType : Property
Definition : string Uid {get;}
Then the error is thrown:
New-VM : 2014-07-14 11:58:31 New-VM The operation for the entity "WIN2012_R2_STD_template" failed with the following message: "A specified parameter was not correct. spec.identity.userData.computerName"
At script.ps1:146 char:6
+ New-VM -Template $Template `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-VM], InvalidArgument
+ FullyQualifiedErrorId : Client20_TaskServiceImpl_CheckServerSideTaskUpdates_OperationFailed,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewVM
I added the commands in between New-OSCustomizationSpec and New-VM.
In the OSCustomizationSpec your are using, called PowerCLI, how did you define the Computer Name entry ?
Is that "Use the virtual machine name" ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
No, it's "Enter a name".
As far as I understand from New-OSCustomizationSpec, -NamingPrefix (together with "-NamingScheme = Fixed") populates this field.
From the help: "If the "Fixed" naming scheme is used, NamingPrefix should indicate the name of the virtual machine."
The reason I use this is so that I can have a different OS hostname than the display name in vSphere because we set a prefix on the display name in vSphere depending on which customer the VM is regarding.
So in my script it's actually:
-NamingScheme "Fixed" `
-NamingPrefix $row.Name `
that sets the OS hostname and:
New-VM -Template $Template `
-Name $VMName `
that sets the vSphere display name.
Here is the content of the OSCust File:
C:\> Get-OSCustomizationSpec "PowerCLI" | select *
Name : PowerCLI
Type : Persistent
ServerId : /VIServer=user@domain.com:443/
Server : vcenter@domain.com
LastUpdate : 2014-07-14 11:57:49
DomainAdminUsername :
DomainUsername :
Description : Only for use with PowerCLI.
AutoLogonCount :
ChangeSid : True
DeleteAccounts : False
DnsServer :
DnsSuffix :
Domain :
FullName : Customer
GuiRunOnce :
NamingPrefix : nickey_test01
NamingScheme : Fixed
OrgName : Customer
OSType : Windows
ProductKey :
TimeZone : W. Europe
Workgroup : WORKGROUP
LicenseMode : NotSpecified
LicenseMaxConnections :
EncryptionKey : {48, -126, 1, -27...}
ExtensionData : VMware.Vim.CustomizationSpecItem
Id : PowerCLI
Uid : /VIServer=user@domain.com:443/OSCustomizationSpec=PowerCLI/
Client : VMware.VimAutomation.ViCore.Impl.V1.VimClient
AdminPassword : raTgAGIwbo8D9MnhgqCKiN8+XnkcyTTYBnhRNOdR6kGq+4W6wSrcGqbzS51BZBg8c7IEZ3z9sg==
DomainAdminPassword :
DomainPassword :
That is correct, but that also means you manipulate the OSCustomizationSpec in your script.
It looks as if something goes wrong there.
There might be some clues in the vpxd.log on the vCenter
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I'm no expert in log diving Any pointers what to look for?
Well, the New-VM cmdlet will most probably call a CloneVM_Task, and then there is the timestamp you can use to locate the entry.
If there is anything in the vpxd log, you should see a complete dump of the object(s) that is (were) passed to the method.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Damn I'm stupid, I do believe it is Monday today! :smileyangry:
Just like you figured, it has something to do with the computer name.
"spec.identity.userData.computerName"
Or more specifically "-NamingPrefix $row.Name". Since this is the NETBIOS name which may only contain letters, numbers and hyphens.
As previously stated I'm stupid. I had $row.Name defined as "nickey_test01", and underscore isn't an allowed character. This explains why the script worked earlier when I created customer VM's. Guess I'll have to build in more checks in the script, to idiot proof it.
Cheers for the help Luc.
Glad you figured it out :smileycool:
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Jeah, thanks - so am I. Next time I post a question here I'll just start with "I guess I'm being stupid again, but..."
@LittleNickey It's been almost exactly 7 years since you posted this, but you just saved my sanity today! Thank you.
Stupid NetBIOS names. I looked at the underscores, and thought there was no way that was the issue! It's Windows! They don't care about silly things like that.....