You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2016/10/18 17:30:54 UTC

svn commit: r1765484 - in /vcl/trunk/managementnode/lib/VCL: DataStructure.pm Module/OS.pm Module/OS/Windows.pm reclaim.pm reserved.pm utils.pm

Author: arkurth
Date: Tue Oct 18 17:30:53 2016
New Revision: 1765484

URL: http://svn.apache.org/viewvc?rev=1765484&view=rev
Log:
VCL-997
Added subroutines:
DataStructure.pm::get_reservation_info_json_string
OS.pm::get_reservation_info_json_file_path
OS.pm::create_reservation_info_json_file
OS.pm::delete_reservation_info_json_file
Windows.pm::get_reservation_info_json_file_path
utils.pm::prune_array_reference
utils.pm::prune_hash_child_references
utils.pm::prune_hash_reference

OS.pm::create_reservation_info_json_file gets called from reserved.pm::process only if a variable named 'enable_experimental_features' is true in the database.

This file is removed when a computer is sanitized in reclaim.pm::call_os_sanitize.


Modified:
    vcl/trunk/managementnode/lib/VCL/DataStructure.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
    vcl/trunk/managementnode/lib/VCL/reclaim.pm
    vcl/trunk/managementnode/lib/VCL/reserved.pm
    vcl/trunk/managementnode/lib/VCL/utils.pm

Modified: vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1765484&r1=1765483&r2=1765484&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/DataStructure.pm Tue Oct 18 17:30:53 2016
@@ -77,6 +77,7 @@ use diagnostics;
 use English '-no_match_vars';
 
 use Object::InsideOut;
+use JSON qw(to_json);
 use List::Util qw(min max);
 use YAML;
 use Storable qw(dclone);
@@ -2236,6 +2237,63 @@ sub get_image_minram {
 }
 
 #/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_reservation_info_json_string
+
+ Parameters  : none
+ Returns     : string
+ Description : Constucts a JSON string based on the reservation data.
+
+=cut
+
+sub get_reservation_info_json_string {
+	my $self = shift;
+	
+	my $reservation_id = $self->reservation_id;
+	my $request_data = $self->request_data;
+	
+	# Clone the hash so that the original isn't altered
+	my $request_data_clone = dclone($request_data);
+	
+	my $json_data = {};
+	
+	# Remove useless keys
+	$request_data_clone = prune_hash_reference($request_data_clone, '.*(resource|current|adminlevel|nextimage|predictive|platform|log|schedule).*');
+	
+	$json_data->{request} 			= prune_hash_child_references($request_data_clone);
+	$json_data->{reservation} 		= prune_hash_child_references($request_data_clone->{reservation}{$reservation_id});
+	$json_data->{imagerevision}	= prune_hash_child_references($request_data_clone->{reservation}{$reservation_id}{imagerevision});
+	$json_data->{image} 				= prune_hash_child_references($request_data_clone->{reservation}{$reservation_id}{image});
+	$json_data->{computer} 			= prune_hash_child_references($request_data_clone->{reservation}{$reservation_id}{computer});
+	
+	if (defined($request_data_clone->{reservation}{$reservation_id}{computer}{vmhost})) {
+		$json_data->{vmhost} 			= prune_hash_child_references($request_data_clone->{reservation}{$reservation_id}{computer}{vmhost});
+		$json_data->{vmhost_computer}	= prune_hash_child_references($request_data_clone->{reservation}{$reservation_id}{computer}{vmhost}{computer});
+	}
+	
+	# TODO: figure out how to handle user info, what structure, etc
+	#$json_data->{users} 				= $request_data_clone->{reservation}{$reservation_id}{users};
+	#$json_data->{user} = $request_data_clone->{user};
+	#$json_data->{user}{username} = $json_data->{user}{unityid};
+	
+	# IMPORTANT: delete vmprofile data and anything else that may contain passwords
+	#delete $json_data->{computer}{vmhost}{vmprofile};
+	
+	# Convert the request data to JSON
+	my $json;
+	eval {
+		$json = to_json($json_data, { pretty => 1 });
+	};
+	if ($EVAL_ERROR) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create convert request data to json, error: $EVAL_ERROR");
+		return;
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "constructed JSON string based on reservation infor:\n$json");
+	return $json;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
 
 1;
 __END__

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1765484&r1=1765483&r2=1765484&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Tue Oct 18 17:30:53 2016
@@ -4510,8 +4510,76 @@ sub get_cluster_info_file_path {
 	return $self->{cluster_info_file_path};
 }
 
