PluginsOspfCode

From VNUML-WIKI
Jump to: navigation, search
# Ospfd.pm
#
# The ospfd plugin

package ospfd;

@ISA = qw(Exporter);
@EXPORT = qw(createPlugin
             bootingCreateFiles
             bootingCommands
             execCreateFiles
             execCommands
             shutdownCommand
             finalizePlugin);

###########################################################
# Modules import
###########################################################

use strict;
use XML::DOM;          					# XML management library
use File::Basename;    					# File management library

use Switch;

use Socket;								# To resolve hostnames to IPs

use XML::DOM::ValParser;				# To check DTD


###########################################################
# Global variables 
###########################################################

my $globalNode;
my $valid_fail;

###########################################################
# Subroutines	
###########################################################

	###########################################################
	# Create plugin
	#
	# To be called always, just before starting procesing the scenario specification
	#
	# Arguments:
	# - the operation mode ("t","x","d" or "P")
	# - the plugin configuration file
	#
	# Returns:
	# - an error message or 0 if all is ok
	#
	#
	###########################################################

sub createPlugin{
	
	my $self = shift;	
	my $mode = shift;
	my $conf = shift;
	
	my $error;
	
	eval{
		$error = &checkConfigFile($conf);
	};
	
	if ($@){
		$error = $@;
	}
	return $error;
}

	###########################################################
	# bootingCreateFiles
	#
	# To be called during "t" mode, for each vm in the scenario
	#
	# Arguments:
	# - vm name
	#
	# Returns:
	# - a hashname which keys are absolute pathnames of files in vm filesystem and
	#   values the the pathname of the file in the host filesystem. The file in the
	#   host filesytesm is removed after VNUML processed it, so temporal files in 
	#   /tmp are preferable)
	###########################################################

sub bootingCreateFiles{
	
	my $self = shift;
	my $vm = shift;
	
	my %files;
	
	my $virtualmList=$globalNode->getElementsByTagName("vm");
	my $longitud = $virtualmList->getLength;
	
	for (my $m=0; $m<$longitud; $m++){
		
		my $virtualm = $virtualmList->item($m);
		my $virtualm_name = $virtualm->getAttribute("name");
		
		if ($virtualm_name eq $vm){
			my $zebra_file = "/tmp/$vm"."_zebra.conf";
			my $ospfd_file = "/tmp/$vm"."_ospfd.conf";
			
			my $zebraTagList = $virtualm->getElementsByTagName("zebra");
			my $zebraTag = $zebraTagList->item($0);
			my $zebra_hostname = $zebraTag->getAttribute("hostname");
			my $zebra_password = $zebraTag->getAttribute("password");
			
      		chomp(my $date = `date`);
      				
			open(ZEBRA, ">$zebra_file") or $files{"ERROR"} = "Cannot open $zebra_file file";
			print ZEBRA "! zebra.conf file generated by ospfd.pm VNUML plugin at $date\n";
			print ZEBRA	"hostname $zebra_hostname\n";
			print ZEBRA "password $zebra_password\n";
			print ZEBRA "log file /var/log/zebra/zebra.log\n";			
			close (ZEBRA);
				
			open(OSPFD, ">$ospfd_file") or $files{"ERROR"} = "Cannot open $ospfd_file file";
			print OSPFD "! ospfd.conf file generated by ospfd.pm VNUML plugin at $date\n";
			print OSPFD "hostname $zebra_hostname\n";
			print OSPFD "password $zebra_password\n";
			print OSPFD "log file /var/log/zebra/ospfd.log\n!\n";
			print OSPFD "router ospf\n";
			
			my $networkTagList = $virtualm->getElementsByTagName("network");
			my $longitudNetwork = $networkTagList->getLength;
			for (my $n=0; $n<$longitudNetwork; $n++){
				my $networkTag = $networkTagList->item($n);
				my $ipTagList = $networkTag->getElementsByTagName("ip");
				
				my $ipTag = $ipTagList->item($0);
				my $ipMask = $ipTag->getAttribute("mask");
				my $ipData = $ipTag->getFirstChild->getData;
				
				my $areaTagList = $networkTag->getElementsByTagName("area");
				my $areaTag = $areaTagList->item($0);
				my $areaData = $areaTag->getFirstChild->getData;
				
				print OSPFD " network $ipData/$ipMask area $areaData\n";
			}
			print OSPFD "!\n";			
			close (OSPFD);	
				
			$files{"/etc/quagga/zebra.conf"} = $zebra_file;
			$files{"/etc/quagga/ospfd.conf"} = $ospfd_file;
		}
		
	
	}
	
	return %files;
}

sub bootingCommands{
	
	
}

sub execVmsToUse {

	my $self = shift;
	my $seq = shift;
	
	# The plugin has nothing to do for VMs with sequences other than
	# start, restart or stop, so in that case it returns an empty list
	unless ($seq eq "start" || $seq eq "ospf-start" || $seq eq "restart" || $seq eq "ospf-restart" || $seq eq "stop" || $seq eq "ospf-stop" || $seq eq "redoconf" || $seq eq "ospf-redoconf") {
		return ();
	}
	
	my @vm_list = ();

	my $virtualmList=$globalNode->getElementsByTagName("vm");
	my $longitud = $virtualmList->getLength;
	
	for (my $m=0; $m<$longitud; $m++){
		
		my $virtualm = $virtualmList->item($m);
		push (@vm_list,$virtualm->getAttribute("name"));
	}
	
	return @vm_list;
	
}
	###########################################################
	# execCreateFiles
	#
	# To be called during "x" mode, for each vm in the scenario
	#
	# Arguments:
	# - vm name
	# - seq command sequence
	#
	# Returns:
	# - a hashname which kyes are absolute pathnames of files in vm filesystem and
	#   values the the pathname of the file in the host filesystem. The file in the
	#   host filesytesm is removed after VNUML processed it, so temporal files in 
	#   /tmp are preferable)
	#
	###########################################################
sub execCreateFiles{
	my $self = shift;
	my $vm = shift;
	my $seq = shift;
	
	my %files;
	
	if (($seq eq "redoconf") || ($seq eq "ospf-redoconf")){	
	

		my $virtualmList=$globalNode->getElementsByTagName("vm");
		my $longitud = $virtualmList->getLength;
		
		for (my $m=0; $m<$longitud; $m++){
			
			my $virtualm = $virtualmList->item($m);
			my $virtualm_name = $virtualm->getAttribute("name");
			
			if ($virtualm_name eq $vm){
				my $zebra_file = "/tmp/$vm"."_zebra.conf";
				my $ospfd_file = "/tmp/$vm"."_ospfd.conf";
				
				my $zebraTagList = $virtualm->getElementsByTagName("zebra");
				my $zebraTag = $zebraTagList->item($0);
				my $zebra_hostname = $zebraTag->getAttribute("hostname");
				my $zebra_password = $zebraTag->getAttribute("password");
				
	      		chomp(my $date = `date`);
	      				
				open(ZEBRA, ">$zebra_file") or $files{"ERROR"} = "Cannot open $zebra_file file";
				print ZEBRA "! zebra.conf file generated by ospfd.pm VNUML plugin at $date\n";
				print ZEBRA	"hostname $zebra_hostname\n";
				print ZEBRA "password $zebra_password\n";
				print ZEBRA "log file /var/log/zebra/zebra.log\n";			
				close (ZEBRA);
					
				open(OSPFD, ">$ospfd_file") or $files{"ERROR"} = "Cannot open $ospfd_file file";
				print OSPFD "! ospfd.conf file generated by ospfd.pm VNUML plugin at $date\n";
				print OSPFD "hostname $zebra_hostname\n";
				print OSPFD "password $zebra_password\n";
				print OSPFD "log file /var/log/zebra/ospfd.log\n!\n";
				print OSPFD "router ospf\n";
				
				my $networkTagList = $virtualm->getElementsByTagName("network");
				my $longitudNetwork = $networkTagList->getLength;
				for (my $n=0; $n<$longitudNetwork; $n++){
					my $networkTag = $networkTagList->item($n);
					my $ipTagList = $networkTag->getElementsByTagName("ip");
					
					my $ipTag = $ipTagList->item($0);
					my $ipMask = $ipTag->getAttribute("mask");
					my $ipData = $ipTag->getFirstChild->getData;
					
					my $areaTagList = $networkTag->getElementsByTagName("area");
					my $areaTag = $areaTagList->item($0);
					my $areaData = $areaTag->getFirstChild->getData;
					
					print OSPFD " network $ipData/$ipMask area $areaData\n";
				}
				print OSPFD "!\n";			
				close (OSPFD);	
					
				$files{"/etc/quagga/zebra.conf"} = $zebra_file;
				$files{"/etc/quagga/ospfd.conf"} = $ospfd_file;
			}
		}
	
	}
	return %files;	
	
}

	###########################################################
	# execCommands
	#
	# To be called during "x" mode, for each vm in the scenario
	#
	# Arguments:
	# - vm name
	# - seq command sequence
	# 
	# Returns:
	# - list of commands to execute in the virtual machine after <exec> processing
	###########################################################
	
