Donnerstag, 27. Juni 2013

PowerShell: export XML content to text file (SCCM Configuration Item)

Hi,
this is one of my favourites scripts i did for SCCM, to manage Desired Configuration Management in a better way, and it was lost for a long time. It helps you to get settings extracted out of an SCCM configurtation item XML-File. Maybe you got some ".cab" files and want to know what settings are in there without using a tool which cannot export those data to a text file or an excel sheet.
What this script does is very simple, it reads the content of an xml file and creates an XML objects which can be used in powershell.

$path = "D:\xml-output.txt" #the text file you want to create
"New file" > $path
$myxml = [XML](get-content "D:\xml-file.xml")
$settings = $myxml.DesiredConfigurationDigest.BusinessPolicy.settings.rootcomplexsetting.ComplexSetting | foreach-object {$_.simplesetting}
"#############################################################################"  >> $path
" All Settings"  >> $path
"#############################################################################"  >> $path
$settings | %{$_.Rules.Rule} | select LogicalName,Operation,OperandA | ft -Property * -AutoSize | Out-String -Width 4000 >> $path
"#############################################################################"  >> $path
"Registry Values"  >> $path
$settings | %{$_.RegistryDiscoverySource} | ft -Property * -AutoSize | Out-String -Width 4000 >> $path
"#############################################################################"  >> $path
"WMI Entries"  >> $path
$settings | %{$_.WqlQueryDiscoverySource} | ft -Property * -AutoSize | Out-String -Width 4000   >> $path
This one is a very specific script for SCCM, but you can edit it and change it to your needs.

Customizing the output that it fits into a table can be done in different ways. The method I used in this example is described here: http://poshoholic.com/2010/11/11/powershell-quick-tip-creating-wide-tables-with-powershell/

Donnerstag, 20. Juni 2013

Problem with VcGuestProcessManager and different vCenter Versions

Hey,
this week we encountered a strange behavior of the scripting class VcGuestProcessManager, which should run a script on virtual machine using its method startProgramInGuest.
The vCO setup is designed to manage two different vCenters (5.0 and 5.1) this does work with the most scriting classes. If you try to run this from a vCO hosted on vCenter 5.0 and try to run a program on virtual machine hosted on vCenter 5.1 it will fail.

The german error message is this one:

Der Vorgang wird für dieses Objekt nicht unterstützt. (Workflow: RunProgramOnGuest / Scriptable task (item0)#22)
In english it is something like that:
The process is not supported to this object
This is roughly translated :D

We figured out that the vCenter version, the vCO is hosted on, has to be the same version as the vCenter version , where the virtual machines is hosted.
 

Sonntag, 16. Juni 2013

vCenter Orchestrator: Mount ISO image into virtual CDrom

Hey there,
it's Sunday and nothing to do, so I decided to solve a task which was ignored for a long time.

The task is to mount an ISO image to a virtual pc, maybe to deploy virtual machines and configure them with prepared images of SCCM for example. I could imagine many use cases to automtically mount images to many machines.
Anyway, I created 3 scripts to find the CD drive, find the correct ISO file at your datastore and finally mount it.

Part 1: find the ISO and its path.

vCO expects a path like : "[datastore1] ISOs/Win8Alpha1.iso"

var ISOpaths = new Array(); //if you have more then one ISO file
var fileQuery = new Array(new VcIsoImageFileQuery());
var querySpec = new VcHostDatastoreBrowserSearchSpec();
querySpec.query = fileQuery;
var myISO = "Win8.iso"; //the ISO you are looking for
var myISOtemp = null; //temp parameter, it is just use to cut the string
var myISOpath = null; // your final path

var task = datastore.browser.searchDatastoreSubFolders_Task("[" + datastore.name + "]", querySpec);
var searchResults = System.getModule("com.vmware.library.vc.basic").vim3WaitTaskEnd(task,false,5);
for (var i in searchResults) {
for (var j in searchResults[i].file) {
ISOpaths.push(searchResults[i].folderPath + searchResults[i].file[j].path);
}
}
for (k in ISOpaths)
{
myISOtemp = ISOpaths[k].substring(ISOpaths[k].search("] ")+2,300)
myISOtemp = myISOtemp.substring(myISOtemp.search("/")+1,300)
System.log(myISOtemp);
if(myISOtemp == "Win8.iso" )
{
myISOpath = ISOpaths[k];
System.log("found :" + myISOpath);
break;
}
}
//http://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.host.DatastoreBrowser.FileInfo.html

Ok that's the script to find the ISO file, you are free to modify this to your own needs. Maybe you have serveral datastores with the same ISO file or different vCenters.

Part 2: Get the CD drive

This is easy, so there are no comments or explanations needed.

var devices = vm.config.hardware.device;

for ( i in devices )  {
if ( devices[i] instanceof VcVirtualCdrom )  {
System.log("Key: " + devices[i].key);
System.log("Label: " + devices[i].deviceInfo.label);
System.log("controllerKey: " + devices[i].controllerKey);
System.log("unitNumber: " + devices[i].unitNumber);
System.log (devices[i]); // will return the scripting class
}
}
Every information you need for part 3 is in there.

Part 3: Mount the ISO image

var spec = new VcVirtualMachineConfigSpec();
var deviceChange = new Array (new VcVirtualDeviceConfigSpec());
var VirtualDeviceConfigSpec = new VcVirtualDeviceConfigSpec();
//http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.vm.device.VirtualDevice.html
VirtualDeviceConfigSpec.operation = VcVirtualDeviceConfigSpecOperation.edit;
var device = new VcVirtualCdrom();
device.key = 3002; //this could be an input parameter
deviceInfo = new VcDescription();
deviceInfo.label = "CD/DVD drive 1";
deviceInfo.summary = "ISO";
device.deviceInfo = new VcDescription();
device.deviceInfo = deviceInfo;
device.controllerKey = 201; //this could be an input parameter
device.unitNumber = 0; //this could be an input parameter
var CdromIsoBackingInfo = new VcVirtualCdromIsoBackingInfo();
CdromIsoBackingInfo.fileName = myISOpath;
var DeviceConnectInfo = new VcVirtualDeviceConnectInfo();
DeviceConnectInfo.startConnected = false;
DeviceConnectInfo.allowGuestControl = true;
DeviceConnectInfo.connected = true;
DeviceConnectInfo.status = "untried";

VirtualDeviceConfigSpec.device = new VcVirtualCdrom();
VirtualDeviceConfigSpec.device = device;

VirtualDeviceConfigSpec.device.backing = CdromIsoBackingInfo;
VirtualDeviceConfigSpec.device.connectable = DeviceConnectInfo;
deviceChange[0] = VirtualDeviceConfigSpec;
spec.deviceChange = deviceChange;
task = vm.reconfigVM_Task(spec);  //task is an output parameter if you want to start a waiting task
The only important thing you have to know is that when you want to add an attribute which is also an object you cannot do something like this: "device.deviceInfo.label" DeviceInfo has to defined before you add a values.

If you have questions, send me an email or post a commend.