Author: arkurth
Date: Wed Aug 3 18:43:06 2011
New Revision: 1153606
URL: http://svn.apache.org/viewvc?rev=1153606&view=rev
Log:
VCL-350
Added snapshot support to the VMware code. Added VMware.pm::snapshot()
subroutine and create_snapshot subroutines in the helper modules.
Changed default virtual disk mode to persistent instead of
independent-persistent or independent-nonpersistent. A snapshot is created
after the VM is registered but before it is powered on. This causes changes to
be written to a delta file in the directory where the vmx resides. This
eliminates the need to create a full copy of the vmdk for imaging and long-term
reservations. Imaging and long-term reservations now use this mode. A full copy
of the vmdk is only created for server requests. Added
DataStructure.pm::is_server_request subroutine to tell if a request is a server
request or not.
Changed all things named nonpersistent to shared, and persistent to dedicated
to avoid confusion.
Other
Added some missing block request values to DataStructure.pm.
Modified:
incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vmware_cmd.pm
incubator/vcl/trunk/managementnode/lib/VCL/utils.pm
Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1153606&r1=1153605&r2=1153606&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm Wed Aug 3
18:43:06 2011
@@ -105,7 +105,7 @@ $SUBROUTINE_MAPPINGS{blockrequest_name}
$SUBROUTINE_MAPPINGS{blockrequest_image_id} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{imageid}';
$SUBROUTINE_MAPPINGS{blockrequest_number_machines} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{numMachines}';
$SUBROUTINE_MAPPINGS{blockrequest_group_id} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{groupid}';
-$SUBROUTINE_MAPPINGS{blockrequest_group_name} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{groupname}';
+$SUBROUTINE_MAPPINGS{blockrequest_group_name} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{usergroup}{name}';
$SUBROUTINE_MAPPINGS{blockrequest_repeating} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{repeating}';
$SUBROUTINE_MAPPINGS{blockrequest_owner_id} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{ownerid}';
$SUBROUTINE_MAPPINGS{blockrequest_admin_group_id} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{admingroupid}';
@@ -114,6 +114,13 @@ $SUBROUTINE_MAPPINGS{blockrequest_expire
$SUBROUTINE_MAPPINGS{blockrequest_processing} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{processing}';
$SUBROUTINE_MAPPINGS{blockrequest_mode} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{MODE}';
+$SUBROUTINE_MAPPINGS{blockrequest_blocktimes_id} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{BLOCKTIMES_ID}';
+
+$SUBROUTINE_MAPPINGS{blockrequest_owner_email} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{owner}{email}';
+$SUBROUTINE_MAPPINGS{blockrequest_owner_affiliation_helpaddress} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{owner}{affiliation}{helpaddress}';
+
+$SUBROUTINE_MAPPINGS{blockrequest_image_prettyname} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{image}{prettyname}';
+
$SUBROUTINE_MAPPINGS{blocktime_id} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{blockTimes}{BLOCKTIME_ID}{id}';
#$SUBROUTINE_MAPPINGS{blocktime_blockrequest_id} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{blockTimes}{BLOCKTIME_ID}{blockRequestid}';
$SUBROUTINE_MAPPINGS{blocktime_start} =
'$self->blockrequest_data->{BLOCKREQUEST_ID}{blockTimes}{BLOCKTIME_ID}{start}';
@@ -230,6 +237,7 @@ $SUBROUTINE_MAPPINGS{computer_provisioni
$SUBROUTINE_MAPPINGS{vmhost_computer_id} =
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{vmhost}{computerid}';
$SUBROUTINE_MAPPINGS{vmhost_hostname} =
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{vmhost}{computer}{hostname}';
+$SUBROUTINE_MAPPINGS{vmhost_short_name} =
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{vmhost}{computer}{SHORTNAME}';
$SUBROUTINE_MAPPINGS{vmhost_id} =
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{vmhost}{id}';
$SUBROUTINE_MAPPINGS{vmhost_image_id} =
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{vmhost}{vmprofile}{imageid}';
$SUBROUTINE_MAPPINGS{vmhost_image_name} =
'$self->request_data->{reservation}{RESERVATION_ID}{computer}{vmhost}{vmprofile}{image}{name}';
@@ -2132,6 +2140,29 @@ sub is_blockrequest {
#/////////////////////////////////////////////////////////////////////////////
+=head2 is_server_request
+
+ Parameters : None.
+ Returns :
+ Description : This subroutine determines whether or not the DataStructure
+ contains data for a server request.
+
+=cut
+
+sub is_server_request {
+ my $self = shift;
+
+ # Check if subroutine was called as an object method
+ unless (ref($self) && $self->isa('VCL::DataStructure')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called
as a VCL::DataStructure module object method");
+ return;
+ }
+
+ return $self->get_server_request_id() ? 1 : 0;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 get_management_node_public_default_gateway
Parameters : None
Modified:
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm?rev=1153606&r1=1153605&r2=1153606&view=diff
==============================================================================
---
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
(original)
+++
incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
Wed Aug 3 18:43:06 2011
@@ -1666,6 +1666,131 @@ sub get_network_names {
#/////////////////////////////////////////////////////////////////////////////
+=head2 create_snapshot
+
+ Parameters : $vmx_file_path, $name (optional)
+ Returns : boolean
+ Description : Creates a snapshot of the VM.
+
+=cut
+
+sub create_snapshot {
+ my $self = shift;
+ if (ref($self) !~ /VCL::Module/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx file path argument
+ my $vmx_file_path = shift;
+ if (!$vmx_file_path) {
+ notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not
supplied");
+ return;
+ }
+
+ my $snapshot_name = shift || ("VCL: " . convert_to_datetime());
+
+ # Get the VM ID
+ my $vm_id = $self->_get_vm_id($vmx_file_path);
+ if (!defined($vm_id)) {
+ notify($ERRORS{'WARNING'}, 0, "unable to create snapshot
because VM ID could not be determined");
+ return;
+ }
+
+ my $vim_cmd_arguments = "vmsvc/snapshot.create $vm_id '$snapshot_name'";
+ my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
+ return if !$output;
+
+ notify($ERRORS{'DEBUG'}, 0, "create snapshot output:\n" . join("\n",
@$output));
+
+ if (grep(/failed|invalid/i, @$output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to create snapshot of VM
$vmx_file_path, VIM command arguments: '$vim_cmd_arguments', output:\n" .
join("\n", @$output));
+ return;
+ }
+
+ # Get the task ID
+ my @task_ids = $self->_get_task_ids($vmx_file_path, 'createSnapshot');
+ if (!@task_ids) {
+ notify($ERRORS{'WARNING'}, 0, "unable to retrieve the ID of the
task created to create snapshot");
+ return;
+ }
+
+ # Wait for the task to complete
+ if ($self->_wait_for_task($task_ids[0])) {
+ notify($ERRORS{'OK'}, 0, "created snapshot of VM:
$vmx_file_path, snapshot name: $snapshot_name");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to create snapshot VM:
$vmx_file_path, the vim task did not complete successfully, vim-cmd
$vim_cmd_arguments output:\n" . join("\n", @$output));
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 snapshot_exists
+
+ Parameters : $vmx_file_path
+ Returns : boolean
+ Description : Determines if a snapshot exists for the VM.
+
+=cut
+
+sub snapshot_exists {
+ my $self = shift;
+ if (ref($self) !~ /VCL::Module/i) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the vmx file path argument
+ my $vmx_file_path = shift;
+ if (!$vmx_file_path) {
+ notify($ERRORS{'WARNING'}, 0, "vmx file path argument was not
supplied");
+ return;
+ }
+
+ # Get the VM ID
+ my $vm_id = $self->_get_vm_id($vmx_file_path);
+ if (!defined($vm_id)) {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine if snapshot
exists because VM ID could not be determined");
+ return;
+ }
+
+ my $vim_cmd_arguments = "vmsvc/snapshot.get $vm_id";
+ my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
+ return if !$output;
+
+ notify($ERRORS{'DEBUG'}, 0, "snapshot.get output:\n" . join("\n",
@$output));
+
+ if (grep(/failed|invalid/i, @$output)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to determine if snapshot
exists for VM $vmx_file_path, VIM command arguments: '$vim_cmd_arguments',
output:\n" . join("\n", @$output));
+ return;
+ }
+
+ # Expected output if shapshot exists:
+ # Get Snapshot:
+ # |-ROOT
+ # --Snapshot Name : 1311966951
+ # --Snapshot Desciption :
+ # --Snapshot Created On : 7/29/2011 19:15:59
+ # --Snapshot State : powered off
+
+ # Expected output if snapshot does not exist:
+ # Get Snapshot:
+
+ if (grep(/-ROOT/, @$output)) {
+ notify($ERRORS{'DEBUG'}, 0, "snapshot exists for VM
$vmx_file_path");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "snapshot does NOT exist for VM
$vmx_file_path");
+ return 0;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 DESTROY
Parameters : none