Author: bmbouter Date: Tue Oct 13 15:49:33 2009 New Revision: 824817 URL: http://svn.apache.org/viewvc?rev=824817&view=rev Log: Removed old vestiges of esx.pm, added configuration file options, updated documentation, added https support, more testing was done, and removed all hardcoded paths.
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README?rev=824817&r1=824816&r2=824817&view=diff ============================================================================== --- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.README Tue Oct 13 15:49:33 2009 @@ -13,6 +13,15 @@ image-flat.vmdk ... +The Config File: +Place a config file named esxthin.conf in the same directory as esxthin.pm (<location of vcld>/../lib/Module/Provisioning/esxthin.conf) Each line of this config file has the form key=value. There are 4 possible keys to use {'ip','user','pass','https'} 'ip', 'user', and 'pass' should each be set to the correct string, but https only accepts values 'on' and 'off' Here is an example config file: + +ip=10.0.3.4 +user=vclnetappuser +pass=f84uhkgh8 +https=on + + Image requirements: All images used by this module must have names in the form of esx3-<anything you want>-v# (where # is the image revision number) ssh must be set to start on boot @@ -38,7 +47,7 @@ Update the database record in the 'vmprofile' table where vmprofile.id=6 with information specific to your environment - datastorepath: <ipaddress>:<NFS mount path> for example a valid entry could be (152.14.17.112:/mnt/export) + datastorepath: <NFS mount path> for example a valid entry could be (/vol/images) virtualswitch0: <name of your private virtual machine port group> virtualswitch1: <name of your public virtual machine port group> username: <name of a valid user on your ESX hypervisors> Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm?rev=824817&r1=824816&r2=824817&view=diff ============================================================================== --- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/esxthin.pm Tue Oct 13 15:49:33 2009 @@ -35,7 +35,6 @@ http://www.vmware.com TODO list: - Refactor all run_ssh_command calls to check the return code and fail if not 0 =cut @@ -170,7 +169,6 @@ my $request_data = shift; my ($package, $filename, $line, $sub) = caller(0); - notify($ERRORS{'DEBUG'}, 0, "****************************************************"); # get various useful vars from the database my $request_id = $self->data->get_request_id; @@ -209,18 +207,11 @@ notify($ERRORS{'DEBUG'}, 0, "Unable to collect hostname_value for vmware host name using hostname from database"); } - - #Get the config datastore information from the database - my $datastore_ip; - my $datastore_share_path; - ($datastore_ip, $datastore_share_path) = split(":", $self->data->get_vmhost_profile_datastore_path()); - - notify($ERRORS{'OK'}, 0, "DATASTORE IP is $datastore_ip and DATASTORE_SHARE_PATH is $datastore_share_path"); notify($ERRORS{'OK'}, 0, "Entered ESX module, loading $image_name on $computer_shortname (on $vmhost_hostname) for reservation $reservation_id"); - notify($ERRORS{'DEBUG'}, 0, "Datastore: $datastore_ip:$datastore_share_path"); - # path to the inuse vm folder on the datastore (not a local path) - my $vmpath = "$datastore_share_path/inuse/$computer_shortname"; + #Get the config datastore information from the database + my $volume_path = $self->data->get_vmhost_profile_datastore_path(); + notify($ERRORS{'OK'}, 0, "Current image library is hosted at $volume_path"); # authenticate with the netapp filer my $s = netapp_login(); @@ -269,55 +260,22 @@ } ## end if ($vminfo_output =~ /^Information of Virtual Machine $computer_shortname/m) # Remove old vm folder - # RRRRRRRRRRR - netapp_delete_dir($s,"/vol/images/inuse/$computer_shortname"); - - # Remove old vm folder - run_ssh_command($datastore_ip, $image_identity, "rm -rf $vmpath"); - notify($ERRORS{'DEBUG'}, 0, "Removed old vm folder"); + netapp_delete_dir($s,"$volume_path/inuse/$computer_shortname"); # Create new folder for this vm - if (!run_ssh_command($datastore_ip, $image_identity, "mkdir $vmpath")) { - notify($ERRORS{'CRITICAL'}, 0, "Could not create new directory"); - return 0; - } - - # Create new folder for this vm - #RRRRRRR - netapp_create_dir($s,"/vol/images/inuse/$computer_shortname",'0755'); - - - # copy appropriate vmdk file - my $from = "$datastore_share_path/golden/$image_name/image.vmdk"; - my $to = "$vmpath/image.vmdk"; - if (!run_ssh_command($datastore_ip, $image_identity, "cp $from $to")) { - notify($ERRORS{'CRITICAL'}, 0, "Could not copy vmdk file!"); - return 0; - } - notify($ERRORS{'DEBUG'}, 0, "COPIED VMDK SUCCESSFULLY"); + netapp_create_dir($s,"$volume_path/inuse/$computer_shortname",'0755'); # clone vmdk file from golden to inuse - #RRRRRRRR - my $from = "/vol/images/golden/$image_name/image.vmdk"; - my $to = "/vol/images/inuse/$computer_shortname/image.vmdk"; + my $from = "$volume_path/golden/$image_name/image.vmdk"; + my $to = "$volume_path/inuse/$computer_shortname/image.vmdk"; netapp_fileclone($s,$from,$to); # Copy the (large) -flat.vmdk file - # This uses ssh to do the copy locally, copying over nfs is too costly - $from = "$datastore_share_path/golden/$image_name/image-flat.vmdk"; - $to = "$vmpath/image-flat.vmdk"; - if (!run_ssh_command($datastore_ip, $image_identity, "cp $from $to")) { - notify($ERRORS{'CRITICAL'}, 0, "Could not copy vmdk-flat file!"); - return 0; - } - - # Copy the (large) -flat.vmdk file - #RRRRRRRRR - $from = "/vol/images/golden/$image_name/image-flat.vmdk"; - $to = "/vol/images/inuse/$computer_shortname/image-flat.vmdk"; + $from = "$volume_path/golden/$image_name/image-flat.vmdk"; + $to = "$volume_path/inuse/$computer_shortname/image-flat.vmdk"; netapp_fileclone($s,$from,$to); - # Author new VMX file, output to temporary file (will scp it below) + # Author new VMX file, output to temporary file (will file-write-file it below) my @vmxfile; my $vmxpath = "/tmp/$computer_shortname.vmx"; @@ -332,18 +290,13 @@ # determine adapter type by looking at vmdk file my $adapter = "lsilogic"; # default - my @output; - if (@output = run_ssh_command($datastore_ip, $image_identity, "grep adapterType $vmpath/image.vmdk 2>&1")) { - my @LIST = @{$output[1]}; - foreach (@LIST) { - if ($_ =~ /(ide|buslogic|lsilogic)/) { - $adapter = $1; - notify($ERRORS{'OK'}, 0, "adapter= $1 "); - } - } + my $vmdk_meta = netapp_read_file($s,"$volume_path/golden/$image_name/image.vmdk"); + if ($vmdk_meta =~ /(ide|buslogic|lsilogic)/) { + $adapter = $1; + notify($ERRORS{'OK'}, 0, "adapter= $1 "); } else { - notify($ERRORS{'CRITICAL'}, 0, "Could not ssh to grep the vmdk file"); + notify($ERRORS{'CRITICAL'}, 0, "Could not determine ssh to grep the vmdk file"); return 0; } @@ -405,24 +358,11 @@ } # Write the VMX file to the NetApp - #RRRRRR - netapp_write_file($s,$ascii_vmx_file,"/vol/images/inuse/$computer_shortname/image.vmx"); - - # write vmx to temp file - if (open(TMP, ">$vmxpath")) { - print TMP @vmxfile; - close(TMP); - notify($ERRORS{'OK'}, 0, "wrote vmxarray to $vmxpath"); - } - else { - notify($ERRORS{'CRITICAL'}, 0, "could not write vmxarray to $vmxpath"); - insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not write vmx file to local tmp file"); - return 0; - } - - # scp $vmxpath to $vmpath/image.vmx - if (!run_scp_command($vmxpath, "$datastore_ip:$vmpath/image.vmx", $image_identity)) { - notify($ERRORS{'CRITICAL'}, 0, "could not scp vmx file to $datastore_ip"); + if (netapp_write_file($s,$ascii_vmx_file,"$volume_path/inuse/$computer_shortname/image.vmx")) { + notify($ERRORS{'OK'}, 0, "Successfully wrote VMX file"); + } else { + notify($ERRORS{'CRITICAL'}, 0, "Could not write VMX file"); + insertloadlog($reservation_id, $vmclient_computerid, "failed", "could not write vmx file to netapp"); return 0; } @@ -630,9 +570,26 @@ sub ascii_to_hex ($) { - ## Convert each ASCII character to a two-digit hex number. + ## Convert each ASCII character to a two-digit hex number (my $str = shift) =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg; - return $str; + return $str; + } + +#///////////////////////////////////////////////////////////////////////// + +=head2 hex_to_ascii + + Parameters : a single hex string + Returns : a single ASCII string + Description : Converts hex to ASCII + +=cut + +sub hex_to_ascii ($) + { + ## Convert each two-digit hex character to an ascii character + (my $str = shift) =~ s/([a-fA-F0-9]{2})/chr(hex $1)/eg; + return $str; } #///////////////////////////////////////////////////////////////////////// @@ -647,23 +604,46 @@ sub netapp_login { - my $s = NaServer->new ('10.4.0.20',1,3); -#TODO: make the ip not hardcoded + my $username = 'root'; + my $password; + my $ip; + my $use_https = 'off'; + + open(NETAPPCONF, "$FindBin::Bin/../lib/VCL/Module/Provisioning/esxthin.conf"); + while (<NETAPPCONF>) + { + chomp($_); + if ($_ =~ /^ip=(.*)/) { + $ip = $1; + } elsif ($_ =~ /^user=(.*)/) { + $username = $1; + } elsif ($_ =~ /^pass=(.*)/) { + $password = $1; + } elsif ($_ =~ /^https=(.*)/) { + $use_https = $1; + } + } + close(NETAPPCONF); + + my $s = NaServer->new ($ip,1,3); my $resp = $s->set_style("LOGIN"); if (ref ($resp) eq "NaElement" && $resp->results_errno != 0) { my $r = $resp->results_reason(); notify($ERRORS{'CRITICAL'}, 0, "Failed to set authentication style $r\n"); exit 2; } - $s->set_admin_user('vcltestuser', 'd8k3hg6g8s9h'); -#TODO: make the user/pass not hardcoded - - $resp = $s->set_transport_type("HTTP"); - if (ref ($resp) eq "NaElement" && $resp->results_errno != 0) { - my $r = $resp->results_reason(); - notify($ERRORS{'CRITICAL'}, 0, "Unable to set HTTP transport $r\n"); - exit 2; + $s->set_admin_user($username, $password); + + # Use https if the config file says to do so + if ($use_https eq 'on') { + $resp = $s->set_transport_type("HTTPS"); + if (ref ($resp) eq "NaElement" && $resp->results_errno != 0) { + my $r = $resp->results_reason(); + notify($ERRORS{'CRITICAL'}, 0, "Unable to set HTTPS transport $r\n"); + exit 2; + } } + return $s } @@ -736,6 +716,33 @@ #///////////////////////////////////////////////////////////////////////// +=head2 netapp_read_file + + Parameters : $s, $path + Returns : $ascii_data + Description : return the contents of $path on the NetApp backing $s in + ASCII format. + +=cut + +sub netapp_read_file +{ + my $s = $_[0]; + my $path = $_[1]; + + #my $hex_data = ascii_to_hex($ascii_data); + my $out = $s->invoke( "file-read-file","length",1048576,"offset",0,"path",$path ); + + if($out->results_status() eq "failed") { + notify($ERRORS{'CRITICAL'}, 0, $out->results_reason() ."\n"); + return 0; + } else { + notify($ERRORS{'DEBUG'}, 0, "Read ASCII data from file $path on netapp"); + return hex_to_ascii($out->child_get_string("data")); + } +} +#///////////////////////////////////////////////////////////////////////// + =head2 netapp_write_file Parameters : $s, $ascii_data, $path @@ -1011,7 +1018,6 @@ =cut sub capture { - notify($ERRORS{'DEBUG'}, 0, "**********************************************************"); notify($ERRORS{'OK'}, 0, "Entering ESX Capture routine"); my $self = shift; @@ -1035,16 +1041,11 @@ my $vmhost_shortname = $1; #Get the config datastore information from the database - my $datastore_ip; - my $datastore_share_path; - ($datastore_ip, $datastore_share_path) = split(":", $self->data->get_vmhost_profile_datastore_path()); - - my $old_vmpath = "$datastore_share_path/inuse/$computer_shortname"; - my $new_vmpath = "$datastore_share_path/golden/$new_imagename"; - - #RRRRRRRRR - my $old_vmpath = "/vol/images/inuse/$computer_shortname"; - my $new_vmpath = "/vol/images/golden/$new_imagename"; + my $volume_path = $self->data->get_vmhost_profile_datastore_path(); + notify($ERRORS{'OK'}, 0, "Current image library is hosted at $volume_path"); + + my $old_vmpath = "$volume_path/inuse/$computer_shortname"; + my $new_vmpath = "$volume_path/golden/$new_imagename"; # These three vars are useful: # $old_vmpath, $new_vmpath, $new_imagename @@ -1064,9 +1065,6 @@ $poweroff_output = `$poweroff_command`; notify($ERRORS{'DEBUG'}, 0, "Powered off: $poweroff_output"); - notify($ERRORS{'OK'}, 0, "Waiting 5 seconds for power off"); - sleep(5); - my $s = netapp_login(); netapp_rename_dir($s,$old_vmpath,$new_vmpath); @@ -1255,9 +1253,8 @@ my $image_name = $self->data->get_image_name(); #Get the config datastore information from the database - my $datastore_ip; - my $datastore_share_path; - ($datastore_ip, $datastore_share_path) = split(":", $self->data->get_vmhost_profile_datastore_path()); + my $volume_path = $self->data->get_vmhost_profile_datastore_path(); + notify($ERRORS{'OK'}, 0, "Current image library is hosted at $volume_path"); if (!$image_name) { notify($ERRORS{'CRITICAL'}, 0, "unable to determine if image exists, unable to determine image name"); @@ -1266,8 +1263,7 @@ my $s = netapp_login(); - #RRRRRRRRR - if (netapp_is_dir($s,"/vol/images/golden/$image_name") == 1) { + if (netapp_is_dir($s,"$volume_path/golden/$image_name") == 1) { notify($ERRORS{'DEBUG'}, 0, "Image $image_name exists"); return 1; } else { @@ -1304,14 +1300,10 @@ notify($ERRORS{'DEBUG'}, 0, "getting size of image: $image_name"); #Get the config datastore information from the database - my $datastore_ip; - my $datastore_share_path; - ($datastore_ip, $datastore_share_path) = split(":", $self->data->get_vmhost_profile_datastore_path()); - - my $IMAGEREPOSITORY = "$datastore_share_path/golden/$image_name"; + my $volume_path = $self->data->get_vmhost_profile_datastore_path(); + notify($ERRORS{'OK'}, 0, "Current image library is hosted at $volume_path"); - #RRRRRRRRRRRR - my $IMAGEREPOSITORY = "/vol/images/golden/$image_name/image-flat.vmdk"; + my $IMAGEREPOSITORY = "$volume_path/golden/$image_name/image-flat.vmdk"; my $s = netapp_login(); return int(netapp_get_size($s,$IMAGEREPOSITORY) / 1024); } ## end sub get_image_size