sub execCommands{
	
	my $self = shift;
	my $vm = shift;
	my $seq = shift;
	
	my @commands;
	
	my $type;
	my $subtype;
	
	my $zebra_bin = "";
	my $ospfd_bin = "";
	
	
	my $virtualmList=$globalNode->getElementsByTagName("vm");
	my $longitud = $virtualmList->getLength;
	
	for (my $m=0; $m<$longitud; $m++){
		
		my $virtualm = $virtualmList->item($m);
		my $virtualm_name = $virtualm->getAttribute("name");
		
		if ( $vm eq $virtualm_name){
			$type = $virtualm->getAttribute("type");
			$subtype = $virtualm->getAttribute("subtype");
			my $zebraBinTagList = $virtualm->getElementsByTagName("zebra_bin");
			my $longitudZebra = $zebraBinTagList->getLength;
			if ($longitudZebra == 1){
				$zebra_bin =  $zebraBinTagList->item($0)->getFirstChild->getData;
			}
			my $ospfdBinTagList = $virtualm->getElementsByTagName("ospfd_bin");
			my $longitudOspfd = $ospfdBinTagList->getLength;
			if ($longitudOspfd == 1){
				$ospfd_bin =  $ospfdBinTagList->item($0)->getFirstChild->getData;
			}
			
			switch ($type) {
				case "quagga"{ 
					switch ($subtype){
						case "lib-install"{
					
							if ($zebra_bin eq ""){
								$zebra_bin = "/usr/lib/quagga/zebra";
							}
							if ($ospfd_bin eq ""){
								$ospfd_bin = "/usr/lib/quagga/ospfd";
							}
							unshift (@commands, "");
						}
						case "sbin-install"{
					
							if ($zebra_bin eq ""){
								$zebra_bin = "/usr/sbin/zebra";
							}
							if ($ospfd_bin eq ""){
								$ospfd_bin = "/usr/sbin/ospfd";
							}
							unshift (@commands, "");
					
						} else {
							unshift (@commands, "Your choice $subtype is not a recognized subtype (yet)\n");
						}
					}
				} else {
					unshift (@commands, "Your choice $type is not a recognized type (yet)\n");
				}
			}
	
			if (($seq eq "start") || ($seq eq "ospf-start")){
		
				push (@commands, "$zebra_bin -d");
				push (@commands, "$ospfd_bin -d");
						
		
			}elsif(($seq eq "restart") || ($seq eq "ospf-restart")){
				
				push (@commands, "killall zebra");
				push (@commands, "killall ospfd");
		
				push (@commands, "$zebra_bin -d");
				push (@commands, "$ospfd_bin -d");
		
			}elsif(($seq eq "stop") || ($seq eq "ospf-stop")){
		
				push (@commands, "killall zebra");
				push (@commands, "killall ospfd");
		
			}
		}
	}
	
	return @commands;	
	
}

sub finalizePlugin{
	
	
}

sub shutdownCommands{
	
	
}


	#############################################################
	#
	# Checks existence and semantics in ospf conf file. 
	# Currently this check consist in:
	#
	#	1. Configuration file exists.
	#	2. Check DTD.
	#
	#############################################################

sub checkConfigFile{
	
	# 1. Configuration file exists.
	my $config_file = shift;
	open(FILEHANDLE, $config_file) or {
		return "cannot open config file $config_file\n",
	};
	close (FILEHANDLE);
	
	# 2. Check DTD
	my $parser = new XML::DOM::ValParser;
	my $dom_tree;
	$valid_fail = 0;
	eval {
		local $XML::Checker::FAIL = \&validation_fail;
		$dom_tree = $parser->parsefile($config_file);
	};

	if ($valid_fail) {
		return ("$config_file is not a well-formed OSPF plugin file\n");
	}

	$globalNode = $dom_tree->getElementsByTagName("ospf_conf")->item(0);
	
	return 0;	
}

sub validation_fail {
   my $code = shift;
   # To set flag
   $valid_fail = 1;
   # To print error message
   XML::Checker::print_error ($code, @_);
}

1