-#///////////////////////////////////////////////////////////////////////////
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_reservation_info_json_file_path
+
+ Parameters  : none
+ Returns     : string
+ Description : Returns the location where the files resides on the computer that
+               contains JSON formatted information about the reservation. For
+               Linux computers, the location is /etc/reservation_info.json.
+
+=cut
+
+sub get_reservation_info_json_file_path {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module::OS/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	return $self->{reservation_info_json_file_path} if $self->{reservation_info_json_file_path};
+	$self->{reservation_info_json_file_path} = '/etc/reservation_info.json';
+	notify($ERRORS{'DEBUG'}, 0, "determined reservation info JSON file path file path for " . ref($self) . " OS module: $self->{reservation_info_json_file_path}");
+	return $self->{reservation_info_json_file_path};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 create_reservation_info_json_file
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Creates a text file on the computer containing reservation data
+               in JSON format.
+
+=cut
 
+sub create_reservation_info_json_file {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module::OS/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my $json_file_path = $self->get_reservation_info_json_file_path() || return;
+	my $json_string = $self->data->get_reservation_info_json_string() || return;
+	return $self->create_text_file($json_file_path, $json_string);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_reservation_info_json_file
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Deletes the text file on the computer containing reservation data
+					in JSON format. This is important when sanitizing a computer.
+
+=cut
+
+sub delete_reservation_info_json_file {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module::OS/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my $json_file_path = $self->get_reservation_info_json_file_path() || return;
+	return $self->delete_file($json_file_path);
+}
+
+#///////////////////////////////////////////////////////////////////////////
 1;
 __END__
 

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1765484&r1=1765483&r2=1765484&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Tue Oct 18 17:30:53 2016
@@ -10973,7 +10973,7 @@ sub run_script {
 		notify($ERRORS{'WARNING'}, 0, "failed to execute script on $computer_node_name: '$script_path', command: '$command'");
 		return;
 	}
-	
+
 	# Create a log file containing the output
 	my $logfile_contents = "$timestamp - $script_path executed by vcld";
 	my $header_line_length = length($logfile_contents);
@@ -12019,6 +12019,30 @@ sub get_cluster_info_file_path {
 	return $self->{cluster_info_file_path};
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_reservation_info_json_file_path
+
+ Parameters  : none
+ Returns     : string
+ Description : Returns the location where the files resides on the computer that
+               contains JSON formatted information about the reservation.
+
+=cut
+
+sub get_reservation_info_json_file_path {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module::OS/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	return $self->{reservation_info_json_file_path} if $self->{reservation_info_json_file_path};
+	
+	my $systemroot_value = $self->get_environment_variable_value('SYSTEMDRIVE') || 'C:';
+	$self->{reservation_info_json_file_path} = "$systemroot_value/reservation_info.json";
+	notify($ERRORS{'DEBUG'}, 0, "determined reservation info JSON file path file path for " . ref($self) . " OS module: $self->{reservation_info_json_file_path}");
+	return $self->{reservation_info_json_file_path};
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 

Modified: vcl/trunk/managementnode/lib/VCL/reclaim.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reclaim.pm?rev=1765484&r1=1765483&r2=1765484&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reclaim.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reclaim.pm Tue Oct 18 17:30:53 2016
@@ -329,6 +329,13 @@ sub call_os_sanitize {
 	
 	my $computer_shortname = $self->data->get_computer_short_name();
 	
+	# Delete the reservation info JSON file
+	my $enable_experimental_features = get_variable('enable_experimental_features', 0);
+	if ($enable_experimental_features && !$self->os->delete_reservation_info_json_file()) {
+		notify($ERRORS{'WARNING'}, 0, "failed to delete reservation info JSON file on $computer_shortname, computer will be reloaded");
+		$self->insert_reload_and_exit();
+	}
+	
 	# Attempt to call OS module's sanitize() subroutine
 	# This subroutine should perform all the tasks necessary to sanitize the OS if it was reserved and not logged in to
 	notify($ERRORS{'DEBUG'}, 0, "calling " . ref($self->os) . "::sanitize() subroutine");

Modified: vcl/trunk/managementnode/lib/VCL/reserved.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reserved.pm?rev=1765484&r1=1765483&r2=1765484&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reserved.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reserved.pm Tue Oct 18 17:30:53 2016
@@ -200,6 +200,12 @@ sub process {
 		$self->reservation_failed("update_cluster failed");
 	}
 	
+	# Create a JSON file containing the reservation info
+	my $enable_experimental_features = get_variable('enable_experimental_features', 0);
+	if ($enable_experimental_features) {
+		$self->os->create_reservation_info_json_file();
+	}
+	
 	# Check if OS module's post_reserve() subroutine exists
 	if ($self->os->can("post_reserve") && !$self->os->post_reserve()) {
 		$self->reservation_failed("OS module post_reserve failed");

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1765484&r1=1765483&r2=1765484&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Tue Oct 18 17:30:53 2016
@@ -70,6 +70,7 @@ use List::Util qw(min max);
 use HTTP::Headers;
 use RPC::XML::Client;
 use Scalar::Util 'blessed';
+use Storable qw(dclone);
 use Data::Dumper;
 use Cwd;
 use Sys::Hostname;
@@ -223,6 +224,9 @@ our @EXPORT = qw(
 	parent_directory_path
 	populate_reservation_natport
 	preplogfile
+	prune_array_reference
+	prune_hash_child_references
+	prune_hash_reference
 	read_file_to_array
 	remove_array_duplicates
 	rename_vcld_process
@@ -2506,7 +2510,7 @@ sub known_hosts {
 =head2 getusergroupmembers
 
  Parameters  : usergroupid
- Returns     : array of user group memebers
+ Returns     : array of user group members
  Description : queries database and collects user members of supplied usergroupid
 
 =cut
@@ -7164,7 +7168,7 @@ sub get_computer_info {
 	# Add the column for predictive module info
    my @columns = @{$database_table_columns->{module}};
    for my $column (@columns) {
-         $select_statement .= "predictivemodule.$column AS 'predictivemodule-$column',\n";
+      $select_statement .= "predictivemodule.$column AS 'predictivemodule-$column',\n";
    }
 	
 	# Remove the comma after the last column line
@@ -14377,6 +14381,159 @@ sub wrap_string {
 }
 
 #/////////////////////////////////////////////////////////////////////////////
+
+=head2 prune_hash_reference
+
+ Parameters  : $hash_ref, $prune_regex
+ Returns     : hash reference
+ Description : 
+
+=cut
+
+sub prune_hash_reference {
+	my ($hash_ref_argument, $prune_regex) = @_;
+	if (!defined($hash_ref_argument)) {
+		notify($ERRORS{'WARNING'}, 0, "hash reference argument was not supplied");
+		return;
+	}
+	elsif (!ref($hash_ref_argument) || ref($hash_ref_argument) ne 'HASH') {
+		notify($ERRORS{'WARNING'}, 0, "argument is not a hash reference:\n" . format_data($hash_ref_argument));
+		return;
+	}
+	elsif (!defined($prune_regex)) {
+		notify($ERRORS{'WARNING'}, 0, "prune regex argument was not supplied, returning original hash reference");
+		return $hash_ref_argument;
+	}
+	
+	# Create a clone if this wasn't recursively called
+	my $calling_subroutine = get_calling_subroutine();
+	my $hash_ref;
+	if ($calling_subroutine =~ /^prune/) {
+		$hash_ref = $hash_ref_argument;
+	}
+	else {
+		$hash_ref = dclone($hash_ref_argument);
+	}
+	
+	my $result = {};
+	for my $key (keys %$hash_ref) {
+		# Don't add keys which match the regex
+		if ($key =~ /$prune_regex/) {
+			next;
+		}
+		
+		my $type = ref($hash_ref->{$key});
+		if (!$type) {
+			# If the value is not a reference, simply add it to the result
+			$result->{$key} = $hash_ref->{$key};
+			next;
+		}
+		elsif ($type eq 'HASH') {
+			$result->{$key} = prune_hash_reference($hash_ref->{$key}, $prune_regex);
+		}
+		elsif ($type eq 'ARRAY') {
+			$result->{$key} = prune_array_reference($hash_ref->{$key}, $prune_regex);
+		}
+		else {
+			notify($ERRORS{'WARNING'}, 0, "unsupported type: $type");
+		}
+	}
+	return $result;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 prune_array_reference
+
+ Parameters  : $array_ref, $prune_regex
+ Returns     : array reference
+ Description : 
+
+=cut
+
+sub prune_array_reference {
+	my ($array_ref_argument, $prune_regex) = @_;
+	if (!defined($array_ref_argument)) {
+		notify($ERRORS{'WARNING'}, 0, "array reference argument was not supplied");
+		return;
+	}
+	elsif (!ref($array_ref_argument) || ref($array_ref_argument) ne 'ARRAY') {
+		notify($ERRORS{'WARNING'}, 0, "argument is not a array reference:\n" . format_data($array_ref_argument));
+		return;
+	}
+	elsif (!defined($prune_regex)) {
+		notify($ERRORS{'WARNING'}, 0, "prune regex argument was not supplied, returning original array reference");
+		return $array_ref_argument;
+	}
+	
+	# Create a clone if this wasn't recursively called
+	my $calling_subroutine = get_calling_subroutine();
+	my $array_ref;
+	if ($calling_subroutine =~ /^prune/) {
+		$array_ref = $array_ref_argument;
+	}
+	else {
+		$array_ref = dclone($array_ref_argument);
+	}
+	
+	my $result = [];
+	for my $element (@$array_ref) {
+		my $type = ref($element);
+		if (!$type) {
+			push @$result, $element;
+		}
+		elsif ($type eq 'ARRAY') {
+			push @$result, prune_array_reference($element, $prune_regex);
+		}
+		elsif ($type eq 'HASH') {
+			push @$result, prune_hash_reference($element, $prune_regex);
+		}
+		else {
+			notify($ERRORS{'WARNING'}, 0, "unsupported type: $type");
+		}
+	}
+	
+	return $result;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 prune_hash_child_references
+
+ Parameters  : $hash_ref
+ Returns     : hash reference
+ Description : Makes a copy of the hash reference. Removes all keys that contain
+               references as data.
+
+=cut
+
+sub prune_hash_child_references {
+	my ($hash_ref_argument) = @_;
+	if (!defined($hash_ref_argument)) {
+		notify($ERRORS{'WARNING'}, 0, "hash reference argument was not supplied");
+		return;
+	}
+	elsif (!ref($hash_ref_argument) || ref($hash_ref_argument) ne 'HASH') {
+		notify($ERRORS{'WARNING'}, 0, "argument is not a hash reference:\n" . format_data($hash_ref_argument));
+		return;
+	}
+	
+	# Create a clone
+	my $hash_ref = dclone($hash_ref_argument);
+	
+	my $result = {};
+	for my $key (keys %$hash_ref) {
+		if (ref($hash_ref->{$key})) {
+			next;
+		}
+		else {
+			$result->{$key} = $hash_ref->{$key};
+		}
+	}
+	return $result;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
 
 1;
 __END__