VMware {code} Community
renriquez
Contributor
Contributor
Jump to solution

PHP5 implementation "nicsettings:adapter:ip Incorrect"

Hi Everyone,

For the last few months, I've been working on a PHP/NuSoap management system which utilizes the webservices API. Things have been working well so far...can get a list of active images, run power tasks on images, clone..etc...etc..etc..

Lately I've been going crazy with an issue with the CustomizeVM_Task. I suppose there could be malformed requests somewhere along the way but my code is simply getting the VirtualMachineCloneSpec by name, assigning the CustomizationSpec to a soap message and sending it along with a VM for Customization. However, the task will error with the message =>"A specified parameter was not correct. nicsettings:adapter:ip".

This cannot be the case as I use the exact same spec within the virtual infrasturucture client and cloning w/ the spec works just fine.

Does anyone have any suggestions? I could post additional code in here as well.

function CustomizeVM_Task($vmName, $configName) {
$vm = $this->FindVMByName($vmName); // custom function, verified to work..correct VM returned

unset($specmsg);
$specmsg[this] =  new soapval('_this', false, $this->session_result[customizationSpecManager], false, false, array("type" =>"CustomizationSpecManager"));
$specmsg[name] =  $configName;
$custom = $this->process("GetCustomizationSpec", $specmsg); // return of getCustomizationSpec also verified, OK 

unset($soapmsg);
$soapmsg[this] = new soapval('_this', false, $vm, false, false, array("type" => "VirtualMachine"));
$soapmsg[spec] = $custom[spec];
$task = $this->process("CustomizeVM_Task", $soapmsg); // at this point the task starts fine, but in the vCenter console the "nicsettings:adapter:IP" error is displayed. 

Reply
0 Kudos
1 Solution

Accepted Solutions
stumpr
Virtuoso
Virtuoso
Jump to solution

Yeah, the VMware SDK toolkits are aware when they're serializing a subclass entity (if its a subclass, it will set the type attribute so the SDK service is aware which child data structure its receiving. I've seen this issue with Python and PHP soap modules, which have no knowledge of the object hierarchies in the VIM SDK model.

As for the dnsServerList, the syntax is off from what the SDK wants to see. I don't think the issue is handling of xsd:string, which probably isn't even required in the XML syntax. I believe it would expect the following format (but I don't have a PHP setup to verify at the moment):

<dnsServerList>9.0.7.1</dnsServerList><dnsServerList>9.0.6.11</dnsServerList>

You may be able to create an array of soapvals (one soapval for each dns address). Basically you want to have the appropriate tag around the data (in this case dnsServerList ). I suspect you'll have this same issue for other array types when you serialize your XML request.

Reuben Stump | http://www.virtuin.com | @ReubenStump

View solution in original post

Reply
0 Kudos
9 Replies
stumpr
Virtuoso
Virtuoso
Jump to solution

Looks like a problem with the IP settings for the new VM. How's your customization spec setup? DHCP? You can try manually setting the ip property to CustomizationIpGenerator.

Reuben Stump | http://www.virtuin.com | @ReubenStump
Reply
0 Kudos
renriquez
Contributor
Contributor
Jump to solution

For our purposes, we are handling the IP address assignments through the backend, as DHCP is not an option for production environments. Here is a dump of the CustomizationSpec

I removed a few items as i'd rather not share those, they have values of *removed*

[options] => Array
	(
		[changeSID] => true
		[deleteAccounts] => false
	)

[identity] => Array
	(
		[guiUnattended] => Array
			(
				[password] => Array
					(
						[value] => **removed**
						[plainText] => false
					)

				[timeZone] => 20
				[autoLogon] => false
				[autoLogonCount] => 0
			)

		[userData] => Array
			(
				[fullName] => **removed**
				[orgName] => **removed**
				[computerName] => Array
					(
						[name] => aimcp211
					)

				[productId] => **removed**
			)

		[identification] => Array
			(
				[joinWorkgroup] => Workgroup
			)

		[licenseFilePrintData] => Array
			(
				[autoMode] => perServer
				[autoUsers] => 5
			)

	)

[globalIPSettings] => Array
	(
		[dnsSuffixList] => **removed**
	)

[nicSettingMap] => Array
	(
		[adapter] => Array
			(
				[ip] => Array
					(
						[ipAddress] => 9.3.75.211
					)

				[subnetMask] => 255.255.255.0
				[gateway] => Array
					(
						[0] => 9.3.75.1
						[1] => 
					)

				[dnsServerList] => Array
					(
						[0] => 9.0.7.1
						[1] => 9.0.6.11
					)

				[primaryWINS] => 
				[secondaryWINS] => 
			)

	)

Message was edited by: renriquez

Previous post was the dump of the contents of a CustomizationSpec I propagated through PHP. This post is updated with a version that was created with the VMware wizard and tested successfully with a clone and customize operation through the infrastructure client.

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

I have couple thoughts.

First, you have more NICs than just the one. I'm guessing its not that easy of a fix. Smiley Happy

Second, your PHP soap message may not be setting an xml attribute for the ip property node for the Customization type. For example, you should have an attribute type = CustomizationFixedIp. CustomizationIpGenerator However, there are other properties that may require that set upstream as well. It may just be the first one the fault request is complaining about.

You can probably test this easily enough by updating the CustomizationSpec ip property with a custom soapval that will use the CustomizationFixedIp string as a type attribute.

Reuben Stump | http://www.virtuin.com | @ReubenStump
renriquez
Contributor
Contributor
Jump to solution

I am currently working on the custom soapval, but I was wondering about your first point. Where were you seeing the additional adapters? Both the original and the clone should only have one NIC.

Thanks for your help.

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

I didn't see a second NIC, just making sure there wasn't one on your source VM. Sounds like you got that covered. Smiley Happy

Reuben Stump | http://www.virtuin.com | @ReubenStump
Reply
0 Kudos
renriquez
Contributor
Contributor
Jump to solution

OK, thanks for the tip, the definition of types helped remove all errors so I now have the CustomizeVM_Task working (code below). Rather than use existing specs, I found it easier just to generate the spec on the fly rather than go back and apply all the necessary types.

So far so good but two minor issues, definition of two dns servers and the encryption key. I think one solution will spill over to the other as well so for now I'll ignore the encryption key.

The code below works just fine for a single DNS but two are needed. I think my problem is I am not sure how to declare type "xsd:string[]". When I make an attempt to create multiple DNS Servers, this is the resulting soap message.

            <dnsServerList xsi:type="SOAP-ENC:Array"
            SOAP-ENC:arrayType="xsd:string[2]">
              <item xsi:type="xsd:string">9.0.7.1</item>
              <item xsi:type="xsd:string">9.0.6.11</item>
            </dnsServerList>

I do not think that is the proper format for the dnsServerList. Is there a specific format I should be shooting for here? Thanks for the guidance.

Code to generate spec for anyone else's reference.

	function generateSpec($key) {
		/*
		 * Windows Customization Options
		 */
		$winOptions[changeSID] = true;
		$winOptions[deleteAccounts] = false;
		$spec[options] = new soapval('options', false, $winOptions, false, false, array("xsi:type" => "CustomizationWinOptions"));

		/*
		 * Identity
		 */	
			$password[value] = "**encryptedPassword**";
			$password[plainText] = false;
		$guiUnattended[password] = $password;
		$guiUnattended[timeZone] = 20;				
		$guiUnattended[autoLogon] = true;
		$guiUnattended[autoLogonCount] = 1;	 
		$identity[guiUnattended] = new soapval('guiUnattended', false, $guiUnattended, false, false, array("xsi:type" => "CustomizationGuiUnattended"));

		$userData[fullName] = "AIMCP";
		$userData[orgName] = "AIMCP";
		$computerName[name] = "AIMCP211";
		$userData[computerName] = new soapval('computerName', false, $computerName, false, false, array("xsi:type" => "CustomizationFixedName"));		
		$userData[productId] = "**hiddenwindowskey**";
		$identity[userData] =  new soapval('userData', false, $userData, false, false, array("xsi:type" => "CustomizationUserData"));
		
		$identification[joinWorkgroup] = "AIMCP";
		$identity[identification] = new soapval('identification', false, $identification, false, false, array("xsi:type" => "CustomizationIdentification"));

		$licenseFilePrintData[autoMode] = "perServer";
		$licenseFilePrintData[autoUsers] = "5";
		$identity[licenseFilePrintData] = new soapval('licenseFilePrintData', false, $licenseFilePrintData, false, false, array("xsi:type" => "CustomizationLicenseFilePrintData"));
		$spec[identity] = new soapval('identity', false, $identity, false, false, array("xsi:type" => "CustomizationSysprep"));
		
		/*
		 * Global IP Settings
		 */
		$globalIPSettings[dnsSuffixList] = "**hiddendomain";
		$spec[globalIPSettings] = new soapval('globalIPSettings', false, $globalIPSettings, false, false, array("xsi:type" => "CustomizationGlobalIPSettings"));
			
		/*
		 * NIC SETTINGS
		 */
		$ip[ipAddress] = "9.3.75.211";
		$adapter[ip] = new soapval('ip', false, $ip, false, false, array("xsi:type" => "CustomizationFixedIp"));
		$adapter[subnetMask] = "255.255.255.0";
                //does not work with multiple DNS
		//$adapter[dnsServerList] = new soapval('dnsServerList', "xsd:string", array("9.0.7.1", "9.0.6.11"), false, false, false);	

                //single fine
		$adapter[dnsServerList] = "9.0.7.1";		
		$adapter[gateway] = "9.3.75.1";		
		$nicSettingMap[adapter] = new soapval('adapter', false, $adapter, false, false, array("xsi:type" => "CustomizationIPSettings"));
		$spec[nicSettingMap] = new soapval('nicSettingMap', false, $nicSettingMap, false, false, array("xsi:type" => "CustomizationAdapterMapping"));
		$spec[encryptionKey] = $key;

		return new soapval('spec', false, $spec, false, false, array("xsi:type" => "CustomizationSpec"));
	}
	

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

Yeah, the VMware SDK toolkits are aware when they're serializing a subclass entity (if its a subclass, it will set the type attribute so the SDK service is aware which child data structure its receiving. I've seen this issue with Python and PHP soap modules, which have no knowledge of the object hierarchies in the VIM SDK model.

As for the dnsServerList, the syntax is off from what the SDK wants to see. I don't think the issue is handling of xsd:string, which probably isn't even required in the XML syntax. I believe it would expect the following format (but I don't have a PHP setup to verify at the moment):

<dnsServerList>9.0.7.1</dnsServerList><dnsServerList>9.0.6.11</dnsServerList>

You may be able to create an array of soapvals (one soapval for each dns address). Basically you want to have the appropriate tag around the data (in this case dnsServerList ). I suspect you'll have this same issue for other array types when you serialize your XML request.

Reuben Stump | http://www.virtuin.com | @ReubenStump
Reply
0 Kudos
Carmageddon
Contributor
Contributor
Jump to solution

Hi, I have noticed you've got the guest Customization options figured out (as I see below).

I would like to do something similar - basically all I need is to change the password of the administrator when I call vmclone.pl (vmware's application).

For that, I need to feed it XML file with the specification for that (and probably XSD file as well).

However my problem is, I have not found a complete documentation for all the customization options - how exactly to define them in XML and XSD files?

Inferring from your example, I would think its something like:

<identity>
  <password>abc</password>
  <plainText>true</plainText>
</identity>

Would this be correct? if so who would be the parent of identity in the XML?

Also what is the

guiUnattended[password]

attribute for?

Thanks!

Code to generate spec for anyone else's reference.

> 	function generateSpec($key) {
> 		/*
> 		 * Windows Customization Options
> 		 */
> 		$winOptions[changeSID] = true;
> 		$winOptions[deleteAccounts] = false;
> 		$spec[options] = new soapval('options', false, $winOptions, false, false, array("xsi:type" => "CustomizationWinOptions"));
> 
> 		/*
> 		 * Identity
> 		 */	
> 			$password[value] = "**encryptedPassword**";
> 			$password[plainText] = false;
> 		$guiUnattended[password] = $password;
> 		$guiUnattended[timeZone] = 20;				
> 		$guiUnattended[autoLogon] = true;
> 		$guiUnattended[autoLogonCount] = 1;	 
> 		$identity[guiUnattended] = new soapval('guiUnattended', false, $guiUnattended, false, false, array("xsi:type" => "CustomizationGuiUnattended"));
> 

> 	
> 

Reply
0 Kudos
renriquez
Contributor
Contributor
Jump to solution

Ok, I finally got the DNS Settings figured out, I'll update the post with the newer code once I get back on my dev machine. As far as the question above...

To answer you immediate question I believe the xml looks like..also note the password on the original VM must be blank for password change to work!

     <identity>
          <guiUnattended>
            <password>
              <value">**the password**</value>
              <plainText>1</plainText>
            </password>
            <timeZone>20</timeZone>
            <autoLogon>0</autoLogon>
            <autoLogonCount>0</autoLogonCount>
          </guiUnattended>
     </idenitity>

...although I thought there was a need for <_type> xml in there also...not positive.

For a long answer answer.....

http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.customization.Specifi...

If you start there and work your way down the rabbit hole, you'll get a perspective on how the XML should look, here is the spec part of the soap message to customize a vm. Some of these are mandatory, so although you are only changing the password, I believe the soap message wants it even it is blank.

    <spec xsi:type="CustomizationSpec">
        <options xsi:type="CustomizationWinOptions">
          <changeSID xsi:type="xsd:boolean">1</changeSID>
          <deleteAccounts xsi:type="xsd:boolean">0</deleteAccounts>
        </options>
        <identity xsi:type="CustomizationSysprep">
          <guiUnattended xsi:type="CustomizationGuiUnattended">
            <password>
              <value xsi:type="xsd:string">**the password**</value>
              <plainText xsi:type="xsd:boolean">1</plainText>
            </password>
            <timeZone xsi:type="xsd:int">20</timeZone>
            <autoLogon xsi:type="xsd:boolean">0</autoLogon>
            <autoLogonCount xsi:type="xsd:int">0</autoLogonCount>
          </guiUnattended>
          <userData xsi:type="CustomizationUserData">
            <fullName xsi:type="xsd:string">***********</fullName>
            <orgName xsi:type="xsd:string">***********</orgName>
            <computerName xsi:type="CustomizationFixedName">
              <name xsi:type="xsd:string">**hostname**</name>
            </computerName>
            <productId xsi:type="xsd:string">****windows key*******</productId>
          </userData>
          <identification xsi:type="CustomizationIdentification">
            <joinWorkgroup xsi:type="xsd:string">***********</joinWorkgroup>
          </identification>
          <licenseFilePrintData xsi:type="CustomizationLicenseFilePrintData">

            <autoMode xsi:type="xsd:string">perServer</autoMode>
            <autoUsers xsi:type="xsd:string">5</autoUsers>
          </licenseFilePrintData>
        </identity>
        <globalIPSettings xsi:type="CustomizationGlobalIPSettings">
          <dnsSuffixList xsi:type="xsd:string">***********</dnsSuffixList>
        </globalIPSettings>
        <nicSettingMap xsi:type="CustomizationAdapterMapping">
          <adapter xsi:type="CustomizationIPSettings">
            <ip xsi:type="CustomizationFixedIp">
              <ipAddress xsi:type="xsd:string">***********</ipAddress>
            </ip>
            <subnetMask xsi:type="xsd:string">*********** </subnetMask>
            <gateway xsi:type="xsd:string">*********** </gateway>
            <dnsServerList xsi:type="xsd:string">*********** </dnsServerList>
            <dnsServerList xsi:type="xsd:string"> ***********</dnsServerList>
          </adapter>
        </nicSettingMap>
    </spec>

Reply
0 Kudos