The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,854 other subscribers

Archive for the ‘Development’ Category

Delphi 10.2 Tokyo introduced a “with” warning: for most “with” statements, W1048 is raised ([RSP-17326] with statements generate W1048 unsafe typecast warning – Embarcadero Technologies)

Posted by jpluimers on 2021/05/05

A cool feature introduced in Delphi 10.2 Tokyo: often [RSP-17326] with statements generate W1048 unsafe typecast warning – Embarcadero Technologies.

Only 2 upvotes, so I assume the “anti with camp” people are finally winning (:

Notes:

Quoted from the bug-report (as they cannot be archived in the wayback machine)

  1. RAD Studio
  2. RSP-17326

with statements generate W1048 unsafe typecast warning

Details

  • Type:Bug Bug
  • Status:Reported Reported
  • Priority:Major Major
  • Resolution:Unresolved
  • Affects Version/s:10.2 Tokyo
  • Fix Version/s:None
  • Component/s:Delphi Compiler
  • Labels: None
  • Build No: 25.0.25948.9960
  • Platform: All
  • Language Version: English
  • Edition: Enterprise
  • InternalID: RS-82298
  • InternalStatus: Validation

Description

All with statements generate this warning. I am on board with the theory that all with statements are inherently somewhat unsafe, but with 1.5 million lines of legacy code (and over 500 new warnings), I would significantly prefer to have a separate warning for with statements.
As it happens I would like to go through and do this work, especially if we can have refactoring to restore non-with code – see RSP-13978. BUT, Godzilla is generating new extra warnings (including unsafe typecasts) in this legacy code and I would prefer to be able to attack these first and attend to with statements later.

Activity

Comments

Jira-Quality Sync Service added a comment – 

Jason Sprenger requested more info in order to validate the issue and commented: Not any code involving “with” statements produces an unsafe typecast warning.

For instance,

program RS82298;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

procedure Use(var X);
begin<
end;

type
  TMyClass = class
    FValue: Integer;
    property Value: Integer read FValue write FValue;
  end;

procedure RunRS82298;
var
  MyClass: TMyClass;
begin
  MyClass := TMyClass.Create;
  with MyClass do
    begin
      Value := 42;
    end;
  with MyClass do
    WriteLn('MyClass.Value=', MyClass.Value);

  Use(MyClass);
end;

begin
  try
    RunRS82298
  except
    on E: Exception do
      begin
        WriteLn('FAIL - Unexpected Exception');
        WriteLn('  ClassName=', E.ClassName);
        WriteLn('    Message=', E.Message);
      end;
  end;
end.

What sort of source involving “with” statements is generating these warnings for you?

With this information our development team can consider addressing your particular circumstance.

Stuart Seath [X] (Inactive) added a comment – 

Try this (obviously a simple made-up example), and you do need to enable W1048 first in the project options:

program Project18;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TAnother = class
  private
    FAmbiguous : Boolean;
  public
    property Ambiguous : Boolean read FAmbiguous write FAmbiguous;
  end;

  TFirst = class
  private
    FAnother : TAnother;
  public
    procedure Doit;
  end;

var
  First : TFirst;

{ TFirst }

procedure TFirst.Doit;
begin
  FAnother := TAnother.Create;
  with FAnother do // WARNING
  begin
    Ambiguous := true;
  end;
end;

var
  XAnother : TAnother;

begin
  try
    XAnother := TAnother.Create;
    with XAnother do // NO WARNING HERE
    begin
      Ambiguous := true;
    end;

  except
    on E: Exception do
  Writeln(E.ClassName, ': ', E.Message);
end;
end.

–jeroen

Posted in Delphi, Delphi 10.2 Tokyo (Godzilla), Development, Software Development | 1 Comment »

Preference variable $ConfirmPreference allows getting more or less PowerShell confirmation prompts

Posted by jpluimers on 2021/05/04

On my list to experiment with are [Wayback] about_Preference_Variables – PowerShell | Microsoft Docs, especially

$ConfirmPreference

Determines whether PowerShell automatically prompts you for confirmation before running a cmdlet or function.

The $ConfirmPreference variable’s valid values are HighMedium, or Low. Cmdlets and functions are assigned a risk of HighMedium, or Low. When the value of the $ConfirmPreference variable is less than or equal to the risk assigned to a cmdlet or function, PowerShell automatically prompts you for confirmation before running the cmdlet or function.

If the value of the $ConfirmPreference variable is None, PowerShell never automatically prompts you before running a cmdlet or function.

To change the confirming behavior for all cmdlets and functions in the session, change $ConfirmPreference variable’s value.

To override the $ConfirmPreference for a single command, use a cmdlet’s or function’s Confirm parameter. To request confirmation, use -Confirm. To suppress confirmation, use -Confirm:$false.

Valid values of $ConfirmPreference:

  • None: PowerShell doesn’t prompt automatically. To request confirmation of a particular command, use the Confirm parameter of the cmdlet or function.
  • Low: PowerShell prompts for confirmation before running cmdlets or functions with a low, medium, or high risk.
  • Medium: PowerShell prompts for confirmation before running cmdlets or functions with a medium, or high risk.
  • High: PowerShell prompts for confirmation before running cmdlets or functions with a high risk.

–jeroen

Posted in .NET, CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »

From Yahoo closing Answers tonight to blocking ads on YouTube

Posted by jpluimers on 2021/05/04

The discussion on Yahoo closing Answers tonight quickly went from alternative text based question/answer sites to long YouTube videos having hardly any content but ads, to blocking these ads: [Wayback] Yahoo sluit Answers-dienst na vijftien jaar en verwijdert inhoud – IT Pro – Nieuws – Tweakers

So here are some links where I can learn a bit of browser plugin and Android development technology as well:

(What I dislike most about ads is that they start at unnatural positions in the stream and cover topics I’m totally not interested in).

–jeroen

Posted in Android, Android Devices, Development, Mobile Development, Power User, SocialMedia, Software Development, Web Development, YouTube | Leave a Comment »

Delphi …hide the scrollbars of a DBGrid?

Posted by jpluimers on 2021/05/04

Recently I needed a plain TDBGrid without a horizontal scrollbar. I based it on the below solutions, but using an interposer class (type TDBGrid = class(TDBGrid) ... end;).

Another solution is to redirect the WinProc for a single grid component to a different method (you can apply it to the similar TDBCtrlGrid class as well):

unit DBGridFormUnit;
uses
  Winapi.Messages,
  Vcl.DBGrids,
  Vcl.Forms;

type
  TDBGridForm = class(TForm)
    DBGrid: TDBGrid;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  strict private
    OriginalDBGridWindowProc : TWndMethod;
    procedure DBGridWindowProc(var Message: TMessage);
  end;

implementation

uses
  Winapi.Windows;
procedure TDBGridForm.FormCreate(Sender: TObject);
begin
  OriginalDBGridWindowProc := DBGrid.WindowProc;
  DBGrid.WindowProc := DBGridWindowProc;
end;

procedure TDBGridForm.FormDestroy(Sender: TObject);
begin
  DBGrid.WindowProc := OriginalDBGridWindowProc;
end;

procedure TDBGridForm.DBGridWindowProc(var Message: TMessage);
const 
  ScrollStylesToExclude = WS_VSCROLL or WS_HSCROLL;
var 
  Style: Integer;
begin
  if Message.Msg = WM_NCCALCSIZE then
  begin
    Style := GetWindowLong(Handle, GWL_STYLE);
    if (Style and ScrollStylesToExclude) <> 0 then // any scroll style to exclude present?
      SetWindowLong(Handle, GWL_STYLE, Style and not ScrollStylesToExclude);
  end
  else
    OrigWndProc(Message);
end;
end.

I think the SwissDelphiCenter solution in [WayBack] …hide the scrollbars of a DBGrid? originally has been copied from the 2003 post by Peter Below at [WayBack] how to hide DBCtrlGrid scrollbars – delphi.

(*
Q:
I want to hide the vertical scrollbar on a dbgrid when the record count
exceed a number. How can I do that?

A:
Make a descendent of the TDBGrid class. Add a handler for the
WM_NCCALCSIZE message.

Title: ...hide the scrollbars of a DBGrid?

Author: P. Below 

Category: VCL
*)
type
  TNoScrollDBGrid = class(TDBGrid)
  private
    procedure WMNCCalcSize(var Msg: TMessage);
    message WM_NCCALCSIZE;
  end;

procedure TNoScrollDBGrid.WMNCCalcSize(var Msg: TMessage);
const
  Scrollstyles = WS_VSCROLL or WS_HSCROLL;
var
  Style: Integer;
begin
  Style := GetWindowLong(Handle, GWL_STYLE);
  if (Style and Scrollstyles) <> 0 then
    SetWindowLong(Handle, GWL_STYLE, Style and not Scrollstyles);
  inherited;
end;

//This removes both scrollbars. If you want to remove only the vertical one
//change the scrollstyles constant accordingly.

I like this derived class from [WayBack] Delphi VCL Component • View topic • Hiding Scrollbars in DBGRID by Chris Luck based on the code from Peter Below more (I slightly condensed it from non-relevant code):

unit NoScrollDBGrid;

interface

uses
  Windows, Messages, DBGrids;

type
  TNoScrollDBGrid = class(TDBGrid)
  private
    FVertScroll: Boolean;
    FHorzScroll: Boolean;
    procedure WMNCCalcSize(var msg: TMessage); message WM_NCCALCSIZE;
    procedure SetVertScroll(Value: Boolean);
    procedure SetHorzScroll(Value: Boolean);
  published
    property VertScroll: Boolean read FVertScroll write SetVertScroll;
    property HorzScroll: Boolean read FHorzScroll write SetHorzScroll;
  end;

procedure Register;

implementation

uses
  Classes;
procedure TNoScrollDBGrid.SetVertScroll(Value: Boolean);
begin
  if FVertScroll <> Value then
  begin
    FVertScroll := Value;
    RecreateWnd;
  end;
end;

procedure TNoScrollDBGrid.SetHorzScroll(Value: Boolean);
begin
  if FHorzScroll <> Value then
  begin
    FHorzScroll := Value;
    RecreateWnd;
  end;
end;

procedure TNoScrollDBGrid.WMNCCalcSize(var msg: TMessage);
var
  style: Integer;
begin
  style := getWindowLong( handle, GWL_STYLE );

  if (NOT(FHorzScroll)) AND ((style and WS_HSCROLL) <> 0) then
    SetWindowLong( handle, GWL_STYLE, style and not WS_HSCROLL );

  if (NOT(FVertScroll)) AND ((style and WS_VSCROLL) <> 0) then
    SetWindowLong( handle, GWL_STYLE, style and not WS_VSCROLL );

  inherited;
end;

procedure Register;
begin
  RegisterComponents('Samples', [TNoScrollDBGrid]);
end;

end.

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

VMware ESXi console: viewing all VMs, suspending and waking them up: part 5

Posted by jpluimers on 2021/04/30

Yesterday’s post got a bit longer than anticipated as there were most steps than I hoped for to create the listing script vim-cmd-list-all-VMs.sh:

#!/bin/sh
# https://wiert.me/2021/04/29/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-4/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
done

This means that today there is a new try to cover the rest of these lists I started yesterday with:

Available commands

  • vim-cmd vmsvc/power.getstate vmid
  • vim-cmd vmsvc/power.hibernate vmid
  • vim-cmd vmsvc/power.off vmid
  • vim-cmd vmsvc/power.on vmid
  • vim-cmd vmsvc/power.reboot vmid
  • vim-cmd vmsvc/power.reset vmid
  • vim-cmd vmsvc/power.shutdown vmid
  • vim-cmd vmsvc/power.suspend vmid
  • vim-cmd vmsvc/power.suspendResume vmid

Unavailable commands

  • vim-cmd vmsvc/power.startup vmid
  • vim-cmd vmsvc/power.resume vmid
  • vim-cmd vmsvc/power.wakeup vmid

So here we go:

vim-cmd-hibernate-running-VMs.sh and vim-cmd-suspend-running-VMs.sh

These files are almost the same: the echo and command are different (Hibernating versus Suspending and power.hibernate versus suspend)

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Powered on" ] ; then
        echo "Powered on  VM with id ${vmid} and name: $name"
        echo "Hibernating VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.hibernate ${vmid}
    fi
done

This hibernates all VMs with power state Powered on and waits for each VM to complete hibernation.

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Powered on" ] ; then
        echo "Powered on VM with id ${vmid} and name: $name"
        echo "Suspending VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.suspend ${vmid}
    fi
done

This suspends all VMs with power state Powered on and waits for each VM to complete suspending.

vim-cmd-resume-suspended-VMs.sh and vim-cmd-wakeup-suspended-VMs.sh

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Suspended" ] ; then
        echo "Suspended VM with id ${vmid} and name: $name"
        echo "Resuming  VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.on ${vmid}
    fi
done

This resumes (as there is no vim-cmd vmsvc/power.resume vmid) all VMs with power state Suspended and waits for each VM to complete resume.

vim-cmd-power-off-powered-on-VMs.sh

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Powered on" ] ; then
        echo "Powered on   VM with id ${vmid} and name: $name"
        echo "Powering off VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.off ${vmid}
    fi
done

This powers off all VMs with power state Power on and waits for each VM to start powering off (but does not wait for them to complete powering off, so parts run in parallel).

vim-cmd-power-on-powered-off-VMs.shvim-cmd-power-on-shutdown-VMs.sh and vim-cmd-startup-shutdown-VMs.sh

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Powered off" ] ; then
        echo "Powered off VM with id ${vmid} and name: $name"
        echo "Powering on VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.on ${vmid}
    fi
done

These powers on all VMs with power state Powered off and waits for each VM to complete power on (but does not wait for them to complete boot, so part runs in parallel!).

These are exactly the same, as you cannot distinguish a VM that has been shutdown by vim-cmd vmsvc/power.off vmid from vim-cmd vmsvc/shutdown vmid.

vim-cmd-reboot-powered-on-VMs.sh

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Powered on" ] ; then
        echo "Powered on VM with id ${vmid} and name: $name"
        echo "Rebooting  VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.reboot ${vmid}
    fi
done

This reboots all VMs with power state Power on and waits for each VM to start rebooting (but does not wait for them to complete reboot, so parts run in parallel).

vim-cmd-reset-powered-on-VMs.sh

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Powered on" ] ; then
        echo "Powered on VM with id ${vmid} and name: $name"
        echo "Resetting  VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.reset ${vmid}
    fi
done

This resets all VMs with power state Power on and waits for each VM to start rebooting (but does not wait for them to complete reboot, so parts run in parallel).

vim-cmd-suspendResume-powered-on-VMs.sh

#!/bin/sh
# https://wiert.me/2021/04/30/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-5/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    # echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    if [ "${powerState}" == "Powered on" ] ; then
        echo "Powered on      VM with id ${vmid} and name: $name"
        echo "SuspendResuming VM with id ${vmid} and name: $name"
        vim-cmd vmsvc/power.suspendResume ${vmid}
    fi
done

This suspends and resumes on all VMs with power state Power on and waits for each VM to start this shirt cycle (but does not wait for them to complete the suspend and resume cycle, so parts run in parallel).

Future episodes

For now, this is OK enough for me, but I might write a new installment trying to run more of these in parallel (as parts already are done on the ESXi side).

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, Scripting, sed, sed script, Software Development, Virtualization, VMware, VMware ESXi | Leave a Comment »

VMware ESXi console: viewing all VMs, suspending and waking them up: part 4

Posted by jpluimers on 2021/04/29

Yesterday we ended with an overview of available and unavailable vim-cmd vmsvc commands and the promise to try running the various power commands on all relevant VMs.

Let’s start with a summary of the commands, so it will be easier to make a list of scripts to run them on relevant VMs.

Available commands

  • vim-cmd vmsvc/power.getstate vmid
  • vim-cmd vmsvc/power.hibernate vmid
  • vim-cmd vmsvc/power.off vmid
  • vim-cmd vmsvc/power.on vmid
  • vim-cmd vmsvc/power.reboot vmid
  • vim-cmd vmsvc/power.reset vmid
  • vim-cmd vmsvc/power.shutdown vmid
  • vim-cmd vmsvc/power.suspend vmid
  • vim-cmd vmsvc/power.suspendResume vmid

Unavailable commands

  • vim-cmd vmsvc/power.startup vmid
  • vim-cmd vmsvc/power.resume vmid
  • vim-cmd vmsvc/power.wakeup vmid

List the vmid values, power status and name of all VMs

Getting the vmid

Yesterday I showed a small statement that gives the list of vmid values on an ESXi system:

vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)s+((S.+S)?)s+([S+])s+(.+.vmx)s+(S+)s+(vmx-[[:digit:]]+)s*?((S.+)?)$/1/p"

