X

Best Practices from Oracle Development's A‑Team

Exalogic Virtual Tea Break Snippets - Cloning an existing vServer

Introduction

This blog describes the process of cloning an existing vServer.

Main Article

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:

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.

  • Connected Networks
  • 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 <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="">] -a <account name=""> Name of the Account that contains the Specified vServer. -u <account user=""> User that is allowed to access the specified account the default is root -p <account password=""> password of the specified user -n <vserver name=""> vServer to be templatised or cloned. -f <asset definition="" file=""> (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 <repository directory=""> Location of the repository the default is /OVS/Repositories/* -w <working directory=""> Working directory where intermediate files will be copied. -d <destination directory=""> Directory where the template tgz will be created. Default is current directory -i <compute node="" ip=""> 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 "****************************************"

Originally posted on The Old Toxophilist blog.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha