PluginsDummyCode

From VNUML-WIKI
Revision as of 09:48, 21 July 2011 by David (talk | contribs) (Created page with "# dhcp.pm # # The dhcp plugin package dhcp; @ISA = qw(Exporter); @EXPORT = qw(createPlugin bootingCreateFiles bootingCommands execCreateF...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
  1. dhcp.pm
  2. The dhcp plugin

package dhcp;

@ISA = qw(Exporter); @EXPORT = qw(createPlugin

            bootingCreateFiles
            bootingCommands
            execCreateFiles
            execCommands
            shutdownCommand
            finalizePlugin);
  1. Modules no import

use strict; use Net::Netmask; 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


  1. Global variables

my $globalNode; my $valid_fail;


  1. Subroutines

########################################################### # createPlugin # # 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;

print "dhcp: $conf\n"; 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 $type;

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 ){

$type = $virtualm->getAttribute("type");

switch ($type) {

case "dhcp3" {

my $serverTagList = $virtualm->getElementsByTagName("server"); my $numservers = $serverTagList->getLength; if ( $numservers == 1 ) {

# open filehandle to create /etc/dhcp3/dhcpd.conf file my $server_file = "/tmp/$vm" . "_server.conf"; chomp( my $date = `date` ); open( SERVER, ">$server_file" ) or $files{"ERROR"} = "Cannot open $server_file file";

# server.conf file defaults print SERVER "# server.conf file generated by dhcp.pm VNUML plugin at $date\n\n"; print SERVER "ddns-update-style none;\n"; print SERVER "default-lease-time 120;\n"; print SERVER "max-lease-time 120;\n"; #print SERVER "log-facility local7;\n\n";

# extract configuration from subnet blocks in dhcp_conf.xml my $server = $serverTagList->item(0); my $subnetTagList = $server->getElementsByTagName("subnet"); my $numsubnets = $subnetTagList->getLength;

for ( my $ns=0; $ns < $numsubnets ; $ns++ ) { my $subnet = $subnetTagList->item($ns); my $ipTagList = $subnet->getElementsByTagName("ip"); my $numip = $ipTagList->getLength;

# subnet declaration my $ipTag = $ipTagList->item($0); my $subnetmask = $ipTag->getAttribute("mask"); my $subnetbaseip = $ipTag->getFirstChild->getData; my $block = new Net::Netmask("$subnetbaseip"."/"."$subnetmask");

my $baseip = $block->base(); my $mask = $block->mask(); print SERVER "subnet $baseip netmask $mask {\n";

# extract ip ranges in subnet my $rangeTagList = $subnet->getElementsByTagName("range"); my $numranges = $rangeTagList->getLength;

for ( my $nr = 0; $nr < $numranges ; $nr++ ) { my $rangeTag = $rangeTagList->item($nr); my $firstTagList = $rangeTag->getElementsByTagName("first"); my $firstTag = $firstTagList->item(0); my $firstip = $firstTag->getFirstChild->getData; my $lastTagList = $rangeTag->getElementsByTagName("last"); my $lastTag = $lastTagList->item(0); my $lastip = $lastTag->getFirstChild->getData; print SERVER " range $firstip $lastip;\n"; }

# extract routers in subnet (if any) my $routerTagList = $subnet->getElementsByTagName("router"); my $numrouters = $routerTagList->getLength;

if ( $numrouters > 0 ) { print SERVER " option routers"; for ( my $nr = 0; $nr < $numrouters ; $nr++ ) { if ( $nr > 0 ) { print SERVER ","; } my $routerTag = $routerTagList->item($nr); my $router = $routerTag->getFirstChild->getData; print SERVER " $router"; } print SERVER ";\n"; }

# extract dns in subnet (if any) my $dnsTagList = $subnet->getElementsByTagName("dns"); my $numdns = $dnsTagList->getLength; if ( $numdns > 0 ) { print SERVER " option domain-name-servers"; for ( my $nd = 0; $nd < $numdns ; $nd++ ) { if ( $nd > 0 ) { print SERVER ","; } my $dnsTag = $dnsTagList->item($nd); my $dns = $dnsTag->getFirstChild->getData; print SERVER " $dns"; } print SERVER ";\n"; }

# extract domain in subnet (if specified) my $domainTagList = $subnet->getElementsByTagName("domain"); my $numdomains = $domainTagList->getLength; if ( $numdomains == 1 ) { my $domainTag = $domainTagList->item(0); my $domain = $domainTag->getFirstChild->getData; print SERVER " option domain-name \"$domain\";\n"; }

# end subnet declaration in configuration file print SERVER "}\n\n";

# extract hosts in subnet (if any) my $hostTagList = $subnet->getElementsByTagName("host"); my $numhosts = $hostTagList->getLength; for ( my $nh = 0; $nh < $numhosts ; $nh++ ) { my $hostTag = $hostTagList->item($nh); my $hostname = $hostTag->getAttribute("name"); my $hostmac = $hostTag->getAttribute("mac"); my $hostip = $hostTag->getAttribute("ip");

# ignore unmatching host declarations if ( $block->match($hostip) ) { print SERVER "host $hostname {\n hardware ethernet $hostmac;\n fixed-address $hostip;\n}\n\n"; } }

} close(SERVER); $files{"/etc/dhcp3/dhcpd.conf"} = $server_file; }

my $relayTagList = $virtualm->getElementsByTagName("relay"); my $numrelays = $relayTagList->getLength; if ( $numrelays == 1 ) {

# Build file /etc/default/dhcp3-relay.conf my $relay_file = "/tmp/$vm" . "_relay.conf"; chomp( my $date = `date` ); open( RELAY, ">$relay_file" ) or $files{"ERROR"} = "Cannot open $relay_file file"; print RELAY "# relay.conf file generated by dhcp.pm VNUML plugin at $date\n"; print RELAY "SERVERS=\""; my $relay = $relayTagList->item(0); my $toserverTagList = $relay->getElementsByTagName("toserver"); my $numtoservers = $toserverTagList->getLength;

for ( my $nt = 0; $nt < $numtoservers ; $nt++ ) { my $toserverTag = $toserverTagList->item($nt); my $toserverData = $toserverTag->getFirstChild->getData; print RELAY "$toserverData "; }

print RELAY "\"\n"; close(RELAY); $files{"/etc/default/dhcp3-relay"} = $relay_file; }

my $clientTagList = $virtualm->getElementsByTagName("client"); my $numclients = $clientTagList->getLength; if ( $numclients == 1 ) { # Build file /etc/dhcp3/dhclient.conf my $client_file = "/tmp/$vm" . "_client.conf"; chomp( my $date = `date` ); open( CLIENT, ">$client_file" ) or $files{"ERROR"} = "Cannot open $client_file file"; print CLIENT "# Configuration file for /sbin/dhclient, which is included in Debian's dhcp3-client package.\n"; print CLIENT "# client.conf file generated by dhcp.pm VNUML plugin at $date\n\n"; print CLIENT "send host-name \"<hostname>\";\n"; print CLIENT "request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, domain-search, host-name, netbios-name-servers, netbios-scope, interface-mtu;\n"; print CLIENT "retry 10;\n"; close(CLIENT); $files{"/etc/dhcp3/dhclient.conf"} = $client_file;

} }else{ $files{"ERROR"} = "Your choice $type for $vm is not a recognized type (yet)\n"; } } } } return %files; }

