VMware/vSphere/esxcli/Custom Plugins

From Omnia
< VMware‎ | vSphere‎ | esxcli
Jump to navigation Jump to search

Custom Plugins

ESXCLI Partner Extensiblity | VMware vSphere Blog - VMware Blogs - http://blogs.vmware.com/vsphere/2012/02/esxcli-partner-extensiblity.html

  • by William Lam
  • "Many vSphere administrators are familiar with the ESXCLI command-line utility that helps manage and configure settings on their ESX and ESXi hosts. With the release of vSphere 5.0, ESXCLI now includes a total of 250 commands that span across various namespaces. One would expect that VMware can easily extend and create new namespaces to expose VMware platform specific functionality. An example of this would be the vcloud namespace that is made available when vCloud Director is installed. What you may not know is, ESXCLI was actually built with a modular and extensible framework from the ground up and can easily be extended by third party providers as well."
  • No instructions though!

-

NOTE: RESTART HOSTD FOR CHANGES TO PLUGINS TO TAKE EFFECT

/etc/init.d/hostd restart

-

VMware Front Experience: How to write your own esxcli plugin - http://www.v-front.de/2013/01/release-esxcli-plugin-to-run-arbitrary.html

-

Documentation - https://vdc-repo.vmware.com/vmwb-repository/sdk_vmkapiddk-2013-vmwb30-ed681d01e7df4111a5f8b1e7910d08a6/doc/#linka7ffebb4150895da6cdd8afd490376de08836e14;vmware.hostextensions/HostExtensions_ESXCLI.4.1.html

-

VIB Package Editor Guide - https://vdc-repo.vmware.com/vmwb-repository/sdk_vmkapiddk-2013-vmwb30-ed681d01e7df4111a5f8b1e7910d08a6/doc/#link5acae8fe22439b3b71b94cacae50bcf0d17fea9f;vmware.hostextensions/HostExtensions_Workbench.3.1.html

Host Extensions - VMware Developer Center - http://developercenter.vmware.com/web/dp/other-programs/host-ext

  • Host-based extensions or plug-ins broaden the ESXi hypervisor platform and give customers a rich set of value-added host management solutions. The Host Extensions Program (HEX) provides partners with development tools and resources for releasing these host-based extensions.

SDKs & APIs - VMware Developer Center - https://developercenter.vmware.com/web/dp/dev-kits/sdks

  • Platform & Compute - Host Extensions SDK - !!LOCKED!!

Documentation - VIB Package Editor Introduction - https://vdc-repo.vmware.com/vmwb-repository/sdk_vmkapiddk-2013-vmwb30-ed681d01e7df4111a5f8b1e7910d08a6/doc/

VMware Front Experience: How to write your own esxcli plugin - http://www.v-front.de/2013/01/how-to-write-your-own-esxcli-plugin.html

Introducing the VIB Author Fling | VMware vSphere Blog - VMware Blogs - http://blogs.vmware.com/vsphere/2012/09/introducing-the-vib-author-fling.html

  • "I’m very excited to announce the new vibauthor fling. This fling is hot off the press and provides the capability to create custom vSphere Installation Bundles (VIBs). Prior to this fling the VIB authoring tools were only available to VMware partners, this fling now extends this capability to everyone. There are a couple of use cases for creating custom VIBs. For example, if you are using Auto Deploy and you need to add a custom firewall rule to your host, or you need to make a configuration change that can’t be made using Host Profiles."

-

How to write your own esxcli plugin - http://www.vmwaredirectory.com/component/mtree/esx-i/console/how-to-write-your-own-esxcli-plugin

  • "I want to share what you need to know about the esxcli plugin system to be able to write your own plugins."

I finally ended up with the following contents for the esxcli-shell.xml file:

01	<?xml version="1.0"?>
02	<plugin xmlns="http://www.vmware.com/Products/ESX/5.0/esxcli/">
03	  <version>1.0.0</version>
04	   
05	  <namespaces>
06	    <namespace path="shell">
07	      <description>Run any ESXi shell command</description>
08	    </namespace>
09	  </namespaces>
10	 
11	  <commands>
12	   
13	    <command path="shell.cmd">
14	      <description>Run shell command(s) passed by parameter</description>
15	      <input-spec>
16	        <parameter name="command" shortname="c" type="string-list" required="true">
17	          <description>Shell command(s) to execute</description>
18	        </parameter>
19	  <parameter name="logfile" shortname="l" type="string" required="false">
20	    <description>Specifies a log file to redirect the commands' standard and error output to (see also --errlog)</description>
21	        </parameter>
22	  <parameter name="errlog" shortname="e" type="string" required="false">
23	    <description>Specifies a log file to redirect the commands' error output to (overrides --logfile if also set)</description>
24	        </parameter>
25	  <parameter name="workdir" shortname="d" type="string" required="false">
26	    <description>Specifies a working directory for the shell command(s)</description>
27	        </parameter>
28	  <parameter name="lappend" shortname="a" type="flag" required="false">
29	    <description>Append to existing log file(s) (ignored if --logfile and/or --errlog is not also set)</description>
30	        </parameter>
31	      </input-spec>
32	      <output-spec>
33	        <string />
34	      </output-spec>
35	      <has-updates value="false" />
36	      <format-parameters>
37	        <formatter>simple</formatter>
38	      </format-parameters>
39	      <execute>/opt/VFrontDe/esxcli-shell/bin/esxcli-shell.sh $multilist{command,-c,true} $if{workdir,-d "$val{workdir}"} $if{logfile,-l "$val{logfile}"} $if{errlog,-e "$val{errlog}"} $if{lappend,-a}</execute>
40	    </command>
41	   
42	    <command path="shell.about">
43	      <description>About the esxcli shell plugin</description>
44	      <input-spec />
45	      <output-spec>
46	        <string />
47	      </output-spec>
48	      <has-updates value="false" />
49	      <format-parameters>
50	        <formatter>simple</formatter>
51	      </format-parameters>
52	      <execute>/opt/VFrontDe/esxcli-shell/bin/esxcli-shell.sh -i</execute>
53	    </command>
54	 
55	  </commands>
56	</plugin>

This is the code of the esxcli-shell.sh script used in the esxcli-shell plugin:

01	#!/bin/sh
02	#
03	TMPSH=/tmp/esxcli-shell.$$
04	#
05	while getopts :c:d:l:e:ai opt; do
06	   case $opt in
07	   c) echo $OPTARG | sed -e 's/\\\(.\)/\1/g' -e 's/^"\(.*\)"$/\1/' -e "s/^'\(.*\)'$/\1/" >>$TMPSH ;;
08	   d) wdir=$OPTARG ;;
09	   l) logfile=$OPTARG ;;
10	   e) errlog=$OPTARG ;;
11	   a) appendlog=">" ;;
12	   i) about=1 ;;
13	   esac
14	done
15	#
16	echo "<?xml version=\"1.0\" ?>"
17	echo "<output xmlns=\"http://www.vmware.com/Products/ESX/5.0/esxcli/\">"
18	echo -n "<string><![CDATA["
19	#
20	if [ "$about" == "1" ]; then
21	   cat <<EOT
22	 
23	Esxcli Shell plugin v1.1 by
24	   Andreas Peetz (http://www.v-front.de)
25	...
42	   possibility of such damages.
43	EOT
44	else
45	   oldPWD="$PWD"
46	   [ -n "$wdir" ] && cd "$wdir"
47	   cmd=". $TMPSH"
48	   [ -n "$logfile" ] && cmd="$cmd >$appendlog\"$logfile\""
49	   if [ -n "$errlog" ]; then
50	      cmd="$cmd 2>$appendlog\"$errlog\""
51	   else
52	      cmd="$cmd 2>&1"
53	   fi
54	   cat $TMPSH | logger -t "shell[$$]: [${VI_USERNAME} via esxcli]"
55	   ( eval $cmd ) 2>&1 || true
56	   cd "$oldPWD"
57	   rm -f $TMPSH
58	fi
59	echo "]]></string>"
60	echo "</output>"

Fusion-io ioMemory Custom Plugin Example

/usr/lib/vmware/esxcli/ext/esxcli-fio.xml

<?xml version="1.0"?>
<plugin xmlns="http://www.vmware.com/Products/ESX/5.0/esxcli/">
    <version>1.0.0</version>
<!--
 Copyright (c) 2013 Fusion-io, Inc. All rights reserved.

 No use, or distribution, of this source code is permitted in any form or
 means without a valid, written license agreement with Fusion-io. Please
 refer to the included "License" or "License.txt" file for terms and
 conditions regarding the use and redistribution of this software.
-->
    <!-- Define an esxcli fio namespace -->
    <namespaces>
        <namespace path="fio">
            <description>Fusion-io utility CLI</description>
        </namespace>
    </namespaces>

    <commands>
        <command path="fio.status">
            <description>General information utility for Fusion-io devices.</description>
            <input-spec>
                <parameter name="all" type="flag" required="false" shortname="a">
                    <description>Report all available information.</description>
                </parameter>
                <parameter name="err-warn" type="flag" required="false" shortname="e">
                    <description>Report only errors and warnings, with minimal device info.</description>
                </parameter>
                <parameter name="data-volume" type="flag" required="false" shortname="d">
                    <description>Report the volume of data read and written.</description>
                </parameter>
                <parameter name="unavailable" type="flag" required="false" shortname="u">
                    <description>Show unavailable fields. Only valid with XML/JSON output format: -f/--format x/j.</description>
                </parameter>
                <parameter name="unavailable-detail" type="flag" required="false" shortname="U">
                    <description>Show unavailable fields and details why. Only valid with XML/JSON output format: -f/--format x/j.</description>
                </parameter>
                <parameter name="field" type="string-list" required="false" shortname="F">
                    <description>Print the value for a single field.  Requires that a device be specified.  Multiple -F options may be specified.</description>
                </parameter>
                <parameter name="list-fields" type="flag" required="false" shortname="l">
                    <description>List the fields that can be individually accessed with --field and exit.</description>
                </parameter>
                <parameter name="list-devices" type="flag" required="false" shortname="L">
                    <description>List all the available ioMemory devices on the system.</description>
                </parameter>
                <parameter name="count" type="flag" required="false" shortname="c">
                    <description>fio-board-count mode: Report the number of Fusion-io boards installed.</description>
                </parameter>
                <parameter name="format" type="string" required="false" shortname="f">
                    <description>Format output. Must be one of s / x/ j.  's' is standard format (default). 'x' is XML output format. 'j' is JSON output format</description>
                    <constraint type="stringenum">
                      <enum>
                        <enum-value value="s">s</enum-value>
                        <enum-value value="x">x</enum-value>
                        <enum-value value="j">j</enum-value>
                      </enum>
                    </constraint>
                </parameter>
                <parameter name="device" type="string" required="false" shortname="D">
                    <description>Pathname to the control device (fctx).</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh status $if{all,-a} $if{err-warn,--err-warn} $if{data-volume,--data-volume} $if{unavailable,-u} $if{unavailable-detail,--unavailable-detail} $if{list-fields,-l} $if{count,-c} $if{format,-f"$val{format}"} $if{field,$multilist{field,-F,false}} $if{list-devices,-L} $if{device,"$val{device}"} </execute>
        </command>

        <command path="fio.updateiodrive">
        <description>Update ioDrive firmware. Note: MUST NOT be used while the ioDrive is attached.</description>
            <input-spec>
                <parameter name="ffffile" type="string" required="true" shortname="F">
                    <description>pathname to the firmware file</description>
                </parameter>
                <parameter name="force" type="flag" required="false" shortname="f">
                    <description>force upgrade (bypass all validation); (may result in data loss)</description>
                </parameter>
                <parameter name="bypass-ecc" type="flag" required="false">
                    <description>bypasses ECC compatibility validation</description>
                </parameter>
                <parameter name="bypass-barrier" type="flag" required="false">
                    <description>bypasses barrier version validation</description>
                </parameter>
                <parameter name="bypass-uptodate" type="flag" required="false">
                    <description>bypasses already up to date validation</description>
                </parameter>
                <parameter name="split" type="flag" required="false">
                    <description>split into virtual controllers</description>
                </parameter>
                <parameter name="merge" type="flag" required="false">
                    <description>merge virtual controllers</description>
                </parameter>
                <parameter name="device" type="string" required="false" shortname="d">
                    <description>specify a device to update (ex: /dev/fct0)</description>
                </parameter>
                <parameter name="pretend" type="flag" required="false" shortname="p">
                    <description>show what updates would be done (firmware will not be modified)</description>
                </parameter>
                <parameter name="list" type="flag" required="false" shortname="l">
                    <description>list the firmware available in the archive</description>
                </parameter>
                <parameter name="clear-lock" type="flag" required="false" shortname="c">
                    <description>clears locks placed on a device</description>
                </parameter>
                <parameter name="quiet" type="flag" required="false" shortname="q">
                    <description>quiet mode - do not show update progress</description>
                </parameter>
        </input-spec>
         <output-spec>
            <string />
         </output-spec>
         <has-updates value="false" />
         <format-parameters>
            <formatter>simple</formatter>
         </format-parameters>
         <execute>/opt/fio/bin/esxcli-fio-script.sh update-iodrive -Q -y $if{quiet,-q} $if{force,--force} $if{bypass-ecc,--bypass-ecc} $if{bypass-barrier,--bypass-barrier} $if{bypass-uptodate,--bypass-uptodate} $if{device,-d "$val{device}"} $if{pretend,-p} $if{split,--split} $if{merge,--merge} $if{list,-l} $if{clear-lock,-c} $if{ffffile,"$val{ffffile}"}</execute>
        </command>

        <command path="fio.bugreport">
            <description>Problem reporting utility for Fusion-io devices.</description>
            <input-spec>
                <parameter name="dest" type="string" required="false">
                    <description>Directory to generate the report tar</description>
                </parameter>
                <parameter name="cmds" type="string" required="false">
                    <description>Additional commands output to include in report.  File format:  "directory=None:cmd args:timeout=None"</description>
                </parameter>
                <parameter name="data" type="string" required="false">
                    <description>Additional files to include in report</description>
                </parameter>
                <parameter name="skip-space-check" type="flag" required="false">
                    <description>Skip check for disk space before collecting logs</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>LOGNAME=$USER /opt/fio/bin/esxcli-fio-script.sh bugreport $if{dest, --dest="$val{dest}"} $if{cmds, --cmds="$val{cmds}"} $if{data, --data="$val{data}"} $if{skip-space-check, --skip-space-check}</execute>
        </command>

        <command path="fio.attach">
            <description>Fusion-io utility to attach an ioDrive.</description>
            <input-spec>
                <parameter name="device" type="string-list" required="true" shortname="d">
                    <description>Device node.</description>
                </parameter>
                <parameter name="clean" type="flag" required="false" shortname="c">
                    <description>Attach only if clean.</description>
                </parameter>
                <parameter name="rescan" type="flag" required="false" shortname="r">
                    <description>Force a metadata rescan.</description>
                </parameter>
                <parameter name="quiet" type="flag" required="false" shortname="q">
                    <description>Disable progress print outs.</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh attach -Q $if{quiet,-q} $if{clean,-c} $if{rescan,-r} $if{device,$multilist{device,"",false}}</execute>
        </command>

        <command path="fio.detach">
            <description>Fusion-io utility to detach an ioDrive.</description>
            <input-spec>
                <parameter name="device" type="string-list" required="true" shortname="d">
                    <description>Device node.</description>
                </parameter>
                <parameter name="quiet" type="flag" required="false" shortname="q">
                    <description>Disable progress display.</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh detach -Q -y $if{quiet,-q} $if{device,$multilist{device,"",false}}</execute>
        </command>

        <command path="fio.beacon">
            <description>Fusion-io utility to enable or disable the beacon for the card attached to a device node.</description>
            <input-spec>
                <parameter name="device" type="string" required="true" shortname="d">
                    <description>Device node.</description>
                </parameter>
                <parameter name="on" type="flag" required="false">
                    <description>Enable beacon of device.</description>
                </parameter>
                <parameter name="off" type="flag" required="false">
                    <description>Disable beacon of device.</description>
                </parameter>
                <parameter name="ppci" type="flag" required="false" shortname="p">
                    <description>Print the pci bus id of device.</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh beacon $if{on,--on} $if{off,--off} $if{ppci,-p} $if{device,"$val{device}"}</execute>
        </command>

        <command path="fio.geterasecount">
            <description>Fusion-io utility to report statistics on block erase counts.</description>
            <input-spec>
                <parameter name="device" type="string" required="true" shortname="d">
                    <description>Device node.</description>
                </parameter>
                <parameter name="bad-blocks" type="flag" required="false" shortname="b">
                    <description>Report on retired blocks.</description>
                </parameter>
                <parameter name="histogram" type="flag" required="false" shortname="H">
                    <description>Print a histogram of erase counts.</description>
                </parameter>
                <parameter name="summary" type="flag" required="false" shortname="s">
                    <description>Only show summary of erase count.</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh get-erase-count $if{bad-blocks,-b} $if{histogram,-H} $if{summary,-s} $if{device,"$val{device}"}</execute>
        </command>

        <command path="fio.pcicheck">
            <description>Fusion-io utility to checks for errors on the PCI bus tree, specifically for ioDrives. It is perfectly normal to see a few correctable errors when initially run.  Subsequent runs should only reveal one or two errors for several hours of operation.  MUST be used while the driver is loaded.</description>
            <input-spec>
                <parameter name="ereport" type="flag" required="false" shortname="e">
                    <description>Enable PCI-e error reporting.</description>
                </parameter>
                <parameter name="verbose" type="flag" required="false" shortname="v">
                    <description>Scan every device in the system.</description>
                </parameter>
                <parameter name="findall" type="flag" required="false" shortname="f">
                    <description>Scan every device in the system.</description>
                </parameter>
                <parameter name="retrain" type="flag" required="false" shortname="r">
                    <description>Force link to retrain.</description>
                </parameter>
                <parameter name="disable" type="string" required="false" shortname="d">
                    <description>1 disable link, or 0 bring link up.</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh pci-check $if{ereport,-e} $if{verbose,-v} $if{findall,-f} $if{retrain,-r} $if{disable,-d "$val{disable}"}</execute>
        </command>

        <command path="fio.readlebmap">
            <description>Fusion-io utility which reads the media event log out of the device.</description>
            <input-spec>
                <parameter name="device" type="string" required="true" shortname="d">
                    <description>ioDrive control node, e.g. /dev/fct0.</description>
                </parameter>
                <parameter name="file" type="string" required="false" shortname="f">
                    <description>Name of the output file to generate.</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh read-lebmap $if{device, "$val{device}"} $if{file, "$val{file}"}</execute>
        </command>

        <command path="fio.format">
            <description>Fusion-io format utility.  [B,K,M,G,T,P,%%] are units: Bytes, KBytes, MBytes, GBytes, TBytes, PBytes and percent.</description>
            <input-spec>
                <parameter name="device" type="string" required="true" shortname="d">
                    <description>ioDrive control node, e.g. /dev/fct0.</description>
                </parameter>
                <parameter name="block-size" type="string" required="false" shortname="b">
                    <description>Set the block (sector) size, in Bytes or KiBytes (base 2)</description>
                </parameter>
                <parameter name="device-size" type="string" required="false" shortname="s">
                    <description>Size to format device where max size is default capacity.</description>
                </parameter>
                <parameter name="overformat" type="string" required="false" shortname="o">
                    <description>Overformat device size where max size is maximum physical capacity.</description>
                </parameter>
                <parameter name="sparse" type="flag" required="false" shortname="e">
                    <description>Sparse format.</description>
                </parameter>
                <parameter name="sparse-logical-sector-count" type="string" required="false" shortname="l">
                    <description>Sparse format optional logical sector count (physical size is defined by -s option). Default = maximum that can be addressed. % means a percentage of the default.</description>
                </parameter>
                <parameter name="enable-atomic-writes" type="flag" required="false" shortname="A">
                    <description>Make atomic writes feature available on the device.</description>
                </parameter>
                <parameter name="enable-persistent-trim" type="flag" required="false" shortname="P">
                    <description>Make persistent trim feature available on the device.</description>
                </parameter>
                <parameter name="slow-rescan" type="flag" required="false" shortname="R">
                    <description>Disable fast rescan on unclean shutdown to reclaim some capacity.</description>
                </parameter>
                <parameter name="force" type="flag" required="false" shortname="f">
                    <description>Force formatting outside standard limits.</description>
                </parameter>
                <parameter name="quiet" type="flag" required="false" shortname="q">
                    <description>Quiet mode - do not print progress.</description>
                </parameter>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh format -Q -y $if{quiet,-q} $if{block-size,-b "$val{block-size}"} $if{device-size,-s "$val{device-size}"} $if{overformat,-o "$val{overformat}"} $if{enable-persistent-trim, -P} $if{slow-rescan, -R} $if{sparse,-e $if{sparse-logical-sector-count,"$val{sparse-logical-sector-count}"}} $if{force, -f} $if{enable-atomic-writes,-A} $if{device, "$val{device}"}</execute>
        </command>

        <command path="fio.version">
            <description>Version of the Fusion-io utilities.</description>
            <input-spec>
            </input-spec>
            <output-spec>
                <string />
            </output-spec>
            <has-updates value="false" />
            <format-parameters>
                <formatter>simple</formatter>
            </format-parameters>
            <execute>/opt/fio/bin/esxcli-fio-script.sh status -v</execute>
        </command>

    </commands>
</plugin>

/opt/fio/bin/esxcli-fio-script.sh

#!/bin/sh

#-----------------------------------------------------------------------------
# Copyright (c) 2013 Fusion-io, Inc. All rights reserved.
#
# No use, or distribution, of this source code is permitted in any form or
# means without a valid, written license agreement with Fusion-io. Please
# refer to the included "License" or "License.txt" file for terms and
# conditions regarding the use and redistribution of this software.
#-----------------------------------------------------------------------------

# esxcli requires that all output be wrapped in xml
echo "<?xml version=\"1.0\" ?>"
echo "<output xmlns=\"http://www.vmware.com/Products/ESX/5.0/esxcli/\">"
echo -n "<string><![CDATA["

utility='/opt/fio/bin/fio-'$1

shift

$utility $@ 2>&1

echo "]]></string>"
echo "</output>"