Last active
March 16, 2022 20:53
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 ([email protected]) @ 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