What I ideally want is not just the vmid and name for each VM from vim-cmd vmsvc/getallvms, but also get the power state information from vim-cmd vmsvc/power.getstate vmid.

For that, we need to parse the output of vim-cmd vmsvc/power.getstate vmid, which can be three outputs:

  • Retrieved runtime info
    Powered off
  • Retrieved runtime info
    Powered on
  • Retrieved runtime info
    Suspended

So basically it involves deleting the first line which was covered in part 2 of this installment, for example on my system:

# vim-cmd vmsvc/power.getstate 10 | sed '1d'
Powered on

Getting VM name

Extracting both vmid and name from vim-cmd vmsvc/getallvms at the same time is not easy, heck even impossible, so I decided to go the vim-cmd vmsvc/get.config vmid way.

Getting multiple values out of some output is already very hard in bash, where usually the less difficult way is to use arrays. Since Busybox has an ash shell (see Busybox sh (actually ash derivative dash): checking exit codes), and ash does not do arrays, that route is gone.

To give you an idea how hard this is in bash and how to sort of workaround the lack of array support in ash:

This partial vim-cmd vmsvc/get.config vmid sample output on one of my VMs that shows how to use head -n 31 to get just the first 31 lines of output:

# vim-cmd vmsvc/get.config 10 | head -n 31
Configuration:

(vim.vm.ConfigInfo) {
   changeVersion = "2021-04-07T22:08:30.548274Z", 
   modified = "1970-01-01T00:00:00Z", 
   name = "X9SRI-3F-W10P-EN-MEDIA", 
   guestFullName = "Microsoft Windows 10 (64-bit)", 
   version = "vmx-14", 
   uuid = "564d51ac-f6cf-e40b-b686-2f53a28a4bea", 
   createDate = "2019-05-17T21:37:11.408173Z", 
   instanceUuid = "52403d0e-7ccd-48da-bb21-7e966defccf7", 
   npivNodeWorldWideName = , 
   npivPortWorldWideName = , 
   npivWorldWideNameType = , 
   npivDesiredNodeWwns = , 
   npivDesiredPortWwns = , 
   npivTemporaryDisabled = true, 
   npivOnNonRdmDisks = , 
   locationId = "564d6b18-ecd1-2261-0127-146b3f3bc636", 
   template = false, 
   guestId = "windows9_64Guest", 
   alternateGuestName = "", 
   annotation = "", 
   files = (vim.vm.FileInfo) {
      vmPathName = "[EVO860_500GB] VM/X9SRI-3F-W10P-EN-MEDIA/X9SRI-3F-W10P-EN-MEDIA.vmx", 
      snapshotDirectory = "[EVO860_500GB] VM/X9SRI-3F-W10P-EN-MEDIA", 
      suspendDirectory = "[EVO860_500GB] VM/X9SRI-3F-W10P-EN-MEDIA", 
      logDirectory = "[EVO860_500GB] VM/X9SRI-3F-W10P-EN-MEDIA", 
      ftMetadataDirectory = 
   }, 
   tools = (vim.vm.ToolsConfigInfo) {

The reason to go the vim-cmd vmsvc/get.config vmid way is that it contains all the configuration info in a kind of JSON format (except the first two lines) and should be relatively easy to parse. Or so at least I hoped.

Basically I am interested in the value of name = "X9SRI-3F-W10P-EN-MEDIA", however, there are multiple name fields in the total configuration:

# vim-cmd vmsvc/get.config 10 | sed -n -E '/name =/p'
   name = "X9SRI-3F-W10P-EN-MEDIA", 
         name = "EVO860_500GB",

So what I really want is the value of name = "X9SRI-3F-W10P-EN-MEDIA", in between the (vim.vm.ConfigInfo) { and files = (vim.vm.FileInfo) { parts.

This can be done using sed as it allows to specify a range using a start and end value using addresses:

  • [Wayback] sed: Addresses in sed

    An address is either a decimal number that counts input lines cumulatively across files, a '$' character that addresses the last line of input, or a context address (which consists of a BRE, as described in Regular Expressions in sed , preceded and followed by a delimiter, usually a slash).

    An editing command with no addresses shall select every pattern space.

    An editing command with one address shall select each pattern space that matches the address.

    An editing command with two addresses shall select the inclusive range from the first pattern space that matches the first address through the next pattern space that matches the second. (If the second address is a number less than or equal to the line number first selected, only one line shall be selected.) Starting at the first line following the selected range, sed shall look again for the first address. Thereafter, the process shall be repeated. Omitting either or both of the address components in the following form produces undefined results:

    [address[,address]]
  • Range Addresses (sed, a stream editor)[Wayback] Range Addresses (sed, a stream editor)

    An address range can be specified by specifying two addresses separated by a comma (,). An address range matches lines starting from where the first address matches, and continues until the second address matches (inclusively):

    $ seq 10 | sed -n '4,6p'
    4
    5
    6
    

    If the second address is a regexp, then checking for the ending match will start with the line following the line which matched the first address: a range will always span at least two lines (except of course if the input stream ends).

  • [Wayback] Regexp Addresses (sed, a stream editor)

For example (with some characters escaped because of [Wayback] ERE syntax (sed, a stream editor)):

# vim-cmd vmsvc/get.config 10 | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/p'
(vim.vm.ConfigInfo) {
   changeVersion = "2021-04-07T22:08:30.548274Z", 
   modified = "1970-01-01T00:00:00Z", 
   name = "X9SRI-3F-W10P-EN-MEDIA", 
   guestFullName = "Microsoft Windows 10 (64-bit)", 
   version = "vmx-14", 
   uuid = "564d51ac-f6cf-e40b-b686-2f53a28a4bea", 
   createDate = "2019-05-17T21:37:11.408173Z", 
   instanceUuid = "52403d0e-7ccd-48da-bb21-7e966defccf7", 
   npivNodeWorldWideName = , 
   npivPortWorldWideName = , 
   npivWorldWideNameType = , 
   npivDesiredNodeWwns = , 
   npivDesiredPortWwns = , 
   npivTemporaryDisabled = true, 
   npivOnNonRdmDisks = , 
   locationId = "564d6b18-ecd1-2261-0127-146b3f3bc636", 
   template = false, 
   guestId = "windows9_64Guest", 
   alternateGuestName = "", 
   annotation = "", 
   files = (vim.vm.FileInfo) { 

With [Wayback] BRE syntax (sed, a stream editor) the filter part would be easier: vim-cmd vmsvc/get.config 10 | sed -n -e '/(vim.vm.ConfigInfo) {/,/files = (vim.vm.FileInfo) {/p', but the print part would be more difficult:

  • # vim-cmd vmsvc/get.config 10 | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/1/p'
    X9SRI-3F-W10P-EN-MEDIA
    
  • # vim-cmd vmsvc/get.config 10 | sed -n -e '/(vim.vm.ConfigInfo) {/,/files = (vim.vm.FileInfo) {/ s/^ +name = "(.*)",.*?/1/p'
    X9SRI-3F-W10P-EN-MEDIA

Since I am used to extended regular expressions (ERE) over basica regular expressions (BRE), I prefer the first solution.

So getting the name in a variable now becomes this:

# name=`vim-cmd vmsvc/get.config 10 | sed -n -e '/(vim.vm.ConfigInfo) {/,/files = (vim.vm.FileInfo) {/ s/^ +name = "(.*)",.*?/1/p'`
# echo ${name}
X9SRI-3F-W10P-EN-MEDIA

List the vmid values, power status and name of all VMs

Back to the listing script vim-cmd-list-all-VMs.sh:

#!/bin/sh
# https://wiert.me/2021/04/29/vmware-esxi-console-viewing-all-vms-suspending-and-waking-them-up-part-4/
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    echo "VM with id ${vmid} has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
done

As a bonus, next to powerState, the script also figures out vmPathName in a similar way to name.

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, head, Power User, Scripting, sed, sed script, Software Development, tee, Virtualization, VMware, VMware ESXi | Leave a Comment »

Some links on Delphi and CHM help files

Posted by jpluimers on 2021/04/29

I hardly use help files, but some older systems do, and when porting really old Delphi code, often odd implementations of accessing them through HHCTRL.OCX are used.

Since I tend to forget the correct way using the HtmlHelpViewer unit, here are some links:

Very old code involving the OCX file:

Quote from the first link [WayBack] How to Connect HTML Help with your Delphi Application:

Linking HTML Help (CHM) Files

You should add the “HTMLHelpViewer” unit to the “Uses” clause in the main form of your application. Then set the full path to your CHM file to Application.HelpFile property. To do so, you can add the following line to the main form’s “On Create” event handler:

Application.HelpFile := ExtractFilePath(Application.ExeName) + 'HelpFile.chm';

where “HelpFile.chm” is the actual name of your HTML Help file, located in the same directory as your application’s executable file.

Using HTML Help from Code

When you need to display your help file or a specific help topic, or perform others actions, you can use the following calls:

Displaying a help topic

Application.HelpContext(IDH_TOPIC);

where IDH_TOPIC is the ContextId value of the topic to display.

Displaying the Table of Contents tab

HtmlHelp(0, Application.HelpFile, HH_DISPLAY_TOC, 0);

Displaying the Index tab

HtmlHelp(0, Application.HelpFile, HH_DISPLAY_INDEX, DWORD(PWideChar('Test')));

Displaying the Search tab

var
  Query: THH_Fts_QueryW;
begin
  with Query do
  begin
    cbStruct := SizeOf(THH_Fts_QueryW);
    fUniCodeStrings := True;
    pszSearchQuery := '';
    iProximity := 0;
    fStemmedSearch := True;
    fTitleOnly := False;
    fExecute := True;
    pszWindow := nil;
  end;
  HtmlHelp(0, Application.HelpFile, HH_DISPLAY_SEARCH, DWORD(@Query));
end;

Performing Keyword Lookup

Application.HelpKeyword('Test');

Providing Help for Controls

You can link specific help topics with any controls located on the form. In this case a control will automatically display the corresponding help topic when the user focuses it and presses F1. Also, you can add the standard [?] button to the caption area of the form: using the Object Inspector, set the form’s BorderStyle property as bsDialog and biHelp member of the BorderIcons property to True. Then set the controls’ HelpContext properties that should correspond to the topic ContextId values as defined in your help project.

–jeroen

Read the rest of this entry »

Posted in Delphi, Development, Software Development | Leave a Comment »

VMware ESXi console: viewing all VMs, suspending and waking them up: part 3

Posted by jpluimers on 2021/04/28

Yesterday’s installment ended with a list of power related vim-cmd vmsvc commands:

Usage: power.getstate vmid
Usage: power.hibernate vmid
Usage: power.off vmid
Usage: power.on vmid
Usage: power.reboot vmid
Usage: power.reset vmid
Usage: power.shutdown vmid
Usage: power.suspend vmid
Usage: power.suspendResume vmid

Getting vmid values

These all have a vmid parameter, so let’s create a small statement that gives the list of vmid on an ESXi system:

vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"

On my system the relevant VMs it returns are these:

10
5

The various power commands

The outcome of the various power commands are not as simple as one might think as they often do not just depend on the current power state of the VM, but also on either VMware Tools or open-vm-tools to be running.

Basically these tools do the same, but their origin is different: open-vm-tools is often included as part of Linux distributions; VMware Tools is often installed separately, see:

I have made a table for this hoping it makes reading easier, the explanations are by empirical usage, as the documentation in the help dump (see [Wayback] delimited vim-cmd help for each vmsvc command.txt) does not seem to match behaviour.

Command Explanation
vim-cmd vmsvc/power.getstate vmid Gets the power state of the VM, returning a line Retrieved runtime info followed by lines indicating the power state:

  • Powered off
  • Powered on
  • Suspended
vim-cmd vmsvc/power.hibernate vmid When neither VMware Tools or open-vm-tools to be running, you get an error:

(vim.fault.ToolsUnavailable) {
   faultCause = (vmodl.MethodFault) null, 
   faultMessage = 
   msg = "Received SOAP response fault from []: standbyGuest
Cannot complete operation because VMware Tools is not running in this virtual machine."
}

When a hibernate/suspend task is already running, you get an error:

(vim.fault.TaskInProgress) {
   faultCause = (vmodl.MethodFault) null, 
   faultMessage = , 
   task = 'vim.Task:haTask-12-vim.VirtualMachine.suspend-1006072588'
   msg = "Received SOAP response fault from []: standbyGuest
Another task is already in progress."
}

Otherwise, depends on the power state of the VM if vmware tools:

  • Powered off: keeps the power state of the VM as Powered off and shows an error
    (vim.fault.InvalidPowerState) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       requestedState = "poweredOn", 
       existingState = "poweredOff"
       msg = "Received SOAP response fault from []: standbyGuest
    The attempted operation cannot be performed in the current state (Powered off)."
    }
  • Powered on: sets the power state of the VM to Suspended and shows no output, unless neither VMware Tools, nor open-vm-tools can be communicated with, then you get this error:
    (vmodl.fault.SystemError) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       reason = "Invalid fault"
       msg = "Received SOAP response fault from []: standbyGuest
    vim.fault.GenericVmConfigFault"
    }
  • Suspended: keeps the power state of the VM as Suspended and shows an error
    (vim.fault.InvalidPowerState) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       requestedState = "poweredOn", 
       existingState = "suspended"
       msg = "Received SOAP response fault from []: standbyGuest
    The attempted operation cannot be performed in the current state (Suspended)."
    }
vim-cmd vmsvc/power.off vmid Depends on the power state of the VM and either VMware Tools or open-vm-tools to be running:

  • Powered off: keeps the power state of the VM as Powered off and shows two lines
    Powering off VM:
    Power off failed
  • Powered on: powers off the VM (bypasses any VMware Tools or open-vm-tools) and sets power state of the VM to Powered off showing one line
    Powering off VM:
  • Suspended: Hardware powers off the VM (bypasses any VMware Tools or open-vm-tools) and sets power state of the VM to Powered off showing one line
    Powering off VM:
vim-cmd vmsvc/power.on vmid Depends on the power state of the VM:

  • Powered on: keeps power state of the VM as Powered off showing two lines
    Powering on VM:
    Power on failed
  • Powered off: keeps the power state of the VM as Powered off and shows one line
    Powering ofn VM:
  • Suspended: keeps the power state of the VM as Suspended showing two lines
    Powering on VM:
    Power on failed

This also undoes a vim-cmd vmsvc/power.hibernate vmid, vim-cmd vmsvc/power.shutdown vmid or vim-cmd vmsvc/power.suspend vmid.

vim-cmd vmsvc/power.reboot vmid Depends on the power state of the VM and either VMware Tools or open-vm-tools to be running:

  • Powered off: keeps the power state of the VM as Powered off and shows the error
    (vim.fault.InvalidPowerState) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       requestedState = "poweredOn", 
       existingState = "poweredOff"
       msg = "Received SOAP response fault from []: rebootGuest
    The attempted operation cannot be performed in the current state (Powered off)."
    }
  • Powered on and either VMware Tools or open-vm-tools are running: uses VMware Tools or open-vm-tools to reboot the VM: keeps the power state of the VM as Powered on.
  • Powered on, but neither VMware Tools nor open-vm-tools are running: keeps the power state of the VM as Powered on and shows the error
    (vim.fault.ToolsUnavailable) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = 
       msg = "Received SOAP response fault from []: rebootGuest
    Cannot complete operation because VMware Tools is not running in this virtual machine."
    }
  • Suspended: keeps the power state of the VM as Suspended and shows the error
    (vim.fault.InvalidPowerState) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       requestedState = "poweredOn", 
       existingState = "suspended"
       msg = "Received SOAP response fault from []: rebootGuest
    The attempted operation cannot be performed in the current state (Suspended)."
    }
vim-cmd vmsvc/power.reset vmid Depends on the power state of the VM:

  • Powered off: keeps the power state of the VM as Powered off and shows two lines
    Reset VM:
    Reset failed
  • Powered on: keeps the power state of the VM as Powered on, bypasses running VMware Tools or open-vm-tools (basically like a hardware reset button) and shows one line
    Reset VM:
  • Suspended: keeps the power state of the VM as Suspended and shows two lines
    Reset VM:
    Reset failed
vim-cmd vmsvc/power.shutdown vmid Depends on the power state of the VM and either VMware Tools or open-vm-tools to be running:

  • Powered off: keeps the power state of the VM as Powered off and shows the error
    (vim.fault.InvalidPowerState) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       requestedState = "poweredOn", 
       existingState = "poweredOff"
       msg = "Received SOAP response fault from []: shutdownGuest
    The attempted operation cannot be performed in the current state (Powered off)."
    }
  • Powered on and either VMware Tools or open-vm-tools are running: uses VMware Tools or open-vm-tools to shutdown the VM and sets the power state of the VM to Powered off without showing any output.
  • Powered on, but neither VMware Tools nor open-vm-tools are running: keeps the power state of the VM as Powered on and shows the error
    (vim.fault.ToolsUnavailable) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = 
       msg = "Received SOAP response fault from []: shutdownGuest
    Cannot complete operation because VMware Tools is not running in this virtual machine."
    }
  • Suspended: keeps the power state of the VM as Suspended and shows the error
    (vim.fault.InvalidPowerState) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       requestedState = "poweredOn", 
       existingState = "suspended"
       msg = "Received SOAP response fault from []: shutdownGuest
    The attempted operation cannot be performed in the current state (Suspended)."
    }
vim-cmd vmsvc/power.suspend vmid When neither VMware Tools or open-vm-tools to be running, you get an error:

(vim.fault.ToolsUnavailable) {
   faultCause = (vmodl.MethodFault) null, 
   faultMessage = 
   msg = "Received SOAP response fault from []: standbyGuest
Cannot complete operation because VMware Tools is not running in this virtual machine."
}

When a hibernate/suspend task is already running, you get an error:

(vim.fault.TaskInProgress) {
   faultCause = (vmodl.MethodFault) null, 
   faultMessage = , 
   task = 'vim.Task:haTask-12-vim.VirtualMachine.suspend-1006072588'
   msg = "Received SOAP response fault from []: standbyGuest
Another task is already in progress."
}

Otherwise, depends on the power state of the VM:

  • Powered off: keeps the power state of the VM as Powered off and shows two lines
    Suspending VM:
    Suspend failed
  • Powered on: keeps the power state of the VM as Powered on, and shows one line
    Suspending VM:

    unless neither VMware Tools, nor open-vm-tools can be communicated with, then you get this error:

    (vmodl.fault.SystemError) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = , 
       reason = "Invalid fault"
       msg = "Received SOAP response fault from []: standbyGuest
    vim.fault.GenericVmConfigFault"
    }
  • Suspended: keeps the power state of the VM as Suspended and shows two lines
    Suspending VM:
    Suspend failed
