Monday 25 February 2013

Exalogic Virtual Tea Break Snippets - Cloning an existing vServer

Following on from my Blog entry "Scripted Template Generation from an existing vServer" I have built a wrapper script that can be used to execute the Template Generation script or Clone a specific vServer. This script was not incorporated into the original script because it must be executed on a Compute Node with access to the /OVS/Repositories directory and the Compute Node are a minimal install and hence do not have all the required software available. As part of the Cloning process this new script will create an Assets input file that can be used with the CreateAssets.sh describe in the blog "Scripting Asset Creation" and optionally execute the result to create the clone.

To successfully run the script you will need the following 3 scripts located in the same directory on a machine with the EMOC cli/api rms installed.
  1. CloneOrTemplateVServer.sh.
  2. CreateTemplateFromVServer.sh.
  3. CreateAssets.sh.
During execute, of the CloneOrTemplateVServer.sh, the script will connect to EMOC and stop the specified vServer before scping the CreateTemplateFromVServer.sh to the specified Compute Node and executing it. Once the vServer has been converted to a Template the script will restart the specified vServer and then retrieve the following information for the vServers and build the Clone Asset file.
  1. Connected Networks
  2. VServer Type
In addition the template that was built, and assumed to be located on the ZFS below /export/common/images/<Sub Dir based on Name>, will have an upload entry, in the Asset file, and then used within the vServer entry. Because during execute we do not know the number of networks associated with the vServer the Clone Asset file will be created with "*" in the IP Address section indicating that the IP should be allocated Automatically. A future enhancement will provide the "-b" flag to indicate a Backup Asset file must be created and this will contain the IP allocated to the current server.

If the opt to execute has been specified, "-e" the CreateAsset.sh script will be executed passing in the Clone Asset file thus importing the template and creating the server.

Usage

