Hi all,
I need to specify the a "Computer Name" in customization spec different from the "Machine Name". I've modified the custom spec in vCenter as shown in the capture below:
But then, I cannot find the way to specify that parameter with custom properties. I always get the same error message: "A specified parameter was not correct: spec.identity.hostname"
I've tried with:
Any ideas?
Thanks.
A specified parameter was not correct: spec.identity.hostname
I don't think what you want to do can be done with a single custom property value.
You can do it with the event broker and a machine lifecycle workflow.
Here is what the example looks like, first the request form of a requested VM:
I add the 'Hostname' property to the blueprint (although you could put it on the vSphere VM itself if you have composite blueprints). I also added a new custom property called 'DisplayNameSuffix'. The point is that the machine will get named according to the Hostname property, but we'll use the suffix to rename it in vSphere later. Lastly, I added the Extensibility.Lifecycle.Properties.VMPSMasterWorkflow32.MachineProvisioned = * property to make sure properties to get passed to vRO later.
After the machine is completely provisioned, a vRO workflow runs which grabs the vCAC UUID from the machine properties, matches it to a vCAC Entity object, grabs the managed object ID, then matches it to a vSphere VM and calles the rename_Task() method on it.
Workflow run output looks like this:
[2017-11-24 22:30:54.389] [I] # VMs = 373
[2017-11-24 22:30:54.402] [I] Matched UUID = 501edba1-69ea-c3f5-b35d-6ae20a324faf ; moid = vm-12239
[2017-11-24 22:30:54.416] [I] vCAC UUID: 501edba1-69ea-c3f5-b35d-6ae20a324faf
[2017-11-24 22:30:54.418] [I] VM MOID: vm-12239
[2017-11-24 22:30:54.736] [I] Found VM in vSphere Inventory: test7
[2017-11-24 22:30:54.738] [I] Renaming VM in vSphere from: test7 to test7.test.local
[2017-11-24 22:30:54.854] [I] Rename_Task 0 %
[2017-11-24 22:30:56.858] [I] Rename_Task end
[2017-11-24 22:30:56.860] [I] Done. Task Result = null
In vSphere:
In the vRA Items tab:
The workflow is fairly simple. Schema looks like this:
There is one attribute, vCACHost, which is of type vCAC:vCACHost. You set it to the vCAC IAAS host you're using for this operation.
It takes a single input called props of type Properties. This is the payload from vRA. It gets wired to the inputs of the Rename VM task.
There is a single output called virtualMachineAddOrUpdateProperties of type Properties. This holds any updates to machine properties you want to make from the workflow. I commented out a section updating the 'VirtualMachine.Admin.Name' property because it's unclear if this is needed and the solution seems to work without it. But you could uncomment it out if you want to test it. Otherwise, there are no property updates made.
The Rename VM scriptable task content is:
virtualMachineAddOrUpdateProperties = new Properties();
if(props != null)
{
var machine = props.get("machine");
if(machine != null)
{
var vraProps = machine.get("properties");
if(vraProps != null)
{
var uuid = vraProps["VirtualMachine.Admin.UUID"];
var hostname = vraProps.get("Hostname");
var suffix = vraProps.get("DisplayNameSuffix");
//Only do something if user entered values for both hostname and suffix
if(hostname != "" && suffix != "") {
var requestId = vraProps.get("__Cafe.Root.Request.Id");
var searchProperties = new Properties();
var vmEntities = vCACEntityManager.readModelEntitiesByCustomFilter(vCACHost.id, "ManagementModelEntities.svc", "VirtualMachines", searchProperties, null);
var vms = new Array;
var vmProps = null;
var vmMOID = "";
System.log("# VMs = " + vmEntities.length);
for each (var v = 0; v < vmEntities.length; v++) {
var vEntity = vmEntities[v];
if(vEntity != null) {
//vCAC UUID
var vmid = vEntity.getProperty("VMUniqueID");
//vSphere Managed Object ID
var moid = vEntity.getProperty("ExternalReferenceId");
if (vmid == uuid) {
System.log("Matched UUID = " + vmid + " ; moid = " + moid);
vmMOID = moid;
}
}
}
System.log("vCAC UUID: " + uuid);
System.log("VM MOID: " + vmMOID);
var vms = VcPlugin.getAllVirtualMachines();
var vm = null;
for(var v in vms) {
if(vms[v].id == vmMOID) {
System.log("Found VM in vSphere Inventory: " + vms[v].name);
vm = vms[v];
var fullName = hostname + "." + suffix;
System.log ("Renaming VM in vSphere from: " + vm.name + " to " + fullName);
var task = vm.rename_Task(fullName);
var taskResult = System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task, true, 2);
System.log(" Done. Task Result = " + taskResult);
//Uncomment if you want to update the VirtualMachine.Admin.Name property
// It's unclear if you really need to do this after renaming the
// machine in vSphere.
//virtualMachineAddOrUpdateProperties.put("VirtualMachine.Admin.Hostname", fullName);
break;
}
}
System.log("Updated Machine Properties Passed Out:");
for(var pk in virtualMachineAddOrUpdateProperties.keys)
{
System.log(" " + pk + ". " + virtualMachineAddOrUpdateProperties.keys[pk] + " = " + virtualMachineAddOrUpdateProperties.get(virtualMachineAddOrUpdateProperties.keys[pk]));
}
}
}
}
}
And to setup the subscription:
And map to the workflow. Be sure to publish after saving.
I have attached the workflow if you would like to review.
You will obviously want to apply these changes to a test environment. You may also want to modify the subscription to only run for a specific blueprint to keep it from impacting others.
One last note - the script adds the dot in between the hostname and suffix, so no need to enter that. You could change this if you want.
Try the Hostname property (no prefixes).
From the Custom Properties Reference guide -
Hostname (page 66):
Specifies the host machine name, overriding the generated machine name contained in the VirtualMachine.Admin.Name property. If Hostname is not used, the VirtualMachine.Admin.Name value is used as the machine name. The maximum number of allowed characters for the Hostname value is 15
VirtualMachine.Admin.Name (page 83):
Specifies the generated machine name for vSphere, for example CodyVM01. When creating custom workflows or plug-ins for customizing a virtual machine name, set this property to match the name of the virtual machine. This is an internal input property for the agent to name the virtual machine. Note This property is for vSphere only. The value specified in the blueprint has no effect on this property. This property is not intended to be used to prompt the user. Use the HostName property to prompt the user. If the property is set at runtime, the container name that is created in the hypervisor might not match the item record name.
Hi Jasnyder,
I've already tested those two also. Same error.
I don't know what else to do. There is no information on Internet about this topic. All posts assume that you use the "use machine name" option in the custom spec.
Thanks anyway.
OK, so your problem is you don't want to set it to that option on the customization spec side of things. Is there a reason why you can't do that? Perhaps one customization spec for users to use in the vSphere client and one to call from the blueprint in vRA? Or is that too many specs to create and maintain?
I need to deploy VMs with names that contains dots (.) but for the hostname, I want only the part before the first dot. Ex: my new Virtual Machine called "mynewserver.domain.com" (we want to see this name on vCenter inventory) but the hostname must be "mynewserver".
So I can use the Hostname property to set the VM name, but I can't set the Hostname on the customization spec. If I use the option "use machine name", the hostname is invented (for windows) or is the hole vm name without dots (for linux). Neither is good.
I need to tell the Custom Spec the hostname but I cannot find a custom property to do it.
D.
So to clarify on this - you want the hostname to be different from the VM display name in vCenter, correct?
And the hostname would be a subset of the display name? i.e. hostname.domain.com, so the VM hostname would be 'hostname' and the vcenter display name would be the full 'hostname.domain.com'
Or should it be the other way around?
And is it OK if the vRA machine display name is the full hostname.domain.com i.e. would match the vCenter display name and not the machine hostname?
Exactly like that. Please help.
I don't think what you want to do can be done with a single custom property value.
You can do it with the event broker and a machine lifecycle workflow.
Here is what the example looks like, first the request form of a requested VM:
I add the 'Hostname' property to the blueprint (although you could put it on the vSphere VM itself if you have composite blueprints). I also added a new custom property called 'DisplayNameSuffix'. The point is that the machine will get named according to the Hostname property, but we'll use the suffix to rename it in vSphere later. Lastly, I added the Extensibility.Lifecycle.Properties.VMPSMasterWorkflow32.MachineProvisioned = * property to make sure properties to get passed to vRO later.
After the machine is completely provisioned, a vRO workflow runs which grabs the vCAC UUID from the machine properties, matches it to a vCAC Entity object, grabs the managed object ID, then matches it to a vSphere VM and calles the rename_Task() method on it.
Workflow run output looks like this:
[2017-11-24 22:30:54.389] [I] # VMs = 373
[2017-11-24 22:30:54.402] [I] Matched UUID = 501edba1-69ea-c3f5-b35d-6ae20a324faf ; moid = vm-12239
[2017-11-24 22:30:54.416] [I] vCAC UUID: 501edba1-69ea-c3f5-b35d-6ae20a324faf
[2017-11-24 22:30:54.418] [I] VM MOID: vm-12239
[2017-11-24 22:30:54.736] [I] Found VM in vSphere Inventory: test7
[2017-11-24 22:30:54.738] [I] Renaming VM in vSphere from: test7 to test7.test.local
[2017-11-24 22:30:54.854] [I] Rename_Task 0 %
[2017-11-24 22:30:56.858] [I] Rename_Task end
[2017-11-24 22:30:56.860] [I] Done. Task Result = null
In vSphere:
In the vRA Items tab:
The workflow is fairly simple. Schema looks like this:
There is one attribute, vCACHost, which is of type vCAC:vCACHost. You set it to the vCAC IAAS host you're using for this operation.
It takes a single input called props of type Properties. This is the payload from vRA. It gets wired to the inputs of the Rename VM task.
There is a single output called virtualMachineAddOrUpdateProperties of type Properties. This holds any updates to machine properties you want to make from the workflow. I commented out a section updating the 'VirtualMachine.Admin.Name' property because it's unclear if this is needed and the solution seems to work without it. But you could uncomment it out if you want to test it. Otherwise, there are no property updates made.
The Rename VM scriptable task content is:
virtualMachineAddOrUpdateProperties = new Properties();
if(props != null)
{
var machine = props.get("machine");
if(machine != null)
{
var vraProps = machine.get("properties");
if(vraProps != null)
{
var uuid = vraProps["VirtualMachine.Admin.UUID"];
var hostname = vraProps.get("Hostname");
var suffix = vraProps.get("DisplayNameSuffix");
//Only do something if user entered values for both hostname and suffix
if(hostname != "" && suffix != "") {
var requestId = vraProps.get("__Cafe.Root.Request.Id");
var searchProperties = new Properties();
var vmEntities = vCACEntityManager.readModelEntitiesByCustomFilter(vCACHost.id, "ManagementModelEntities.svc", "VirtualMachines", searchProperties, null);
var vms = new Array;
var vmProps = null;
var vmMOID = "";
System.log("# VMs = " + vmEntities.length);
for each (var v = 0; v < vmEntities.length; v++) {
var vEntity = vmEntities[v];
if(vEntity != null) {
//vCAC UUID
var vmid = vEntity.getProperty("VMUniqueID");
//vSphere Managed Object ID
var moid = vEntity.getProperty("ExternalReferenceId");
if (vmid == uuid) {
System.log("Matched UUID = " + vmid + " ; moid = " + moid);
vmMOID = moid;
}
}
}
System.log("vCAC UUID: " + uuid);
System.log("VM MOID: " + vmMOID);
var vms = VcPlugin.getAllVirtualMachines();
var vm = null;
for(var v in vms) {
if(vms[v].id == vmMOID) {
System.log("Found VM in vSphere Inventory: " + vms[v].name);
vm = vms[v];
var fullName = hostname + "." + suffix;
System.log ("Renaming VM in vSphere from: " + vm.name + " to " + fullName);
var task = vm.rename_Task(fullName);
var taskResult = System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task, true, 2);
System.log(" Done. Task Result = " + taskResult);
//Uncomment if you want to update the VirtualMachine.Admin.Name property
// It's unclear if you really need to do this after renaming the
// machine in vSphere.
//virtualMachineAddOrUpdateProperties.put("VirtualMachine.Admin.Hostname", fullName);
break;
}
}
System.log("Updated Machine Properties Passed Out:");
for(var pk in virtualMachineAddOrUpdateProperties.keys)
{
System.log(" " + pk + ". " + virtualMachineAddOrUpdateProperties.keys[pk] + " = " + virtualMachineAddOrUpdateProperties.get(virtualMachineAddOrUpdateProperties.keys[pk]));
}
}
}
}
}
And to setup the subscription:
And map to the workflow. Be sure to publish after saving.
I have attached the workflow if you would like to review.
You will obviously want to apply these changes to a test environment. You may also want to modify the subscription to only run for a specific blueprint to keep it from impacting others.
One last note - the script adds the dot in between the hostname and suffix, so no need to enter that. You could change this if you want.
So you suggest that I should provision the vm with the hostname, and then, in post provision, rename the vm and the vcac entity. Right?
It's a good workaround. Thanks. I will try that.
But should be a custom property for this in the next version.
I agree that there should be better handling of unforeseen provisioning details in all kinds of resources. If the devs would look into matching a prefix to object creation in the code, it would be helpful. In your case, it's creating a customizationspec and submitting it as part of a machine reconfiguration in vSphere. If you could dynamically drive the details of that request by looking for custom properties that match a pattern, then they could leave it open ended to fix problems like this. In your case, if you could add something like "VMware.VirtualMachine.Provisioning.CustomizationSpec.identity.hostname" then their code would read the first 4 sections of that and determine the last 2 are there to set the spec.identity.hostname parameter according to the value of the custom property. Seems easy enough...
The same issues apply to Amazon EC2 provisioning. Almost nothing on the instance request object is customizable and they could easily make this work by doing he same custom property pattern matching as above and setting request object members according to those things. I say easily, but I know it would take some work, and it would be hard to document the whole thing given how open ended it would be. But it sure would make things a lot more flexible.
I will try your suggested approach, I'll might change some parts or the code (don't like the "getAllVms" part) but, if it works, I'll mark your answer as the correct one.
Thanks,
D.
Fair enough. One other thing you might want to change in the code:
//Only do something if user entered values for both hostname and suffix
if(hostname != "" && suffix != "") {
Should be
//Only do something if user entered values for both hostname and suffix
if(hostname != null && suffix != null hostname != "" && suffix != "") {
Just in case you end up calling the workflow from a request that doesn't have one or both of those properties present, it will show up as null which would pass the != "" test, and may inadvertently end up renaming a machine unnecessarily.
Thanks a lot jasnyder, it works smoothly,
Here is my final solution with a little code just to add some value to this thread:
In vRA subscriptions, I've used the "VMPSMasterWorkflow32.MachineActivated" state and phase POST
In the workflow, I've started using "getVirtualMachineEntity" from the plugin library to get the vRA entity, then I've wrote the following code (with comments)
var props = vmEntity.getProperties();
var vmName = props.get("VirtualMachineName");
var moid = props.get('ExternalReferenceId');
// Again I'm using an action from the vRA plugin library
var vms = System.getModule("com.vmware.vcac.asd").findVcObjectsByMoRefId('VC:VirtualMachine',moid);
// Because could have many vCenter endpoints, I could get more that one VM. Check the name to be sure
var vm = null;
for each(var v in vms) {
if (v.name == vmName) {
vm = v;
}
}
if (vm==null) throw 'Cannot find the VM ' + vmName + ' with moid ' + moid;
// Rename the VM and wait until is finished
var task = vm.rename_Task(newVmName);
System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task,null,null);
// Change the name on vRA properties
props.remove('VirtualMachineName');
props.put('VirtualMachineName', newVmName);
// This could be used to update any property in a vRA entity
var hostId = vmEntity.hostId;
var modelName = vmEntity.modelName;
var entitySetName = vmEntity.entitySetName;
var entityIdString = vmEntity.keyString;
System.getModule("com.vmware.library.vcac").updateVCACEntity(hostId,modelName,entitySetName,entityIdString,props,null,null);
I hope this could be useful for other people.
D.
This solution has worked for years. My only issue with it is that my vSphere team doesnt like the fact that the underlying artifacts (vmx, vmdk, folder, etc) are named with the hostname instead of the FQDN until a sVMotion is performed. What i ended up doing was exactly like jasnyder suggested just a bit more complex.
1. Create the VM with the FQDN
2. In the cloneMachine POST state, rename the VM to the hostname.
3. In the machineProvisoined state, rename the VM back to the FQDN.
It would be nice to have a custom property to feed to the customization spec to avoid all the run around.
Hello , In my case, we use the deployed VM's host name same with VM name. Now, our environment changed the option to get the host name input from custom properties and change the host name with user input one (not with VM name). I think my scenario is same like you. Could you please kindly mention about
I hope your answer.
Hi KoThwin,
The solution is exactly the one is marked as a correct answer. The Custom Property to ask for the name is "hostname" (is a shortcut).
The correct answer has all the steps you need to do.
Hello Damian,
Thanks for your explanation.
According to marked one(correct answer), I tried to configure the vRA setting like below screenshots.
But, I still get the errors associated with this error.
I hope you will see and give some advices for my case. Thanks
The way I do it is to name the VM what we want it to be named in the end, which in our case is the FQDN. The machine is built with the FQDN as the name, this ensures all related files have the same name as the VM. Then through a vRO workflow I rename the machine to what I want it named in the OS. My customization Spec is set to set the OS name the same as the VM name. Then once the customization spec has completed running i rename the VM back to what i want the VM named via another vRO workflow.
Hi KoThwin,
I cannnot see your screenshots. But you need to use "hostname" and a second custom property that you like for the Machine Name. When the deployment is finished, you need to change the name of the VM for the one specified in the second custom property.
If you set a name for hostname or Machine Name that already exists in vCenter, the Blueprint will raise an error.
D.
Hello Damian,
I have reattached the screenshot files on my original post.
My VM deployment scenario brief
--------------------------------------------
I have attached my customization specification also.
Thanks for continuous replying me.