vim-cmd vmsvc/power.suspendResume vmid Depends on the power state of the VM:

  • Powered off: keeps the power state of the VM as Powered off and shows two lines
    Suspend/Resuming the VM:
    Suspend/Resume failed
  • Powered on: keeps the power state of the VM as Powered on, and shows one line
    Suspend/Resuming the VM:
  • Suspended: keeps the power state of the VM as Suspended and shows two lines
    Suspend/Resuming the VM:
    Suspend/Resume failed

Note that in the VMware web console, this is shown as “Invoke FSR” which is a Fast Suspend Resume, which I think has to do with vMotion.

Notes:

  • there is no command vim-cmd vmsvc/power.startup vmid (to undo vim-cmd vmsvc/power.shutdown vmid), use vim-cmd vmsvc/power.on vmid in stead.
  • there is no command vim-cmd vmsvc/power.resume vmid (to undo vim-cmd vmsvc/power.suspend vmid), use vim-cmd vmsvc/power.on vmid in stead.
  • there is no command vim-cmd vmsvc/power.wakeup vmid (to undo vim-cmd vmsvc/power.hibernate vmid), use vim-cmd vmsvc/power.on vmid in stead.

Running the various power commands on all relevant VMs

This will be the topic for the next installment.

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, Scripting, sed, sed script, Software Development, Virtualization, VMware, VMware ESXi | 1 Comment »

