#!/usr/bin/perl
#
# Quick hack to display relations between VMWare snapshots
# VMWare Fusion is missing this feature, since a list of snapshots is
# displayed instead of a tree
#
# (c) 2009 Richard van den Berg <richard@vdberg.org>
# Distrubuted under the GPLv3, see http://www.gnu.org/copyleft/gpl.html
# Latest version avaiable from http://www.vdberg.org/~richard/vmsd-grapher.html
#
# 2009/07/20 v1.0: initial version
# 2009/07/21 v1.1: added orphan node detection

use File::Basename;
use Getopt::Std;
use Graph::Easy;

$version="1.1";
$svg=$html=0;

getopts('?ahs',\%opt) || exit;
&usage  if($opt{'?'} || $#ARGV<0);
$html=1 if($opt{'h'});
$svg=1  if($opt{'s'});

$file=$ARGV[0];
$dir=dirname($file);
open(FILE,"<$file") || die("Can't open $file: $!\n");
while(<FILE>){
	chomp;
	next if(m/^\s*$/o);
	($l,$e,$r)=split(/\s+/,$_,3);
	($l1,$l2)=split(/\./,$l,2);
	$r =~ s/"//go;
	$d{$l1}{$l2}=$r;
}
close(FILE);

foreach $k (keys %d) {
	delete $d{$k} if(!$d{$k}{uid} || !$d{$k}{filename} || ! -f $dir."/".$d{$k}{filename});
}

$g = Graph::Easy->new();

foreach $k (keys %d) {
	$d{$k}{node}=$g->add_node($d{$k}{uid}.": ".$d{$k}{displayName});
}

foreach $k (keys %d) {
	next if(!$d{$k}{parent});
	$p=getnode($d{$k}{parent});
	if($p) {
		$g->add_edge($p,$d{$k}{node});
	} else {
		print STDERR "WARNING: snapshot with uid = ".$d{$k}{parent}." (parent of uid = ".$d{$k}{uid}.") not found\n";
	}
}

if($html) {
	print $g->as_html_file();
} elsif($svg) {
	print $g->as_svg_file();
} else {
	print $g->as_ascii();
}

exit;

sub getnode {
	my $uid=shift;
	foreach $k (keys %d) {
		return $d{$k}{node} if($d{$k}{uid} == $uid);
	}
	return undef;
}

sub usage {
	$name=basename($0);
	print "vmsd-grapher($version): display relations between VMWare snapshots\n\n";
	print "Usage: $name [-?] vitual_machine.vmsd\n";
	print "        -?  print this help page\n";
	print "        -a  output graph as ASCII (default)\n";
	print "        -h  output graph as HTML\n";
	print "        -s  output graph as SVG (requires Graph::Easy::As_svg)\n";
	exit;
}
