Insanely well written Tutorial for Git and Github.
Check it out.
http://readwrite.com/2013/09/30/understanding-github-a-journey-for-beginners-part-1
Insanely well written Tutorial for Git and Github.
Check it out.
http://readwrite.com/2013/09/30/understanding-github-a-journey-for-beginners-part-1
Shellshock – A bug discovered in the widely used Bash command interpreter.
It does poses a critical security risk to Unix and Linux systems –and, thanks to their ubiquity, the internet at large.
More info here:
http://www.theregister.co.uk/2014/09/24/bash_shell_vuln/
Some more nice info:
https://blog.cloudflare.com/inside-shellshock/
I didn’t find this anywhere else so i decided to create my own ViewCLI script.
Just run it against a View Event Database to get all information you need.
Please note:
If there is more than one machine assigned to a user it will show “System.Object[]” instead of a machine name.
You can still use “get-desktopVM | where { $_.user_displayname -eq “domain\username” } to list all machines in that case.
It actually results users that did login to the broker. This is enough for me as i don’t need the agent_login itself.
Just make sure you edit the sql query if you want to see agent connects.
Let me know if you have any questions or problems:
<# .SYNOPSIS Check environment for users login times and get machines with no login since more than 90days. #> [CmdletBinding()] param( [Parameter(Mandatory=$False)] [string]$choice ) #generate a timestamp that can be used in filename Function logstamp { $now=get-Date $yr=$now.Year.ToString() $mo=$now.Month.ToString() $dy=$now.Day.ToString() $hr=$now.Hour.ToString() $mi=$now.Minute.ToString() if ($mo.length -lt 2) { $mo="0"+$mo #pad single digit months with leading zero } if ($dy.length -lt 2) { $dy="0"+$dy #pad single digit day with leading zero } if ($hr.length -lt 2) { $hr="0"+$hr #pad single digit hour with leading zero } if ($mi.length -lt 2) { $mi="0"+$mi #pad single digit minute with leading zero } Write-Output $yr$mo$dy$hr$mi } #variables - modify accordingly $dbserver = "" $user = "" $pwd = read-host 'View Event DB Password' -AsSecureString $database = "VIEWEVENTS" $connectionString = "Server=$dbserver;uid=$user; pwd=$pwd;Database=$database;Integrated Security=False;" $domain = "" #this query actually gets all users that did not login between today and -90 days but before -90 days until -180 days. #you could choose to increase or decrease the -180 as you want. $query = " SELECT ModuleAndEventText FROM VE_event_historical WHERE (EventType = 'BROKER_USERLOGGEDIN') AND (Time BETWEEN dateadd(day,-180,getdate()) AND dateadd(day,-90,getdate())) EXCEPT SELECT ModuleAndEventText FROM VE_event_historical WHERE (EventType = 'BROKER_USERLOGGEDIN') AND (Time BETWEEN dateadd(day,-90,getdate()) AND dateadd(day,0,getdate())) " $connection = New-Object System.Data.SqlClient.SqlConnection $connection.ConnectionString = $connectionString $connection.Open() $command = $connection.CreateCommand() $command.CommandText = $query $result = $command.ExecuteReader() $table = new-object “System.Data.DataTable” $table.Load($result) $connection.Close() $properties = @{UserID = ''; VM=''} $object = New-Object -TypeName PSObject -Property $properties $collection=@() $table | foreach-object { $objloop = $object.PSObject.Copy() #make sure to edit the 2nd -replace to match your domain $objloop.UserID = $_.ModuleAndEventText -replace " has logged in", "" -replace "User domain\\", "" $objloop.VM = get-desktopvm | where { $_.user_displayname -eq "$domain\$($objloop.UserID)" } | Select-Object -exp Name $collection += $objloop } write-output "Logging output to InactiveDesktops_$timestamp.csv" $timestamp = logstamp $filename = "InactiveDesktops_$timestamp.csv" $collection | Export-Csv $filename -NoTypeInformation
If you want to have a template that delivers some basic functionality just use this as and modify it to your needs.
It needs to have an input but also accepts input from a pipeline (like get-content input.txt | script.ps1).
It offers basic error handling for terminating errors. The variable $ErrorActionPreference = stop makes them all terminating though 🙂
Have fun and let me know if you need any advice.
<# .SYNOPSIS Check if VM(s) still exist .EXAMPLE get-content "list-of-machines.txt" | check if vm exists.ps1 .EXAMPLE check if vm exists.ps1 vm1 .EXAMPLE check if vm exists.ps1 vm1, vm2, vm3 .PARAMETER VM One or more Virtual Machine names #> [CmdletBinding()] param( [Parameter(Mandatory=$True,ValueFromPipeline=$True)] [string[]]$VM ) BEGIN { $ErrorActionPreference = "Stop" $collection = @() } PROCESS { try { $collection += get-vm $desktop write-output "$desktop does exist!" } catch { $collection += "$desktop does not exist!" } finally {} } END { $collection | out-gridview }
If find this script really useful for finding orphaned VMDKs.
Just put it as task once a week and you will be able to cleanup nicely 🙂
Make sure to change the variables on the top of the script to fit your needs.
######################### # BEGIN: User Variables # ######################### # Log File location $LogFile = "Snapshot.log" # Virtual Centre server to connect to $VCServer = "" # Email parameters for emailing logfile results # emailTo is a comma separated list of strings eg. "email1","email2" $emailEnable = $true $emailFrom = "vcs" $emailTo = "vcs" $emailSubject = "VMware Health Check" $emailServer = "" ######################### # END: User Variables # ######################### ############################### # BEGIN: Function Definitions # ############################### function Output-Data { <# .SYNOPSIS Outputs Data or messages in the desired method .DESCRIPTION This function is designed to use the $LogFile global variable to avoid having to specify the output file each time it is called. Data is output to the log file by default and optionally to the console as well. .NOTES Author: Grant Brunton .PARAMETER Data: The message or object to ouput to the log .PARAMETER ToHost: TH: Optional switch to include displaying the output to the console .EXAMPLE PS> Output-Data $object .EXAMPLE PS> Output-Data "Message" -ToHost #> [CmdletBinding()] Param ( [parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)] [Object]$Data, [alias("TH")] [switch]$ToHost ) Process { if ($ToHost) { $Data | fl } $Data | fl | Out-File $LogFile -Encoding ASCII -Append } } function Load-VMLibrary { <# .SYNOPSIS Loads VMware core modules and connects to VI Server .DESCRIPTION The function loads the VMware core modules required for processing VMware PowerCLI commands. This requires the PowerCLI modules to be installed. It will also connect to the VIServer ready for accepting commands. .NOTES Author: Grant Brunton .PARAMETER VIServer: The Virtual Centre Server to connect to. The default is "VirtualCentre" .PARAMETER Credential: A PSCredential object used to authenticate with the VIServer to connect to. Credential objects can be created using the Get-Credential cmdlet By default the logged on user credentials are used to authenticate. .EXAMPLE PS> Load-VMLibrary .EXAMPLE PS> Load-VMLibrary "server1" .EXAMPLE PS> $cred = Get-Credential PS> Load-VMLibrary -VIServer "server1" -Credential $cred .EXAMPLE PS> $cred = $host.ui.PromptForCredential("ESX/ESXi Credentials Required", "Please enter credentials to log into the ESX/ESXi host.", "", "") PS> "server1" | Load-VMLibrary -Credential $cred #> [CmdletBinding()] Param ( [parameter(ValueFromPipeline=$true,Position=0)] [String]$VIServer = "VirtualCentre", [object]$Credential = $null ) Process { $vmwaretoolkit = Get-PSSnapin | where {$_.Name -eq "VMware.VimAutomation.Core"} if (!$vmwaretoolkit) { $vmwaretoolkit = Get-PSSnapin -registered | where {$_.Name -eq "VMware.VimAutomation.Core"} if ($vmwaretoolkit) { Add-PSSnapin "VMware.VimAutomation.Core" if (!$?) { Output-Data -TH "Failed to load VMware snapin. Ensure VMware vSphere PowerCLI is installed correctly." ; exit } } else { Output-Data -TH "Please install VMware vSphere PowerCLI to use this script." exit } } Set-PowerCLIConfiguration -DefaultVIServerMode Single -Confirm:$false > $null if ($Credential -ne $null) { if ($Credential.GetType().Name -ne "PSCredential") { Output-Data -TH "Invalid credential format supplied" exit } $VIServer = Connect-VIServer $VIServer -Credential $Credential } else { $VIServer = Connect-VIServer $VIServer } if (!$?) { Output-Data -TH "Failed to connect to VM host. Please ensure the correct VIServer is specified and you have correct logon credentials." ; exit } } } function Check-OrphanedData{ <# .SYNOPSIS Remove orphaned folders and VMDK files .DESCRIPTION The function searches orphaned folders and VMDK files on one or more datastores and reports its findings. Optionally the function removes the orphaned folders and VMDK files .NOTES Author: Luc Dekens Modified by: Grant Brunton .PARAMETER Datastore One or more datastores. The default is to investigate all shared VMFS datastores .PARAMETER Delete A switch that indicates if you want to remove the folders and VMDK files .EXAMPLE PS> Remove-OrphanedData .EXAMPLE PS> Get-Datastore ds* | Remove-OrphanedData .EXAMPLE PS> Remove-OrphanedData -Datastore $ds -Delete #> [CmdletBinding()] param( [parameter(ValueFromPipeline=$true)] [PSObject[]]$Datastore, [switch]$Delete ) begin{ $fldList = @{} $hdList = @{} $fileMgr = Get-View FileManager } process{ if(!$Datastore){ $Datastore = Get-Datastore } foreach($ds in $Datastore){ if($ds.GetType().Name -eq "String"){ $ds = Get-Datastore -Name $ds } if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess){ Get-VM -Datastore $ds | %{ $_.Extensiondata.LayoutEx.File | where{"diskDescriptor","diskExtent" -contains $_.Type} | %{ $fldList[$_.Name.Split('/')[0]] = $_.Name $hdList[$_.Name] = $_.Name } } Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{ $_.Extensiondata.LayoutEx.File | where{"diskDescriptor","diskExtent" -contains $_.Type} | %{ $fldList[$_.Name.Split('/')[0]] = $_.Name $hdList[$_.Name] = $_.Name } } $dc = $ds.Datacenter.Extensiondata $flags = New-Object VMware.Vim.FileQueryFlags $flags.FileSize = $true $flags.FileType = $true $disk = New-Object VMware.Vim.VmDiskFileQuery $disk.details = New-Object VMware.Vim.VmDiskFileQueryFlags $disk.details.capacityKb = $true $disk.details.diskExtents = $true $disk.details.diskType = $true $disk.details.thin = $true $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec $searchSpec.details = $flags $searchSpec.Query += $disk $searchSpec.sortFoldersFirst = $true $dsBrowser = Get-View $ds.ExtensionData.browser $rootPath = "[" + $ds.Name + "]" $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec) foreach($folder in $searchResult){ if($fldList.ContainsKey($folder.FolderPath.TrimEnd('/'))){ foreach ($file in $folder.File){ if(!$hdList.ContainsKey($folder.FolderPath + $file.Path)){ $obj = New-Object PSObject -Property @{ Datastore = $ds.Name Folder = $folder.FolderPath FileName = $file.Path Size = $file.FileSize #CapacityKB = $file.CapacityKb #Thin = $file.Thin #Extents = [string]::Join(',',($file.DiskExtents | %{$_})) Problem = "Orphaned file" } Output-data $obj if($Delete){ $dsBrowser.DeleteFile($folder.FolderPath + $file.Path) } } } } elseif($folder.File | where {"cos.vmdk","esxconsole.vmdk" -notcontains $_.Path}){ $obj = New-Object PSObject -Property @{ Datastore = $ds.Name Folder = $folder.FolderPath Problem = "Orphaned folder" } Output-data $obj if($Delete){ $fileMgr.DeleteDatastoreFile($folder.FolderPath,$dc.MoRef) } } } } } } } function Check-Snapshot { <# .SYNOPSIS Checks VM guests for invalid snapshot images .DESCRIPTION This function checks VM guests to see if their harddisks are pointing to snapshot files. If they are it reports a detected problem if there are no snapshots listed for the guest or if a Consolidate Helper snapshot exists for the guest. A Consolidate Helper snapshot is usually created by a VCB type backup process and can be left behind if a snapshot removal process failed or the datastore ran out of room. If the Consolidate Helper snapshot appears by itself this is an indicator of a failed process. If the Consolidate Helper exists with other snapshots it may still be in the middle of the removal process. .NOTES Author: Grant Brunton .PARAMETER VMGuest: Can be an array or a single VM guest to check. Input should be either the VM object or a string of the VM name. By default all VM guests are checked. .EXAMPLE PS> Check-Snapshot .EXAMPLE PS> Check-Snapshot [-VMGuest] "vmguest" .EXAMPLE PS> $vm = Get-VM "vmguest" PS> $vm | Check-Snapshot #> [CmdletBinding()] Param ( [parameter(ValueFromPipeline=$true, Position=0)] [PSObject]$VMGuest ) Process { if(!$VMGuest) { $VMGuest = Get-VM } foreach($vm in $VMGuest) { if($vm.GetType().Name -eq "String") { $vm = Get-VM -Name $vm } $vm | Get-HardDisk | %{ if ($_.Filename -match ".*-[0-9]{6}.vmdk") { $obj = $null if (!(Get-Snapshot $vm)) { $obj = New-Object PSObject -Property @{ VMName = $vm.Name VMHost = $vm.Host Problem = "Missing Snapshot from Snapshot Manager" } } elseif (Get-Snapshot $vm | where{$_.Name -like "Consolidate*"}) { if (@(Get-Snapshot $vm).Length -eq 1) { $obj = New-Object PSObject -Property @{ VMName = $vm.Name VMHost = $vm.Host Problem = "Consolidate Helper exists for VM with no snapshots" } } else { $obj = New-Object PSObject -Property @{ VMName = $vm.Name VMHost = $vm.Host Problem = "Consolidate Helper exists for VM but has snapshots" } } } if ($obj -ne $null) { Output-Data $obj } Continue } } } } } ############################### # END: Function Definitions # ############################### #################### # BEGIN: MAIN CODE # #################### if (Test-Path $LogFile) { del $LogFile } Load-VMLibrary $VCServer Check-Snapshot Check-OrphanedData if ($emailEnable -and (Test-Path $LogFile)) { Send-MailMessage -smtpserver $emailServer -to $emailTo -from $emailFrom -subject $emailSubject -body (Get-Content $LogFile | Out-String) }
If you ever encounter the problem that you can’t update or install vmware tools (uninstall is also affected) due to missing soure.
Try this KB from VMWare.
Referenced from: http://www.symantec.com/connect/blogs/windows-installer-safe-mode
Windows Installer will not work under Safe Mode, this means that programs cannot be installed or uninstalled in safe mode without giving a specific command using msiexec in command prompt.
To make Windows Installer work under safe mode, you need to create a registry entry for every type of safe mode you are logged in to.
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Minimal\MSIServer" /VE /T REG_SZ /F /D "Service"
and then
net start msiserver
This will start the Windows Installer Service.
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer" /VE /T REG_SZ /F /D "Service"
and followed by
net start msiserver
This will start the Windows Installer Service.
If you ever happen to be in the same position as me and your registry doesn’t let you change keys/values, check this article as it resolved my issue.
—-
Download PsExec.exe to your desktop (IMPORTANT!)
Go Start and in “Start search” type in:
cmd
Hold CTRL and SHIFT keys, press Enter.
Command prompt window will open.
Copy and paste following command:
“%userprofile%\desktop\psexec” -i -d -s c:\windows\regedit.exe
Press Enter.
Registry Editor will open.
Now you’ll be able to change permissions for any key.
—-