Little Delphi tip: after “Build the current build group”, do not be surprised debugging fails

Posted by jpluimers on 2021/04/28

The Delphi Build groups are great for quickly building a lot of projects in your project group with their various build configuration.

One very important tip though: it builds in DEBUG, then RELEASE mode, then leaves the IDE thinking all projects have been built in the project manager “Build Configuration”.

That assumption is only true, if no “Build Configuration” is “DEBUG”.

It means that if you start debugging your application right after performing a “Build the current build group”, and those include RELEASE as final mode, that your debugger will be using a RELEASE mode build instead of a DEBUG build.

Quick screenshot:

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

VMware ESXi console: viewing all VMs, suspending and waking them up: part 2

Posted by jpluimers on 2021/04/27

Last week ended up to be a kind of VMware ESXi heavey, and this week will be similar. So it is time for following up on VMware ESXi console: viewing all VMs, suspending and waking them up: part 1.

That one ended with

Then we get this to print some of the capture groups:

vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/Vmid:\1 Guest:\6 Version:\7 Name:\3 Datastore:\4 File:\5 Annotation:\8/p"

With this output:

Vmid:10 Guest:windows9_64Guest Version:vmx-14 Name:X9SRI-3F-W10P-EN-MEDIA Datastore:[EVO860_500GB] File:VM/X9SRI-3F-W10P-EN-MEDIA/X9SRI-3F-W10P-EN-MEDIA.vmx Annotation:
Vmid:5 Guest:centos64Guest Version:vmx-11 Name:PPB Local_Virtual Machine_v4.0 Datastore:[EVO860_500GB] File:VM/PPB-Local_Virtual-Machine_v4.0/PPB Local_Virtual Machine_v4.0.vmx Annotation:PowerPanel Business software(Local) provides the service which communicates

Figuring out power state for each VM