########################################################### # bootingCommands # # To be called during "t" mode, for each vm in the scenario # # Arguments: # - vm name # # Returns: # - list of commands to execute in the virtual machine at booting time # ###########################################################

sub bootingCommands {

}


########################################################### # execVmsToUse # # To be called once during "x" mode # # Arguments: # - seq command sequence # # Returns: # - list of virtual machines where the command has effect # ###########################################################

sub execVmsToUse {

my $self = shift; my $seq = shift;

# Four lists are built, one is returned depending on the executed command my @vm_list = (); my @server_vm_list = (); my @relay_vm_list = (); my @client_vm_list = ();

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"); push (@vm_list,$virtualm_name);

my $serverTagList = $virtualm->getElementsByTagName("server"); my $numservers = $serverTagList->getLength; my $relayTagList = $virtualm->getElementsByTagName("relay"); my $numrelays = $relayTagList->getLength; my $clientTagList = $virtualm->getElementsByTagName("client"); my $numclients = $clientTagList->getLength;

if ( $numservers == 1 ) { push (@server_vm_list,$virtualm_name); } if ( $numrelays == 1 ) { push (@relay_vm_list,$virtualm_name); } if (!($numclients == 0)) { push (@client_vm_list,$virtualm_name); } }

if ($seq eq "start" || $seq eq "restart" || $seq eq "stop" || $seq eq "dhcp-start" || $seq eq "dhcp-restart" || $seq eq "dhcp-stop") { return @vm_list; }elsif ($seq eq "dhcp-server-start"|| $seq eq "dhcp-server-stop" || $seq eq "dhcp-server-restart" || $seq eq "dhcp-server-force-reload"){ return @server_vm_list; }elsif ( $seq eq "dhcp-relay-start"|| $seq eq "dhcp-relay-restart"|| $seq eq "dhcp-relay-stop"|| $seq eq "dhcp-relay-force-reload"){ return @relay_vm_list; }elsif ($seq eq "dhcp-client-start"||$seq eq "dhcp-client-restart"||$seq eq "dhcp-client-stop"){ return @client_vm_list; }else{ return (); } }



