You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by yo...@apache.org on 2014/06/23 21:01:27 UTC

svn commit: r1604908 - /vcl/trunk/managementnode/lib/VCL/Module/Provisioning/openstack.pm

Author: yoh
Date: Mon Jun 23 19:01:26 2014
New Revision: 1604908

URL: http://svn.apache.org/r1604908
Log:
update _get_flavor_type to automatically select the flavor type by using List::BinarySearch package.
Required to install List::BinarySearch package.

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

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/openstack.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/openstack.pm?rev=1604908&r1=1604907&r2=1604908&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/openstack.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/openstack.pm Mon Jun 23 19:01:26 2014
@@ -1,995 +1,1030 @@
-#!/usr/bin/perl -w
-###############################################################################
-# $Id: openstack.pm 2012-4-14 
-###############################################################################
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###############################################################################
-
-=head1 NAME
-
-VCL::Provisioning::openstack - VCL module to support the Openstack provisioning engine
-
-=head1 SYNOPSIS
-
- Needs to be written
-
-=head1 DESCRIPTION
-
-This module provides VCL support for Openstack
-
-=cut
-
-##############################################################################
-package VCL::Module::Provisioning::openstack;
-
-# Include File Copying for Perl
-use File::Copy;
-
-# Specify the lib path using FindBin
-use FindBin;
-use lib "$FindBin::Bin/../../..";
-
-# Configure inheritance
-use base qw(VCL::Module::Provisioning);
-
-# Specify the version of this module
-our $VERSION = '2.3.2';
-
-# Specify the version of Perl to use
-use 5.008000;
-
-use strict;
-use warnings;
-use diagnostics;
-use English qw( -no_match_vars );
-use IO::File;
-use Fcntl qw(:DEFAULT :flock);
-use File::Temp qw( tempfile );
-use List::Util qw( max );
-
-use VCL::utils;
-
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 initialize
-
- Parameters  :
- Returns     :
- Description :
-
-=cut
-
-sub initialize {
-	my $self = shift;
-        notify($ERRORS{'DEBUG'}, 0, "OpenStack module initialized");
-	
-	if($self->_set_openstack_user_conf) {
-        	notify($ERRORS{'OK'}, 0, "Success to OpenStack user configuration");
-	}
-	else {
-        	notify($ERRORS{'CRITICAL'}, 0, "Failure to Openstack user configuration");
-		return 0;
-	}
-	
-        return 1;
-} ## end sub initialize
-
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 provision
-
- Parameters  : hash
- Returns     : 1(success) or 0(failure)
- Description : loads virtual machine with requested image
-
-=cut
-
-sub load {
-        my $self = shift;
-        if (ref($self) !~ /openstack/i) {
-                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-                return;
-        }
-
-        my $reservation_id = $self->data->get_reservation_id() || return;
-        my $computer_id = $self->data->get_computer_id() || return;
-        my $computer_name = $self->data->get_computer_short_name() || return;
-        my $image_name = $self->data->get_image_name() || return;
-        my $vmhost_name = $self->data->get_vmhost_short_name() || return;
-
-        insertloadlog($reservation_id, $computer_id, "doesimageexists", "image exists $image_name");
-
-        insertloadlog($reservation_id, $computer_id, "startload", "$computer_name $image_name");
-
-        # Remove existing VMs which were created for the reservation computer
-        if (!$self->_terminate_instances) {
-                notify($ERRORS{'WARNING'}, 0, "failed to remove existing VMs created for computer $computer_name on VM host: $vmhost_name");
-                return;
-        }
-
-	# Create new instance 
-        if (!$self->_run_instances) {
-                notify($ERRORS{'WARNING'}, 0, "failed to create VMs for computer $computer_name on VM host: $vmhost_name");
-                return;
-	}
-	my $instance_id = $self->_get_instance_id;
-        if (!$instance_id) {
-                notify($ERRORS{'WARNING'}, 0, "failed to get the instance id for $computer_name");
-                return;
-	}
-
-	# Update the private ip of the instance in /etc/hosts file
-	if($self->_update_private_ip($instance_id)) 
-	{
-		notify($ERRORS{'OK'}, 0, "Update the private ip of instance $instance_id is succeeded\n");
-	}
-	else
-	{
-		notify($ERRORS{'CRITICAL'}, 0, "Fail to update private ip of the instance in /etc/hosts");
-		return;
-	}
-
-
-	# Instances have the ip instantly when it use FlatNetworkManager
-	# Need to wait for copying images from repository or cache to instance directory
-	# 15G for 3 to 5 minutes (depends on systems)
-	#sleep 300;
-	sleep 10;
-
-	# Call post_load 
-	if ($self->os->can("post_load")) {
-		notify($ERRORS{'DEBUG'}, 0, "calling " . ref($self->os) . "->post_load()");
-		if ($self->os->post_load()) {
-			notify($ERRORS{'DEBUG'}, 0, "successfully ran OS post_load subroutine");
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "failed to run OS post_load subroutine");
-			return;
-		}
-	}
-	else {
-		notify($ERRORS{'DEBUG'}, 0, ref($self->os) . "::post_load() has not been implemented");
-	}
-
-	return 1;
-
-} ## end sub load
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 capture
-
- Parameters  : $request_data_hash_reference
- Returns     : 1 if sucessful, 0 if failed
- Description : Creates a new vmware image.
-
-=cut
-
-sub capture {
-        notify($ERRORS{'DEBUG'}, 0, "**********************************************************");
-        notify($ERRORS{'OK'},    0, "Entering Openstack Capture routine");
-        my $self = shift;
-
-        if (ref($self) !~ /openstack/i) {
-                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-                return 0;
-        }
-
-        my $image_name     = $self->data->get_image_name();
-        my $computer_name = $self->data->get_computer_short_name;
-	my $instance_id;
-	
-        if(_pingnode($computer_name))
-        {
-		$instance_id = $self->_get_instance_id;
-		notify($ERRORS{'OK'}, 0, "instance id: $instance_id is done");
-		if(!$instance_id)
-		{
-			notify($ERRORS{'DEBUG'}, 0, "unable to get instance id for $computer_name");
-			return 0;
-		}
-        }
-	else {
-		notify($ERRORS{'DEBUG'}, 0, "unable to ping to $computer_name");
-		return 0;
-	}
-		
-        if($self->_prepare_capture)
-	{
-		notify($ERRORS{'OK'}, 0, "Prepare_Capture for $computer_name is done");
-	}
-	
-	my $new_image_name = $self->_image_create($instance_id);
-
-	if($new_image_name)
-	{
-		notify($ERRORS{'OK'}, 0, "Create Image for $computer_name is done");
-	}
-
-	if($self->_insert_openstack_image_name($new_image_name))
-	{
-	        notify($ERRORS{'OK'}, 0, "Successfully insert image name");
-        }
-
-	if($self->_wait_for_copying_image($instance_id)) 
-	{
-		notify($ERRORS{'OK'}, 0, "Wait for copying $new_image_name is succeeded\n");
-	}
-
-        return 1;
-} ## end sub capture
-
-sub _image_create{
-	my $self = shift;
-	my $instance_id = shift;
-	my $imagerevision_comments = $self->data->get_imagerevision_comments(0);
-        my $image_name     = $self->data->get_image_name();
-	
-	my $image_version;
-        if($image_name =~ m/(-+)(.+)(-v\d+)/g)
-        {
-                $image_version = $3;
-                notify($ERRORS{'OK'}, 0, "Acquire the Image Version: $image_version");
-        }
-
-        my $image_description = $image_name . $imagerevision_comments;
-        #my $image_description = $image_name . '-' . $imagerevision_comments;
-        my $capture_image = "nova image-create $instance_id $image_description";
-        notify($ERRORS{'OK'}, 0, "New Image Capture Command: $capture_image");
-        my $capture_image_output = `$capture_image`;
-
-        my $openstack_image_id;
-        my $new_image_name;
-        my $describe_image = "nova image-list |grep $instance_id";
-        my $run_describe_image_output = `$describe_image`;
-        notify($ERRORS{'OK'}, 0, "The images: $run_describe_image_output");
-
-	sleep 10;
-
-        if($run_describe_image_output  =~ m/^\|\s(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/g )
-        {
-                $openstack_image_id = $1;
-                $new_image_name = $openstack_image_id . $image_version;
-                #$new_image_name = $openstack_image_id .'-v'. $image_version;
-                notify($ERRORS{'OK'}, 0, "The Openstack Image ID:$openstack_image_id");
-                notify($ERRORS{'OK'}, 0, "The New Image Name:$new_image_name");
-                return $new_image_name;
-        }
-        else
-        {
-                notify($ERRORS{'DEBUG'}, 0, "Fail to capture new Image");
-                return 0;
-        }
-}
-
-sub _prepare_capture {
-	my $self = shift;
-	
-        my ($package, $filename, $line, $sub) = caller(0);
-        my $request_data = $self->data->get_request_data;
-
-        if (!$request_data) {
-                notify($ERRORS{'WARNING'}, 0, "unable to retrieve request data hash");
-                return 0;
-        }
-
-        my $request_id     = $self->data->get_request_id;
-        my $reservation_id = $self->data->get_reservation_id;
-        my $management_node_keys     = $self->data->get_management_node_keys();
-
-        my $image_id       = $self->data->get_image_id;
-        my $image_os_name  = $self->data->get_image_os_name;
-        my $image_identity = $self->data->get_image_identity;
-        my $image_os_type  = $self->data->get_image_os_type;
-        my $image_name     = $self->data->get_image_name();
-
-        my $computer_id        = $self->data->get_computer_id;
-        my $computer_name = $self->data->get_computer_short_name;
-        my $computer_nodename  = $computer_name;
-        my $computer_hostname  = $self->data->get_computer_hostname;
-        my $computer_type      = $self->data->get_computer_type;
-
-        if (write_currentimage_txt($self->data)) {
-                notify($ERRORS{'OK'}, 0, "currentimage.txt updated on $computer_name");
-        }
-        else {
-                notify($ERRORS{'DEBUG'}, 0, "unable to update currentimage.txt on $computer_name");
-                return 0;
-        }
-
-        $self->data->set_imagemeta_sysprep(0);
-        notify($ERRORS{'OK'}, 0, "Set the imagemeta Sysprep value to 0");
-
-        if ($self->os->can("pre_capture")) {
-                notify($ERRORS{'OK'}, 0, "calling OS module's pre_capture() subroutine");
-
-                if (!$self->os->pre_capture({end_state => 'on'})) {
-                        notify($ERRORS{'DEBUG'}, 0, "OS module pre_capture() failed");
-                        return 0;
-                }
-        }
-	return 1;
-}
-
-sub _insert_openstack_image_name {
-
-	my $self = shift;
-	my $openstack_image_name = shift;
-        my $image_name     = $self->data->get_image_name();       
-
-        my $insert_statement = "
-        INSERT INTO
-        openstackImageNameMap (
-          openstackImageNameMap.openstackimagename,
-          openstackImageNameMap.vclimagename
-        ) VALUES (
-          '$openstack_image_name',
-          '$image_name')";
-
-        notify($ERRORS{'OK'}, 0, "$insert_statement");
-
-        my $requested_id = database_execute($insert_statement);
-        notify($ERRORS{'OK'}, 0, "SQL Insert is first time or requested_id : $requested_id");
-
-        if (!$requested_id) {
-                notify($ERRORS{'DEBUG'}, 0, "unable to insert image name");
-                return 0;
-        }
-        notify($ERRORS{'OK'}, 0, "Successfully insert image name");
-	return 1;
-}
-
-sub _wait_for_copying_image {
-	my $self = shift;
-	
-	my $instance_id = shift;
-	
-        my $query_image = "nova image-list | grep $instance_id";
-        my $query_image_output = `$query_image`;
-        my $loop = 50;
-
-        notify($ERRORS{'OK'}, 0, "The describe image output for $instance_id : $query_image_output");
-        while ($loop > 0)
-        {
-		if($query_image_output  =~ m/\|\s(\w{6})\s\|/g )
-		{
-                        my $temp = $1;
-
-                        if( $temp eq 'ACTIVE') {
-                               notify($ERRORS{'OK'}, 0, "$instance_id is available now");
-                               goto RELOAD;
-                        }
-                        elsif ($temp eq 'SAVING') {
-                                notify($ERRORS{'OK'}, 0, "Sleep to capture New Image for 25 secs");
-                                sleep 25;
-                        }
-                        else {
-                                notify($ERRORS{'DEBUG'}, 0, "Failure for $instance_id");
-				return 0;
-                        }
-                }
-                $query_image_output = `$query_image`;
-                notify($ERRORS{'OK'}, 0, "The describe image output of loop #$loop: $query_image_output");
-                $loop--;
-        }
-        RELOAD:
-        #notify($ERRORS{'OK'}, 0, "Sleep until image is available");
-        sleep 30;
-	
-	return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////
-
-=head2 node_status
-
- Parameters  : $computer_id or $hash->{computer}{id} (optional)
- Returns     : string -- 'READY', 'POST_LOAD', or 'RELOAD'
- Description : Checks the status of a VM. 'READY' is returned if the VM is
-               accessible via SSH, and the OS module's post-load tasks have 
-	       run. 'POST_LOAD' is returned if the VM only needs to have 
-	       the OS module's post-load tasks run before it is ready. 
-	       'RELOAD' is returned otherwise.
-
-=cut
-
-sub node_status {
-	my $self;
-
-        # Get the argument
-        my $argument = shift;
-
-        # Check if this subroutine was called an an object method or an argument was passed
-        if (ref($argument) =~ /VCL::Module/i) {
-                $self = $argument;
-        }
-        elsif (!ref($argument) || ref($argument) eq 'HASH') {
-                # An argument was passed, check its type and determine the computer ID
-                my $computer_id;
-                if (ref($argument)) {
-                        # Hash reference was passed
-                        $computer_id = $argument->{id};
-                }
-                elsif ($argument =~ /^\d+$/) {
-                        # Computer ID was passed
-                        $computer_id = $argument;
-                }
-                else {
-                        # Computer name was passed
-                        ($computer_id) = get_computer_ids($argument);
-                }
-
-                if ($computer_id) {
-                        notify($ERRORS{'DEBUG'}, 0, "computer ID: $computer_id");
-                }
-
-                else {
-                        notify($ERRORS{'WARNING'}, 0, "unable to determine computer ID from argument:\n" . format_data($argument));
-                        return;
-                }
-
-                # Create a DataStructure object containing data for the computer specified as the argument
-                my $data;
-                eval {
-                        $data= new VCL::DataStructure({computer_identifier => $computer_id});
-                };
-                if ($EVAL_ERROR) {
-                        notify($ERRORS{'WARNING'}, 0, "failed to create DataStructure object for computer ID: $computer_id, error: $EVAL_ERROR");
-                        return;
-                }
-                elsif (!$data) {
-                        notify($ERRORS{'WARNING'}, 0, "failed to create DataStructure object for computer ID: $computer_id, DataStructure object is not defined");
-                        return;
-                }
-                else {
-                        notify($ERRORS{'DEBUG'}, 0, "created DataStructure object  for computer ID: $computer_id");
-                }
-
-                # Create a VMware object
-                my $object_type = 'VCL::Module::Provisioning::openstack';
-                if ($self = ($object_type)->new({data_structure => $data})) {
-                        notify($ERRORS{'DEBUG'}, 0, "created $object_type object to check the status of computer ID: $computer_id");
-                }
-                else {
-                        notify($ERRORS{'WARNING'}, 0, "failed to create $object_type object to check the status of computer ID: $computer_id");
-                        return;
-                }
-
-                # Create an OS object for the VMware object to access
-                if (!$self->create_os_object()) {
-                        notify($ERRORS{'WARNING'}, 0, "failed to create OS object");
-                        return;
-                }
-        }
-
-        my $reservation_id = $self->data->get_reservation_id();
-        my $computer_name = $self->data->get_computer_node_name();
-        my $image_name = $self->data->get_image_name();
-        my $request_forimaging = $self->data->get_request_forimaging();
-	my $imagerevision_id = $self->data->get_imagerevision_id();
-
-        notify($ERRORS{'DEBUG'}, 0, "attempting to check the status of computer $computer_name, image: $image_name");
-
-        # Create a hash reference and populate it with the default values
-        my $status;
-        $status->{currentimage} = '';
-        $status->{ssh} = 0;
-        $status->{image_match} = 0;
-        $status->{status} = 'RELOAD';
-
-        # Check if node is pingable and retrieve the power status if the reservation ID is 0
-        # The reservation ID will be 0 is this subroutine was not called as an object method, but with a computer ID argument
-        # The reservation ID will be 0 when called from healthcheck.pm
-        # The reservation ID will be > 0 if called from a normal VCL reservation
-        # Skip the ping and power status checks for a normal reservation to speed things up
-        if (!$reservation_id) {
-                if (_pingnode($computer_name)) {
-                        notify($ERRORS{'DEBUG'}, 0, "VM $computer_name is pingable");
-                        $status->{ping} = 1;
-                }
-                else {
-                        notify($ERRORS{'DEBUG'}, 0, "VM $computer_name is not pingable");
-                        $status->{ping} = 0;
-                }
-
-        }
-
-	notify($ERRORS{'DEBUG'}, 0, "Trying to ssh...");
-        # Check if SSH is available
-        if ($self->os->is_ssh_responding()) {
-                notify($ERRORS{'DEBUG'}, 0, "VM $computer_name is responding to SSH");
-                $status->{ssh} = 1;
-        }
-        else {
-                notify($ERRORS{'OK'}, 0, "VM $computer_name is not responding to SSH, returning 'RELOAD'");
-                $status->{status} = 'RELOAD';
-                $status->{ssh} = 0;
-
-                # Skip remaining checks if SSH isn't available
-                return $status;
-        }
-
-        my $current_image_revision_id = $self->os->get_current_image_info();
-	$status->{currentimagerevision_id} = $current_image_revision_id;
-
-	$status->{currentimage} = $self->data->get_computer_currentimage_name();
-        my $current_image_name = $status->{currentimage};
-        my $vcld_post_load_status = $self->data->get_computer_currentimage_vcld_post_load();
-
-        if (!$current_image_revision_id) {
-                notify($ERRORS{'OK'}, 0, "unable to retrieve image name from currentimage.txt on VM $computer_name, returning 'RELOAD'");
-                return $status;
-        }
-        elsif ($current_image_revision_id eq $imagerevision_id) {
-                notify($ERRORS{'OK'}, 0, "currentimage.txt image $current_image_revision_id ($current_image_name) matches requested imagerevision_id $imagerevision_id  on VM $computer_name");
-                $status->{image_match} = 1;
-        }
-        else {
-                notify($ERRORS{'OK'}, 0, "currentimage.txt imagerevision_id $current_image_revision_id ($current_image_name) does not match requested imagerevision_id $imagerevision_id on VM $computer_name, returning 'RELOAD'");
-                return $status;
-        }
-
-
-	# Determine the overall machine status based on the individual status results
-	if ($status->{ssh} && $status->{image_match}) {
-		$status->{status} = 'READY';
-	}
-	else {
-		$status->{status} = 'RELOAD';
-	}
-
-	notify($ERRORS{'DEBUG'}, 0, "status set to $status->{status}");
-
-
-	if ($request_forimaging) {
-		$status->{status} = 'RELOAD';
-		notify($ERRORS{'OK'}, 0, "request_forimaging set, setting status to RELOAD");
-	}
-
-        if ($vcld_post_load_status) {
-                notify($ERRORS{'DEBUG'}, 0, "OS module post_load tasks have been completed on VM $computer_name");
-                $status->{status} = 'READY';
-        }
-        else {
-                notify($ERRORS{'OK'}, 0, "OS module post_load tasks have not been completed on VM $computer_name, returning 'POST_LOAD'");
-                $status->{status} = 'POST_LOAD';
-        }
-
-
-	notify($ERRORS{'DEBUG'}, 0, "returning node status hash reference (\$node_status->{status}=$status->{status})");
-	return $status;
-
-} ## end sub node_status
-
-
-sub does_image_exist {
-	my $self = shift;
-	if (ref($self) !~ /openstack/i) {
-		notify($ERRORS{'CRITICAL'}, 0, "does_image_exist() subroutine was called as a function, it must be called as a class method");
-		return 0;
-	}
-
-	my $vcl_image_name = $self->data->get_image_name();
-
-	# Match image name between VCL database and openstack Hbase database
-        my $openstack_image_name = _match_image_name($vcl_image_name);
-
-	if($openstack_image_name  =~ m/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})-v/g ) {
-                $openstack_image_name = $1;
-                notify($ERRORS{'OK'}, 0, "Acquire the OpenStack image name: $openstack_image_name");
-        }
-        else {
-                notify($ERRORS{'DEBUG'}, 0, "Fail to acquire the OpenStack image name for $vcl_image_name");
-                return 0;
-        }
-
-	my $list_openstack_image = "nova image-list | grep $openstack_image_name";
-	my $list_openstack_image_output = `$list_openstack_image`;
-
-	notify($ERRORS{'OK'}, 0, "The describe_image output: $list_openstack_image_output");
-
-	if ($list_openstack_image_output =~ /$openstack_image_name/) {
-		notify($ERRORS{'OK'}, 0, "The openstack image for $vcl_image_name exists");
-		return 1;
-	}
-	else
-	{
-		notify($ERRORS{'WARNING'}, 0, "The openstack image for $vcl_image_name does NOT exists");
-		return 0;
-	}
-
-} ## end sub does_image_exist
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2  getimagesize
-
- Parameters  : imagename
- Returns     : 0 failure or size of image
- Description : in size of Kilobytes
-
-=cut
-
-sub get_image_size {
-	my $self = shift;
-	if (ref($self) !~ /openstack/i) {
-		notify($ERRORS{'CRITICAL'}, 0, "get_image_size subroutine was called as a function, it must be called as a class method");
-		return 0;
-	}
- 
-        notify($ERRORS{'OK'}, 0, "No image size information in Openstack");
-
-	return 0;
-} ## end sub get_image_size
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 _set_openstack_user_conf 
-
- Parameters  : None 
- Returns     : 1(success) or 0(failure)
- Description : load environment profile and set global environemnt variables 
-
-example: openstack.conf
-"os_tenant_name" => "admin",
-"os_username" => "admin",
-"os_password" => "adminpassword",
-"os_auth_url" => "http://openstack_nova_url:5000/v2.0/",
-"vcl_windows_key" => "vcl_windows_key",
-"vcl_linux_key" => "vcl_linux_key",
-
-
-=cut
-
-sub _set_openstack_user_conf {
-
-	my $self = shift;
-        notify($ERRORS{'OK'}, 0, "********* Set OpenStack User Configuration******************");
-	my $computer_name   = $self->data->get_computer_short_name;
-        notify($ERRORS{'OK'}, 0,  "computer_name: $computer_name");
-	# User's environment file
-	my $user_config_file = '/etc/vcl/openstack/openstack.conf';
-        notify($ERRORS{'OK'}, 0,  "loading $user_config_file");
-        my %config = do($user_config_file);
-        if (!%config) {
-                notify($ERRORS{'CRITICAL'},0, "failure to process $user_config_file");
-                return 0;
-        }
-        $self->{config} = \%config;
-        my $os_auth_url = $self->{config}->{os_auth_url};
-        my $os_tenant_name = $self->{config}->{os_tenant_name};
-        my $os_username = $self->{config}->{os_username};
-        my $os_password = $self->{config}->{os_password};
-        my $vcl_windows_key = $self->{config}->{vcl_windows_key};
-        my $vcl_linux_key = $self->{config}->{vcl_linux_key};
-
-	# Set Environment File
-	$ENV{'OS_AUTH_URL'} = $os_auth_url;
-	$ENV{'OS_TENANT_NAME'} = $os_tenant_name;
-	$ENV{'OS_USERNAME'} = $os_username;
-	$ENV{'OS_PASSWORD'} = $os_password;
-	$ENV{'VCL_WINDOWS_KEY'} = $vcl_windows_key;
-	$ENV{'VCL_LINUX_KEY'} = $vcl_linux_key;
-
-        return 1;
-}# _set_openstack_user_conf close
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 _match_image_name 
-
- Parameters  : None 
- Returns     : image_name of Openstack 
- Description : match VCL image name with Openstack image name and set the image_name
-
-=cut
-
-sub _match_image_name {
-
-	# Set image name
-	my $vcl_image_name = shift;
-
-	my $select_statement = "
-	SELECT
-	openstackImageNameMap.openstackimagename as openstack_name, 
-	openstackImageNameMap.vclimagename as vcl_name 
-	FROM
-	openstackImageNameMap
-	WHERE
-	openstackImageNameMap.vclimagename = '$vcl_image_name'
-	";
-
-	notify($ERRORS{'OK'}, 0, "$select_statement");
-        # Call the database select subroutine
-        # This will return an array of one or more rows based on the select statement
-        my @selected_rows = database_select($select_statement);
-	# Check to make sure 1 row was returned
-        if (scalar @selected_rows == 0) {
-                return 1;
-        }
-        elsif (scalar @selected_rows > 1) {
-                notify($ERRORS{'WARNING'}, 0, "" . scalar @selected_rows . " rows were returned from database select");
-                return 0;
-        }
-        my $openstack_image_name = $selected_rows[0]{openstack_name};
-        my $vcl_imagename  = $selected_rows[0]{vcl_name};
-
-        notify($ERRORS{'OK'}, 0, "The OpenStack image name $openstack_image_name is matched to $vcl_imagename");
-
-	return $openstack_image_name;
-}
-
-sub _get_flavor_type {
-	my $openstack_image_name = shift;
-	my $image_size;
-	my $openstack_image_info = "qemu-img info /var/lib/glance/images/$openstack_image_name";
-	my $openstack_image_info_output = `$openstack_image_info`;
-        if($openstack_image_info_output =~ m/virtual size:(\s\d{1,4})G/g)
-        {
-                $image_size = $1;
-                notify($ERRORS{'OK'}, 0, "The disk size for $openstack_image_name  is $image_size G");
-        } else {
-                notify($ERRORS{'WARNING'}, 0, "Unable to find $openstack_image_name in /var/lib/glance/images");
-                return 0;
-        }
-
-	# Change the disk size based on the OpenStack flavor info
-	my @flavor_disk_sizes = (1, 20, 40, 80, 160);
-	my $flavor_type;
-
-	if($image_size < $flavor_disk_sizes[0]){
-       		$flavor_type = 1;
-	} 
-	elsif($flavor_disk_sizes[0] <= $image_size && $image_size < $flavor_disk_sizes[1]) {
-       		$flavor_type = 2;
-	} 
-	elsif($flavor_disk_sizes[1] <= $image_size && $image_size < $flavor_disk_sizes[2]) {
-        	$flavor_type = 3;
-	} 
-	elsif($flavor_disk_sizes[2] <= $image_size && $image_size < $flavor_disk_sizes[3]) {
-        	$flavor_type = 4;
-	} 
-	elsif($flavor_disk_sizes[3] <= $image_size && $image_size < $flavor_disk_sizes[4]) {
-        	$flavor_type = 5;
-	} 
-	else {
-		notify($ERRORS{'OK'}, 0, "No available OpenStack flavor for  $openstack_image_name");
-		return 0;
-	}
-
-	notify($ERRORS{'OK'}, 0, "The flavor type for  $openstack_image_name is $flavor_type");
-	return $flavor_type;
-
-}
-
-sub _terminate_instances {
-	my $self = shift;
-
-	my $computer_name = $self->data->get_computer_short_name;
-	my $instance_id = $self->_get_instance_id;
-	$self->_delete_computer_mapping;
-
-	if ($instance_id) {
-		notify($ERRORS{'OK'}, 0, "Terminate the existing instance");
-		my $terminate_instances = "nova delete $instance_id";
-		my $run_terminate_instances = `$terminate_instances`;
-		notify($ERRORS{'OK'}, 0, "The nova delete : $instance_id is terminated");
-		# nova.conf, set force_dhcp_release=true 
-		sleep 30; # wait for completely removing from nova list
-	}
-	else {
-		notify($ERRORS{'OK'}, 0, "No instance found for $computer_name");
-	}
-
-	return 1;
-}
-
-sub _run_instances {
-	my $self = shift;
-	
-
-	my $image_full_name = $self->data->get_image_name;
-	my $computer_name  = $self->data->get_computer_short_name;
-
-        my $image_name = _match_image_name($image_full_name);
-	if($image_name  =~ m/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})-v/g )
-	{
-                $image_name = $1;
-                notify($ERRORS{'OK'}, 0, "Acquire the openstack image name: $image_name");
-        }
-        else {
-                notify($ERRORS{'DEBUG'}, 0, "Failed to acquire the openstack image name: $image_name");
-                return 0;
-        }
-
-        my $flavor_type = _get_flavor_type($image_name);
-	if(!$flavor_type) {
-                notify($ERRORS{'DEBUG'}, 0, "Fail to acquire openstack flavor type for $image_name");
-                return 0;
-	}
-
-	my $openstack_key;
-        my $image_os_type  = $self->data->get_image_os_type;
-	if ($image_os_type eq 'linux') {
-		$openstack_key =  $ENV{'VCL_LINUX_KEY'}; 	
-        	notify($ERRORS{'OK'}, 0, "VCL Linux key is $openstack_key");
-	} 
-	elsif ($image_os_type eq 'windows') {
-		$openstack_key =  $ENV{'VCL_WINDOWS_KEY'}; 	
-        	notify($ERRORS{'OK'}, 0, "VCL Windows key is $openstack_key");
-	}
-	else {
-        	notify($ERRORS{'OK'}, 0, "No available openstack keys for $image_full_name");
-		return;
-	}
-
-	my $run_instance = "nova boot --flavor $flavor_type --image $image_name --key_name $openstack_key $computer_name";
-	notify($ERRORS{'OK'}, 0, "The run_instance: $run_instance\n");
-	
-	my $run_instance_output = `$run_instance`;
-	my $instance_id;
-	my $insert_success;
-	
-	notify($ERRORS{'OK'}, 0, "The run_instance Output: $run_instance_output\n");
-	if($run_instance_output  =~ m/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/g )
-	{
-		$instance_id = $&;
-		notify($ERRORS{'OK'}, 0, "The indstance_id: $instance_id\n");
-	}
-	else {
-		notify($ERRORS{'OK'}, 0, "Failed to run the instance");
-		return 0;
-	}
-
-	if (!$self->_insert_instance_id($instance_id)) {
-		notify($ERRORS{'OK'}, 0, "Failed to insert the instance id : $instance_id");
-		return 0;
-	}
-
-	return 1;
-}
-
-sub _insert_instance_id {
-	my $self = shift;
-	my $instance_id = shift;
-	my $computer_id = $self->data->get_computer_id;
-
-	my $insert_statement = "
-	INSERT INTO
-	openstackComputerMap (
-	instanceid,
-	computerid
-	) VALUES (
-		'$instance_id',
-		'$computer_id'
-	)";
-
-	notify($ERRORS{'OK'}, 0, "$insert_statement");
-	my $success = database_execute($insert_statement);
-
-	if ($success) {
-		notify($ERRORS{'OK'}, 0, "Successfully inserted instance id");
-		return 1;
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "Unable to insert instance id");
-		return 0;
-	}
-}
-
-sub _get_instance_id {
-	my $self = shift;
-	my $computer_id = $self->data->get_computer_id;
-
-	my $select_statement = "
-	SELECT
-	instanceid
-	FROM
-	openstackComputerMap
-	WHERE
-	computerid = '$computer_id'
-	";
-
-	notify($ERRORS{'OK'}, 0, "$select_statement");
-	my @selected_rows = database_select($select_statement);
-
-	if (scalar @selected_rows == 0) {
-		notify($ERRORS{'WARNING'}, 0, "Unable to find the instance id");
-		return 0;
-	}
-
-	my $instance_id = $selected_rows[0]{instanceid};
-	notify($ERRORS{'OK'}, 0, "Openstack id for $computer_id is $instance_id");
-
-	return $instance_id;
-}
-
-sub _delete_computer_mapping {
-	my $self = shift;
-	my $computer_id = $self->data->get_computer_id;
-
-	my $delete_statement = "
-	DELETE FROM
-	openstackComputerMap
-	WHERE
-	computerid = '$computer_id'
-	";
-
-	notify($ERRORS{'OK'}, 0, "$delete_statement");
-	my $success = database_execute($delete_statement);
-
-	if ($success) {
-		notify($ERRORS{'OK'}, 0, "Successfully deleted computer mapping");
-		return 1;
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "Unable to delete computer mapping");
-		return 0;
-	}
-}
-
-
-
-sub _update_private_ip {
-	my $self = shift;
-	
-	my $instance_id = shift;
-	my $main_loop = 60;
-	my $private_ip;
-	my $describe_instance_output;
-        my $computer_id = $self->data->get_computer_id;
-	my $computer_name  = $self->data->get_computer_short_name;
-	my $describe_instance = "nova list |grep  $instance_id";
-	notify($ERRORS{'OK'}, 0, "Describe Instance: $describe_instance");
-	notify($ERRORS{'OK'}, 0, "Computer ID: $computer_id");
-
-	# Find the correct instance among running instances using the private IP
-	while($main_loop > 0 && !defined($private_ip))
-	{
-		notify($ERRORS{'OK'}, 0, "Try to fetch the Private IP on Computer $computer_name: Number $main_loop");	
-		$describe_instance_output = `$describe_instance`;
-		notify($ERRORS{'OK'}, 0, "Describe Instance: $describe_instance_output");
-
-		if($describe_instance_output =~ m/((10|192|172).(\d{1,3}|68|16).(\d{1,3}).(\d{1,3}))/g) 
-		{
-			$private_ip = $1;
-			notify($ERRORS{'OK'}, 0, "The instance private IP on Computer $computer_name: $private_ip");
-			if (defined($private_ip) && $private_ip ne "") {
-				my $new_private_ip = update_computer_private_ip_address($computer_id, $private_ip);
-				if(!$new_private_ip) {
-					notify($ERRORS{'OK'}, 0, "The $private_ip on Computer $computer_name is NOT updated");
-					return 0;
-				}
-				goto EXIT_WHILELOOP;
-			}
-		}
-		else {
-				notify($ERRORS{'DEBUG'}, 0, "Private IP for $computer_name is not determined");
-		}
-
-		sleep 20;
-		$main_loop--;
-	}
-	EXIT_WHILELOOP:
-	
-	return 1;
-}
-#/////////////////////////////////////////////////////////////////////////////
-
-1;
-__END__
+#!/usr/bin/perl -w
+###############################################################################
+# $Id: openstack.pm 2014-6-22 
+###############################################################################
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###############################################################################
+
+=head1 NAME
+
+VCL::Provisioning::openstack - VCL module to support the Openstack provisioning engine
+
+=head1 SYNOPSIS
+
+ Needs to be written
+
+=head1 DESCRIPTION
+
+This module provides VCL support for Openstack
+
+=cut
+
+##############################################################################
+package VCL::Module::Provisioning::openstack;
+
+# Include File Copying for Perl
+use File::Copy;
+
+# Specify the lib path using FindBin
+use FindBin;
+use lib "$FindBin::Bin/../../..";
+
+# Configure inheritance
+use base qw(VCL::Module::Provisioning);
+
+# Specify the version of this module
+our $VERSION = '2.3.2';
+
+# Specify the version of Perl to use
+use 5.008000;
+
+use strict;
+use warnings;
+use diagnostics;
+use English qw( -no_match_vars );
+use IO::File;
+use Fcntl qw(:DEFAULT :flock);
+use File::Temp qw( tempfile );
+use List::Util qw( max );
+use VCL::utils;
+use List::BinarySearch qw(binsearch_pos);
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 initialize
+
+ Parameters  :
+ Returns     :
+ Description :
+
+=cut
+
+sub initialize {
+	my $self = shift;
+        notify($ERRORS{'DEBUG'}, 0, "OpenStack module initialized");
+	
+	if($self->_set_openstack_user_conf) {
+        	notify($ERRORS{'OK'}, 0, "Success to OpenStack user configuration");
+	}
+	else {
+        	notify($ERRORS{'CRITICAL'}, 0, "Failure to Openstack user configuration");
+		return 0;
+	}
+	
+        return 1;
+} ## end sub initialize
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 provision
+
+ Parameters  : hash
+ Returns     : 1(success) or 0(failure)
+ Description : loads virtual machine with requested image
+
+=cut
+
+sub load {
+        my $self = shift;
+        if (ref($self) !~ /openstack/i) {
+                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+                return;
+        }
+
+        my $reservation_id = $self->data->get_reservation_id() || return;
+        my $computer_id = $self->data->get_computer_id() || return;
+        my $computer_name = $self->data->get_computer_short_name() || return;
+        my $image_name = $self->data->get_image_name() || return;
+        my $vmhost_name = $self->data->get_vmhost_short_name() || return;
+
+        insertloadlog($reservation_id, $computer_id, "doesimageexists", "image exists $image_name");
+
+        insertloadlog($reservation_id, $computer_id, "startload", "$computer_name $image_name");
+
+        # Remove existing VMs which were created for the reservation computer
+        if (!$self->_terminate_instances) {
+                notify($ERRORS{'WARNING'}, 0, "failed to remove existing VMs created for computer $computer_name on VM host: $vmhost_name");
+                return;
+        }
+
+	# Create new instance 
+        if (!$self->_run_instances) {
+                notify($ERRORS{'WARNING'}, 0, "failed to create VMs for computer $computer_name on VM host: $vmhost_name");
+                return;
+	}
+	my $instance_id = $self->_get_instance_id;
+        if (!$instance_id) {
+                notify($ERRORS{'WARNING'}, 0, "failed to get the instance id for $computer_name");
+                return;
+	}
+
+	# Update the private ip of the instance in /etc/hosts file
+	if($self->_update_private_ip($instance_id)) 
+	{
+		notify($ERRORS{'OK'}, 0, "Update the private ip of instance $instance_id is succeeded\n");
+	}
+	else
+	{
+		notify($ERRORS{'CRITICAL'}, 0, "Fail to update private ip of the instance in /etc/hosts");
+		return;
+	}
+
+
+	# Instances have the ip instantly when it use FlatNetworkManager
+	# Need to wait for copying images from repository or cache to instance directory
+	# 15G for 3 to 5 minutes (depends on systems)
+	#sleep 300;
+	sleep 10;
+
+	# Call post_load 
+	if ($self->os->can("post_load")) {
+		notify($ERRORS{'DEBUG'}, 0, "calling " . ref($self->os) . "->post_load()");
+		if ($self->os->post_load()) {
+			notify($ERRORS{'DEBUG'}, 0, "successfully ran OS post_load subroutine");
+		}
+		else {
+			notify($ERRORS{'WARNING'}, 0, "failed to run OS post_load subroutine");
+			return;
+		}
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, ref($self->os) . "::post_load() has not been implemented");
+	}
+
+	return 1;
+
+} ## end sub load
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 capture
+
+ Parameters  : $request_data_hash_reference
+ Returns     : 1 if sucessful, 0 if failed
+ Description : Creates a new vmware image.
+
+=cut
+
+sub capture {
+        notify($ERRORS{'DEBUG'}, 0, "**********************************************************");
+        notify($ERRORS{'OK'},    0, "Entering Openstack Capture routine");
+        my $self = shift;
+
+        if (ref($self) !~ /openstack/i) {
+                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+                return 0;
+        }
+
+        my $image_name     = $self->data->get_image_name();
+        my $computer_name = $self->data->get_computer_short_name;
+	my $instance_id;
+	
+        if(_pingnode($computer_name))
+        {
+		$instance_id = $self->_get_instance_id;
+		notify($ERRORS{'OK'}, 0, "instance id: $instance_id is done");
+		if(!$instance_id)
+		{
+			notify($ERRORS{'DEBUG'}, 0, "unable to get instance id for $computer_name");
+			return 0;
+		}
+        }
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "unable to ping to $computer_name");
+		return 0;
+	}
+		
+        if($self->_prepare_capture)
+	{
+		notify($ERRORS{'OK'}, 0, "Prepare_Capture for $computer_name is done");
+	}
+	
+	my $new_image_name = $self->_image_create($instance_id);
+
+	if($new_image_name)
+	{
+		notify($ERRORS{'OK'}, 0, "Create Image for $computer_name is done");
+	}
+
+	if($self->_insert_openstack_image_name($new_image_name))
+	{
+	        notify($ERRORS{'OK'}, 0, "Successfully insert image name");
+        }
+
+	if($self->_wait_for_copying_image($instance_id)) 
+	{
+		notify($ERRORS{'OK'}, 0, "Wait for copying $new_image_name is succeeded\n");
+	}
+
+        return 1;
+} ## end sub capture
+#/////////////////////////////////////////////////////////////////////////
+
+=head2 node_status
+
+ Parameters  : $computer_id or $hash->{computer}{id} (optional)
+ Returns     : string -- 'READY', 'POST_LOAD', or 'RELOAD'
+ Description : Checks the status of a VM. 'READY' is returned if the VM is
+               accessible via SSH, and the OS module's post-load tasks have 
+	       run. 'POST_LOAD' is returned if the VM only needs to have 
+	       the OS module's post-load tasks run before it is ready. 
+	       'RELOAD' is returned otherwise.
+
+=cut
+
+sub node_status {
+	my $self;
+
+        # Get the argument
+        my $argument = shift;
+
+        # Check if this subroutine was called an an object method or an argument was passed
+        if (ref($argument) =~ /VCL::Module/i) {
+                $self = $argument;
+        }
+        elsif (!ref($argument) || ref($argument) eq 'HASH') {
+                # An argument was passed, check its type and determine the computer ID
+                my $computer_id;
+                if (ref($argument)) {
+                        # Hash reference was passed
+                        $computer_id = $argument->{id};
+                }
+                elsif ($argument =~ /^\d+$/) {
+                        # Computer ID was passed
+                        $computer_id = $argument;
+                }
+                else {
+                        # Computer name was passed
+                        ($computer_id) = get_computer_ids($argument);
+                }
+
+                if ($computer_id) {
+                        notify($ERRORS{'DEBUG'}, 0, "computer ID: $computer_id");
+                }
+
+                else {
+                        notify($ERRORS{'WARNING'}, 0, "unable to determine computer ID from argument:\n" . format_data($argument));
+                        return;
+                }
+
+                # Create a DataStructure object containing data for the computer specified as the argument
+                my $data;
+                eval {
+                        $data= new VCL::DataStructure({computer_identifier => $computer_id});
+                };
+                if ($EVAL_ERROR) {
+                        notify($ERRORS{'WARNING'}, 0, "failed to create DataStructure object for computer ID: $computer_id, error: $EVAL_ERROR");
+                        return;
+                }
+                elsif (!$data) {
+                        notify($ERRORS{'WARNING'}, 0, "failed to create DataStructure object for computer ID: $computer_id, DataStructure object is not defined");
+                        return;
+                }
+                else {
+                        notify($ERRORS{'DEBUG'}, 0, "created DataStructure object  for computer ID: $computer_id");
+                }
+
+                # Create a VMware object
+                my $object_type = 'VCL::Module::Provisioning::openstack';
+                if ($self = ($object_type)->new({data_structure => $data})) {
+                        notify($ERRORS{'DEBUG'}, 0, "created $object_type object to check the status of computer ID: $computer_id");
+                }
+                else {
+                        notify($ERRORS{'WARNING'}, 0, "failed to create $object_type object to check the status of computer ID: $computer_id");
+                        return;
+                }
+
+                # Create an OS object for the VMware object to access
+                if (!$self->create_os_object()) {
+                        notify($ERRORS{'WARNING'}, 0, "failed to create OS object");
+                        return;
+                }
+        }
+
+        my $reservation_id = $self->data->get_reservation_id();
+        my $computer_name = $self->data->get_computer_node_name();
+        my $image_name = $self->data->get_image_name();
+        my $request_forimaging = $self->data->get_request_forimaging();
+	my $imagerevision_id = $self->data->get_imagerevision_id();
+
+        notify($ERRORS{'DEBUG'}, 0, "attempting to check the status of computer $computer_name, image: $image_name");
+
+        # Create a hash reference and populate it with the default values
+        my $status;
+        $status->{currentimage} = '';
+        $status->{ssh} = 0;
+        $status->{image_match} = 0;
+        $status->{status} = 'RELOAD';
+
+        # Check if node is pingable and retrieve the power status if the reservation ID is 0
+        # The reservation ID will be 0 is this subroutine was not called as an object method, but with a computer ID argument
+        # The reservation ID will be 0 when called from healthcheck.pm
+        # The reservation ID will be > 0 if called from a normal VCL reservation
+        # Skip the ping and power status checks for a normal reservation to speed things up
+        if (!$reservation_id) {
+                if (_pingnode($computer_name)) {
+                        notify($ERRORS{'DEBUG'}, 0, "VM $computer_name is pingable");
+                        $status->{ping} = 1;
+                }
+                else {
+                        notify($ERRORS{'DEBUG'}, 0, "VM $computer_name is not pingable");
+                        $status->{ping} = 0;
+                }
+
+        }
+
+	notify($ERRORS{'DEBUG'}, 0, "Trying to ssh...");
+        # Check if SSH is available
+        if ($self->os->is_ssh_responding()) {
+                notify($ERRORS{'DEBUG'}, 0, "VM $computer_name is responding to SSH");
+                $status->{ssh} = 1;
+        }
+        else {
+                notify($ERRORS{'OK'}, 0, "VM $computer_name is not responding to SSH, returning 'RELOAD'");
+                $status->{status} = 'RELOAD';
+                $status->{ssh} = 0;
+
+                # Skip remaining checks if SSH isn't available
+                return $status;
+        }
+
+        my $current_image_revision_id = $self->os->get_current_image_info();
+	$status->{currentimagerevision_id} = $current_image_revision_id;
+
+	$status->{currentimage} = $self->data->get_computer_currentimage_name();
+        my $current_image_name = $status->{currentimage};
+        my $vcld_post_load_status = $self->data->get_computer_currentimage_vcld_post_load();
+
+        if (!$current_image_revision_id) {
+                notify($ERRORS{'OK'}, 0, "unable to retrieve image name from currentimage.txt on VM $computer_name, returning 'RELOAD'");
+                return $status;
+        }
+        elsif ($current_image_revision_id eq $imagerevision_id) {
+                notify($ERRORS{'OK'}, 0, "currentimage.txt image $current_image_revision_id ($current_image_name) matches requested imagerevision_id $imagerevision_id  on VM $computer_name");
+                $status->{image_match} = 1;
+        }
+        else {
+                notify($ERRORS{'OK'}, 0, "currentimage.txt imagerevision_id $current_image_revision_id ($current_image_name) does not match requested imagerevision_id $imagerevision_id on VM $computer_name, returning 'RELOAD'");
+                return $status;
+        }
+
+
+	# Determine the overall machine status based on the individual status results
+	if ($status->{ssh} && $status->{image_match}) {
+		$status->{status} = 'READY';
+	}
+	else {
+		$status->{status} = 'RELOAD';
+	}
+
+	notify($ERRORS{'DEBUG'}, 0, "status set to $status->{status}");
+
+
+	if ($request_forimaging) {
+		$status->{status} = 'RELOAD';
+		notify($ERRORS{'OK'}, 0, "request_forimaging set, setting status to RELOAD");
+	}
+
+        if ($vcld_post_load_status) {
+                notify($ERRORS{'DEBUG'}, 0, "OS module post_load tasks have been completed on VM $computer_name");
+                $status->{status} = 'READY';
+        }
+        else {
+                notify($ERRORS{'OK'}, 0, "OS module post_load tasks have not been completed on VM $computer_name, returning 'POST_LOAD'");
+                $status->{status} = 'POST_LOAD';
+        }
+
+
+	notify($ERRORS{'DEBUG'}, 0, "returning node status hash reference (\$node_status->{status}=$status->{status})");
+	return $status;
+
+} ## end sub node_status
+
+
+
+#/////////////////////////////////////////////////////////////////////////
+
+=head2 does_image_exist
+
+ Parameters  : 
+ Returns     : 1 or 0
+ Description : Checks the existence of an image.
+
+=cut
+
+sub does_image_exist {
+	my $self = shift;
+	if (ref($self) !~ /openstack/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "does_image_exist() subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+
+	my $vcl_image_name = $self->data->get_image_name();
+
+	# Match image name between VCL database and openstack Hbase database
+        my $openstack_image_name = _match_image_name($vcl_image_name);
+
+	if($openstack_image_name  =~ m/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})-v/g ) {
+                $openstack_image_name = $1;
+                notify($ERRORS{'OK'}, 0, "Acquire the OpenStack image name: $openstack_image_name");
+        }
+        else {
+                notify($ERRORS{'DEBUG'}, 0, "Fail to acquire the OpenStack image name for $vcl_image_name");
+                return 0;
+        }
+
+	my $list_openstack_image = "nova image-list | grep $openstack_image_name";
+	my $list_openstack_image_output = `$list_openstack_image`;
+
+	notify($ERRORS{'OK'}, 0, "The describe_image output: $list_openstack_image_output");
+
+	if ($list_openstack_image_output =~ /$openstack_image_name/) {
+		notify($ERRORS{'OK'}, 0, "The openstack image for $vcl_image_name exists");
+		return 1;
+	}
+	else
+	{
+		notify($ERRORS{'WARNING'}, 0, "The openstack image for $vcl_image_name does NOT exists");
+		return 0;
+	}
+
+} ## end sub does_image_exist
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2  getimagesize
+
+ Parameters  : imagename
+ Returns     : 0 failure or size of image
+ Description : in size of Kilobytes
+
+=cut
+
+sub get_image_size {
+	my $self = shift;
+	if (ref($self) !~ /openstack/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "get_image_size subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+ 
+        notify($ERRORS{'OK'}, 0, "No image size information in Openstack");
+
+	return 0;
+} ## end sub get_image_size
+
+sub _delete_computer_mapping {
+	my $self = shift;
+	my $computer_id = $self->data->get_computer_id;
+
+	my $delete_statement = "
+	DELETE FROM
+	openstackComputerMap
+	WHERE
+	computerid = '$computer_id'
+	";
+
+	notify($ERRORS{'OK'}, 0, "$delete_statement");
+	my $success = database_execute($delete_statement);
+
+	if ($success) {
+		notify($ERRORS{'OK'}, 0, "Successfully deleted computer mapping");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "Unable to delete computer mapping");
+		return 0;
+	}
+}
+
+sub _get_flavor_type {
+	my $openstack_image_name = shift;
+	my $image_disk_size;
+	my $openstack_image_info = "qemu-img info /var/lib/glance/images/$openstack_image_name";
+	my $openstack_image_info_output = `$openstack_image_info`;
+        if($openstack_image_info_output =~ m/virtual size:(\s\d{1,4})G/g)
+        {
+                $image_disk_size = $1;
+                notify($ERRORS{'OK'}, 0, "The disk size for $openstack_image_name  is $image_disk_size G");
+        } else {
+                notify($ERRORS{'WARNING'}, 0, "Unable to find $openstack_image_name in /var/lib/glance/images");
+                return 0;
+        }
+	my @flavor_ids;
+	my @flavor_disk_sizes;
+	my $openstack_flavor_info = "nova flavor-list";
+	my $openstack_flavor_info_output = `$openstack_flavor_info`;
+	my @lines = split /\n/, $openstack_flavor_info_output;
+	foreach my $line (@lines) {
+        	if($line =~ m/^\|\s(\d+)\s+\|/g) {
+                	push(@flavor_ids, $1);
+        	}
+        	if($line =~ m/\|\s\d+\s+\|\s(\d{1,4})\s+\|/g) {
+                	push(@flavor_disk_sizes, $1);
+        	}
+	}
+	notify($ERRORS{'OK'}, 0, "OpenStack flavor IDs: @flavor_ids, disk sizes: @flavor_disk_sizes");
+	my $num_of_ids = @flavor_ids;
+	if(!$num_of_ids || $image_disk_size > $flavor_disk_sizes[$num_of_ids-1]) {
+		notify($ERRORS{'WARNING'}, 0, "No flavor information or disk size is greater than the maximum flavor");
+		return 0;
+	}
+	
+	# Use List::BinarySearch package to find the proper flavor type for the image based on its size.
+	my $index = binsearch_pos { $a <=> $b} $image_disk_size, @flavor_disk_sizes;
+	my $flavor_type = $flavor_ids[$index];
+	notify($ERRORS{'OK'}, 0, "OpenStack flavor type = $flavor_type");
+
+=for comment
+# if you do not want to use List::BinarySearch package 
+# then use if, elsif, else based on your OpenStack flavor info
+# OR, use database to get the flavor information
+# for example,
+        my @flavor_disk_sizes = (1, 20, 40, 80, 160);
+        my $flavor_type;
+
+        if($image_size < $flavor_disk_sizes[0]){
+                $flavor_type = 1;
+        }
+        elsif($flavor_disk_sizes[0] <= $image_size && $image_size < $flavor_disk_sizes[1]) {
+                $flavor_type = 2;
+        }
+        elsif($flavor_disk_sizes[1] <= $image_size && $image_size < $flavor_disk_sizes[2]) {
+                $flavor_type = 3;
+        }
+        elsif($flavor_disk_sizes[2] <= $image_size && $image_size < $flavor_disk_sizes[3]) {
+                $flavor_type = 4;
+        }
+        elsif($flavor_disk_sizes[3] <= $image_size && $image_size < $flavor_disk_sizes[4]) {
+                $flavor_type = 5;
+        }
+        else {
+                notify($ERRORS{'OK'}, 0, "No available OpenStack flavor for  $openstack_image_name");
+                return 0;
+        }
+
+=cut
+	return $flavor_type;
+}
+
+sub _get_instance_id {
+	my $self = shift;
+	my $computer_id = $self->data->get_computer_id;
+
+	my $select_statement = "
+	SELECT
+	instanceid
+	FROM
+	openstackComputerMap
+	WHERE
+	computerid = '$computer_id'
+	";
+
+	notify($ERRORS{'OK'}, 0, "$select_statement");
+	my @selected_rows = database_select($select_statement);
+
+	if (scalar @selected_rows == 0) {
+		notify($ERRORS{'WARNING'}, 0, "Unable to find the instance id");
+		return 0;
+	}
+
+	my $instance_id = $selected_rows[0]{instanceid};
+	notify($ERRORS{'OK'}, 0, "Openstack id for $computer_id is $instance_id");
+
+	return $instance_id;
+}
+
+sub _image_create{
+	my $self = shift;
+	my $instance_id = shift;
+	my $imagerevision_comments = $self->data->get_imagerevision_comments(0);
+        my $image_name     = $self->data->get_image_name();
+	
+	my $image_version;
+        if($image_name =~ m/(-+)(.+)(-v\d+)/g)
+        {
+                $image_version = $3;
+                notify($ERRORS{'OK'}, 0, "Acquire the Image Version: $image_version");
+        }
+
+        my $image_description = $image_name . $imagerevision_comments;
+        #my $image_description = $image_name . '-' . $imagerevision_comments;
+        my $capture_image = "nova image-create $instance_id $image_description";
+        notify($ERRORS{'OK'}, 0, "New Image Capture Command: $capture_image");
+        my $capture_image_output = `$capture_image`;
+
+        my $openstack_image_id;
+        my $new_image_name;
+        my $describe_image = "nova image-list |grep $instance_id";
+        my $run_describe_image_output = `$describe_image`;
+        notify($ERRORS{'OK'}, 0, "The images: $run_describe_image_output");
+
+	sleep 10;
+
+        if($run_describe_image_output  =~ m/^\|\s(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/g )
+        {
+                $openstack_image_id = $1;
+                $new_image_name = $openstack_image_id . $image_version;
+                #$new_image_name = $openstack_image_id .'-v'. $image_version;
+                notify($ERRORS{'OK'}, 0, "The Openstack Image ID:$openstack_image_id");
+                notify($ERRORS{'OK'}, 0, "The New Image Name:$new_image_name");
+                return $new_image_name;
+        }
+        else
+        {
+                notify($ERRORS{'DEBUG'}, 0, "Fail to capture new Image");
+                return 0;
+        }
+}
+
+sub _insert_instance_id {
+	my $self = shift;
+	my $instance_id = shift;
+	my $computer_id = $self->data->get_computer_id;
+
+	my $insert_statement = "
+	INSERT INTO
+	openstackComputerMap (
+	instanceid,
+	computerid
+	) VALUES (
+		'$instance_id',
+		'$computer_id'
+	)";
+
+	notify($ERRORS{'OK'}, 0, "$insert_statement");
+	my $success = database_execute($insert_statement);
+
+	if ($success) {
+		notify($ERRORS{'OK'}, 0, "Successfully inserted instance id");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "Unable to insert instance id");
+		return 0;
+	}
+}
+
+
+sub _insert_openstack_image_name {
+
+	my $self = shift;
+	my $openstack_image_name = shift;
+        my $image_name     = $self->data->get_image_name();       
+
+        my $insert_statement = "
+        INSERT INTO
+        openstackImageNameMap (
+          openstackImageNameMap.openstackimagename,
+          openstackImageNameMap.vclimagename
+        ) VALUES (
+          '$openstack_image_name',
+          '$image_name')";
+
+        notify($ERRORS{'OK'}, 0, "$insert_statement");
+
+        my $requested_id = database_execute($insert_statement);
+        notify($ERRORS{'OK'}, 0, "SQL Insert is first time or requested_id : $requested_id");
+
+        if (!$requested_id) {
+                notify($ERRORS{'DEBUG'}, 0, "unable to insert image name");
+                return 0;
+        }
+        notify($ERRORS{'OK'}, 0, "Successfully insert image name");
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _match_image_name 
+
+ Parameters  : None 
+ Returns     : image_name of Openstack 
+ Description : match VCL image name with Openstack image name and set the image_name
+
+=cut
+
+sub _match_image_name {
+
+	# Set image name
+	my $vcl_image_name = shift;
+
+	my $select_statement = "
+	SELECT
+	openstackImageNameMap.openstackimagename as openstack_name, 
+	openstackImageNameMap.vclimagename as vcl_name 
+	FROM
+	openstackImageNameMap
+	WHERE
+	openstackImageNameMap.vclimagename = '$vcl_image_name'
+	";
+
+	notify($ERRORS{'OK'}, 0, "$select_statement");
+        # Call the database select subroutine
+        # This will return an array of one or more rows based on the select statement
+        my @selected_rows = database_select($select_statement);
+	# Check to make sure 1 row was returned
+        if (scalar @selected_rows == 0) {
+                return 1;
+        }
+        elsif (scalar @selected_rows > 1) {
+                notify($ERRORS{'WARNING'}, 0, "" . scalar @selected_rows . " rows were returned from database select");
+                return 0;
+        }
+        my $openstack_image_name = $selected_rows[0]{openstack_name};
+        my $vcl_imagename  = $selected_rows[0]{vcl_name};
+
+        notify($ERRORS{'OK'}, 0, "The OpenStack image name $openstack_image_name is matched to $vcl_imagename");
+
+	return $openstack_image_name;
+}
+
+sub _prepare_capture {
+	my $self = shift;
+	
+        my ($package, $filename, $line, $sub) = caller(0);
+        my $request_data = $self->data->get_request_data;
+
+        if (!$request_data) {
+                notify($ERRORS{'WARNING'}, 0, "unable to retrieve request data hash");
+                return 0;
+        }
+
+        my $request_id     = $self->data->get_request_id;
+        my $reservation_id = $self->data->get_reservation_id;
+        my $management_node_keys     = $self->data->get_management_node_keys();
+
+        my $image_id       = $self->data->get_image_id;
+        my $image_os_name  = $self->data->get_image_os_name;
+        my $image_identity = $self->data->get_image_identity;
+        my $image_os_type  = $self->data->get_image_os_type;
+        my $image_name     = $self->data->get_image_name();
+
+        my $computer_id        = $self->data->get_computer_id;
+        my $computer_name = $self->data->get_computer_short_name;
+        my $computer_nodename  = $computer_name;
+        my $computer_hostname  = $self->data->get_computer_hostname;
+        my $computer_type      = $self->data->get_computer_type;
+
+        if (write_currentimage_txt($self->data)) {
+                notify($ERRORS{'OK'}, 0, "currentimage.txt updated on $computer_name");
+        }
+        else {
+                notify($ERRORS{'DEBUG'}, 0, "unable to update currentimage.txt on $computer_name");
+                return 0;
+        }
+
+        $self->data->set_imagemeta_sysprep(0);
+        notify($ERRORS{'OK'}, 0, "Set the imagemeta Sysprep value to 0");
+
+        if ($self->os->can("pre_capture")) {
+                notify($ERRORS{'OK'}, 0, "calling OS module's pre_capture() subroutine");
+
+                if (!$self->os->pre_capture({end_state => 'on'})) {
+                        notify($ERRORS{'DEBUG'}, 0, "OS module pre_capture() failed");
+                        return 0;
+                }
+        }
+	return 1;
+}
+
+sub _run_instances {
+	my $self = shift;
+	
+
+	my $image_full_name = $self->data->get_image_name;
+	my $computer_name  = $self->data->get_computer_short_name;
+
+        my $image_name = _match_image_name($image_full_name);
+	if($image_name  =~ m/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})-v/g )
+	{
+                $image_name = $1;
+                notify($ERRORS{'OK'}, 0, "Acquire the openstack image name: $image_name");
+        }
+        else {
+                notify($ERRORS{'DEBUG'}, 0, "Failed to acquire the openstack image name: $image_name");
+                return 0;
+        }
+
+        my $flavor_type = _get_flavor_type($image_name);
+	if(!$flavor_type) {
+                notify($ERRORS{'DEBUG'}, 0, "Fail to acquire openstack flavor type for $image_name");
+                return 0;
+	}
+
+	my $openstack_key;
+        my $image_os_type  = $self->data->get_image_os_type;
+	if ($image_os_type eq 'linux') {
+		$openstack_key =  $ENV{'VCL_LINUX_KEY'}; 	
+        	notify($ERRORS{'OK'}, 0, "VCL Linux key is $openstack_key");
+	} 
+	elsif ($image_os_type eq 'windows') {
+		$openstack_key =  $ENV{'VCL_WINDOWS_KEY'}; 	
+        	notify($ERRORS{'OK'}, 0, "VCL Windows key is $openstack_key");
+	}
+	else {
+        	notify($ERRORS{'OK'}, 0, "No available openstack keys for $image_full_name");
+		return;
+	}
+
+	my $run_instance = "nova boot --flavor $flavor_type --image $image_name --key_name $openstack_key $computer_name";
+	notify($ERRORS{'OK'}, 0, "The run_instance: $run_instance\n");
+	
+	my $run_instance_output = `$run_instance`;
+	my $instance_id;
+	my $insert_success;
+	
+	notify($ERRORS{'OK'}, 0, "The run_instance Output: $run_instance_output\n");
+	if($run_instance_output  =~ m/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/g )
+	{
+		$instance_id = $&;
+		notify($ERRORS{'OK'}, 0, "The indstance_id: $instance_id\n");
+	}
+	else {
+		notify($ERRORS{'OK'}, 0, "Failed to run the instance");
+		return 0;
+	}
+
+	if (!$self->_insert_instance_id($instance_id)) {
+		notify($ERRORS{'OK'}, 0, "Failed to insert the instance id : $instance_id");
+		return 0;
+	}
+
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _set_openstack_user_conf 
+
+ Parameters  : None 
+ Returns     : 1(success) or 0(failure)
+ Description : load environment profile and set global environemnt variables 
+
+example: openstack.conf
+"os_tenant_name" => "admin",
+"os_username" => "admin",
+"os_password" => "adminpassword",
+"os_auth_url" => "http://openstack_nova_url:5000/v2.0/",
+"vcl_windows_key" => "vcl_windows_key",
+"vcl_linux_key" => "vcl_linux_key",
+
+
+=cut
+
+sub _set_openstack_user_conf {
+	my $self = shift;
+	my $computer_name   = $self->data->get_computer_short_name;
+	# User's environment file
+	my $user_config_file = '/etc/vcl/openstack/openstack.conf';
+        notify($ERRORS{'OK'}, 0, "********* Set OpenStack User Configuration******************");
+        notify($ERRORS{'OK'}, 0,  "computer_name: $computer_name");
+        notify($ERRORS{'OK'}, 0,  "loading $user_config_file");
+        my %config = do($user_config_file);
+        if (!%config) {
+                notify($ERRORS{'CRITICAL'},0, "failure to process $user_config_file");
+                return 0;
+        }
+        $self->{config} = \%config;
+        my $os_auth_url = $self->{config}->{os_auth_url};
+        my $os_tenant_name = $self->{config}->{os_tenant_name};
+        my $os_username = $self->{config}->{os_username};
+        my $os_password = $self->{config}->{os_password};
+        my $vcl_windows_key = $self->{config}->{vcl_windows_key};
+        my $vcl_linux_key = $self->{config}->{vcl_linux_key};
+
+	# Set Environment File
+	$ENV{'OS_AUTH_URL'} = $os_auth_url;
+	$ENV{'OS_TENANT_NAME'} = $os_tenant_name;
+	$ENV{'OS_USERNAME'} = $os_username;
+	$ENV{'OS_PASSWORD'} = $os_password;
+	$ENV{'VCL_WINDOWS_KEY'} = $vcl_windows_key;
+	$ENV{'VCL_LINUX_KEY'} = $vcl_linux_key;
+
+        return 1;
+}# _set_openstack_user_conf close
+
+sub _terminate_instances {
+	my $self = shift;
+
+	my $computer_name = $self->data->get_computer_short_name;
+	my $instance_id = $self->_get_instance_id;
+	$self->_delete_computer_mapping;
+
+	if ($instance_id) {
+		notify($ERRORS{'OK'}, 0, "Terminate the existing instance");
+		my $terminate_instances = "nova delete $instance_id";
+		my $run_terminate_instances = `$terminate_instances`;
+		notify($ERRORS{'OK'}, 0, "The nova delete : $instance_id is terminated");
+		# nova.conf, set force_dhcp_release=true 
+		sleep 30; # wait for completely removing from nova list
+	}
+	else {
+		notify($ERRORS{'OK'}, 0, "No instance found for $computer_name");
+	}
+
+	return 1;
+}
+
+sub _update_private_ip {
+	my $self = shift;
+	
+	my $instance_id = shift;
+	my $main_loop = 60;
+	my $private_ip;
+	my $describe_instance_output;
+        my $computer_id = $self->data->get_computer_id;
+	my $computer_name  = $self->data->get_computer_short_name;
+	my $describe_instance = "nova list |grep  $instance_id";
+	notify($ERRORS{'OK'}, 0, "Describe Instance: $describe_instance");
+	notify($ERRORS{'OK'}, 0, "Computer ID: $computer_id");
+
+	# Find the correct instance among running instances using the private IP
+	while($main_loop > 0 && !defined($private_ip))
+	{
+		notify($ERRORS{'OK'}, 0, "Try to fetch the Private IP on Computer $computer_name: Number $main_loop");	
+		$describe_instance_output = `$describe_instance`;
+		notify($ERRORS{'OK'}, 0, "Describe Instance: $describe_instance_output");
+
+		if($describe_instance_output =~ m/((10|192|172).(\d{1,3}|68|16).(\d{1,3}).(\d{1,3}))/g) 
+		{
+			$private_ip = $1;
+			notify($ERRORS{'OK'}, 0, "The instance private IP on Computer $computer_name: $private_ip");
+			if (defined($private_ip) && $private_ip ne "") {
+				my $new_private_ip = update_computer_private_ip_address($computer_id, $private_ip);
+				if(!$new_private_ip) {
+					notify($ERRORS{'OK'}, 0, "The $private_ip on Computer $computer_name is NOT updated");
+					return 0;
+				}
+				goto EXIT_WHILELOOP;
+			}
+		}
+		else {
+				notify($ERRORS{'DEBUG'}, 0, "Private IP for $computer_name is not determined");
+		}
+
+		sleep 20;
+		$main_loop--;
+	}
+	EXIT_WHILELOOP:
+	
+	return 1;
+}
+
+sub _wait_for_copying_image {
+	my $self = shift;
+	
+	my $instance_id = shift;
+        my $query_image = "nova image-list | grep $instance_id";
+        my $query_image_output = `$query_image`;
+
+        my $loop = 50;
+        notify($ERRORS{'OK'}, 0, "The describe image output for $instance_id : $query_image_output");
+        while ($loop > 0)
+        {
+		if($query_image_output  =~ m/\|\s(\w{6})\s\|/g )
+		{
+                        my $temp = $1;
+
+                        if( $temp eq 'ACTIVE') {
+                               notify($ERRORS{'OK'}, 0, "$instance_id is available now");
+                               goto RELOAD;
+                        }
+                        elsif ($temp eq 'SAVING') {
+                                notify($ERRORS{'OK'}, 0, "Sleep to capture New Image for 25 secs");
+                                sleep 25;
+                        }
+                        else {
+                                notify($ERRORS{'DEBUG'}, 0, "Failure for $instance_id");
+				return 0;
+                        }
+                }
+                $query_image_output = `$query_image`;
+                notify($ERRORS{'OK'}, 0, "The describe image output of loop #$loop: $query_image_output");
+                $loop--;
+        }
+        RELOAD:
+        #notify($ERRORS{'OK'}, 0, "Sleep until image is available");
+        sleep 30;
+	
+	return 1;
+}
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
+1;
+__END__