This will be in the next installment, as by now this already has become a big blog-post (:

I basically went the vim-cmd vmsvc way instead of the esxcli vm way. My motivation was the easier to understand ID values. They are the basis of virtually all vim-cmd vmsvc based commands:

# vim-cmd vmsvc --help
Commands available under vmsvc/:
acquiremksticket                 get.snapshotinfo                 
acquireticket                    get.spaceNeededForConsolidation  
createdummyvm                    get.summary                      
destroy                          get.tasklist                     
device.connection                getallvms                        
device.connusbdev                gethostconstraints               
device.ctlradd                   message                          
device.ctlrremove                power.getstate                   
device.disconnusbdev             power.hibernate                  
device.diskadd                   power.off                        
device.diskaddexisting           power.on                         
device.diskextend                power.reboot                     
device.diskremove                power.reset                      
device.getdevices                power.shutdown                   
device.nvdimmadd                 power.suspend                    
device.nvdimmremove              power.suspendResume              
device.toolsSyncSet              queryftcompat                    
devices.createnic                reload                           
get.capability                   setscreenres                     
get.config                       snapshot.create                  
get.config.cpuidmask             snapshot.dumpoption              
get.configoption                 snapshot.get                     
get.datastores                   snapshot.remove                  
get.disabledmethods              snapshot.removeall               
get.environment                  snapshot.revert                  
get.filelayout                   snapshot.setoption               
get.filelayoutex                 tools.cancelinstall              
get.guest                        tools.install                    
get.guestheartbeatStatus         tools.upgrade                    
get.managedentitystatus          unregister                       
get.networks                     upgrade                          
get.runtime                      

My “goto” for getting information is [Wayback] “vim-cmd vmsvc” site:vmware.com – Google Search, and a few sample pages are here:

  1. [Wayback] Performing common virtual machine-related tasks with command-line utilities (2012964) (showing that there are many tasks only vim-cmd vmsvc can do, but esxcli vm cannot)
  2. [Wayback] Powering on a virtual machine from the command line when the host cannot be managed using vSphere Client (1038043) (showing how to combine vim-cmd vmsvc/getallvms, vim-cmd vmsvc/power.getstate and vim-cmd vmsvc/power.on)
  3. [Wayback] Determine the power status of a virtual machine on an ESX or ESXi host (1003737) (showing vim-cmd vmsvc/getallvms, vim-cmd vmsvc/power.getstate and ps –auxwww | grep –i VM_NAME)
  4. [Wayback] Collecting information about tasks in VMware ESXi/ESX (1013003) (showing the relation between VMs and tasks using  vim-cmd vimsvc/task_list, vim-cmd vmsvc/getallvms and vim-cmd vimsvc/task_info)
  5. [Wayback] Unable to Power off a Virtual Machine in an ESXi host (1014165) (focussing on vim-cmd vmsvc/getallvms, vim-cmd vmsvc/power.getstate, vim-cmd vmsvc/power.shutdown and vim-cmd vmsvc/power.off)
  6. [Wayback] Reloading a vmx file without removing the virtual machine from inventory (1026043) (showing vim-cmd vmsvc/getallvms and vim-cmd vmsvc/reload)
  7. [Wayback] Investigating virtual machine file locks on ESXi hosts (10051) (trying to show how to combine vim-cmd vmsvc/getallvms, grep, awk, find and xargs to find vmdk files, but fails because of parsing errors)

The pattern above is that most of the vim-cmd vmsvc examples are for power state and tasks. Not fully sure why, but my guess is it is what most people use it for. That kind of use what this series of posts also focuses on too, but certainly not the only use. Read the first numbered entry above to get a full grasp of what is possible. I hope to find time in the future to show some more examples outside the power and task realms.

Basically the only time you need to check out esxcli with VMs is when you cannot shut down a VM in a normal way. These links explain what to do in that case:

So let’s go back to basics, and start with getting info on all vim-cmd vmsvc commands.

Help on all vim-cmd vmsvc commands

Executing vim-cmd help vmsvc (preferred) or vim-cmd help vmsvc --help gives you all commands prepended with the line Commands available under vmsvc/:.

Executing vim-cmd help vmsvc/command prints the help for a single command (but vim-cmd help vmsvc/command -help first prints an error, then the help).

Here are the steps how I got the help help for all commands.

First I needed a list of all commands. This is already a multi-stage process, so below the full command I will explain the bits.

vim-cmd help vmsvc | sed '1d' | xargs -n 1 -r echo | sort
  1. vim-cmd help vmsvc gives all the commands (two per line!) prepended by the line Commands available under vmsvc/:.
  2. sed '1d' stripts that line.
  3. xargs -n 1 -r echo does a lot of things:
    1. It parses the sed '1d' input line by line, splits each line into parts, combines all the parts, then executes echo with the combined parts
    2. The -n 1 ensures each invocation of echo takes only a single one of the combined parts
    3. -r is just a protection: if there is no input, then echo is never executed, resulting in empty output
  4. sort will sort all the combined output of all the echo invocations to undo the horizontal combination of parts that xargs did

Now getting the help is doing more of the above, with some more bits to explain:

vim-cmd help vmsvc | sed '1d' | xargs -n 1 -r echo | sort | xargs -n 1 -r -I {} vim-cmd help vmsvc/{}
  1. Normally, xargs will execute each command by appending the parameter inserting a space in front of each parameter
  2. -I {} will force xargs to put each argument just as is in the place where {} is used in the argument
  3. This executes vim-cmd help vmsvc/command in stead of vim-cmd help vmsvc/ command

The result is a long blob of text that is very hard to read as there are no separators between the commands. I saved it as a [Wayback] vim-cmd help for each vmsvc command.txt gist.

With a sh -c shell trick, you can add some more information and separation to the output by embedding :

vim-cmd help vmsvc | sed '1d' | xargs -n 1 -r echo | sort | xargs -n 1 -r -I {} sh -c 'echo "-----" ; echo "help for vim-cmd help vmsvc/{}" ; echo ; vim-cmd help vmsvc/{}'

I have added the output to the [Wayback] delimited vim-cmd help for each vmsvc command.txt gist.

Commands taking a vmid parameter

Now that we know how to output all help, we can filter on it.

An interesting one is to filder only commands taking a vmid parameter:

vim-cmd help vmsvc | sed '1d' | xargs -n 1 -r echo | sort | xargs -n 1 -r -I {} vim-cmd help vmsvc/{} | grep -iw vmid

On VMware ESXi 6.7, this gets you the list:

Usage: acquiremksticket vmid
Usage: acquireticket vmid ticketType
Usage: destroy vmid
Usage: device.connection vmid deviceKey connect
Usage: device.connusbdev vmid usbid
Usage: device.ctlradd vmid ctlr_type bus_number
Usage: device.ctlrremove vmid ctlr_type bus_number
Usage: device.disconnusbdev vmid usbid
Usage: device.diskadd vmid size controller_numer unit_number datastore [ctlr_type]
Usage: device.diskaddexisting vmid disk_file controller_number unit_number [ctlr_type]
Usage: device.diskextend vmid new_size controller_numer unit_number [ctlr_type]
Usage: device.diskremove vmid controller_number unit_number delete_file [controller_type]
Usage: device.getdevices vmid
Usage: device.nvdimmadd vmid size
Usage: device.nvdimmremove vmid deviceKey
Usage: device.toolsSyncSet vmid new state
Usage: devices.createnic vmid adapter-type network-id [network-type]
Usage: get.capability vmid
Usage: get.config vmid
Usage: get.config.cpuidmask vmid
Usage: get.configoption vmid
Usage: get.datastores vmid
Usage: get.disabledmethods vmid
Usage: get.environment vmid
Usage: get.filelayout vmid
Usage: get.filelayoutex vmid
Usage: get.guest vmid
Usage: get.guestheartbeatStatus vmid
Usage: get.managedentitystatus vmid
Usage: get.networks vmid
Usage: get.runtime vmid
Usage: get.snapshotinfo vmid
Usage: get.spaceNeededForConsolidation vmid
Usage: get.summary vmid
Usage: get.tasklist vmid
Usage: message vmid [messageId] [messageChoice]
Usage: power.getstate vmid
Usage: power.hibernate vmid
Usage: power.off vmid
Usage: power.on vmid
Usage: power.reboot vmid
Usage: power.reset vmid
Usage: power.shutdown vmid
Usage: power.suspend vmid
Usage: power.suspendResume vmid
Usage: queryftcompat vmid [faultToleranceType]
Usage: reload vmid
Usage: setscreenres vmid width height
Usage: snapshot.create vmid [snapshotName] [snapshotDescription] [includeMemory] [quiesced]
Usage: snapshot.get vmid
Usage: snapshot.remove vmid snapshotId [removeChildren]
Usage: snapshot.removeall vmid
Usage: snapshot.revert vmid snapshotId suppressPowerOn
Usage: snapshot.setoption [OPTIONS] vmid
Usage: tools.cancelinstall vmid
Usage: tools.install vmid
Usage: tools.upgrade vmid [args]
Usage: unregister vmid
Usage: upgrade vmid [vm_hwversion]

In the above list, the bold entries have to do with power, that is what this series is supposed to center around, so more on that tomorrow.

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Awk, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, fgrep, Power User, Scripting, sed, sed script, sh, Sh Shell, Software Development, sort, Virtualization, VMware, VMware ESXi, xargs | Leave a Comment »