Skip to content

Instantly share code, notes, and snippets.

@peterfroehlich
Last active March 16, 2022 20:53
Show Gist options
  • Save peterfroehlich/6130179 to your computer and use it in GitHub Desktop.
Save peterfroehlich/6130179 to your computer and use it in GitHub Desktop.
Virtual Machine Snapshots - This tool eases the usage on virtual machine snapshots from inside the target vm. It can list, create and delete snapshots. Needs authorized credentials of ESX/ESXi/vCenter Server.
#!/usr/bin/env python
# List, create, delete vmware vsphere snapshots with unix-like user interface.
# This assumes that the vm name are equal to the hostname or the fqdn
# Requirements: pysphere >= 0.1.6 If Python < 2.7: argparse
#
# Peter Froehlich (tarwin@tarwin.de) @ 03/2013
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from pysphere import *
from getpass import getpass
from sys import exit
import argparse
from socket import gethostname, getfqdn
from time import strftime
# Hosts to use if no -h is specified
# Domain : Host
hosts = {
"finance.example.com" : "vsphere.finance.example.com",
"example.com" : "vsphere.example.com"
}
# If nothing matches, use the following. (optional, set to False if not used)
fallback_host = False
def complete_and_split_fqdn(hostname):
'''
Check if hostname includes a dot, get fqdn from dns if not, and return list
'''
if hostname.count(".") == 0:
hostname = getfqdn(hostname)
return hostname.split(".")
def get_host(vm_hostname):
'''
Try to match domain part of fqdn to hosts dict. return if found else return fallback_host or fail.
'''
for part in range(1, len(vm_hostname)):
domain = ".".join(vm_hostname[part:])
if domain in hosts.keys():
return hosts[domain]
if fallback_host:
return fallback_host
else:
raise EnvironmentError, "Can't find matching ESX/ESXi or vSphere host in configuration."
def build_connection(host, user, password):
'''
Connect to the ESX/ESXi or vSphere server
'''
vpx_connection = VIServer()
vpx_connection.connect(host, user, password)
return vpx_connection
def get_VM_object(vpx_connection, VM):
'''
returns VM object
'''
return vpx_connection.get_vm_by_name(VM)
def for_all_do(vpx_connection, passed_function, *args):
'''
execute passed_function on all vms found on host/cluster
'''
for vm in vpx_connection.get_registered_vms():
vm_object = vpx_connection.get_vm_by_path(vm)
passed_function(vpx_connection, vm_object, args)
def list_snapshots(vpx_connection, vm_object, *args):
'''
list snapshots with name and timestamp
ToDo: Build nice tree view of parent/children relationships
'''
for snapshot in vm_object.get_snapshots():
print vm_object.get_property('name')+" - "+strftime("%d %b %Y %H:%M:%S", snapshot.get_create_time())+" - Type:"+snapshot.get_state()+" - '"+snapshot.get_name()+"'"
def delete_snapshot(vpx_connection, vm_object, args):
'''
Delete snapshots
'''
name, sync_run = args[:2]
vm_object.delete_named_snapshot(name, sync_run = sync_run)
def create_snapshot(vpx_connection, vm_object, args):
'''
Well... create snapshots!
ToDo: Description field
'''
name, memory, sync_run = args[:3]
vm_object.create_snapshot(name, memory=memory, sync_run = sync_run)
def main():
# Get local hostname
local_hostname_fqdn = gethostname()
# Arg parse
opts = argparse.ArgumentParser(description = 'vms.py - Virtual Machine Snapshots ' \
'- This tool eases the usage on virtual machine snapshots from inside the target vm. It can list, create and delete snapshots. ' \
'Needs authorized credentials of ESX/ESXi/vCenter Server.' )
opts.add_argument("mode", help = "List, create or delete snapshots", choices = ["list", "create", "delete"])
all_or_one_vm = opts.add_mutually_exclusive_group()
opts.add_argument("-n", "--name", help = "Name of snapshot")
all_or_one_vm.add_argument("-v", "--vm", help = "VM to access. Default is this VM.")
all_or_one_vm.add_argument("-a", "--all", help = "Apply operation to all found VMs",
action="store_true")
opts.add_argument("-b", "--nonblocking", help = "Do not wait for snapshot operation to finish",
action="store_true")
opts.add_argument("-m", "--memory", help = "Snapshot memory as well (PowerOn Snapshot)",
action="store_true")
opts.add_argument("-e", "--host", help = "ESX/ESXi or vSphere host. Config says: "+get_host(complete_and_split_fqdn(local_hostname_fqdn)))
opts.add_argument("-u", "--user", help = "ESX/ESXi or vSphere user")
opts.add_argument("-p", "--password", help = "Password of user")
# Run the option parser
parsed_options = opts.parse_args()
## ++ Resolve options
if parsed_options.user:
user = parsed_options.user
else:
user = raw_input("Username: ")
if parsed_options.password:
password = parsed_options.password
else:
password = getpass()
if parsed_options.name:
name = parsed_options.name
elif parsed_options.mode in ["create", "delete"]:
name = raw_input("Snapshot name: ")
if parsed_options.nonblocking:
sync_run=False
else:
sync_run=True
if parsed_options.memory:
memory=True
else:
memory=False
if parsed_options.vm:
VM_fqdn = complete_and_split_fqdn(parsed_options.vm)
else:
VM_fqdn = complete_and_split_fqdn(local_hostname_fqdn)
if parsed_options.host:
host = parsed_options.host
else:
host = get_host(VM_fqdn)
## -- Resolve options done
VM_hostname = VM_fqdn[0]
# Build connection.
vpx_connection = build_connection(host, user, password)
# what do you want to do?
if parsed_options.mode == "list":
if parsed_options.all:
for_all_do(vpx_connection, list_snapshots)
else:
list_snapshots(vpx_connection, get_VM_object(vpx_connection, VM_hostname))
elif parsed_options.mode == "delete":
if parsed_options.all:
print "Not implemented yet..."
else:
delete_snapshot(vpx_connection, get_VM_object(vpx_connection, VM_hostname), (name, sync_run))
elif parsed_options.mode == "create":
if parsed_options.all:
print "Not implemented yet..."
else:
create_snapshot(vpx_connection, get_VM_object(vpx_connection, VM_hostname), (name, memory, sync_run))
# Makes import from other programs possible, without running the logic in __main__.
try:
if __name__ == '__main__':
main()
except VIException as detail:
print detail
exit(1)
except Exception, err:
print "Exception: "+str(err)
exit(10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment