#compdef virsh
# ------------------------------------------------------------------------------
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the zsh-users nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL ZSH-USERS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
# Description
# -----------
#
#  Completion script for LibVirt's Shell (virsh) (http://libvirt.org).
#
# ------------------------------------------------------------------------------
# Authors
# -------
#
#  * Jan-Philipp Litza <janphilipp@litza.de>
#  * Vadim A. Misbakh-Soloviov <mva@mva.name>
#
# ------------------------------------------------------------------------------

local -a args reply

function _virsh-domains() {
  local -a out
  out=( ${${${${(f)"$(virsh list "$@")"}:#(---| Id)*}## #[0-9-]## ##}%% *} )
  _describe -t domains "${${1#--}:-running} domains" out
  return $?
}

local -a expand_files
expand_files=(/$'[^\0]##\0'/ ':file:file name:_files')

local -a expand_dirs
expand_dirs=(/$'[^\0]##\0'/ ":dir:dir name:_files -/")

local -a expand_domains
expand_domains=(
  /$'[^\0]##\0'/
  ":domains:domains:{_virsh-domains --all}"
)

local -a expand_domains_running
expand_domains_running=(
  /$'[^\0]##\0'/
  ":domains:running domains:{_virsh-domains}"
)

local -a expand_domains_inactive
expand_domains_inactive=(
  /$'[^\0]##\0'/
  ":domains:inactive domains:{_virsh-domains --inactive}"
)

local -a expand_kilobytes
expand_kilobytes=(
  /'\d+'/
  ":kilobytes:kilobytes:"
)

local -a expand_count
expand_count=(
  /'\d+'/
  ":count:count:"
)

local -a subcmd_help
subcmd_help=(
  /$'[^\0]##\0'/
  ":command:virsh command:"
)

local -a subcmd_list
_regex_words \
  list-options 'list options' \
  '--all:list all domains, not only active' \
  '--inactive:list only inactive domains'
subcmd_list=("$reply[@]")

local -a subcmd_freecell
subcmd_freecell=(
  /'\d*'/
  ":numa-cell:NUMA cell:"
)

local -a subcmd_autostart
_regex_words \
  autostart-options 'autostart options' \
  '--disable:disables autostart instead of enabling'
subcmd_autostart=("(" "$reply[@]" "|" ")" $expand_domains)

local -a subcmd_create
_regex_words \
  create-options 'create options' \
  '--console:attach to the console after creation' \
  '--paused:pause domain after creation (if supported by driver)'
subcmd_create=("(" "$reply[@]" "|" ")" $expand_files)

local -a subcmd_dumpxml
_regex_words \
  dumpxml-options 'dumpxml options' \
  '--inactive:use the config for next reboot instead of current' \
  '--security-info:include security sensitive information' \
  '--update-cpu:update CPU requirements according to host CPU'
subcmd_dumpxml=("(" "$reply[@]" "|" ")" $expand_domains)

local -a subcmd_start
_regex_words \
  start-options 'start options' \
  '--console:attach to console after start' \
  '--paused: pause after start (if supported by driver)'
subcmd_start=("(" "$reply[@]" "|" ")" $expand_domains_inactive)

args=( /$'[^\0]#\0'/ )

_regex_words \
  commands "virsh command" \
    'help:print help:$subcmd_help' \
    'attach-device:attach device from an XML file:$expand_domains $expand_files' \
    'attach-disk:attach disk device' \
    'attach-interface:attach network interface' \
    'autostart:autostart a domain:$subcmd_autostart' \
    'capabilities:capabilities:' \
    'cd:change the current directory:$expand_dirs' \
    'connect:(re)connect to hypervisor' \
    'console:connect to the guest console:$expand_domains_running' \
    'cpu-baseline:compute baseline CPU:$expand_files' \
    'cpu-compare:compare host CPU with a CPU described by an XML file:$expand_files' \
    'create:create a domain from an XML file:$subcmd_create' \
    'start:start a (previously defined) inactive domain:$subcmd_start' \
    'destroy:destroy a domain:$expand_domains_running' \
    'detach-device:detach device from an XML file:$expand_domains $expand_files' \
    'detach-disk:detach disk device' \
    'detach-interface:detach network interface' \
    'define:define (but don'"\'"'t start) a domain from an XML file:$expand_files' \
    'domid:convert a domain name or UUID to domain id:$expand_domains' \
    'domuuid:convert a domain name or id to domain UUID:$expand_domains' \
    'dominfo:domain information:$expand_domains' \
    'domjobinfo:domain job information:$expand_domains' \
    'domjobabort:abort active domain job:$expand_domains' \
    'domname:convert a domain id or UUID to domain name:$expand_domains' \
    'domstate:domain state:$expand_domains' \
    'domblkstat:get device block stats for a domain' \
    'domifstat:get network interface stats for a domain' \
    'dommemstat:get memory statistics for a domain:$expand_domains_running' \
    'domblkinfo:domain block device size information' \
    'domxml-from-native:Convert native config to domain XML' \
    'domxml-to-native:Convert domain XML to native config' \
    'dumpxml:domain information in XML:$subcmd_dumpxml' \
    'edit:edit XML configuration for a domain:$expand_domains' \
    'find-storage-pool-sources:discover potential storage pool sources' \
    'find-storage-pool-sources-as:find potential storage pool sources' \
    'freecell:NUMA free memory:$subcmd_freecell' \
    'hostname:print the hypervisor hostname:' \
    'list:list domains:$subcmd_list' \
    'migrate:migrate domain to another host' \
    'migrate-setmaxdowntime:set maximum tolerable downtime' \
    'net-autostart:autostart a network' \
    'net-create:create a network from an XML file:$expand_files' \
    'net-define:define (but don'"\'"'t start) a network from an XML file:$expand_files' \
    'net-destroy:destroy a network' \
    'net-dumpxml:network information in XML' \
    'net-edit:edit XML configuration for a network' \
    'net-list:list networks' \
    'net-name:convert a network UUID to network name' \
    'net-start:start a (previously defined) inactive network' \
    'net-undefine:undefine an inactive network' \
    'net-uuid:convert a network name to network UUID' \
    'iface-list:list physical host interfaces' \
    'iface-name:convert an interface MAC address to interface name' \
    'iface-mac:convert an interface name to interface MAC address' \
    'iface-dumpxml:interface information in XML' \
    'iface-define:define (but don'"\'"'t start) a physical host interface from an XML file' \
    'iface-undefine:undefine a physical host interface (remove it from configuration)' \
    'iface-edit:edit XML configuration for a physical host interface' \
    'iface-start:start a physical host interface (enable it / "if-up")' \
    'iface-destroy:destroy a physical host interface (disable it / "if-down")' \
    'managedsave:managed save of a domain state:$expand_domains_running' \
    'managedsave-remove:Remove managed save of a domain:$expand_domains' \
    'nodeinfo:node information:' \
    'nodedev-list:enumerate devices on this host' \
    'nodedev-dumpxml:node device details in XML' \
    'nodedev-dettach:dettach node device from its device driver' \
    'nodedev-reattach:reattach node device to its device driver' \
    'nodedev-reset:reset node device' \
    'nodedev-create:create a device defined by an XML file on the node' \
    'nodedev-destroy:destroy a device on the node' \
    'nwfilter-define:define or update a network filter from an XML file:$expand_files' \
    'nwfilter-undefine:undefine a network filter' \
    'nwfilter-dumpxml:network filter information in XML' \
    'nwfilter-list:list network filters' \
    'nwfilter-edit:edit XML configuration for a network filter' \
    'pool-autostart:autostart a pool' \
    'pool-build:build a pool' \
    'pool-create:create a pool from an XML file:$expand_files' \
    'pool-create-as:create a pool from a set of args' \
    'pool-define:define (but don'"\'"'t start) a pool from an XML file:$expand_files' \
    'pool-define-as:define a pool from a set of args' \
    'pool-destroy:destroy a pool' \
    'pool-delete:delete a pool' \
    'pool-dumpxml:pool information in XML' \
    'pool-edit:edit XML configuration for a storage pool' \
    'pool-info:storage pool information' \
    'pool-list:list pools' \
    'pool-name:convert a pool UUID to pool name' \
    'pool-refresh:refresh a pool' \
    'pool-start:start a (previously defined) inactive pool' \
    'pool-undefine:undefine an inactive pool' \
    'pool-uuid:convert a pool name to pool UUID' \
    'secret-define:define or modify a secret from an XML file:$expand_files' \
    'secret-dumpxml:secret attributes in XML' \
    'secret-set-value:set a secret value' \
    'secret-get-value:Output a secret value' \
    'secret-undefine:undefine a secret' \
    'secret-list:list secrets' \
    'pwd:print the current directory:' \
    'quit:quit this interactive terminal:' \
    'exit:quit this interactive terminal:' \
    'reboot:reboot a domain:$expand_domains' \
    'restore:restore a domain from a saved state in a file:$expand_files' \
    'resume:resume a domain:$expand_domains_running' \
    'save:save a domain state to a file:$expand_domains $expand_files' \
    'schedinfo:show/set scheduler parameters' \
    'dump:dump the core of a domain to a file for analysis:$expand_domains $expand_files' \
    'shutdown:gracefully shutdown a domain:$expand_domains_running' \
    'setmem:change memory allocation:$expand_domains $expand_kilobytes' \
    'setmaxmem:change maximum memory limit:$expand_domains $expand_kilobytes' \
    'setvcpus:change number of virtual CPUs:$expand_domains $expand_count' \
    'suspend:suspend a domain:$expand_domains_running' \
    'ttyconsole:tty console:$expand_domains_running' \
    'undefine:undefine an inactive domain:$expand_domains_inactive' \
    'update-device:update device from an XML file' \
    'uri:print the hypervisor canonical URI:' \
    'vol-create:create a vol from an XML file' \
    'vol-create-from:create a vol, using another volume as input' \
    'vol-create-as:create a volume from a set of args' \
    'vol-clone:clone a volume.' \
    'vol-delete:delete a vol' \
    'vol-wipe:wipe a vol' \
    'vol-dumpxml:vol information in XML' \
    'vol-info:storage vol information' \
    'vol-list:list vols' \
    'vol-pool:returns the storage pool for a given volume key or path' \
    'vol-path:returns the volume path for a given volume name or key' \
    'vol-name:returns the volume name for a given volume key or path' \
    'vol-key:returns the volume key for a given volume name or path' \
    'vcpuinfo:domain vcpu information:$expand_domains_running' \
    'vcpupin:control domain vcpu affinity' \
    'version:show version:' \
    'vncdisplay:vnc display:$expand_domains_running' \
    'snapshot-create:Create a snapshot:$expand_domains $expand_files' \
    'snapshot-current:Get the current snapshot:$expand_domains' \
    'snapshot-delete:Delete a domain snapshot' \
    'snapshot-dumpxml:Dump XML for a domain snapshot' \
    'snapshot-list:List snapshots for a domain:$expand_domains' \
    'snapshot-revert:Revert a domain to a snapshot'
args+=("$reply[@]")

_regex_arguments _virsh "${args[@]}"

_virsh "$@"
