You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by di...@apache.org on 2013/10/18 21:50:58 UTC

svn commit: r1533611 - /vcl/trunk/managementnode/lib/VCL/Module/Provisioning/one.pm

Author: dimach
Date: Fri Oct 18 19:50:57 2013
New Revision: 1533611

URL: http://svn.apache.org/r1533611
Log:
VCL-722:  added support for ONE templates - allows to use ONE templates to build custom VMs. Template name should match image name. Templates are optional, one.pm will create VM based on disk image using default values.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/one.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/one.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/one.pm?rev=1533611&r1=1533610&r2=1533611&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/one.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/one.pm Fri Oct 18 19:50:57 2013
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl -w -d
 ###############################################################################
 # $Id: $ 
 ###############################################################################
@@ -62,17 +62,6 @@ use Data::Dumper;
 my %one;
 my $xml;
 
-##############################################################################
-
-
-##############################################################################
-
-=head1 OBJECT METHODS
-
-=cut
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 initialize
 
  Parameters  :
@@ -128,6 +117,7 @@ sub load {
 		return 0;
 	}
 	
+	
 	my $reservation_id = $self->data->get_reservation_id();
 	my $computer_id = $self->data->get_computer_id();
 	my $image_name = $self->data->get_image_name();
@@ -143,76 +133,110 @@ sub load {
 	my $computer_name = $self->data->get_computer_hostname();
 	if ($memory < 512) {
 		$memory = 512;
-		$memory = $cpu_count * 2048;
+		#$memory = $cpu_count * 2048;
 	}
 	my $one_vm_name = "$computer_name ($image_name)";
 
-	
 	#delete running VM, if present
-	my $one_computer_id = $self->one_get_object_id("computer",$computer_name);
+	notify($ERRORS{'OK'}, 0, "Checking if computer $computer_name already loaded on ONE...");
+	my $one_computer_id = $self->_one_get_object_id("computer",$computer_name);
 	if ($one_computer_id) {
-		$self->one_delete_vm($one_computer_id);
+		$self->_one_delete_vm($one_computer_id);
+		notify($ERRORS{'OK'}, 0, "Computer $computer_name already loaded on ONE ... deleted.");
 	}
 	
-	my $one_network_0_id = $self->one_get_object_id("network",$one_network_0);
-	my $one_network_1_id = $self->one_get_object_id("network",$one_network_1);
-	my $one_image_id = $self->one_get_object_id("image",$image_name);
-	my $one_virtio = '';
-	$one_virtio = $self->one_get_virtio($one_image_id);
-	
-	my $one_network = 'NIC=[NETWORK_ID="'.$one_network_0_id.'",IP="'.$eth0_ip.'"'.$one_virtio.']';
-	
-	if ($self->data->can("get_vNetwork")) {
-		my @vNetwork = $self->data->get_vNetwork();
-		if (@vNetwork) {
-			# yes, add custom network(s);
-			notify($ERRORS{'OK'}, 0, "Reservation will be loaded with addition Networks:");
-			foreach (@vNetwork) {
-				my $one_net_id = $self->one_get_object_id("network",'VLAN_ID='.$_);
-				$one_network = $one_network.'NIC=[NETWORK_ID="'.$one_net_id.'"'.$one_virtio.']';
-				}
-		} else { 
-			# no custom networks, add eth1 as default public;
-			$one_network = $one_network.'NIC=[NETWORK_ID="'.$one_network_1_id.'"'.$one_virtio.']';
-		}
-	} else {
-		# custom networking is not implemented, add eth1 as default public;
-		$one_network = $one_network.'NIC=[NETWORK_ID="'.$one_network_1_id.'"'.$one_virtio.']';
-	}
+	# check if there is ONE template already exsist for the image
+	# and create VM based on the template. If no template create 'manually'
 	
-	# Check if SWAP disk needed, format: DISK=[DEV_PREFIX="vd",TYPE="swap",SIZE="4096"]
-	my $swap_disk = '';
-	my $swap_size = $self->one_get_image_tag_value("SWAP");
-	if (defined($swap_size)) {
-		if ($self->one_get_image_tag_value("DEV_PREFIX") eq "vd") {
-			$swap_disk = 'DISK=[DEV_PREFIX="vd",TYPE="swap",SIZE="'.$swap_size.'"]';
+	my $one_template_id = $self->_one_get_template_id($image_name);
+	if ($one_template_id) {
+		my @template_info = $one{'server'}->call('one.template.info',$one{'auth'},$one_template_id);
+		if ($template_info[0][0]->value()) {
+			my $data = XMLin($template_info[0][1]);
+			my $template;
+			$template = $data->{TEMPLATE};
+			$template->{NAME} = $one_vm_name;
+			$template->{NIC}[0]{IP} = $eth0_ip;
+			
+			my $one_new_vmid = $self->_one_create_vm(XMLout($template,NoAttr => 1,RootName=>'TEMPLATE',));	
+			if ($one_new_vmid) {
+				notify($ERRORS{'OK'}, 0, "New VM $template->{NAME} deployed with ID $one_new_vmid using template ID $one_template_id");
+				insertloadlog($reservation_id, $computer_id, "vmsetupconfig", "defined $computer_name");
+				insertloadlog($reservation_id, $computer_id, "startvm", "powered on $computer_name");
+			} else {
+				notify($ERRORS{'CRITICAL'}, 0, "Could't create requested VM. Abort.");
+				return 0;
+			}
 		} else {
-			$swap_disk = 'DISK=[TYPE="swap",SIZE="'.$swap_size.'"]';
+			notify($ERRORS{'CRITICAL'}, 0, "Error while making one.template.info call: $template_info[0][1]");
 		}
-	}
-	
-	my $VM_TEMPLATE = 'OS=[BOOT="hd",ARCH="'.$image_arch.'",ACPI="YES"] 
-		NAME="'.$one_vm_name.'"
-		CPU="'.$cpu_count.'"
-		VCPU="'.$cpu_count.'" 
-		INPUT=[BUS="usb",TYPE="tablet"]
-		MEMORY="'.$memory.'" 
-		GRAPHICS=[TYPE="VNC",LISTEN="0.0.0.0"] 
-		DISK=[IMAGE_ID="'.$one_image_id.'"]'.$swap_disk.$one_network;
-	
-	# create VM
-	my @reply = $one{'server'}->call('one.vm.allocate',$one{'auth'},$VM_TEMPLATE,$one{'false'});
-	
-	if ( $reply[0][0]->value() ) {
-		notify($ERRORS{'OK'}, 0, "New VM ".$vm_name." deployed with ID: $reply[0][1] using template: $VM_TEMPLATE");
-		insertloadlog($reservation_id, $computer_id, "vmsetupconfig", "defined $computer_name");
-		insertloadlog($reservation_id, $computer_id, "startvm", "powered on $computer_name");
 	} else {
-		notify($ERRORS{'CRITICAL'}, 0, "\n".$VM_TEMPLATE."\n".$reply[0][1]);
-		return 0;
+		
+		# No template, create VM manually:
+		my $template = {};
+		my $one_network_0_id = $self->_one_get_object_id("network",$one_network_0);
+		my $one_network_1_id = $self->_one_get_object_id("network",$one_network_1);
+		my $one_image_id = $self->_one_get_object_id("image",$image_name);
+		my $one_virtio = $self->_one_get_virtio($one_image_id);
+		my $virtio = 0;
+		if ($self->_one_get_image_tag_value($image_name,"DEV_PREFIX") eq "vd") {
+			$virtio = 1;
+		}
+		
+		$template->{NAME} = $one_vm_name;
+		$template->{CPU} = $cpu_count;
+		$template->{VCPU} = $cpu_count;
+		$template->{MEMORY} = $memory;
+		$template->{OS}{ARCH} = $image_arch; 
+		$template->{INPUT}{BUS} = "usb";
+		$template->{INPUT}{TYPE} = "tablet";
+		$template->{GRAPHICS}{TYPE} = "VNC";
+		$template->{GRAPHICS}{LISTEN} = "0.0.0.0";
+		$template->{REQUIREMENTS} = "CLUSTER_ID=\"100\"";
+		$template->{DISK}[0]{IMAGE_ID} = $one_image_id;
+		$template->{NIC}[0]{NETWORK_ID} = $one_network_0_id;
+		$template->{NIC}[0]{IP} = $eth0_ip;
+		$template->{NIC}[0]{MODEL} = "virtio" if ($virtio);
+		
+		if ($self->data->can("get_vNetwork")) {
+			my @vNetwork = $self->data->get_vNetwork();
+			if (@vNetwork) {
+				# yes, add custom network(s);
+				notify($ERRORS{'OK'}, 0, "Reservation will be loaded with addition Network(s):");
+				foreach (@vNetwork) {
+					my $one_net_id = $self->_one_get_object_id("network",'VLAN_ID='.$_);
+					$template->{NIC}[1]{NETWORK_ID} = $one_net_id;
+					}
+			} else { 
+				# no custom networks, add eth1 as default public;
+				$template->{NIC}[1]{NETWORK_ID} = $one_network_1_id;
+			}
+		} else {
+			# custom networking is not implemented, add eth1 as default public;
+			$template->{NIC}[1]{NETWORK_ID} = $one_network_1_id;
+		}
+		
+		$template->{NIC}[1]{MODEL} = "virtio" if ($virtio);
+			
+		# Check if SWAP disk needed. Does image have SWAP=<size_MB> attribute?
+		my $swap_disk = '';
+		my $swap_size = $self->_one_get_image_tag_value($image_name,"SWAP");
+		if ($swap_size) {
+			$template->{DISK}[1]{TYPE} = "swap";
+			$template->{DISK}[1]{SIZE} = $swap_size;
+			$template->{DISK}[1]{DEV_PREFIX} = "vd" if ($virtio); 
+		}
+		
+		# create VM
+		
+		my $one_new_vmid = $self->_one_create_vm(XMLout($template,NoAttr => 1,RootName=>'TEMPLATE',));	
+		if ($one_new_vmid) {
+			notify($ERRORS{'OK'}, 0, "New VM $template->{NAME} deployed with ID $one_new_vmid");
+			insertloadlog($reservation_id, $computer_id, "vmsetupconfig", "defined $computer_name");
+			insertloadlog($reservation_id, $computer_id, "startvm", "powered on $computer_name");
+		}	
 	}
-	
-
+	# VM is created and loading, execute "post_load"
 	if ($self->os->can("post_load")) {
 		if ($self->os->post_load()) {
 			insertloadlog($reservation_id, $computer_id, "loadimagecomplete", "performed OS post-load tasks for $computer_name");
@@ -229,38 +253,7 @@ sub load {
 	return 1;
 }
 
-#/////////////////////////////////////////////////////////////////////////////
-=head2 one_get_virtio
-
- Parameters  : imagename
- Returns     : '' or MODEL="virtio"
- Description : 
-
-=cut
 
-sub one_get_virtio {
-	my $self = shift;
-	unless (ref($self) && $self->isa('VCL::Module')) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method");
-		return;	
-	}
-	
-	my $one_image_id = shift;
-	
-	my @reply = $one{'server'}->call('one.image.info',$one{'auth'},$one_image_id);
-	
-	if ( $reply[0][0]->value() ) {
-		my $data = $xml->XMLin($reply[0][1]);
-		if ($data->{TEMPLATE}{DEV_PREFIX} eq 'vd' ) {
-			return ',MODEL="virtio"';
-		}
-	} else {
-		notify($ERRORS{'WARNING'}, 0, "couldn't get image configuration for image_id $one_image_id, won't use VIRTIO driver.");
-		return '';
-	}
-	
-	return '';
-}
 #/////////////////////////////////////////////////////////////////////////////
 
 =head2 does_image_exist
@@ -287,7 +280,7 @@ sub does_image_exist {
 		return;
 	}
 	
-	my $one_image_id = $self->one_get_object_id("image",$image_name);
+	my $one_image_id = $self->_one_get_object_id("image",$image_name);
 	if ($one_image_id) {
 		notify($ERRORS{'DEBUG'}, 0, "Found image $image_name with id $one_image_id");
 		return $one_image_id;
@@ -299,118 +292,6 @@ sub does_image_exist {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 one_get_object_id
-
- Parameters  : $o_type, $o_name
- Returns     : ONE Object ID (INT)
- Description : 
-
-=cut
-
-sub one_get_object_id {
-	my $self = shift;
-	unless (ref($self) && $self->isa('VCL::Module')) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-		return 0;
-	}
-	
-	my $o_type = shift;
-	my $o_name = shift;
-	
-	if ($o_type eq "computer") {
-		my @reply = $one{server}->call('one.vmpool.info',$one{'auth'},-3,-1,-1,-1);
-		if ( $reply[0][0]->value() ) {
-			
-			my $data = $xml->XMLin($reply[0][1]);
-			if ( (ref($data->{VM})) eq "ARRAY" ){
-				foreach (@{$data->{VM}}) {
-			    	if ($_->{NAME} =~ /$o_name/i) {
-			        	return $_->{ID};
-			        }
-			  	}
-		    } else { #HASH, found only one entry
-				if ($data->{VM}{NAME} =~ /$o_name/i) {
-			    	return $data->{VM}{ID};
-			    }
-			}
-		} else {
-			notify($ERRORS{'CRITICAL'}, 0, $reply[0][1]);
-			return 0;
-		}	
-	} elsif ($o_type eq "image") {
-		my @reply = $one{'server'}->call('one.imagepool.info', $one{'auth'},-3,-1,-1);
-		if ( $reply[0][0]->value() ) {
-			
-			my $rs_data = $xml->XMLin($reply[0][1]);
-				if ( (ref($rs_data->{IMAGE})) eq "ARRAY" ) {
-					foreach (@{$rs_data->{IMAGE}}) {
-						if ($_->{NAME} eq $o_name) {
- 							return $_->{ID};
-						}
-					}
-					} else { #HASH, only one entry
-						if ($rs_data->{IMAGE}{NAME} eq $o_name) {
-							return $rs_data->{IMAGE}{ID};
-						}
-					}
-		} else {
-			notify($ERRORS{'CRITICAL'}, 0, $reply[0][1]);
-			return 0;
-		}
-	} elsif ($o_type eq "network") {
-		my @reply = $one{'server'}->call('one.vnpool.info',$one{'auth'},-1,-1,-1);
-		if ($reply[0][0]->value()) {
-			my $rs_data = $xml->XMLin($reply[0][1]);
-			# don't check if ARRAY or HASH since we always have more then 1 network
-			foreach (@{$rs_data->{VNET}}) {
-				# if $o_name is in VLAN_ID= then lookup by VLAN_ID, not NAME
-				
-				if ($o_name =~ /^VLAN_ID=/i) {
-					my @vlan_id = split('=',$o_name);
-					if ($_->{VLAN_ID} == $vlan_id[1]) {
-						return $_->{ID};
-					}
-				} else {
-					if ($_->{NAME} eq $o_name) {
-						return $_->{ID};
-					}
-				}
-			}
-		} else {
-			notify($ERRORS{'CRITICAL'},0,$reply[0][1]);
-			return 0;
-		}
-	} else {
-		notify($ERRORS{'CRITICAL'}, 0, "$o_type is UNKNOWN type");
-		return 0;
-	} 
-	
-	return 0;	
-} 
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 one_delete_vm
-
- Parameters  : $vmid
- Returns     : 
- Description : one.vm.action
-
-=cut
-
-sub one_delete_vm {
-	my $self = shift;
-	my $vmid = shift;
-	my @reply;
-	
-	@reply = $one{'server'}->call('one.vm.action', $one{'auth'},'delete',$vmid);
-	if ( $reply[0][0]->value() ) {
-		notify($ERRORS{'OK'}, 0, "ONE VM $vmid deleted");
-	} else {
-		notify($ERRORS{'CRITICAL'}, 0, $reply[0][1]);
-	}
-	
-} 
 
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -430,6 +311,7 @@ sub capture {
 		return;
 	}
 	
+	my $old_image_name;
 	my $image_name = $self->data->get_image_name();
 	
 	my $image_id = $self->data->get_image_id();
@@ -442,8 +324,12 @@ sub capture {
 	
 	notify($ERRORS{'OK'}, 0, "ONE module starting image capture.");
 	
-	my $vmid = $self->one_get_object_id("computer",$computer_name);
+	my $vmid = $self->_one_get_object_id("computer",$computer_name);
 	if ($vmid) {
+		# get {TEMPLATE}{DISK}{IMAGE} of $vmid, the name of current image
+		
+		$old_image_name = $self->_one_get_vm_disk($vmid);
+		
 		my @savedisk = $one{'server'}->call('one.vm.savedisk', $one{'auth'},$vmid,0,$image_name,'OS',$one{'false'});
 		if ( $savedisk[0][0]->value() ) {
 			notify($ERRORS{'OK'}, 0, "VM $vmid will be captured as $image_name");
@@ -485,15 +371,15 @@ sub capture {
 		my $lcm_state;
 		
 		notify($ERRORS{'OK'}, 0, "Wait for the VM $vmid to enter ACTIVE/EPILOG (3/11) state...");
-		while (1) {
-			$state = $self->one_get_vm_state($vmid);
+		EPILOG: while (1) {
+			$state = $self->_one_get_vm_state($vmid);
 			notify($ERRORS{'OK'}, 0, "VM $vmid is in $state state");
 			if ($state == 3) {
-				$lcm_state = $self->one_get_vm_lcm_state($vmid);
+				$lcm_state = $self->_one_get_vm_lcm_state($vmid);
 				notify($ERRORS{'OK'}, 0, "VM $vmid is in $lcm_state lcm_state");
 				if ($lcm_state == 11) {
 					notify($ERRORS{'OK'}, 0, "VM $vmid is in EPILOG state. OK");
-					last;
+					last EPILOG;
 				} else {
 					notify($ERRORS{'OK'}, 0, "VM $vmid is in $state / $lcm_state state...");
 				}
@@ -505,15 +391,15 @@ sub capture {
 			$wait_time = $wait_time - $sleep;
 			notify($ERRORS{'OK'}, 0, "Waiting for VM $vmid to enter ACTIVE/EPILOG state, $wait_time sec left ...");
 			
-			if ($wait_time <= 0) {
+			if ($wait_time <= $sleep) {
 				notify($ERRORS{'DEBUG'}, 0, "VM $vmid never reached EPILOG state. Wait for ACTIVE/RUNNING (3/3) and send 'shutdown-hard'");
 				my $sleep = 15;
 				my $wait_time = 20 * 60; #how long to wait for ACTIVE/RUNNING (3/3)
 				
 				while (1) {
-					$state = $self->one_get_vm_state($vmid);
+					$state = $self->_one_get_vm_state($vmid);
 					if ($state == 3) {
-						$lcm_state = $self->one_get_vm_lcm_state($vmid);
+						$lcm_state = $self->_one_get_vm_lcm_state($vmid);
 						if ($lcm_state == 3) {
 							notify($ERRORS{'OK'}, 0, "VM $vmid is in $state / $lcm_state state. Wait $sleep sec and send 'shutdown-hard'");
 							sleep $sleep;
@@ -521,34 +407,31 @@ sub capture {
 								notify($ERRORS{'CRITICAL'}, 0, "Couldn't shutdown $computer_name with power_off('hard')");
 								return 0;
 							} 
-							last;
+							last EPILOG;
 						} else {
 							notify($ERRORS{'OK'}, 0, "VM $vmid is in $state / $lcm_state state...");
 						}
 					} else {
 						notify($ERRORS{'OK'}, 0, "VM $vmid is in $state state...");
 					}
-					sleep $sleep;
+					sleep $sleep if ($wait_time > 0);
 					$wait_time = $wait_time - $sleep;
 					notify($ERRORS{'OK'}, 0, "Waiting for VM $vmid to enter ACTIVE/RUNNING state, $wait_time sec left ...");
-					if ($wait_time <= 0) {
+					if ($wait_time <= $sleep) {
 						notify($ERRORS{'CRITICAL'}, 0, "VM $vmid is in $state / $lcm_state after $wait_time sec ... Fail!");
 						return 0;
 					}
 				}
-				
 			}
 		}
 	}
 
-	#
-	
 	# Check that we have new_image_name created on ONE (it will be in LOCKED state until disk_save is done).
 	# just procation, image stub should be created already.
 	my $sleep = 5;
 	my $wait_time = 20 * 60; # in min * 60 = seconds
 	while (1) {
-		$one_new_image_id = $self->one_get_object_id("image",$image_name);
+		$one_new_image_id = $self->_one_get_object_id("image",$image_name);
 		last if ($one_new_image_id);
 		$wait_time = $wait_time - $sleep;
 		if ($wait_time <= 0) {
@@ -563,7 +446,7 @@ sub capture {
 	$wait_time = 30 * 60; # in min * 60 = seconds
 	while (1) {
 		notify($ERRORS{'OK'}, 0, "check status for new image id $one_new_image_id, $wait_time sec left...");
-		my $one_image_state = $self->one_get_image_state($one_new_image_id);
+		my $one_image_state = $self->_one_get_image_state($one_new_image_id);
 		if ($one_image_state == 4) {
 			notify($ERRORS{'OK'}, 0, "disk save in pregress, image id $one_new_image_id is LOCKED");
 		}
@@ -573,6 +456,31 @@ sub capture {
 		}
 		if ($one_image_state == 1) {
 			notify($ERRORS{'OK'}, 0, "disk save OK, image id $one_new_image_id is READY");
+			# check if template exists for the old image and create template for the new image.
+			my $one_template_id = $self->_one_get_template_id($old_image_name); 
+			if ($one_template_id) {
+				notify($ERRORS{'OK'}, 0, "Found existing template id $one_template_id for $old_image_name");
+				my @template_info = $one{'server'}->call('one.template.info',$one{'auth'},$one_template_id);
+				if ($template_info[0][0]->value()) {
+					my $data = XMLin($template_info[0][1]);
+					my $template = $data->{TEMPLATE};
+					$template->{NAME} = $image_name;
+					
+					if ( (ref($template->{DISK})) eq "ARRAY" ) { # template has multiple disks, update [0]
+						$template->{DISK}[0]{IMAGE_ID} = $one_new_image_id;
+					} else { #template has one disk
+						$template->{DISK}{IMAGE_ID} = $one_new_image_id;
+					}	
+					
+					if (!$self->_one_create_template(XMLout($template,NoAttr => 1,RootName=>'TEMPLATE',))) {
+						notify($ERRORS{'CRITICAL'}, 0, "Could't create $image_name template. Abort.");
+					}
+				} else {
+					notify($ERRORS{'CRITICAL'}, 0, "Error while making one.template.info call: $template_info[0][1]");
+				}
+			} else {
+				notify($ERRORS{'OK'}, 0, "No template exists for $old_image_name");
+			}
 			return 1;
 		}
 		if ( $wait_time <= 0 ) {
@@ -587,24 +495,7 @@ sub capture {
 	
 }
 
-sub one_get_image_state {
-	my $self = shift;
-	unless (ref($self) && $self->isa('VCL::Module')) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-		return;
-	}
-	
-	my $image_id = shift;
-	
-	my @status = $one{'server'}->call('one.image.info',$one{'auth'},$image_id);
-	if ( $status[0][0]->value() ) {
-		my $data = $xml->XMLin($status[0][1]);
-		return $data->{STATE};
-	} else {
-		notify($ERRORS{'CRITICAL'}, 0, $status[0][1]);
-	}
-	
-}
+
 
 =head2 power_off
 
@@ -624,7 +515,7 @@ sub power_off {
 	
 	my $action = shift;
 	my $computer_name = $self->data->get_computer_hostname();
-	my $vmid = $self->one_get_object_id("computer",$computer_name);
+	my $vmid = $self->_one_get_object_id("computer",$computer_name);
 	my @poweroff;
 	
 	if (defined($action) and $action eq 'hard') {
@@ -654,7 +545,7 @@ sub power_reset() {
 	}
 	
 	my $computer_name = $self->data->get_computer_hostname();
-	my $vmid = $self->one_get_object_id("computer",$computer_name);
+	my $vmid = $self->_one_get_object_id("computer",$computer_name);
 	my @poweroff = $one{'server'}->call('one.vm.action', $one{'auth'},'reboot',$vmid);
 	
 	if ( $poweroff[0][0]->value() ) {
@@ -666,136 +557,46 @@ sub power_reset() {
 	}
 }
 
-#/////////////////////////////////////////////////////////////////////////////
 
-=head2 one_wait_for_vm_status
 
- Parameters  : 
- Returns     : 
- Description : 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 power_status
 
+ Parameters  : $domain_name (optional)
+ Returns     : string
+ Description : Determines the power state of the domain. A string is returned
+               containing one of the following values:
+                  * 'on'
+                  * 'off'
+                  * 'suspended'
 =cut
 
-sub one_wait_for_vm_state {
+sub power_status {
 	my $self = shift;
 	unless (ref($self) && $self->isa('VCL::Module')) {
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
 		return;
 	}
 	
-	my $vmid = shift;
-	my $state = shift;
-	my $wait = shift;
-	my $sleep = 15;
-	my $num_state = 0;
-	
-	# 6 - POWEROFF
-	
-	$num_state = 6 if ($state eq "SHUTDOWN");
-	
-	
-	if (!$num_state) {
-		notify($ERRORS{'CRITICAL'}, 0, "Unknown vm_state $state requested");
-		return 0;
-	}
+	my $computer_name = $self->data->get_computer_hostname();
+	my $vmid = $self->_one_get_object_id("computer",$computer_name);
 	
-	while (1) {
-		notify($ERRORS{'OK'}, 0, "Check state of VM $vmid ...");
-		my $ttime;
-		my $one_vm_state = $self->one_get_vm_state($vmid);
-		if ( $self->one_get_vm_state($vmid) == $num_state ) {
-			notify($ERRORS{'OK'}, 0, "VM $vmid is in $state state");
-			return 1;
-		} else {
-			notify($ERRORS{'OK'}, 0, "VM $vmid is NOT in $state state. Waiting $sleep sec...");
-			sleep $sleep;
-			$ttime = $ttime + $sleep;
-			if ($ttime >= $wait) {
-				notify($ERRORS{'CRITICAL'}, 0, "VM $vmid is still NOT in $state state after $wait sec, abort");
-				last;
+	my @result = $one{'server'}->call('one.vm.info', $one{'auth'},$vmid);
+	if ( $result[0][0]->value() ) {
+		my $data = $xml->XMLin($result[0][1]);
+		if ($data->{STATE} == 3) {
+			if ($data->{LCM_STATE} == 3) {
+				notify($ERRORS{'OK'}, 0, "vm $vmid is RUNNING, STATE=3 and LCM_STATE=3");
+				return 'on';
 			}
 		}
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
+		return 0;
 	}
-	
-	return 0;
-	
-} ## end sub one_wait_for_vm_status
-
-# 
-sub one_get_vm_state {
-	my $self = shift;
-	my $vmid = shift;
-	
-	my @result = $one{'server'}->call('one.vm.info', $one{'auth'},$vmid);
-	if ( $result[0][0]->value() ) {
-		my $data = $xml->XMLin($result[0][1]);
-		return $data->{STATE}; 
-	} else {
-		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
-		return 0;
-	}
-}
-
-# gets LCM_STATE values, this sub-state is relevant only when STATE is ACTIVE (3)
-sub one_get_vm_lcm_state {
-	my $self = shift;
-	my $vmid = shift;
-	
-	my @result = $one{'server'}->call('one.vm.info', $one{'auth'},$vmid);
-	if ( $result[0][0]->value() ) {
-		my $data = $xml->XMLin($result[0][1]);
-		if ($data->{STATE} == 3) {
-			return $data->{LCM_STATE}; 
-		} else {
-			notify($ERRORS{'DEBUG'}, 0, "Cannot return LCM_STATE of VM $vmid, VM's STATE is not ACTIVE");
-			return;
-		}
-	} else {
-		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
-		return 0;
-	}
-}
-
-
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 power_status
-
- Parameters  : $domain_name (optional)
- Returns     : string
- Description : Determines the power state of the domain. A string is returned
-               containing one of the following values:
-                  * 'on'
-                  * 'off'
-                  * 'suspended'
-=cut
-
-sub power_status {
-	my $self = shift;
-	unless (ref($self) && $self->isa('VCL::Module')) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-		return;
-	}
-	
-	my $computer_name = $self->data->get_computer_hostname();
-	my $vmid = $self->one_get_object_id("computer",$computer_name);
-	
-	my @result = $one{'server'}->call('one.vm.info', $one{'auth'},$vmid);
-	if ( $result[0][0]->value() ) {
-		my $data = $xml->XMLin($result[0][1]);
-		if ($data->{STATE} == 3) {
-			if ($data->{LCM_STATE} == 3) {
-				notify($ERRORS{'OK'}, 0, "vm $vmid is RUNNING, STATE=3 and LCM_STATE=3");
-				return 'on';
-			}
-		}
-	} else {
-		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
-		return 0;
-	}
-
-	return 'off';
+
+	return 'off';
 	
 } ## end sub power_status
 
@@ -813,7 +614,7 @@ sub power_on {
 		return;
 	}
 	my $computer_name = $self->data->get_computer_hostname();
-	my $vmid = $self->one_get_object_id("computer",$computer_name);
+	my $vmid = $self->_one_get_object_id("computer",$computer_name);
 	#later
 	return 1;
 	
@@ -835,27 +636,16 @@ sub get_image_size {
 		return;
 	}
 	
-	return $self->one_get_image_tag_value("SIZE");
-#	
-#	my $image_name = $self->data->get_image_name();
-#	
-#	my $imid = $self->one_get_object_id("image",$image_name);
-#	my @result = $one{server}->call('one.image.info',$one{'auth'},$imid);
-#	if ( $result[0][0]->value() ) {
-#		my $data = $xml->XMLin($result[0][1]);
-#		return $data->{SIZE}; 
-#	} else {
-#		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
-#		return 0;
-#	}
+	return $self->_one_get_image_tag_value($self->data->get_image_name(),"SIZE");
+
 }
 
-sub one_get_image_tag_value {
+sub _one_get_image_tag_value {
 	my $self = shift;
+	my $image_name = shift;
 	my $tag = shift;
-	my $image_name = $self->data->get_image_name();
 	
-	my $imid = $self->one_get_object_id("image",$image_name);
+	my $imid = $self->_one_get_object_id("image",$image_name);
 	my @result = $one{server}->call('one.image.info',$one{'auth'},$imid);
 	if ( $result[0][0]->value() ) {
 		my $data = $xml->XMLin($result[0][1]);
@@ -864,7 +654,7 @@ sub one_get_image_tag_value {
 			if (defined($data->{$tag})) {
 				return $data->{$tag};
 			} else {
-				return;
+				return 0;
 			}
 		}
 		
@@ -872,7 +662,7 @@ sub one_get_image_tag_value {
 			if (defined($data->{TEMPLATE}{$tag})) {
 				return $data->{TEMPLATE}{$tag};
 			} else {
-				return;
+				return 0;
 			}
 		}
 		
@@ -880,19 +670,326 @@ sub one_get_image_tag_value {
 			if (defined($data->{TEMPLATE}{$tag})) {
 				return $data->{TEMPLATE}{$tag};
 			} else {
-				return;
+				return 0;
 			}
 		}
 		
 	} else {
-		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
+		notify($ERRORS{'CRITICAL'}, 0, "Error while making one.image.info call: $result[0][1]");
 		return 0;
 	}
 	notify($ERRORS{'CRITICAL'},0,"requested tag = $tag, don't know how to get it...");
 	return 0;
 }
 
+sub _one_get_template_id {
+	# in: $template_name
+	# out: $template_id or 0
+	my $self = shift;
+	my $template_name = shift;
+	
+	my @templatepool_info = $one{'server'}->call('one.templatepool.info',$one{'auth'},-1,-1,-1);
+	if ($templatepool_info[0][0]->value()) {
+		my $data = XMLin($templatepool_info[0][1]);
+		foreach (@{$data->{VMTEMPLATE}}) {
+			if ($template_name eq $_->{NAME}) {
+				return $_->{ID};
+			}
+		}
+	} else {
+		print "Error while making one.templatepool.info call: $templatepool_info[0][1]";
+	}
+	return 0;
+}
+
+
+
+#/////////////////////////////////////////////////////////////////////////////
+=head2 _one_get_virtio
+
+ Parameters  : imagename
+ Returns     : '' or MODEL="virtio"
+ Description : 
+
+=cut
+
+sub _one_get_virtio {
+	my $self = shift;
+	my $one_image_id = shift;
+	
+	my @reply = $one{'server'}->call('one.image.info',$one{'auth'},$one_image_id);
+	
+	if ( $reply[0][0]->value() ) {
+		my $data = $xml->XMLin($reply[0][1]);
+		if ($data->{TEMPLATE}{DEV_PREFIX} eq 'vd' ) {
+			return ',MODEL="virtio"';
+		}
+	} else {
+		notify($ERRORS{'WARNING'}, 0, "couldn't get image configuration for image_id $one_image_id, won't use VIRTIO driver.");
+		return '';
+	}
+	
+	return '';
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 one_wait_for_vm_status
+
+ Parameters  : 
+ Returns     : 
+ Description : 
+
+=cut
+
+sub _one_wait_for_vm_state {
+	my $self = shift;
+	my $vmid = shift;
+	my $state = shift;
+	my $wait = shift;
+	my $sleep = 15;
+	my $num_state = 0;
+	
+	# 6 - POWEROFF
+	
+	$num_state = 6 if ($state eq "SHUTDOWN");
+	
+	
+	if (!$num_state) {
+		notify($ERRORS{'CRITICAL'}, 0, "Unknown vm_state $state requested");
+		return 0;
+	}
+	
+	while (1) {
+		notify($ERRORS{'OK'}, 0, "Check state of VM $vmid ...");
+		my $ttime;
+		my $one_vm_state = $self->_one_get_vm_state($vmid);
+		if ( $self->_one_get_vm_state($vmid) == $num_state ) {
+			notify($ERRORS{'OK'}, 0, "VM $vmid is in $state state");
+			return 1;
+		} else {
+			notify($ERRORS{'OK'}, 0, "VM $vmid is NOT in $state state. Waiting $sleep sec...");
+			sleep $sleep;
+			$ttime = $ttime + $sleep;
+			if ($ttime >= $wait) {
+				notify($ERRORS{'CRITICAL'}, 0, "VM $vmid is still NOT in $state state after $wait sec, abort");
+				last;
+			}
+		}
+	}
+	
+	return 0;
+	
+} ## end sub one_wait_for_vm_status
+
+# 
+sub _one_get_vm_state {
+	my $self = shift;
+	my $vmid = shift;
+	
+	my @result = $one{'server'}->call('one.vm.info', $one{'auth'},$vmid);
+	if ( $result[0][0]->value() ) {
+		my $data = $xml->XMLin($result[0][1]);
+		return $data->{STATE}; 
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
+		return 0;
+	}
+}
+
+# gets LCM_STATE values, this sub-state is relevant only when STATE is ACTIVE (3)
+sub _one_get_vm_lcm_state {
+	my $self = shift;
+	my $vmid = shift;
+	
+	my @result = $one{'server'}->call('one.vm.info', $one{'auth'},$vmid);
+	if ( $result[0][0]->value() ) {
+		my $data = $xml->XMLin($result[0][1]);
+		if ($data->{STATE} == 3) {
+			return $data->{LCM_STATE}; 
+		} else {
+			notify($ERRORS{'DEBUG'}, 0, "Cannot return LCM_STATE of VM $vmid, VM's STATE is not ACTIVE");
+			return;
+		}
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, $result[0][1]);
+		return 0;
+	}
+}
+
+sub _one_get_image_state {
+	my $self = shift;
+	my $image_id = shift;
+	
+	my @status = $one{'server'}->call('one.image.info',$one{'auth'},$image_id);
+	if ( $status[0][0]->value() ) {
+		my $data = $xml->XMLin($status[0][1]);
+		return $data->{STATE};
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, $status[0][1]);
+	}
+	
+}
+
+=head2 _one_get_object_id
+
+ Parameters  : $o_type, $o_name
+ Returns     : ONE Object ID (INT)
+ Description : 
+
+=cut
+
+sub _one_get_object_id {
+	my $self = shift;	
+	my $o_type = shift;
+	my $o_name = shift;
+	
+	if ($o_type eq "computer") {
+		my @reply = $one{'server'}->call('one.vmpool.info',$one{'auth'},-3,-1,-1,-1);
+		if ( $reply[0][0]->value() ) {
+			
+			my $data = $xml->XMLin($reply[0][1]);
+			
+			if ( (ref($data->{VM})) eq "ARRAY" ){
+				foreach (@{$data->{VM}}) {
+					if ($_->{NAME} =~ /$o_name/) {
+						return $_->{ID};
+					}
+			  	}
+			} else { #HASH, found only one entry
+				if ($data->{VM}{NAME} =~ /$o_name/) {
+					return $data->{VM}{ID};
+			    }
+			}
+		} else {
+			notify($ERRORS{'CRITICAL'}, 0, $reply[0][1]);
+			return 0;
+		}	
+	} elsif ($o_type eq "image") {
+		my @reply = $one{'server'}->call('one.imagepool.info', $one{'auth'},-3,-1,-1);
+		if ( $reply[0][0]->value() ) {
+			
+			my $rs_data = $xml->XMLin($reply[0][1]);
+				if ( (ref($rs_data->{IMAGE})) eq "ARRAY" ) {
+					foreach (@{$rs_data->{IMAGE}}) {
+						if ($_->{NAME} eq $o_name) {
+ 							return $_->{ID};
+						}
+					}
+					} else { #HASH, only one entry
+						if ($rs_data->{IMAGE}{NAME} eq $o_name) {
+							return $rs_data->{IMAGE}{ID};
+						}
+					}
+		} else {
+			notify($ERRORS{'CRITICAL'}, 0, $reply[0][1]);
+			return 0;
+		}
+	} elsif ($o_type eq "network") {
+		my @reply = $one{'server'}->call('one.vnpool.info',$one{'auth'},-1,-1,-1);
+		if ($reply[0][0]->value()) {
+			my $rs_data = $xml->XMLin($reply[0][1]);
+			# don't check if ARRAY or HASH since we always have more then 1 network
+			foreach (@{$rs_data->{VNET}}) {
+				# if $o_name is in VLAN_ID= then lookup by VLAN_ID, not NAME
+				
+				if ($o_name =~ /^VLAN_ID=/i) {
+					my @vlan_id = split('=',$o_name);
+					if ($_->{VLAN_ID} == $vlan_id[1]) {
+						return $_->{ID};
+					}
+				} else {
+					if ($_->{NAME} eq $o_name) {
+						return $_->{ID};
+					}
+				}
+			}
+		} else {
+			notify($ERRORS{'CRITICAL'},0,$reply[0][1]);
+			return 0;
+		}
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, "$o_type is UNKNOWN type");
+		return 0;
+	} 
+	
+	return 0;	
+} 
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _one_delete_vm
+
+ Parameters  : $vmid
+ Returns     : 
+ Description : one.vm.action
+
+=cut
+
+sub _one_delete_vm {
+	my $self = shift;
+	my $vmid = shift;
+	my @reply;
+	
+	@reply = $one{'server'}->call('one.vm.action', $one{'auth'},'delete',$vmid);
+	if ( $reply[0][0]->value() ) {
+		notify($ERRORS{'OK'}, 0, "ONE VM $vmid deleted");
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, $reply[0][1]);
+	}
+	
+} 
+
+sub _one_create_vm {
+	# in: $VM_TEMPLATE in XML
+	# out: new VM ID | 0
+	my $self = shift;
+	my $VM_TEMPLATE = shift;
+	my @vm_allocate = $one{'server'}->call('one.vm.allocate',$one{'auth'},$VM_TEMPLATE,$one{'false'});
+	if ( $vm_allocate[0][0]->value() ) {	
+		return $vm_allocate[0][1];
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, "Error while making one.vm.allocate call : $vm_allocate[0][1]");
+		return 0;
+	}
+
+}
+
+sub _one_create_template {
+	# in: VM_TEMPLATE
+	# OUT: template_id | 0
+	# http://opennebula.org/documentation:rel4.2:api#onetemplateallocate
+	my $self = shift;
+	my $VM_TEMPLATE = shift;
+	
+	my @template_allocate = $one{'server'}->call('one.template.allocate',$one{'auth'},$VM_TEMPLATE);
+	if ($template_allocate[0][0]->value()) {
+		notify($ERRORS{'OK'}, 0, "New template created with id $template_allocate[0][1]");
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, "Error while making one.template.allocate call : $template_allocate[0][1]");
+	}	
+}
 
+sub _one_get_vm_disk {
+	my $self = shift;
+	my $vmid = shift;
+	
+	my @vm_info = $one{'server'}->call('one.vm.info', $one{'auth'},$vmid);
+	if ($vm_info[0][0]->value()) {
+		my $data = $xml->XMLin($vm_info[0][1]);
+		
+		if ( (ref($data->{TEMPLATE}{DISK})) eq "ARRAY" ) { # template has multiple disks, return [0]
+			return $data->{TEMPLATE}{DISK}[0]{IMAGE};
+		} else { #template has one disk
+			return $data->{TEMPLATE}{DISK}{IMAGE};
+		}
+		
+		
+		
+	} else {
+		notify($ERRORS{'CRITICAL'}, 0, "Error while making one.vm.info call : $vm_info[0][1]");
+	}
+}
 1;
 __END__