########################################################### # 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 { }


########################################################### # 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 $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");

switch ($type) {

case "dhcp3" { # recognized type } else { unshift( @commands, "Your choice $type for $vm is not a recognized type (yet)\n"); } }

my $serverTagList = $virtualm->getElementsByTagName("server"); my $numservers = $serverTagList->getLength; my $relayTagList = $virtualm->getElementsByTagName("relay"); my $numrelays = $relayTagList->getLength; my $clientTagList = $virtualm->getElementsByTagName("client"); my $numclients = $clientTagList->getLength;

switch ($seq){

case ["start","dhcp-start"]{ # Start server, relay and clients in the virtual machine, if any unshift( @commands, "" ); if ( $numservers == 1 ) { push( @commands, "/etc/init.d/dhcp3-server start" ); } if ( $numrelays == 1 ) { push( @commands, "/etc/init.d/dhcp3-relay start" ); } if (!($numclients == 0)) { unshift(@commands, "" ); my $client = $clientTagList->item(0); my $ifTagList = $client->getElementsByTagName("if"); my $numif = $ifTagList->getLength; for (my $ni=0; $ni<$numif ; $ni++) { my $ifTag = $ifTagList->item($ni); my $ifData = $ifTag->getFirstChild->getData; if (!($ifData == 0)) { push(@commands,"dhclient eth"."$ifData"); } } }

} case ["restart","dhcp-restart"]{ # Restart server, relay and clients in the virtual machine, if any unshift( @commands, "" ); if ( $numservers == 1 ) { push( @commands, "/etc/init.d/dhcp3-server restart" ); } if ( $numrelays == 1 ) { push( @commands, "/etc/init.d/dhcp3-relay restart" ); } if (!($numclients == 0)) { unshift(@commands, "" ); my $client = $clientTagList->item(0); my $ifTagList = $client->getElementsByTagName("if"); my $numif = $ifTagList->getLength; for (my $ni=0; $ni<$numif ; $ni++) { my $ifTag = $ifTagList->item($ni); my $ifData = $ifTag->getFirstChild->getData; if (!($ifData == 0)) { push(@commands,"dhclient -r"); push(@commands,"killall dhclient"); push(@commands,"dhclient eth"."$ifData"); } } }

} case ["stop","dhcp-stop"]{ # Stop server and relay in the virtual machine, if any unshift( @commands, "" ); if ( $numservers == 1 ) { push( @commands, "/etc/init.d/dhcp3-server stop" ); } if ( $numrelays == 1 ) { push( @commands, "/etc/init.d/dhcp3-relay stop" ); } if (!($numclients == 0)) { unshift(@commands, "" ); my $client = $clientTagList->item(0); my $ifTagList = $client->getElementsByTagName("if"); my $numif = $ifTagList->getLength; for (my $ni=0; $ni<$numif ; $ni++) { my $ifTag = $ifTagList->item($ni); my $ifData = $ifTag->getFirstChild->getData; if (!($ifData == 0)) { push(@commands,"dhclient -r"); push(@commands,"killall dhclient"); } } }

} case ("dhcp-server-start"){ # Start the server in the virtual machine. Return error if there isn't any. if ( $numservers == 0 ) { unshift( @commands, "$vm is not configured as a dhcp server. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-server start" ); } } case ("dhcp-relay-start"){ # Start the relay in the virtual machine. Return error if there isn't any. if ( $numrelays == 0 ) { unshift( @commands, "$vm is not configured as a dhcp relay. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-relay start" ); } } case ("dhcp-client-start"){ # Start the clients in the virtual machine. Return error if there aren't any. if ( $numclients == 0 ) { unshift( @commands, "$vm is not configured as a dhcp client. Choose the appropriate virtual machine with flag -M name" ); } else { unshift(@commands, "" ); my $client = $clientTagList->item(0); my $ifTagList = $client->getElementsByTagName("if"); my $numif = $ifTagList->getLength; for (my $ni=0; $ni<$numif ; $ni++) { my $ifTag = $ifTagList->item($ni); my $ifData = $ifTag->getFirstChild->getData; if (!($ifData == 0)) { push(@commands,"dhclient eth"."$ifData"); } }

} } case ("dhcp-server-restart"){ # Restart the server in the virtual machine. Return error if there isn't any. if ( $numservers == 0 ) { unshift( @commands, "$vm is not configured as a dhcp server. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-server restart" ); } } case ("dhcp-relay-restart"){ # Restart the relay in the virtual machine. Return error if there isn't any. if ( $numrelays == 0 ) { unshift( @commands, "$vm is not configured as a dhcp relay. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-relay restart" ); } }

case ("dhcp-client-restart"){ # Start the clients in the virtual machine. Return error if there aren't any. if ( $numclients == 0 ) { unshift( @commands, "$vm is not configured as a dhcp client. Choose the appropriate virtual machine with flag -M name" ); } else { unshift(@commands, "" ); my $client = $clientTagList->item(0); my $ifTagList = $client->getElementsByTagName("if"); my $numif = $ifTagList->getLength; for (my $ni=0; $ni<$numif ; $ni++) { my $ifTag = $ifTagList->item($ni); my $ifData = $ifTag->getFirstChild->getData; if (!($ifData == 0)) { push(@commands,"dhclient -r"); push(@commands,"killall dhclient"); push(@commands,"dhclient eth"."$ifData"); } }

} }

case ("dhcp-server-stop"){ # Stop the server in the virtual machine. Return error if there isn't any. if ( $numservers == 0 ) { unshift( @commands, "$vm is not configured as a dhcp server. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-server stop" ); }

} case ("dhcp-relay-stop"){ # Stop the relay in the virtual machine. Return error if there isn't any. if ( $numrelays == 0 ) { unshift( @commands, "$vm is not configured as a dhcp relay. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-relay stop" ); }

}

case ("dhcp-client-stop"){ # Start the clients in the virtual machine. Return error if there aren't any. if ( $numclients == 0 ) { unshift( @commands, "$vm is not configured as a dhcp client. Choose the appropriate virtual machine with flag -M name" ); } else { unshift(@commands, "" ); my $client = $clientTagList->item(0); my $ifTagList = $client->getElementsByTagName("if"); my $numif = $ifTagList->getLength; for (my $ni=0; $ni<$numif ; $ni++) { my $ifTag = $ifTagList->item($ni); my $ifData = $ifTag->getFirstChild->getData; if (!($ifData == 0)) { push(@commands,"dhclient -r"); push(@commands,"killall dhclient"); } }

} }

case ("dhcp-server-force-reload"){ # Force reload of the server in the virtual machine. Return error if there isn't any. if ( $numservers == 0 ) { unshift( @commands, "$vm is not configured as a dhcp server. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-server force-reload" ); }

} case ("dhcp-relay-force-reload"){ # Force reload of the relay in the virtual machine. Return error if there isn't any. if ( $numservers == 0 ) { unshift( @commands, "$vm is not configured as a dhcp relay. Choose the appropriate virtual machine with flag -M name" ); } else { unshift( @commands, "" ); push( @commands, "/etc/init.d/dhcp3-relay force-reload" ); }

}else{ unshift( @commands, "\nYour choice \"$seq\" is not a recognized command (yet).\nAvailable commands: start, stop, restart, dhcp-start, dhcp-stop, dhcp-restart, dhcp-server-start, dhcp-server-stop, dhcp-server-restart, dhcp-server-force-reload, dhcp-relay-start, dhcp-relay-stop, dhcp-relay-restart, dhcp-relay-force-reload, dhcp-client-start.\n" ); } } return @commands; } } }



