Showing posts with label vmware. Show all posts
Showing posts with label vmware. Show all posts

Tuesday, November 8, 2011

ESX or Linux update Automation for windows users: su root and password

Today, I improved an old post. (I recommend you to read it before this post)
These scripts work correctly but for security reasons I could not use this work. Indeed, we must log before with an user then su in root. Moreover, with these previous scripts, that was not possible to transfert any other files like binaries files. So I decided to work on this problem to avoid to manually update 150 esx.
Sure, some trick exist like "expect" (not included in esx) or cpan perl expect, but it was simpliest to me to improve my scripts.

To use my scripts, just create a file yourfile.zip containing a script yourfile.sh and all needed files
process of these scripts:
script use a computer listing file (here servers.txt file) including all your computers you need to update
Script upload on your esx or linux computers yourfile.zip to /tmp directory, then decompress yourfile.zip and run yourfile.sh file

In update_esx_v2.zip, I give you a script example which permit you to update ESX with 2 patchs
[EDIT 15 february 2012] I re-upload zip file and add some informations in this post

In update.zip, file update.sh script contains all commands to do update
#!/bin/sh
# Update
cd ESX350-201012404-BG/
esxupdate --nosig update
cd ..
cd ESX350-201012410-BG/
esxupdate --nosig update
cd ..
In update.zip, there is also all necessary files used by update.sh

update\
update\update.sh
update\ESX350-201012404-BG\
update\ESX350-201012404-BG\contents.xml
update\ESX350-201012404-BG\contents.xml.sig
update\ESX350-201012404-BG\descriptor.xml
update\ESX350-201012404-BG\VMware-esx-scripts-3.5.0-317866.i386.rpm
update\ESX350-201012404-BG\headers\
update\ESX350-201012404-BG\headers\contents.xml
update\ESX350-201012404-BG\headers\contents.xml.sig
update\ESX350-201012404-BG\headers\header.info
update\ESX350-201012404-BG\headers\VMware-esx-scripts-0-3.5.0-317866.i386.hdr
update\ESX350-201012410-BG\
update\ESX350-201012410-BG\contents.xml
update\ESX350-201012410-BG\contents.xml.sig
update\ESX350-201012410-BG\descriptor.xml
update\ESX350-201012410-BG\vmware-keying-data-1-20100930.noarch.rpm
update\ESX350-201012410-BG\headers\
update\ESX350-201012410-BG\headers\contents.xml
update\ESX350-201012410-BG\headers\contents.xml.sig
update\ESX350-201012410-BG\headers\header.info
update\ESX350-201012410-BG\headers\vmware-keying-data-0-1-20100930.noarch.hdr



Now, you can run "run_update.cmd" which run your updates with user esxadmin
(only if this user can do all that you want - if user to connect your esx is not esxadmin change line with set usern=esxadmin)
@echo off
set usern=esxadmin
set zipfile=update.zip
set computerfile=servers.txt

if "%1"=="" goto :nopass
set password=%1

cscript //nologo update_esx.vbs %computerfile% %zipfile% %usern% %password%
goto :eof

:nopass
echo you need a password for user %usern%
goto :eof

To run your update with user esxadmin then su root
@echo off
set usern=esxadmin
set userroot=root
set zipfile=update.zip
set computerfile=servers.txt

if "%1"=="" goto :nopass
if "%2"=="" goto :nopass2
set password=%1
set pwdroot=%2

cscript //nologo update_esx.vbs %computerfile% %zipfile% %usern% %password% %userroot% %pwdroot%
goto :eof

:nopass
echo you need a password for user %usern%
goto :eof

:nopass2
echo you need a password for user %userroot% 
goto :eof

all computers to update are in file servers.txt below
computer1
computer2
computer3

Main script update_esx.vbs that permit to transfert and decompress "yourfile.zip" and execute "yourfile.sh" on your linux or esx
'
' update_esx.vbs
'
' by F.RICHARD
'
' v1.00 2007 Nov - Initial release
' v1.01 2008 Jan - Display Standard output
' v2.00 2011 Nov - Modify script to use and send ZIP file
'
Option Explicit

Const ForReading = 1
Const ForWriting = 2

'
' Detect WScript or CScript
'
If InStr(LCase(WScript.FullName), "wscript")>0 Then  ' ex: FullName = C:\WINNT\system32\wscript.exe 
 WScript.Echo "This script must be run under CScript."
 WScript.Quit
End If

'
' Get Command Line Args
'
Dim Args
Set Args = Wscript.Arguments
If Args.Count < 4 Then
 Wscript.Echo "Syntax : " & WScript.ScriptName & " input_computer_list_file zip_file_to_send_uncompress_and_execute user password"
 Wscript.Echo "Syntax : " & WScript.ScriptName & " input_computer_list_file zip_file_to_send_uncompress_and_execute user password [root] [root password]"
 Wscript.Echo "         Example : cscript " & WScript.ScriptName & " servers.txt myfile.zip user password"
 Wscript.Echo "         Example : cscript " & WScript.ScriptName & " servers.txt myfile.zip user password root rootpass"
 Wscript.Echo ""
 Wscript.Echo "computer_list_file: line begin by # or ; indicate start of a comment, everything after is ignored"
 Wscript.Echo ""
 Wscript.Quit
End If


' Args(0) = computer list
Dim strInputList
strInputList = Trim(args(0))

' Args(1) = zip file to send and execute
Dim strScriptToExecute, strCompressFile, strDirectory, strCompressFileExt
strCompressFile = Trim(args(1))
strCompressFileExt = Right(strCompressFile, Len(strCompressFile)-InStr(1, strCompressFile, ".") )
If (StrComp(strCompressFileExt, "zip", vbTextCompare) <> 0) Then
 WScript.Echo "File to send: '" & strCompressFile & "'is not a .zip file"
 WScript.Quit
End If
strDirectory = Left(strCompressFile, InStr(1, strCompressFile, ".")-1)
strScriptToExecute = strDirectory & ".sh"

' Args(2) = user
Dim strUser
strUser = Trim(args(2))

' Args(3) = password
Dim strPassword
strPassword = Trim(args(3))

' Args(4) = root name
' Args(5) = root password
Dim strRootPassword, strRootName
If Args.Count > 5 Then
 strRootName = Trim(args(4))
 strRootPassword = Trim(args(5))
End If


'
' Get Path
'
Dim strScriptFullName, strScriptPath
strScriptFullName = WScript.ScriptFullName ' ex: C:\Program Files\MyFolder\MyProg.exe
strScriptPath = Left(strScriptFullName, InStrRev(strScriptFullName, "\") - 1) ' ex: C:\Program Files\MyFolder

Dim objFso
Set objFso = CreateObject("Scripting.FileSystemObject")


'
' Test If all Files Exist
'
If Not isFileExist(strInputList) Then
 strInputList = strScriptPath & "\" & strInputList
 If Not isFileExist(strInputList) Then
  WScript.Echo "Computer list:" & strInputList & " File Not Exist !"
  WScript.Quit
 End If   
End If   
WScript.Echo "Computer list:" & strInputList & " File Exist"

If Not isFileExist(strCompressFile) Then
 strCompressFile = strScriptPath & "\" & strCompressFile
 If Not isFileExist(strCompressFile) Then
  WScript.Echo "Compress file:" & strCompressFile & """" & " File Not Exist !"
  WScript.Quit
 End If   
End If   
WScript.Echo "Script to uncompress:" & strCompressFile & " File Exist"

Dim strPlink
strPlink= strScriptPath & "\" & "plink.exe"
If Not isFileExist(strPlink) Then
 WScript.Echo "PuTTY Link:" & strPlink & " File Not Exist !"
 WScript.Quit
End If     
WScript.Echo "PuTTY Link:" & strPlink & " File Exist"

Dim strPscp
strPscp= strScriptPath & "\" & "pscp.exe"
If Not isFileExist(strPscp) Then
 WScript.Echo "PuTTY Secure Copy client:" & strPscp & " File Not Exist !"
 WScript.Quit
End If     
WScript.Echo "PuTTY Secure Copy client:" & strPscp & " File Exist"


Dim objShell, ComSpec
Set objShell = CreateObject( "WScript.Shell" )
ComSpec=objShell.ExpandEnvironmentStrings("%ComSpec%")

'
' Read computer list file into dictionary
'
Dim objDictionary, return
return = ReadFileToDict(strInputList, objDictionary)
If return = 0 Then
 WScript.Echo "Error during computer list file read"
 WScript.Quit
End If


'
' Generate .sh file to execute
'
Dim strContent, strScriptToDecFile
strScriptToDecFile = "decfile.sh"
strContent = "#!/bin/sh" & vbLf & _
 "# Unzip " & strCompressFile & " then enter in " & strDirectory & " directory and execute " & strScriptToExecute & " file" & vbLf & _
 "cd /tmp" & vbLf & _
 "unzip -o " & strCompressFile & vbLf
return = WriteStrToFile(strScriptToDecFile, strContent)


' Display file
Dim objItem, strServer, objCmd, strCmdline, continue, strGenerateKey
For Each objItem in objDictionary
 strServer = objDictionary.Item(objItem)
 Wscript.Echo ""
 WScript.Echo "Server:" & strServer
 
 ' Test Connection
 strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " " & strUser & "@" & strServer & " pwd "
 strGenerateKey = ComSpec & " /c echo y | """ & strPlink & """ " & strServer & " -pw " & strPassword & " " & strUser

 WScript.Echo "Test Connection on server " & strServer
 return = DoConnection(strCmdline, strGenerateKey, strServer, True)

 If (return > 0) Then
  strGenerateKey=""
  Do
   WScript.Echo "Re-verify Connection on server " & strServer
   return = DoConnection(strCmdline, strGenerateKey, strServer, True)
  Loop While (return > 0 and return < 255)
  If (return > 0) Then
   WScript.Echo "Transfer " & strScriptToDecFile & " script on server " & strServer
   strCmdline = ComSpec & " /c """ & strPscp & """ -batch -C -pw " & strPassword & " " & strScriptToDecFile & " " & strUser & "@" & strServer & ":/tmp"
   return = DoConnection(strCmdline, strGenerateKey, strServer, True)

   WScript.Echo "Transfer " & strCompressFile & " script on server " & strServer
   strCmdline = ComSpec & " /c """ & strPscp & """ -batch -C -pw " & strPassword & " " & strCompressFile & " " & strUser & "@" & strServer & ":/tmp"
   return = DoConnection(strCmdline, strGenerateKey, strServer, True)

   WScript.Echo "Execute " & strScriptToDecFile & " script on server " & strServer
   strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " " & strUser & "@" & strServer & " " & "cd /tmp; sh " & strScriptToDecFile
   return = DoConnection(strCmdline, strGenerateKey, strServer, True)

   ' if root / or not root
   If Args.Count > 5 Then

    objShell.Run "putty.exe -ssh " & strUser & "@" & strServer
    WScript.Sleep 5000
    objShell.AppActivate strServer & " - PuTTY"
    WScript.Sleep 5000
    objShell.SendKeys "" &  strPassword & "{ENTER}"
    WScript.Sleep 5000     
    objShell.SendKeys "su - " & strRootName & "{ENTER}"
    WScript.Sleep 5000     
    objShell.SendKeys "" & strRootPassword & "{ENTER}"
    WScript.Sleep 5000     
    objShell.SendKeys "cd /tmp/" & strDirectory & "; sh " & strScriptToExecute & "{ENTER}"
    WScript.Sleep 5000     
   Else
    WScript.Echo "Execute " & strScriptToExecute & " script on server " & strServer
    strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " " & strUser & "@" & strServer & " " & "cd /tmp/" & strDirectory & "; sh " & strScriptToExecute
    return = DoConnection(strCmdline, strGenerateKey, strServer, True)
   End If
  End If
 End If

Next



'
' Quit
'
WScript.Sleep 1000
WScript.Quit

'--------------------

' DoConnection
'
' 
'
Function DoConnection(strCmdline, strGenerateKey, strServer, displayLogfile)
 Dim objCmd, return, Continue

 'WScript.Echo "cmdline->" & strCmdline
 Set objCmd = objShell.Exec(strCmdline)
 Do While objCmd.Status = 0
  return = objCmd.stdErr.ReadAll
  WScript.Sleep 100
 Loop
 If (displayLogfile) Then
  Dim strStdOut
  strStdOut = objCmd.StdOut.ReadAll()
  If (len(strStdOut) > 0) Then
   Wscript.Echo strStdOut
  End If
 End If

 continue = 0
 If Instr(return, "Access denied" ) > 0 Then ' Access denied
  WScript.Echo "ERROR on server " & strServer & vbCrLf & return
  continue = 0

 Elseif Instr(return, "Unable to open connection" ) > 0 Then ' Unable to open connection
  WScript.Echo "ERROR on server " & strServer & vbCrLf & return
  continue = 0

 Elseif Instr(return, "ERROR" ) > 0 Then ' FATAL ERROR: Network error: Connection timed out
  WScript.Echo "ERROR on server " & strServer & vbCrLf & return
  continue = 0

 Elseif Instr(return, "fingerprint" ) > 0 Then
  If (len(strGenerateKey) > 2) Then
   WScript.Echo "GENERATE key fingerprint on server " & strServer
   'WScript.Echo "generatekey->" & strGenerateKey
   objShell.Exec(strGenerateKey)
   continue = 1
  Else
   WScript.Echo "NOT GENERATE key fingerprint " & strServer
   continue = 2
  End If
 Else
  continue = 255
  'WScript.Echo "Logged on " & strServer & " - " & return
 End if

 DoConnection = continue
End Function



'--------------------

' isFileExist
'
' Test if File Exist
'
Function IsFileExist(strInputFile)
 Dim objFSO
 Set objFSO = CreateObject("Scripting.FileSystemObject")
 If Not objFSO.FileExists(strInputFile) Then
  Wscript.echo strInputFile & " file not exist !"
  IsFileExist = False
 Else
  IsFileExist = True
 End If
End Function


'--------------------

' ReadFileToDict
'
' Read each line -> put in Dictionary
' strInputfile = file to read
' objDictionary = dictionary for results
'
Function ReadFileToDict(strInputFile, ByRef objDictionary)
 Dim objFSO, objTextFile, strNextLine, i
 Set objDictionary = CreateObject("Scripting.Dictionary")
 Set objFSO = CreateObject("Scripting.FileSystemObject")
 If isFileExist(strInputFile) Then
  Set objTextFile = objFSO.OpenTextFile(strInputFile, ForReading)
  i = 0
  Do Until objTextFile.AtEndOfStream
   strNextLine = Trim(objTextFile.Readline)
   If ( (Not Left(strNextLine, 1) = "#") _
    and (Not Left(strNextLine, 1) = ";") _
    and (Len(strNextLine)>1) _
    ) Then
    objDictionary.Add i, strNextLine
    i = i + 1
   End If
  Loop
  objTextFile.Close
  ReadFileToDict = True
 Else
  ReadFileToDict = False
 End If
End Function


'--------------------

' WriteStrToFile
'
' Write string to file
' strOutputFile = file to write
' strContent = string to write
'
Function WriteStrToFile(strOutputFile, ByRef strContent)
 Dim objFSO, objTextFile
 Set objFSO = CreateObject("Scripting.FileSystemObject")
 Set objTextFile = objFSO.CreateTextFile(strOutputFile, True)  ' delete file
 objTextFile.Write(strContent)
 objTextFile.Close
End Function


'--------------------

Wednesday, June 29, 2011

Find your VMware local VMFS datastore with powershell

To find your local VMFS datastore

Solution 1: name all your local vmfs LOCAL_xxx
Get all your local datastore by using
Get-Datastore | Get-View | Where-Object { $_.Name -match "LOCAL_*" } | Select-Object  @{n="Name";e={$_.Name}}}

Name
----
LOCAL_ESX01
LOCAL_ESX02
LOCAL_ESX03



Solution 2: use MultipleHostAccess info from Get-Datastore
(Thanks to http://blogs.vmware.com/vipowershell/2009/08/how-to-list-datastores-that-are-on-shared-storage.html?cid=6a00d8341c328153ef0120a52e7f0b970b for MultipleHostAccess tip)
You can use this:
Get-Datastore | Get-View | Select-Object  @{n="Name";e={$_.Name}}, @{n="San_Nas";e={$_.Summary.MultipleHostAccess}}

Name San_Nas
---- -------
NFS_VOL2 True
LOCAL_ESX01 False
NFS_VOL1 True
LOCAL_ESX02 False
LOCAL_ESX03 False



Solution 3: use Vendor / Model SCSILun informations from VMHost get-view
Get-VMHost | Get-View | Foreach-Object { $vmhost=$_.Name; $_.Config.StorageDevice.ScsiLun |  Select-Object @{n="Hostname";e={$vmhost}},@{n="Model";e={$_.Model}},@{n="Vendor";e={$_.Vendor}} }


Hostname Model Vendor
-------- ----- ------
esx01 LOGICAL VOLUME HP
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx01 SYMMETRIX EMC
esx02 RAID 5 DGC
esx02 SYMMETRIX EMC
esx02 SYMMETRIX EMC
esx02 RAID 5 DGC
esx03 LOGICAL VOLUME HP
esx03 2810XIV IBM
esx03 2810XIV IBM
esx03 2810XIV-LUN-0 IBM
esx03 2810XIV IBM



Example of SAN vendor/model
Vendor / Model
VMware / Block device
EMC / SYMMETRIX
IBM / 2810XIV

Example of Local storage
Vendor / Model
HP / LOGICAL VOLUME
DGC / RAID 5

Friday, June 17, 2011

Optimize your vmware powershell: part 1 - Get-Datacenter

Remember Get-Datacenter | Get-View = Get-View -ViewType Datacenter
For better performance, use
Get-View -ViewType
Use "-Property property1,property2,property3" switch if you don't need all properties. Less data to take = better performance too.

Execution time results after the execution of some commands:

Command

seconds

Get-View -ViewType Datacenter -Property Name

0,093652985

Get-View -ViewType Datacenter

0,128286732

Get-Datacenter

0,190378198

Get-Datacenter | Get-View

0,241663792

Get-View -ViewType Datacenter -Property Name | Foreach-Object { Get-VIObjectByVIView $_.MoRef }

0,296987547

Get-View -ViewType Datacenter | Foreach-Object { Get-VIObjectByVIView $_.MoRef

0,342440257



Get-Datastore fields and its equivalent fields with Get-View

Command

Equivalent Fields

$dc0 = Get-Datacenter | Where-Object { $_.Name -eq "Datacenter_1" }

$dc1 = Get-View -ViewType Datacenter | Where-Object { $_.Name -eq "Datacenter_1" }

$dc0.ExtensionData

$dc1

$dc0.Name

$dc1.Name

$dc0.Id

$dc1.MoRef

$dc0.ParentFolderId

$dc1.Parent

$dc0.CustomFields

[Array] $arrFields = @()
$dc1 | Foreach-Object {
$datacenter = $_
$datacenter.AvailableField | Foreach-Object {
$availablefield = $_
$Key = $availablefield.Name
$Value = ($datacenter.CustomValue | Where-Object { $_.Key -eq $availablefield.Key}).Value

$objParent = New-Object PSObject
$objParent | Add-Member -MemberType noteproperty -Name "Key" -Value $key
$objParent | Add-Member -MemberType noteproperty -Name "Value" -Value $value
$arrFields += $objParent
}
}

$arrFields

Another way to improve your scripts: use -Filter switch when you want specific data. Some lines can also be better than 1 cmdlets , but it's not always the case (see below)

Command

seconds

#Equivalent

#Get-Datacenter -Name Datacenter_2

Get-View -ViewType Datacenter -Filter @{"Name"="Datacenter_2"}

0,11421332

#Equivalent

#Get-Datacenter -Name Datacenter_2

Get-View -ViewType Datacenter | Where-Object { $_.Name -eq "Datacenter_2" }

0,13915101

Get-Datacenter -Name Datacenter_2

0,18590567

Get-Datacenter -Id Datacenter-datacenter-3472

0,18141816

Get-Datacenter -Cluster Cluster_2

0,37470311

#Equivalent

# Get-Datacenter -Cluster Cluster_2

$cluster=" Cluster_2"

$parent = (Get-View -ViewType ComputeResource -Filter @{"Name"=$cluster} -Property Parent).Parent.ToString()

While ($parent.ToString().Substring(0,5).ToUpper() -ne "DATAC") {

$parent = (Get-View -ViewType Folder -Property Parent | Where-Object { $_.MoRef.ToString() -eq $parent}).Parent.ToString()

}

Get-Datacenter -Id $parent

0,4999502

Get-Datacenter -VMHost ESX01

0,8159789

#Equivalent

# Get-Datacenter -VMHost ESX01

$parent = (Get-View -ViewType HostSystem -Filter @{"Name"=" ESX01"} -Property Parent).Parent.ToString()

If ($parent.ToString().Substring(0,5).ToUpper() -eq "CLUST") {

$parent = (Get-View -ViewType ComputeResource -Property Parent | Where-Object { $_.MoRef.ToString() -eq $parent}).Parent.ToString()

}

While ($parent.ToString().Substring(0,5).ToUpper() -ne "DATAC") {

$parent = (Get-View -ViewType Folder -Property Parent | Where-Object { $_.MoRef.ToString() -eq $parent}).Parent.ToString()

}

Get-Datacenter -Id $parent

0,7234534

#Equivalent

# Get-Datacenter -VM VM01

$vm=" VM01"

$parent = (Get-View -ViewType VirtualMachine -Filter @{"Name"=$vm} -Property Parent).Parent.ToString()

While ($parent.ToString().Substring(0,5).ToUpper() -ne "DATAC") {

$parent = (Get-View -ViewType Folder -Property Parent | Where-Object { $_.MoRef.ToString() -eq $parent}).Parent.ToString()

}

Get-Datacenter -Id $parent

0,6182902

Get-Datacenter -VM VM01

5,26492918



Some cmdlets result properties

[vSphere PowerCLI]> Get-Datacenter | select *

ParentFolderId : Folder-group-d1
ParentFolder : Datacenters
CustomFields : {}
ExtensionData : VMware.Vim.Datacenter
Id : Datacenter-datacenter-3472
Name : Datacenter_2
Uid : /VIServer=@localhost:443/Datacenter=Datacenter-datacenter-3472/

ParentFolderId : Folder-group-d1
ParentFolder : Datacenters
CustomFields : {}
ExtensionData : VMware.Vim.Datacenter
Id : Datacenter-datacenter-10
Name : Datacenter_1
Uid : /VIServer=@localhost:443/Datacenter=Datacenter-datacenter-10/


[vSphere PowerCLI]> Get-View -ViewType Datacenter


VmFolder : Folder-group-v11
HostFolder : Folder-group-h12
DatastoreFolder :
NetworkFolder :
Datastore : {Datastore-datastore-123, Datastore-datastore-233, Datastore-datastore-235, Datastore-datastore-237...}
Network : {Network-network-1634, Network-network-1636, Network-network-6006, Network-network-3456...}
Parent : Folder-group-d1
CustomValue : {}
OverallStatus : gray
ConfigStatus : gray
ConfigIssue : {}
EffectiveRole : {-1}
Permission : {113, 113, -5, -2...}
Name : Datacenter_1
DisabledMethod : {}
RecentTask : {}
DeclaredAlarmState : {alarm-1.datacenter-10, alarm-2.datacenter-10, alarm-3.datacenter-10, alarm-4.datacenter-10...}
TriggeredAlarmState : {alarm-3.host-184, alarm-3.host-3310, alarm-3.host-3834, alarm-3.host-5972...}
AlarmActionsEnabled : False
Tag :
Value : {}
AvailableField : {}
MoRef : Datacenter-datacenter-10
Client : VMware.Vim.VimClient

VmFolder : Folder-group-v3473
HostFolder : Folder-group-h3474
DatastoreFolder :
NetworkFolder :
Datastore : {Datastore-datastore-3554, Datastore-datastore-3556, Datastore-datastore-3558, Datastore-datastore-3560...}
Network : {Network-network-9660, Network-network-6759, Network-network-6761, Network-network-6760...}
Parent : Folder-group-d1
CustomValue : {}
OverallStatus : gray
ConfigStatus : gray
ConfigIssue : {}
EffectiveRole : {-1}
Permission : {107, 107, 107, 107...}
Name : Datacenter_2
DisabledMethod : {}
RecentTask : {}
DeclaredAlarmState : {alarm-1.datacenter-3472, alarm-2.datacenter-3472, alarm-3.datacenter-3472, alarm-4.datacenter-3472...}
TriggeredAlarmState : {alarm-3.host-11857, alarm-3.host-11873, alarm-3.host-6439, alarm-4.vm-9648}
AlarmActionsEnabled : False
Tag :
Value : {}
AvailableField : {}
MoRef : Datacenter-datacenter-3472
Client : VMware.Vim.VimClient

[vSphere PowerCLI]> Get-Datacenter | Where-Object { $_.Name -eq "Datacenter_1" } | Get-Member

TypeName: VMware.VimAutomation.ViCore.Impl.V1.Inventory.DatacenterImpl

Name MemberType Definition
---- ---------- ----------
ConvertToVersion Method ConvertToVersion()
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetHostFolder Method VMware.VimAutomation.ViCore.Interop.V1.Inventory.FolderInterop GetHostFolder()
GetType Method System.Type GetType()
GetVmFolder Method VMware.VimAutomation.ViCore.Interop.V1.Inventory.FolderInterop GetVmFolder()
get_CustomFields Method System.Collections.Generic.IDictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] get_CustomFields()
get_ExtensionData Method System.Object get_ExtensionData()
get_Id Method System.String get_Id()
get_Name Method System.String get_Name()
get_ParentFolder Method VMware.VimAutomation.ViCore.Types.V1.Inventory.Folder get_ParentFolder()
get_ParentFolderId Method System.String get_ParentFolderId()
get_Uid Method System.String get_Uid()
IsConvertableTo Method System.Boolean IsConvertableTo(Type toType)
ToString Method System.String ToString()
CustomFields Property System.Collections.Generic.IDictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] CustomFields {get;}
ExtensionData Property System.Object ExtensionData {get;}
Id Property System.String Id {get;}
Name Property System.String Name {get;}
ParentFolder Property VMware.VimAutomation.ViCore.Types.V1.Inventory.Folder ParentFolder {get;}
ParentFolderId Property System.String ParentFolderId {get;}
Uid Property System.String Uid {get;}

[vSphere PowerCLI]>Get-View -ViewType Datacenter | Where-Object { $_.Name -eq "Datacenter_1"   } | Get-Member

TypeName: VMware.Vim.Datacenter

Name MemberType Definition
---- ---------- ----------
Destroy Method System.Void Destroy()
Destroy_Task Method VMware.Vim.ManagedObjectReference Destroy_Task()
Equals Method System.Boolean Equals(Object obj)
GetAllEventsView Method VMware.Vim.EventHistoryCollector GetAllEventsView(EventFilterSpec eventFilterSpec)
GetAllTasksView Method VMware.Vim.TaskHistoryCollector GetAllTasksView(TaskFilterSpec taskFilterSpec)
GetEntityOnlyEventsCollectorView Method VMware.Vim.EventHistoryCollector GetEntityOnlyEventsCollectorView(EventFilterSpec eventFilterSpec)
GetEntityOnlyTasksCollectorView Method VMware.Vim.TaskHistoryCollector GetEntityOnlyTasksCollectorView(TaskFilterSpec taskFilterSpec)
GetEventCollectorView Method VMware.Vim.EventHistoryCollector GetEventCollectorView(EventFilterSpecRecursionOption recursionOption, EventFilterSpec eventFilterSpec)
GetHashCode Method System.Int32 GetHashCode()
GetTaskCollectorView Method VMware.Vim.TaskHistoryCollector GetTaskCollectorView(TaskFilterSpecRecursionOption recursionOption, TaskFilterSpec taskFilterSpec)
GetType Method System.Type GetType()
get_AlarmActionsEnabled Method System.Boolean get_AlarmActionsEnabled()
get_AvailableField Method VMware.Vim.CustomFieldDef[] get_AvailableField()
get_Client Method VMware.Vim.VimClient get_Client()
get_ConfigIssue Method VMware.Vim.Event[] get_ConfigIssue()
get_ConfigStatus Method VMware.Vim.ManagedEntityStatus get_ConfigStatus()
get_CustomValue Method VMware.Vim.CustomFieldValue[] get_CustomValue()
get_Datastore Method VMware.Vim.ManagedObjectReference[] get_Datastore()
get_DatastoreFolder Method VMware.Vim.ManagedObjectReference get_DatastoreFolder()
get_DeclaredAlarmState Method VMware.Vim.AlarmState[] get_DeclaredAlarmState()
get_DisabledMethod Method System.String[] get_DisabledMethod()
get_EffectiveRole Method System.Int32[] get_EffectiveRole()
get_HostFolder Method VMware.Vim.ManagedObjectReference get_HostFolder()
get_MoRef Method VMware.Vim.ManagedObjectReference get_MoRef()
get_Name Method System.String get_Name()
get_Network Method VMware.Vim.ManagedObjectReference[] get_Network()
get_NetworkFolder Method VMware.Vim.ManagedObjectReference get_NetworkFolder()
get_OverallStatus Method VMware.Vim.ManagedEntityStatus get_OverallStatus()
get_Parent Method VMware.Vim.ManagedObjectReference get_Parent()
get_Permission Method VMware.Vim.Permission[] get_Permission()
get_RecentTask Method VMware.Vim.ManagedObjectReference[] get_RecentTask()
get_Tag Method VMware.Vim.Tag[] get_Tag()
get_TriggeredAlarmState Method VMware.Vim.AlarmState[] get_TriggeredAlarmState()
get_Value Method VMware.Vim.CustomFieldValue[] get_Value()
get_VmFolder Method VMware.Vim.ManagedObjectReference get_VmFolder()
PowerOnMultiVM Method VMware.Vim.ClusterPowerOnVmResult PowerOnMultiVM(ManagedObjectReference[] vm, OptionValue[] option)
PowerOnMultiVM_Task Method VMware.Vim.ManagedObjectReference PowerOnMultiVM_Task(ManagedObjectReference[] vm, OptionValue[] option)
QueryConnectionInfo Method VMware.Vim.HostConnectInfo QueryConnectionInfo(String hostname, Int32 port, String username, String password, String sslThumbprint)
Reload Method System.Void Reload()
Rename Method System.Void Rename(String newName)
Rename_Task Method VMware.Vim.ManagedObjectReference Rename_Task(String newName)
setCustomValue Method System.Void setCustomValue(String key, String value)
SetViewData Method System.Void SetViewData(ObjectContent objectContent, String[] properties)
ToString Method System.String ToString()
UpdateViewData Method System.Void UpdateViewData(Params String[] properties), System.Void UpdateViewData()
WaitForTask Method System.Object WaitForTask(ManagedObjectReference taskReference)
AlarmActionsEnabled Property System.Boolean AlarmActionsEnabled {get;}
AvailableField Property VMware.Vim.CustomFieldDef[] AvailableField {get;}
Client Property VMware.Vim.VimClient Client {get;}
ConfigIssue Property VMware.Vim.Event[] ConfigIssue {get;}
ConfigStatus Property VMware.Vim.ManagedEntityStatus ConfigStatus {get;}
CustomValue Property VMware.Vim.CustomFieldValue[] CustomValue {get;}
Datastore Property VMware.Vim.ManagedObjectReference[] Datastore {get;}
DatastoreFolder Property VMware.Vim.ManagedObjectReference DatastoreFolder {get;}
DeclaredAlarmState Property VMware.Vim.AlarmState[] DeclaredAlarmState {get;}
DisabledMethod Property System.String[] DisabledMethod {get;}
EffectiveRole Property System.Int32[] EffectiveRole {get;}
HostFolder Property VMware.Vim.ManagedObjectReference HostFolder {get;}
MoRef Property VMware.Vim.ManagedObjectReference MoRef {get;}
Name Property System.String Name {get;}
Network Property VMware.Vim.ManagedObjectReference[] Network {get;}
NetworkFolder Property VMware.Vim.ManagedObjectReference NetworkFolder {get;}
OverallStatus Property VMware.Vim.ManagedEntityStatus OverallStatus {get;}
Parent Property VMware.Vim.ManagedObjectReference Parent {get;}
Permission Property VMware.Vim.Permission[] Permission {get;}
RecentTask Property VMware.Vim.ManagedObjectReference[] RecentTask {get;}
Tag Property VMware.Vim.Tag[] Tag {get;}
TriggeredAlarmState Property VMware.Vim.AlarmState[] TriggeredAlarmState {get;}
Value Property VMware.Vim.CustomFieldValue[] Value {get;}
VmFolder Property VMware.Vim.ManagedObjectReference VmFolder {get;}

Friday, March 18, 2011

Get/Set custom field in Vmware - Is your VM replicated example ?

For billing and production information, I need to know if SAN is replicated or not.
I use a powershell script to indicate me if ESX host is replicate or not using Virtual Center Custom Field.

First, I must set a value to all ESX for indicate me if this ESX have replicated LUN

To set "Replication" in all your hosts

$VMHosts = Get-VMHost | Sort Name
$CustomField = "Replication"
Foreach ($VMHost in $VMHosts){
Write-Host ($VMHost).Name
Set-CustomField -Entity $VMHost -name $CustomField -Value "Yes"
}



Now, for some ESX with no replication set Custom Field Replication manually to No

To do that, select your host then in summary tab in annotations click on edit


















Then in "Edit Annotations" window change value of Replication field











Now, if you need to know if your VM is replicated use this powershell code

$ArrVM = Get-VM
foreach ($VM in $arrVM) {
$VMHost = Get-VMHost -VM $VM
$Replication = $True
If ($VMHost.CustomFields["Replication"].ToUpper() -eq "NO") {
$Replication = $False
}
Write-Host $VM.Name "replication:" $Replication
}

Tuesday, February 15, 2011

Get / Determine / Check your ESX version, major version or build version

To check your esx version, use in command line:


vmware -v
return for example in a 3.0.1 ESX
VMware ESX Server 3.0.1 build-32039

vmware -v
return for example in a 3.5 ESX
VMware ESX Server 3.5.0 build-238493

vmware -v
return for example in a 4.1 ESX
VMware ESX 4.1.0 build-260247



But If you need to know only version use

vmware -v | awk -F "uild" '{print $1}' | sed -e 's/[A-Za-z ]//g'

return in our 3 examples
3.0.1
3.5.0
4.1.0


In your script you can use this information into a variable

ESX_VERSION=`vmware -v | awk -F "uild" '{print $1}' | sed -e 's/[A-Za-z ]//g'`
echo $ESX_VERSION

return in our 3 examples
3.0.1
3.5.0
4.1.0




To know major version only

vmware -v | awk -F "uild" '{print $1}' | sed -e 's/[A-Za-z ]//g' | cut '-d.' -f1

return in our 3 examples
3
3
4


To know major and minor version only

vmware -v | awk -F "uild" '{print $1}' | sed -e 's/[A-Za-z ]//g' | awk -F "." '{print $1"."$2}'

return in our 3 examples
3.0
3.5
4.1


If you need to know build only

vmware -v | awk -F "uild-" '{print $2}'

return in our 3 examples
32039
238493
260247

Tuesday, January 25, 2011

Register all VM to a new ESX host

A standalone ESX has been reinstalled. All VM are on a shared storage.
I registered all VM with this following command:


find /vmfs/volumes -name "*.vmx" | xargs -i{} vmware-cmd -s register {}


For information, you can replace xargs -I{} by xargs -i{} for certain esx version

Monday, January 3, 2011

Unregister all VM in a ESX host

Problem with an old ESX v3.0.2. All VM have been stopped. I must unregister all VM from this ESX. So I use replace-str xargs option like this:

vmware-cmd -l | xargs -i{} vmware-cmd -s unregister {}


You can stop / start / suspend / reset all VM using the same tip:

vmware-cmd -l | xargs -i{} vmware-cmd {} stop
vmware-cmd -l | xargs -i{} vmware-cmd {} start
vmware-cmd -l | xargs -i{} vmware-cmd {} suspend
vmware-cmd -l | xargs -i{} vmware-cmd {} reset


For information, you can replace xargs -I{} by xargs -i{} for certain esx version

Monday, November 29, 2010

How to develop your own VMWare application in C#

First, download and install "Visual Studio Express 2008" (http://www.microsoft.com/express/Downloads/)
Then download and install "VMware vSphere Web Services SDK" (http://www.vmware.com/download/sdk/)

In file Build2008.cmd (from your "VMware vSphere Web Services SDK directory\samples\DotNet" directory) if you installed your VS2008 Express in an other directory than default directory modify line
set VSINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0"

Run a command line prompt.

Verify in command line prompt you can run
- WSDL.exe (by default at C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin)
- csc.Exe (by default at C:\WINDOWS\Microsoft.NET\Framework\v3.5)
- VCSExpress.exe (by default at C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE)

Else add path of these programs with something like this in command line before running Build2008.cmd:
Set path=%path%;C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin;C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE

In command line prompt do not forget to run this line too:
set WSDLFILE=your VMware vSphere Web Services SDK directory\wsdl

Then run Build2008.cmd
You should have all your .dll libraries created.

Run in your VMware vSphere Web Services SDK directory\samples\DotNet\cs\SimpleClient\bin\Debug this line to verify all is ok:
SimpleClient.exe https://yourvc/sdk yourvcuser yourvcpassword

Now, if you need to create your own application, just add line
using Vim25Api;
and in your project "add reference" tab browse
"Vim25Service2008.dll" and "Vim25Service2008.XmlSerializers.dll"

Use examples in your vSphere Web Services SDK\directory\samples\DotNet\cs for helping you to create your 1st C# vmware application

Friday, July 30, 2010

Powershell to display Storage Model for each VMWare VM

Script below permit to display which storage model is used for each VM of you Virtual Center
Download it


#
# Storage Model by VM
#
# by Franck RICHARD
# 2010 July
#

# Connect VC
$VC = "localhost"
Connect-VIServer -Server $VC | Out-Null

# Get all Datastores
$datastores = Get-Datastore
# Get All VMs
$ArrVM = Get-VM
foreach ($VM in $arrVM) {
# Get VMHost View
$VMHostView = Get-VMHost -VM $VM | Get-View

# Get all HardDisks
$HardDisks = $VM | Get-HardDisk
foreach ($HardDisk in $HardDisks) {
# Filename = "[VMFS-PROD] COMPUTER01/COMPUTER01.vmdk" for example
$DatastoreVM = $HardDisk.Filename.Split("[]")[1]
$DatastoreVMView = $datastores | where {$_.name -eq $DatastoreVM} | Get-View

# Diskname = "vmhba2:0:20" for example
$VMFSextents = $DatastoreVMView.info.vmfs.extent
foreach ($VMFSextent in $VMFSextents) {
$Diskname = $vmfsextent.Diskname
#Write-Host "Diskname:"$Diskname
}

$ScsiLuns = $VMHostView.Config.StorageDevice.ScsiLun
$bDiskFound = $False
foreach ($ScsiLun in $ScsiLuns) {
if ($ScsiLun.CanonicalName -eq $Diskname) {
#For Example
# CanonicalName = "vmhba2:0:0"
# Vendor = "EMC"
# Model = "SYMMETRIX"
$bDiskFound = $True
break
}
}

if ($bDiskFound) {
Write-Host "Name:" $VM.Name $HardDisk.Name $ScsiLun.CanonicalName "Vendor:"$ScsiLun.Vendor "Model:"$ScsiLun.Model
} else {
Write-Host "Name:" $VM.Name $diskname "not found"
}
# break # if all HardDisks are on the SAN
} # Foreach $HardDisk
} # Foreach $VM

Thursday, April 10, 2008

How to update or configure automatically vmware esx or linux servers when you are a windows user ?

Problem when you have 32 esx 3.01 to upgrade is that takes long time. And ask to windows prod team to realize these - not interesting - tasks needs a really big documentation to avoid errors. So I decided to create something to automatize this process.
So, today I give you a script which permit you to update or configure any linux/vmware redhat/unix server with simple vbscript file. First, you need at least plink.exe and pscp.exe from http://www.chiark.greenend.org.uk/~sgtatham/putty/ (Alternative Download). Put these files in the same directory than you will put update_esx.vbs file.

But why this script is magic? Because plink and pscp could do it for you really easily, no ? In fact, problem with plink.exe is when you need to automatize your process. Each time you will try to log on a new server, plink will ask you to create ssh host keys. (for security)
With this script you do no need to create plink ssh host keys before running script on your servers. This script do it for you.
Now, you need to create servers.txt file containing all servers you need to update or configure. (1 line = 1 server). For example:

esxserver001
esxserver002


You need also a .sh file which will be executed on esx - linux server (don't forget to use a unix text file with only line feed, and not Windows text file with line feed and carriage return ASCII characters. So do not use notepad to modify files. Use Textpad or other tools that recognize file encoding. )

Below an example to send to your esx. This file ls.sh

#!/bin/sh
# Configure ESX Server
ls


Last thing: root password should be the same on each esx - linux server (else modify my vbscript using a second column in servers.txt like server;rootpassword)
You must also permit root user to log on your esx.

How to use it: run in you windows command line something like


cscript //nologo update_esx.vbs servers.txt file_to_execute.sh your_esx_root_password


If you need to write log, redirect standard output to a file like this:


cscript //nologo update_esx.vbs servers.txt file_to_execute.sh your_esx_root_password > mylog.txt


And now the last but not least, the main tool, update_esx.vbs

'
' update_esx.vbs
'
' by F.RICHARD
'
' v1.00 2007 Nov - Initial release
' v1.01 2008 Jan - Display Standard output
'
Option Explicit

Const ForReading = 1

'
' Detect WScript or CScript
'
If InStr(LCase(WScript.FullName), "wscript")>0 Then ' ex: FullName = C:\WINNT\system32\wscript.exe
WScript.Echo "This script must be run under CScript."
WScript.Quit
End If

'
' Get Command Line Args
'
Dim Args
Set Args = Wscript.Arguments
If Args.Count < 3 Then
Wscript.Echo "Syntax : " & WScript.ScriptName & " input_computer_list_file script_to_execute root_password"
Wscript.Echo " Example : cscript " & WScript.ScriptName & " servers.txt update.sh password"
Wscript.Echo ""
Wscript.Echo "computer_list_file: line begin by # or ; indicate start of a comment, everything after is ignored"
Wscript.Echo ""
Wscript.Quit
End If


' Arg(0) = computer list
Dim strInputList
strInputList = Trim(args(0))

' Arg(1) = script to execute
Dim strScriptToExecute
strScriptToExecute = Trim(args(1))


' Arg(2) = root password
Dim strPassword
strPassword = Trim(args(2))


'
' Get Path
'
Dim strScriptFullName, strScriptPath
strScriptFullName = WScript.ScriptFullName ' ex: C:\Program Files\MyFolder\MyProg.exe
strScriptPath = Left(strScriptFullName, InStrRev(strScriptFullName, "\") - 1) ' ex: C:\Program Files\MyFolder

Dim objFso
Set objFso = CreateObject("Scripting.FileSystemObject")


'
' Test If all Files Exist
'
If Not isFileExist(strInputList) Then
strInputList = strScriptPath & "\" & strInputList
If Not isFileExist(strInputList) Then
WScript.Echo "Computer list:" & strInputList & " File Not Exist !"
WScript.Quit
End If
End If
WScript.Echo "Computer list:" & strInputList & " File Exist"

If Not isFileExist(strScriptToExecute) Then
strScriptToExecute = strScriptPath & "\" & strScriptToExecute
If Not isFileExist(strScriptToExecute) Then
WScript.Echo "Script to execute:" & strScriptToExecute & """" & " File Not Exist !"
WScript.Quit
End If
End If
WScript.Echo "Script to execute:" & strScriptToExecute & " File Exist"

Dim strPlink
strPlink= strScriptPath & "\" & "plink.exe"
If Not isFileExist(strPlink) Then
WScript.Echo "PuTTY Link:" & strPlink & " File Not Exist !"
WScript.Quit
End If
WScript.Echo "PuTTY Link:" & strPlink & " File Exist"

Dim strPscp
strPscp= strScriptPath & "\" & "pscp.exe"
If Not isFileExist(strPscp) Then
WScript.Echo "PuTTY Secure Copy client:" & strPscp & " File Not Exist !"
WScript.Quit
End If
WScript.Echo "PuTTY Secure Copy client:" & strPscp & " File Exist"


Dim objShell, ComSpec
Set objShell = CreateObject( "WScript.Shell" )
ComSpec=objShell.ExpandEnvironmentStrings("%ComSpec%")

'
' Read computer list file into dictionary
'
Dim objDictionary, return
return = ReadFileToDict(strInputList, objDictionary)
If return = 0 Then
WScript.Echo "Error during computer list file read"
WScript.Quit
End If

' Display file
Dim objItem, strServer, objCmd, strCmdline, continue, strGenerateKey
For Each objItem in objDictionary
strServer = objDictionary.Item(objItem)
Wscript.Echo ""
WScript.Echo "Server:" & strServer

' Test Connection
strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " root" & "@" & strServer & " pwd "
strGenerateKey = ComSpec & " /c echo y | """ & strPlink & """ " & strServer & " -pw " & strPassword & " root"

WScript.Echo "Test Connection on server " & strServer
return = DoConnection(strCmdline, strGenerateKey, strServer, True)

If (return > 0) Then
strGenerateKey=""
Do
WScript.Echo "Re-verify Connection on server " & strServer
return = DoConnection(strCmdline, strGenerateKey, strServer, True)
Loop While (return > 0 and return < 255)
If (return > 0) Then
WScript.Echo "Transfer " & strScriptToExecute & " script on server " & strServer
strCmdline = ComSpec & " /c """ & strPscp & """ -batch -C -pw " & strPassword & " " & strScriptToExecute & " root" & "@" & strServer & ":/tmp"
return = DoConnection(strCmdline, strGenerateKey, strServer, True)

WScript.Echo "Execute " & strScriptToExecute & " script on server " & strServer
strCmdline = ComSpec & " /c """ & strPlink & """ -batch -C -pw " & strPassword & " root" & "@" & strServer & ":/tmp" & " sh /tmp/" & strScriptToExecute
return = DoConnection(strCmdline, strGenerateKey, strServer, True)
End If
End If

Next


'
' Quit
'
WScript.Sleep 1000
WScript.Quit



'--------------------

' DoConnection
'
'
'
Function DoConnection(strCmdline, strGenerateKey, strServer, displayLogfile)
Dim objCmd, return, Continue

'WScript.Echo "cmdline->" & strCmdline
Set objCmd = objShell.Exec(strCmdline)
Do While objCmd.Status = 0
return = objCmd.stdErr.ReadAll
WScript.Sleep 100
Loop
If (displayLogfile) Then
Dim strStdOut
strStdOut = objCmd.StdOut.ReadAll()
If (len(strStdOut) > 0) Then
Wscript.Echo strStdOut
End If
End If

continue = 0
If Instr(return, "Access denied" ) > 0 Then ' Access denied
WScript.Echo "ERROR on server " & strServer & vbCrLf & return
continue = 0

Elseif Instr(return, "Unable to open connection" ) > 0 Then ' Unable to open connection
WScript.Echo "ERROR on server " & strServer & vbCrLf & return
continue = 0

Elseif Instr(return, "ERROR" ) > 0 Then ' FATAL ERROR: Network error: Connection timed out
WScript.Echo "ERROR on server " & strServer & vbCrLf & return
continue = 0

Elseif Instr(return, "fingerprint" ) > 0 Then
If (len(strGenerateKey) > 2) Then
WScript.Echo "GENERATE key fingerprint on server " & strServer
'WScript.Echo "generatekey->" & strGenerateKey
objShell.Exec(strGenerateKey)
continue = 1
Else
WScript.Echo "NOT GENERATE key fingerprint " & strServer
continue = 2
End If
Else
continue = 255
'WScript.Echo "Logged on " & strServer & " - " & return
End if

DoConnection = continue
End Function



'--------------------

' isFileExist
'
' Test if File Exist
'
Function IsFileExist(strInputFile)
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FileExists(strInputFile) Then
Wscript.echo strInputFile & " file not exist !"
IsFileExist = False
Else
IsFileExist = True
End If
End Function


'--------------------

' ReadFileToDict
'
' Read each line -> put in Dictionary
' strInputfile = file to read
' objDictionary = dictionary for results
'
Function ReadFileToDict(strInputFile, ByRef objDictionary)
Dim objFSO, objTextFile, strNextLine, i
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")
If isFileExist(strInputFile) Then
Set objTextFile = objFSO.OpenTextFile(strInputFile, ForReading)
i = 0
Do Until objTextFile.AtEndOfStream
strNextLine = Trim(objTextFile.Readline)
If ( (Not Left(strNextLine, 1) = "#") _
and (Not Left(strNextLine, 1) = ";") _
and (Len(strNextLine)>1) _
) Then
objDictionary.Add i, strNextLine
i = i + 1
End If
Loop
objTextFile.Close
ReadFileToDict = True
Else
ReadFileToDict = False
End If
End Function


'--------------------



You can download a .zip file here including an example with change_ntp.sh

Next step, if I had some time, a graphical interface with a description of each script and variables for each script.