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.

Thursday, March 27, 2008

RIS: blocked on "Setup is starting windows"...

Sometimes, you can really lose your time for a little error. Your eyes see, but you don't see what is visible... During my IT Life, I had installed a lot of RIS / WDS. This time, it wasn't me but a colleague with my documentation which had installed a mixed RIS / WDS server on a subsidiary site . Problem when he came back from his trip, he said me it was impossible to install a workstation. Every time, PXE works then we enter all normal information (user, password, then select os...). All works until it hang in "Setup is starting windows...". (This is just after loading drivers in memory or just before windows format your partition).

Strange. In my first analyze, it looked like to be a router problem. Well, I decided to see DHCP configuration: Server options and vlan options seems to be good. I try to find some information on the net about this error, but all that I find is error on windows 2000. (we are in 2003) or problem with network card or graphic card but these workstation had been already installed before at QG without any problems. I search on cisco router to find something, but configuration on core or switch like ip-helper are the same than other sites. I Had tested all what I know, try options 66, 67 and even 60. Well, I had even installed ethereal/wireshark to analyze all frames.

For information, there is no IT on this subidiary at 4000km on south where I work. And like there is no ILO on workstation, to test RIS, I installed vmware player with a .vmx folder containing just definition of a windows XP vmware. I can test a lot of time RIS installation by pushing F12, and try, and try...

Come back to my problem. I test RIS installation on ris server vlan (by changing workstation vlan port), and here it works ! That confirm it is really a router problem. I retest dhcp vlan options, I re-check ethereal capture. Nothing wrong. Switch and core all well configured. All is correct. What's wrong ? ......my eyes... Yes. All the time I will see vlan option, I only see yyy.zzz in router ip address www.xxx.yyy.zzz , and problem was xxx.... My colleague had type 10.20.210.1 as router and not 10.19.210.1 . But something is fun: why workstations already installed didn't have any problem even if this gateway was not good ???... All work on this workstation on this vlan... Except if you try to RIS it...because this wrong gateway didn't exist...

So next time, "put your glasses", Mr Franck RICHARD, put your glasses...

Thursday, January 17, 2008

Welcome to my blog

Hello and welcome to my blog. My name is Franck RICHARD. I am french. I live near Paris, France. I work in IT since 1996 and I code since 1990. My goal with this blog is to share my experience and my programs for optimizing your time.I hope you will find in my blog something which will help you.