usage: ./CloneOrTemplateVServer.sh -a  -n  -u  -p  -t|-b|-c [-e] -i  [-r ] [-w ] [-d ] [-f ]
       -a  Name of the Account that contains the Specified vServer.
       -u  User that is allowed to access the specified account the default is root
       -p  password of the specified user
       -n  vServer to be templatised or cloned.
       -f  (Default is CreateAssets.in) Defines the file that will be built during the clode operation.
       -t|-b|-c Indicates if only a template should be created (-t) or if the cloning file should be generated as well (-c). Specifying -b will cause the current IP Addresses to be used in the Asset File
             -e If the action is to clone then the presence of this flag indicates that the resulting AssetsFile should be executed
       -r  Location of the repository the default is /OVS/Repositories/*
       -w  Working directory where intermediate files will be copied.
       -d  Directory where the template tgz will be created. Default is current directory
       -i  Address of Compute Node to run the Template functionality from.

Script

Download

 
#!/bin/bash

################################################################################
#
#  Exalogic EL X2-2 2.0.0.4 (Linux x86-64) Configuration Script.
#
#  HEADER START
# 
#  THIS SCRIPT IS PROVIDED ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND, 
#  EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT 
#  THE COVERED SCRIPT IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR 
#  PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE 
#  OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE 
#  DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER 
#  CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION.
#  NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS 
#  DISCLAIMER.
#
#  When distributing this Code, include this HEADER in each file.
#  If applicable, add the following below this this HEADER, with the fields
#  enclosed by brackets "[]" replaced with your own identifying information:
#       Portions Copyright [yyyy] [name of copyright owner]
# 
#  HEADER END
# 
# 
#       Copyright 2011 Andrew Hopkinson, Oracle Corporation UK Ltd.
#
################################################################################

export OCCLI=/opt/sun/occli/bin
export IAAS_HOME=/opt/oracle/iaas/cli
export IAAS_BASE_URL=https://localhost
export BASE_IAAS_ACCESS_KEY_FILE=iaas_access.key
export BASE_KEY_NAME=cli.asset.create
export BASE_KEY_FILE=iaas_access.pub
export RUN_DATE=`date +"%Y%m%d-%H%M"`
#CloudUser used to create vServers & Volumes
export IAAS_USER=root
export IAAS_PASSWORD_FILE=root.pwd
export INPUT_FILE=CreateAssets.in

export ACCOUNTS_FILE=accounts.out
export VOLUMES_FILE=volumes.out
export DISTGRPS_FILE=distgrp.out
export VNETS_FILE=vnets.out
export VSERVER_TYPES_FILE=vstype.out
export VSERVER_FILE=vserver.out
export VSERVER_TEMPLATES=template.out
export NETWORK_STATIC_IPS=staticips.out
export KEY_PAIRS=keypairs.out


## **********************************************************

PROCESSING_ACCOUNT=""

function connectToAccount() {
 if [[ "$ACCOUNT" != "$PROCESSING_ACCOUNT" ]]
 then
  if [[ "" != "$PROCESSING_ACCOUNT" ]]
  then
   $IAAS_HOME/bin/iaas-delete-key-pair --key-name $KEY_NAME --access-key-file $IAAS_ACCESS_KEY_FILE
   $IAAS_HOME/bin/akm-delete-access-key $AK
  fi
  # Set run specific key information
  export IAAS_ACCESS_KEY_FILE=$ACCOUNT"."$RUN_DATE"."$BASE_IAAS_ACCESS_KEY_FILE
  export KEY_NAME=$ACCOUNT"."$RUN_DATE"."$BASE_KEY_NAME
  export KEY_FILE=$ACCOUNT"."$RUN_DATE"."$BASE_KEY_FILE
  #echo "IAAS_ACCESS_KEY_FILE=$IAAS_ACCESS_KEY_FILE"
  #echo "KEY_NAME=$KEY_NAME"
  echo "KEY_FILE=$KEY_FILE"
  # Save current processing account
  PROCESSING_ACCOUNT=$ACCOUNT
  IAAS_USER=$ACCOUNT_USER
  echo "$ACCOUNT_PASSWORD" > $IAAS_PASSWORD_FILE
  $IAAS_HOME/bin/akm-describe-accounts --sep "|" > $ACCOUNTS_FILE
  while read line
  do
   ACCOUNT_ID=${line%%|*}
   line=${line#*|}
   ACCOUNT_NAME=${line%%|*}
 #  echo "Id = $ACCOUNT_ID"
 #  echo "Name = $ACCOUNT_NAME"
   if [[ "$ACCOUNT_NAME" == "$ACCOUNT" ]]
   then
    #echo "Found Account $line"
    AK=`$IAAS_HOME/bin/akm-create-access-key --account $ACCOUNT_ID --access-key-file $IAAS_ACCESS_KEY_FILE`
    KEYPAIR=`$IAAS_HOME/bin/iaas-create-key-pair --key-name $KEY_NAME --key-file $KEY_FILE`
    echo "Connected to $ACCOUNT_NAME"
    
    #cp $IAAS_ACCESS_KEY_FILE $ACCOUNT_NAME$IAAS_ACCESS_KEY_FILE
    #cp $KEY_FILE $ACCOUNT_NAME$KEY_FILE
    break
   fi    
  done < $ACCOUNTS_FILE 
 fi
}

function disconnectFromAccount() {
  $IAAS_HOME/bin/iaas-delete-key-pair --key-name $KEY_NAME --access-key-file $IAAS_ACCESS_KEY_FILE
  $IAAS_HOME/bin/akm-delete-access-key $AK
  PROCESSING_ACCOUNT=""
}

function getDistributionGroups() {
 $IAAS_HOME/bin/iaas-describe-distribution-groups --sep "|" > $DISTGRPS_FILE
}

function getNetworks() {
 $IAAS_HOME/bin/iaas-describe-vnets --sep "|" > $VNETS_FILE
}

function getVSTypes() {
 $IAAS_HOME/bin/iaas-describe-vserver-types --sep "|" > $VSERVER_TYPES_FILE
}

function getTemplates() {
 $IAAS_HOME/bin/iaas-describe-server-templates --sep "|" > $VSERVER_TEMPLATES
}

function getVolumes() {
 $IAAS_HOME/bin/iaas-describe-volumes --sep "|" > $VOLUMES_FILE
}

function getVServers() {
 $IAAS_HOME/bin/iaas-describe-vservers --sep "|" > $VSERVER_FILE
}

function getVServerId() {
 while read line
 do
  VSERVER_ID=${line%%|*}
  line=${line#*|}
  NAME=${line%%|*}
  if [[ "$VSERVER_NAME" == "$NAME" ]]
  then
   break;
  fi
  VSERVER_ID=""
 done < $VSERVER_FILE
}


function getVServerState() {
 getVServers
 while read line
 do
  VSERVER_ID=${line%%|*}
  line=${line#*|}
  NAME=${line%%|*}
  line=${line#*|}
  line=${line#*|}
  VSERVER_STATE=${line%%|*}
  if [[ "$VSERVER_NAME" == "$NAME" ]]
  then
   break;
  fi
 done < $VSERVER_FILE
}

function pauseUntilVServerRunning() {
 # Wait until the Server is running before creating the next
 echo "Pausing until vServer is Running"
  getVServerState
  while [[ "$VSERVER_STATE" != "RUNNING" ]]
  do
   echo "$NAME $VSERVER_STATE"
   if [[ "$VSERVER_STATE" != "RUNNING" ]]
   then
    echo "Sleeping......."
    sleep 30
   fi
   getVServerState
  done
  echo "$NAME $VSERVER_STATE"
  # Lets pause for a minute or two
  echo "Just Chilling......"
  sleep 30
}

## **********************************************************




function pauseUntilVServerShutdown() {
 # Wait until the Server is running before creating the next
 echo "Pausing until vServer has Shutdown"
  getVServerState
  while [[ "$VSERVER_STATE" != "SHUTDOWNDETACHED" ]]
  do
   echo "$NAME $VSERVER_STATE"
   if [[ "$VSERVER_STATE" != "SHUTDOWNDETACHED" ]]
   then
    echo "Sleeping......."
    sleep 30
   fi
   getVServerState
  done
  echo "$NAME $VSERVER_STATE"
  # Lets pause for a minute or two
  echo "Just Chilling......"
  sleep 30
}

#############################################################
##
## stopVServer
## ===========
##
## Find and stop a vServer.
##
#############################################################

function stopVServer() {
 echo "Stopping vServer $VSERVER_NAME"
 getVServers
 getVServerId
 $IAAS_HOME/bin/iaas-stop-vservers --vserver-ids $VSERVER_ID --force
 pauseUntilVServerShutdown
}

#############################################################
##
## startVServer
## ============
##
## Find and stop a vServer.
##
#############################################################

function startVServer() {
 echo "Starting vServer $VSERVER_NAME"
 getVServers
 getVServerId
 $IAAS_HOME/bin/iaas-start-vservers --vserver-ids $VSERVER_ID
 pauseUntilVServerRunning
}

#############################################################
##
## executeRemoteCreateTemplate
## ===========================
##
## Execute the CreateTemplateFromVServer.sh on the specified 
## Compute Node. This is required because the Repository is
## not accessible from the EC VM. It's assumed we will not 
## need to enter a password.
##
#############################################################

function executeRemoteCreateTemplate() {
 echo "Executing Remote Functions"
 if [[ "$CN_IP_ADDRESS" != "" ]]
 then
  #ssh root@$CN_IP_ADDRESS "bash -s" < CreateTemplateFromVServer.sh -n $VSERVER_NAME -r $REPOSITORY_DIR -w $WORKING_DIR -d $DESTINATION_DIR
  #ssh root@$CN_IP_ADDRESS "bash -s -n $VSERVER_NAME -r $REPOSITORY_DIR -w $WORKING_DIR -d $DESTINATION_DIR" < CreateTemplateFromVServer.sh
  #cat CreateTemplateFromVServer.sh | ssh root@$CN_IP_ADDRESS "bash -s -n $VSERVER_NAME -r $REPOSITORY_DIR -w $WORKING_DIR -d $DESTINATION_DIR"
  echo "Copying script to $CN_IP_ADDRESS"
  scp CreateTemplateFromVServer.sh root@$CN_IP_ADDRESS:/tmp
  ssh root@$CN_IP_ADDRESS "chmod a+x /tmp/CreateTemplateFromVServer.sh"
  ssh root@$CN_IP_ADDRESS "/tmp/CreateTemplateFromVServer.sh -n $VSERVER_NAME -r $REPOSITORY_DIR -w $WORKING_DIR -d $DESTINATION_DIR"
  ssh root@$CN_IP_ADDRESS "rm -f /tmp/CreateTemplateFromVServer.sh"
  
  TEMPLATE_TGZ=$DESTINATION_DIR/el_template_$VSERVER_NAME.tgz
 fi
}

#############################################################
##
## createTemplate
## ==============
##
## High level template creation function that will call the 
## required processing function in the necessary sequence.
##
#############################################################

function createTemplate() {
 stopVServer
 executeRemoteCreateTemplate
 startVServer
 echo ""
 echo ""
 echo "****************************************************"
 echo "**"
 echo "** $TEMPLATE_TGZ has been created from"
 echo "** vServer $VSERVER_NAME "
 echo "**"
 echo "****************************************************"
 echo ""
 echo ""
}

#############################################################
##
## getNetworkName
## ==============
##
## Gets the name of a network based on the Id.
##
#############################################################

function getNetworkName() {
  NETWORK_NAME=""
  while read line
  do
   ID=${line%%|*}
   line=${line#*|}
   NAME=${line%%|*}
   if [[ "$ID" == "$NETWORK_ID" ]]
   then
    NETWORK_NAME=$NAME
    break
   fi
  done < $VNETS_FILE
}

#############################################################
##
## getVSTypeName
## =============
##
## Gets the name of a vServer Type based on the Id.
##
#############################################################

function getVSTypeName() {
  VSTYPE_NAME=""
  while read line
  do
   ID=${line%%|*}
   line=${line#*|}
   NAME=${line%%|*}
   if [[ "$ID" == "$VSTYPE_ID" ]]
   then
    VSTYPE_NAME=$NAME
    break
   fi
  done < $VSERVER_TYPES_FILE
}

#############################################################
##
## generateAssetFile
## =================
##
## Generates a Input script that can be used with the 
## CreateAssets.sh to create a server based on the new 
## template.
##
#############################################################

function generateAssetFile() {
 echo "Generating Clones CreateAsset input file"
 if [[ "$ASSET_FILE" == "" ]]
 then
  if [[ "$BACKUP" == "true" ]]
  then
   ASSET_FILE=$VSERVER_NAME"BackupAsset.in"
  else
   ASSET_FILE=$VSERVER_NAME"CreateCloneAsset.in"
  fi
 fi
 echo "$ACCOUNT:Connect|$ACCOUNT_USER|$ACCOUNT_PASSWORD" > $ASSET_FILE
 # Here we are assuming that we have used the recommended mount
 SN_TEMPLATE_FILE=${TEMPLATE_TGZ/u01/export}
 echo "$ACCOUNT:Upload|ServerTemplate|$VSERVER_NAME-Template|http://$SN_IP_ADDRESS/shares$SN_TEMPLATE_FILE" >> $ASSET_FILE
 # Get VServer specific information
 getVServers
 getNetworks
 getVSTypes
 
 while read line
 do
  VSERVER_ID=${line%%|*}
  line=${line#*|}
  NAME=${line%%|*}
  line=${line#*|}
  if [[ "$NAME" == "$VSERVER_NAME" ]]
  then
   URL=${line%%|*}
   line=${line#*|}
   STATE=${line%%|*}
   line=${line#*|}
   NETWORK_IDS=${line%%|*}
   line=${line#*|}
   NETWORK_IPS=${line%%|*}
   line=${line#*|}
   TEMPLATE_ID=${line%%|*}
   line=${line#*|}
   SSH_KEY=${line%%|*}
   line=${line#*|}
   VSTYPE_ID=${line%%|*}
   line=${line#*|}
   
   NETWORK_NAMES=""
   #NETWORK_IPS=""
   for NETWORK_ID in ${NETWORK_IDS//,/ }
   do
    getNetworkName
    if [[ "$NETWORK_NAMES" == "" ]]
    then
     NETWORK_NAMES=$NETWORK_NAME
     if [[ "$BACKUP" != "true" ]]
     then
      NETWORK_IPS="*"
     fi
    else
     NETWORK_NAMES=$NETWORK_NAMES","$NETWORK_NAME
     if [[ "$BACKUP" != "true" ]]
     then
      NETWORK_IPS=$NETWORK_IPS",*"
     fi
    fi
   done
   
   # Get VServer Type Name
   getVSTypeName
   
   echo "$ACCOUNT:Create|vServer|$VSERVER_NAME-Clone|$VSTYPE_NAME|$VSERVER_NAME-Template|$NETWORK_NAMES|$NETWORK_IPS" >> $ASSET_FILE
   
   break
  fi
 done < $VSERVER_FILE

 echo "$ACCOUNT:Disconnect" >> $ASSET_FILE
 
 echo "Generated Asset File $ASSET_FILE"
 
}

#############################################################
##
## executeAssetFile
## =================
##
## Execute the CreateAssets.sh script using the generated 
## Asset file. We assume it is in the same directory.
##
#############################################################

function executeAssetFile() {
 echo "Executing the Generated $ASSET_FILE file"
 echo ""
 ./CreateAssets.sh -f $ASSET_FILE -r
}

#############################################################
##
## usage
## =====
##
## Show usage.
##
#############################################################

function usage() {
 echo ""
 echo >&2 "usage: $0 -a <Account Name> -n <vServer Name> -u <Account User> -p <Account Password> -t|-b|-c [-e] -i <Compute Node IP> [-r <Repository Directory>] [-w <Working Directory>] [-d <Destination Directory>] [-f <Asset Definition File>]"
 echo >&2 "          -a <Account Name> Name of the Account that contains the Specified vServer."
 echo >&2 "                     -u <Account User> User that is allowed to access the specified account the default is root"
 echo >&2 "                     -p <Account Password> password of the specified user"
 echo >&2 "                     -n <vServer Name> vServer to be templatised or cloned."
 echo >&2 "          -f <Asset Definition File> (Default is CreateAssets.in) Defines the file that will be built during the clode operation."
 echo >&2 "          -t|-b|-c Indicates if only a template should be created (-t) or if the cloning file should be generated as well (-c). Specifying -b will cause the current IP Addresses to be used in the Asset File"
 echo >&2 "                     -e If the action is to clone then the presence of this flag indicates that the resulting AssetsFile should be executed"
 echo >&2 "          -r <Repository Directory> Location of the repository the default is /OVS/Repositories/*"
 echo >&2 "          -w <Working Directory> Working directory where intermediate files will be copied."
 echo >&2 "          -d <Destination Directory> Directory where the template tgz will be created. Default is current directory"
 echo >&2 "          -i <Compute Node IP> Address of Compute Node to run the Template functionality from."
 echo""
 exit 1
}

###############################################################
##
## Simple start for the script that will extract the parameters
## and call the appriate start function.
##
###############################################################

export CLONE=""
export BACKUP=""
export TEMPLATE=""
export EXECUTE=""
export WORKING_DIR="/u01/common/images/vServerTemplateWIP"
export DESTINATION_DIR="/u01/common/images/vServerTemplates"
export REPOSITORY_DIR="/OVS/Repositories/*"
export ACCOUNT_USER="root"
export ACCOUNT_PASSWORD="welcome1"
export SYSTEMIMGDIR=/mnt/elsystem
export CN_IP_ADDRESS=""
export SN_IP_ADDRESS="172.17.0.9"

while [ $# -gt 0 ]
do
 case "$1" in 
  -f) ASSET_FILE="$2"; shift;;
  -a) ACCOUNT="$2"; shift;;
  -n) VSERVER_NAME="$2"; shift;;
  -r) REPOSITORY_DIR="$2"; shift;;
  -d) DESTINATION_DIR="$2"; shift;;
  -u) ACCOUNT_USER="$2"; shift;;
  -p) ACCOUNT_PASSWORD="$2"; shift;;
  -w) WORKING_DIR="$2"; shift;;
  -i) CN_IP_ADDRESS="$2"; shift;;
  -s) SN_IP_ADDRESS="$2"; shift;;
  -c) CLONE=true;;
  -b) BACKUP=true;;
  -t) TEMPLATE=true;;  
  -e) EXECUTE=true;;  
  *) usage;;
  *) break;;
 esac
 shift
done


# Check if the JAVA_HOME is set
if [[ "$JAVA_HOME" == "" ]]
then
 export JAVA_HOME=/usr/java/latest
 echo "JAVA_HOME is not defined using $JAVA_HOME"
fi

# Processing function call
if [[ "$VSERVER_NAME" == "" || "$REPOSITORY_DIR" == "" || "$CN_IP_ADDRESS" == "" ]]
then
 usage
elif [[ "$TEMPLATE" == "true" || "$CLONE" == "true" || "$BACKUP" == "true" ]]
then
 connectToAccount
 createTemplate
 if [[ "$CLONE" == "true" || "$BACKUP" == "true" ]]
 then
  generateAssetFile
 fi
 disconnectFromAccount
 if [[ "$EXECUTE" == "true" && "$BACKUP" != "true" ]]
 then
  executeAssetFile
 fi
fi



echo "****************************************"
echo "*****  Finished Processing Assets  *****"
echo "****************************************"


No comments:

Post a Comment