########################################################### # shutdownCommands # # To be called during "d" mode, for each vm in the scenario # # Arguments: # - vm name # # Returns: # - list of commands to execute in the virtual machine at shutdown time # ###########################################################

sub shutdownCommands {

my $self = shift; my $vm = shift;

my @commands;

my $type;

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");

switch ($type) {

case "dhcp3" {

unshift( @commands, "" ); my $serverTagList = $virtualm->getElementsByTagName("server"); my $numservers = $serverTagList->getLength;

if ( $numservers == 1 ) { push( @commands, "/etc/init.d/dhcp3-server stop" ); }

my $relayTagList = $virtualm->getElementsByTagName("relay"); my $numrelays = $relayTagList->getLength;

if ( $numrelays == 1 ) { push( @commands, "/etc/init.d/dhcp3-relay stop" ); } } else { unshift( @commands,"Your choice $type for $vm is not a recognized type (yet)\n"); }

} }

return @commands;

} }

############################################################# # finalizePlugin # # To be called always, just before ending the procesing the scenario specification # # Arguments: # - none # # Returns: # - none # #############################################################

sub finalizePlugin {

}

############################################################# # # Checks existence and semantics in ospf conf file. # Currently this check consist in: # # 1. Configuration file exists. # 2. Check DTD. # 3. IP tag contains mask attribute and data. # 4. Area tag is unique and contains data. # #############################################################

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 DHCP plugin file\n"); }

$globalNode = $dom_tree->getElementsByTagName("dhcp_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