Exalogic 2.0.1 Tea Break Snippets - Scripting Asset Creation

Posted by The Old Toxophilist on Oracle Blogs See other posts from Oracle Blogs or by The Old Toxophilist
Published on Fri, 21 Sep 2012 14:26:22 +0000 Indexed on 2012/09/21 15:46 UTC
Read the original article Hit count: 621

Filed under:

So far in this series we have looked at creating asset within the EMOC BUI but the Exalogic 2.0.1 installation also provide the Iaas cli as an alternative to most of the common functionality available within EMOC. The IaaS cli interface provides access to the functions that are available to a user logged into the BUI with the CloudUser Role.

As such not all functionality is available from the command line interface however having said that the IaaS cli provides all the functionality required to create the Assets within a specific Account (Tenure). Because these action are common and repeatable I decided to wrap the functionality within a simple script that takes a simple input file and creates the Asset.

Following the Script through will show us the required steps needed to create the various Assets within an Account and hence I will work through the various functions within the script below describing the steps.

You will note from the various steps within the script that it is designed to pause between actions allowing the proceeding action to complete. The reason for this is because we could swamp EMOC with a series of actions and may end up with a situation where we are trying to action a Volume attached before the creation of the vServer and Volume have completed.

processAssets()

This function simply reads through the passed input file identifying what assets need to be created. An example of the input file can be found below. It can be seen that the input file can be used to create Assets in multiple Accounts during a single run. The order of the entries define the functions that need to be actioned as follows:

Input Command
Iaas Actions
Parameters
Production:Connect
  1. akm-describe-accounts
  2. akm-create-access-key
  3. iaas-create-key-pair
  4. iaas-describe-vnets
  5. iaas-describe-vserver-types
  6. iaas-describe-server-templates
  1. Username
  2. Password
Production:Create|vServer
  1. iaas-run-vserver
  1. vServer Name
  2. vServer Type Name
  3. Template Name
  4. Comma separated list of network names which the vServer will connect to.
  5. Comma separated list of IPs for the specified networks.
Production:Create|Volume
  1. iaas-create-volume
  1. Volume Name
  2. Volume Size
Production:Attach|Volume
  1. iaas-attach-volumes-to-vserver
  1. vServer Name
  2. Comma separated list of volume names
Production:Disconnect
  1. iaas-delete-key-pair
  2. akm-delete-access-key
None

connectToAccount()

It can be seen from the connectToAccount function that before we can execute any Asset creation we must first connect to the appropriate account. To do this we will need the ID associated with the Account. This can be found by executing the akm-describe-accounts cli command which will return a list of all Accounts and there IDs. Once we have the Account ID we generate and Access key using the akm-create-access-key command and then a keypair with the iaas-create-key-pair command.

At this point we now have all the information we need to access the specific named account.

createVServer()

This function simply retrieved the information from the input line and then will create the vServer using the iaas-run-vserver cli command. Reading the function you will notice that it takes the various input names for vServer Type, Template and Networks and converts them into the appropriate IDs. The IaaS cli will not work directly with component names and hence all IDs need to be found.

createVolume()

Function that simply takes the Volume name and Size then executes the iaas-create-volume command to create the volume.

attachVolume()

Takes the name of the Volume, which we may have just created, and a Volume then identifies the appropriate IDs before assigning the Volume to the vServer with the iaas-attach-volumes-to-vserver.

disconnectFromAccount()

Once we have finished connecting to the Account we simply remove the key pair with iaas-delete-key-pair and the access key with akm-delete-access-key although it may be useful to keep this if ssh is required and you do not subsequently modify the sshd information to allow unsecured access. By default the key is required for ssh access when a vServer is created from the command-line.

CreateAssets.sh

  1 export OCCLI=/opt/sun/occli/bin
  2 export IAAS_HOME=/opt/oracle/iaas/cli
  3 export JAVA_HOME=/usr/java/latest
  4 export IAAS_BASE_URL=https://127.0.0.1
  5 export IAAS_ACCESS_KEY_FILE=iaas_access.key
  6 export KEY_FILE=iaas_access.pub
  7 #CloudUser used to create vServers & Volumes
  8 export IAAS_USER=exaprod
  9 export IAAS_PASSWORD_FILE=root.pwd
 10 export KEY_NAME=cli.recreate
 11 export INPUT_FILE=CreateAssets.in
 12 
 13 export ACCOUNTS_FILE=accounts.out
 14 export VOLUMES_FILE=volumes.out
 15 export DISTGRPS_FILE=distgrp.out
 16 export VNETS_FILE=vnets.out
 17 export VSERVER_TYPES_FILE=vstype.out
 18 export VSERVER_FILE=vserver.out
 19 export VSERVER_TEMPLATES=template.out
 20 export KEY_PAIRS=keypairs.out
 21 
 22 PROCESSING_ACCOUNT=""
 23 
 24 function cleanTempFiles() {
 25         rm -f $ACCOUNTS_FILE $VOLUMES_FILE $DISTGRPS_FILE $VNETS_FILE $VSERVER_TYPES_FILE $VSERVER_FILE $VSERVER_TEMPLATES $KEY_PAIRS $IAAS_PASSWORD_FILE $KEY_FILE $IAAS_ACCESS_KEY_FILE
 26 }
 27 
 28 function connectToAccount() {
 29         if [[ "$ACCOUNT" != "$PROCESSING_ACCOUNT" ]]
 30         then
 31                 if [[ "" != "$PROCESSING_ACCOUNT" ]]
 32                 then
 33                         $IAAS_HOME/bin/iaas-delete-key-pair --key-name $KEY_NAME --access-key-file $IAAS_ACCESS_KEY_FILE
 34                         $IAAS_HOME/bin/akm-delete-access-key $AK
 35                 fi
 36                 PROCESSING_ACCOUNT=$ACCOUNT
 37                 IAAS_USER=$ACCOUNT_USER
 38                 echo "$ACCOUNT_PASSWORD" > $IAAS_PASSWORD_FILE
 39                 $IAAS_HOME/bin/akm-describe-accounts --sep "|" > $ACCOUNTS_FILE
 40                 while read line
 41                 do
 42                         ACCOUNT_ID=${line%%|*}
 43                         line=${line#*|}
 44                         ACCOUNT_NAME=${line%%|*}
 45         #               echo "Id = $ACCOUNT_ID"
 46         #               echo "Name = $ACCOUNT_NAME"
 47                         if [[ "$ACCOUNT_NAME" == "$ACCOUNT" ]]
 48                         then
 49                                 echo "Found Production Account $line"
 50                                 AK=`$IAAS_HOME/bin/akm-create-access-key --account $ACCOUNT_ID --access-key-file $IAAS_ACCESS_KEY_FILE`
 51                                 KEYPAIR=`$IAAS_HOME/bin/iaas-create-key-pair --key-name $KEY_NAME --key-file $KEY_FILE`
 52                                 echo "Connected to $ACCOUNT_NAME"
 53                                 break
 54                         fi                              
 55                 done < $ACCOUNTS_FILE   
 56         fi
 57 }
 58 
 59 function disconnectFromAccount() {
 60                 $IAAS_HOME/bin/iaas-delete-key-pair --key-name $KEY_NAME --access-key-file $IAAS_ACCESS_KEY_FILE
 61                 $IAAS_HOME/bin/akm-delete-access-key $AK
 62                 PROCESSING_ACCOUNT=""
 63 }
 64 
 65 function getNetworks() {
 66         $IAAS_HOME/bin/iaas-describe-vnets --sep "|" > $VNETS_FILE
 67 }
 68 
 69 function getVSTypes() {
 70         $IAAS_HOME/bin/iaas-describe-vserver-types --sep "|" > $VSERVER_TYPES_FILE
 71 }
 72 
 73 function getTemplates() {
 74         $IAAS_HOME/bin/iaas-describe-server-templates --sep "|" > $VSERVER_TEMPLATES
 75 }
 76 
 77 function getVolumes() {
 78         $IAAS_HOME/bin/iaas-describe-volumes --sep "|" > $VOLUMES_FILE
 79 }
 80 
 81 function getVServers() {
 82         $IAAS_HOME/bin/iaas-describe-vservers --sep "|" > $VSERVER_FILE
 83 }
 84 
 85 function getNetworkId() {
 86         while read line
 87         do
 88                 NETWORK_ID=${line%%|*}
 89                 line=${line#*|}
 90                 NAME=${line%%|*}
 91                 if [[ "$NAME" == "$NETWORK_NAME" ]]
 92                 then
 93                         break
 94                 fi
 95         done < $VNETS_FILE
 96 }
 97 
 98 function getVSTypeId() {
 99         while read line
100         do
101                 VSTYPE_ID=${line%%|*}
102                 line=${line#*|}
103                 NAME=${line%%|*}
104                 if [[ "$VSTYPE_NAME" == "$NAME" ]]
105                 then
106                         break
107                 fi
108         done < $VSERVER_TYPES_FILE
109 }
110 
111 function getTemplateId() {
112         while read line
113         do
114                 TEMPLATE_ID=${line%%|*}
115                 line=${line#*|}
116                 NAME=${line%%|*}
117                 if [[ "$TEMPLATE_NAME" == "$NAME" ]]
118                 then
119                         break
120                 fi
121         done < $VSERVER_TEMPLATES
122 }
123 
124 function getVolumeId() {
125         while read line
126         do
127                 export VOLUME_ID=${line%%|*}
128                 line=${line#*|}
129                 NAME=${line%%|*}
130                 if [[ "$NAME" == "$VOLUME_NAME" ]]
131                 then
132                         break;
133                 fi
134         done < $VOLUMES_FILE
135 }
136 
137 function getVServerId() {
138         while read line
139         do
140                 VSERVER_ID=${line%%|*}
141                 line=${line#*|}
142                 NAME=${line%%|*}
143                 if [[ "$VSERVER_NAME" == "$NAME" ]]
144                 then
145                         break;
146                 fi
147         done < $VSERVER_FILE
148 }
149 
150 function getVServerState() {
151         getVServers
152         while read line
153         do
154                 VSERVER_ID=${line%%|*}
155                 line=${line#*|}
156                 NAME=${line%%|*}
157                 line=${line#*|}
158                 line=${line#*|}
159                 VSERVER_STATE=${line%%|*}
160                 if [[ "$VSERVER_NAME" == "$NAME" ]]
161                 then
162                         break;
163                 fi
164         done < $VSERVER_FILE
165 }
166 
167 function pauseUntilVServerRunning() {
168         # Wait until the Server is running before creating the next
169   getVServerState
170   while [[ "$VSERVER_STATE" != "RUNNING" ]]
171   do
172         getVServerState
173         echo "$NAME $VSERVER_STATE"
174         if [[ "$VSERVER_STATE" != "RUNNING" ]]
175         then
176                 echo "Sleeping......."
177                 sleep 60
178         fi
179         if [[ "$VSERVER_STATE" == "FAILED" ]]
180         then
181                 echo "Will Delete $NAME in 5 Minutes....."
182                 sleep 300
183                 deleteVServer
184                 echo "Deleted $NAME waiting 5 Minutes....."
185                 sleep 300
186                 break
187         fi
188   done
189   # Lets pause for a minute or two
190   echo "Just Chilling......"
191   sleep 60
192   echo "Ahhhhh we're getting there......."
193   sleep 60
194   echo "I'm almost at one with the universe......."
195   sleep 60
196   echo "Bong Reality Check !"
197 }
198 
199 function deleteVServer() {
200         $IAAS_HOME/bin/iaas-terminate-vservers --force --vserver-ids $VSERVER_ID
201 }
202 
203 function createVServer() {
204         VSERVER_NAME=${ASSET_DETAILS%%|*}
205         ASSET_DETAILS=${ASSET_DETAILS#*|}
206         VSTYPE_NAME=${ASSET_DETAILS%%|*}
207         ASSET_DETAILS=${ASSET_DETAILS#*|}
208         TEMPLATE_NAME=${ASSET_DETAILS%%|*}
209         ASSET_DETAILS=${ASSET_DETAILS#*|}
210         NETWORK_NAMES=${ASSET_DETAILS%%|*}
211         ASSET_DETAILS=${ASSET_DETAILS#*|}
212         IP_ADDRESSES=${ASSET_DETAILS%%|*}
213         # Get Ids associated with names
214         getVSTypeId
215         getTemplateId
216         # Convert Network Names to Ids
217         NETWORK_IDS=""
218         while true
219         do
220                 NETWORK_NAME=${NETWORK_NAMES%%,*}
221                 NETWORK_NAMES=${NETWORK_NAMES#*,}
222                 getNetworkId
223                 if [[ "$NETWORK_IDS" != "" ]]
224                 then
225                         NETWORK_IDS="$NETWORK_IDS,$NETWORK_ID"
226                 else
227                         NETWORK_IDS=$NETWORK_ID
228                 fi
229                 if [[ "$NETWORK_NAME" == "$NETWORK_NAMES" ]]
230                 then
231                         break
232                 fi
233         done
234         # Create vServer
235         echo "About to execute : $IAAS_HOME/bin/iaas-run-vserver --name $VSERVER_NAME --key-name $KEY_NAME --vserver-type $VSTYPE_ID --server-template-id $TEMPLATE_ID --vnets $NETWORK_IDS --ip-addresses $IP_ADDRESSES"
236         $IAAS_HOME/bin/iaas-run-vserver --name $VSERVER_NAME --key-name $KEY_NAME --vserver-type $VSTYPE_ID --server-template-id $TEMPLATE_ID --vnets $NETWORK_IDS --ip-addresses $IP_ADDRESSES
237         pauseUntilVServerRunning
238 }
239 
240 function createVolume() {
241         VOLUME_NAME=${ASSET_DETAILS%%|*}
242         ASSET_DETAILS=${ASSET_DETAILS#*|}
243         VOLUME_SIZE=${ASSET_DETAILS%%|*}
244         # Create Volume
245         echo "About to execute : $IAAS_HOME/bin/iaas-create-volume --name $VOLUME_NAME --size $VOLUME_SIZE"
246         $IAAS_HOME/bin/iaas-create-volume --name $VOLUME_NAME --size $VOLUME_SIZE
247   # Lets pause
248   echo "Just Waiting 30 Seconds......"
249   sleep 30
250 }
251 
252 function attachVolume() {
253         VSERVER_NAME=${ASSET_DETAILS%%|*}
254         ASSET_DETAILS=${ASSET_DETAILS#*|}
255         VOLUME_NAMES=${ASSET_DETAILS%%|*}
256         # Get vServer Id
257         getVServerId
258         # Convert Volume Names to Ids
259         VOLUME_IDS=""
260         while true
261         do
262                 VOLUME_NAME=${VOLUME_NAMES%%,*}
263                 VOLUME_NAMES=${VOLUME_NAMES#*,}
264                 getVolumeId
265                 if [[ "$VOLUME_IDS" != "" ]]
266                 then
267                         VOLUME_IDS="$VOLUME_IDS,$VOLUME_ID"
268                 else
269                         VOLUME_IDS=$VOLUME_ID
270                 fi
271                 if [[ "$VOLUME_NAME" == "$VOLUME_NAMES" ]]
272                 then
273                         break
274                 fi
275         done
276         # Attach Volumes
277         echo "About to execute : $IAAS_HOME/bin/iaas-attach-volumes-to-vserver --vserver-id $VSERVER_ID --volume-ids $VOLUME_IDS"
278         $IAAS_HOME/bin/iaas-attach-volumes-to-vserver --vserver-id $VSERVER_ID --volume-ids $VOLUME_IDS
279   # Lets pause
280   echo "Just Waiting 30 Seconds......"
281   sleep 30
282 }
283 
284 function processAssets() {
285         while read line
286         do
287                 ACCOUNT=${line%%:*}
288                 line=${line#*:}
289                 ACTION=${line%%|*}
290                 line=${line#*|}
291                 if [[ "$ACTION" == "Connect" ]]
292                 then
293                         ACCOUNT_USER=${line%%|*}
294                         line=${line#*|}
295                         ACCOUNT_PASSWORD=${line%%|*}
296                         connectToAccount
297                         
298                         ## Account Info
299                         getNetworks
300                         getVSTypes
301                         getTemplates
302                         
303                         continue
304                 fi
305                 if [[ "$ACTION" == "Create" ]]
306                 then
307                         ASSET=${line%%|*}
308                         line=${line#*|}
309                         ASSET_DETAILS=$line
310                         if [[ "$ASSET" == "vServer" ]]
311                         then
312                                 createVServer
313                                 
314                                 continue
315                         fi
316                         if [[ "$ASSET" == "Volume" ]]
317                         then
318                                 createVolume
319                                 
320                                 continue
321                         fi
322                 fi
323                 if [[ "$ACTION" == "Attach" ]]
324                 then
325                         ASSET=${line%%|*}
326                         line=${line#*|}
327                         ASSET_DETAILS=$line
328                         if [[ "$ASSET" == "Volume" ]]
329                         then
330                                 getVolumes
331                                 getVServers
332                                 attachVolume
333                                 
334                                 continue
335                         fi
336                 fi
337                 if [[ "$ACTION" == "Connect" ]]
338                 then
339                         disconnectFromAccount
340                                 
341                         continue
342                 fi
343         done < $INPUT_FILE
344 }
345 
346 # Should Parameterise this
347 
348 while [ $# -gt 0 ]
349 do
350         case "$1" in    
351                 -a) INPUT_FILE="$2"; shift;;
352                 *) echo ""; echo >&2 \
353                     "usage: $0 [-a <Asset Definition File>] (Default is CreateAssets.in)"
354                     echo""; exit 1;;
355                 *) break;;
356         esac
357         shift
358 done
359 
360 
361 
362 
363 processAssets
364 
365 echo "**************************************"
366 echo "*****  Finished Creating Assets  *****"
367 echo "**************************************"
368 

CreateAssetsProd.in

Production:Connect|exaprod|welcome1

Production:Create|vServer|VS006|VSTProduction|BaseOEL56ServerTemplate|EoIB-otd-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.223.13,192.168.0.13,10.117.81.67,172.17.0.14
Production:Create|vServer|VS007|VSTProduction|BaseOEL56ServerTemplate|EoIB-otd-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.223.14,192.168.0.14,10.117.81.68,172.17.0.15
Production:Create|vServer|VS008|VSTProduction|BaseOEL56ServerTemplate|EoIB-wls-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.225.61,192.168.0.61,10.117.81.61,172.17.0.16
Production:Create|vServer|VS009|VSTProduction|BaseOEL56ServerTemplate|EoIB-wls-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.225.62,192.168.0.62,10.117.81.62,172.17.0.17
Production:Create|vServer|VS000|VSTProduction|BaseOEL56ServerTemplate|EoIB-wls-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.225.63,192.168.0.63,10.117.81.63,172.17.0.18
Production:Create|vServer|VS001|VSTProduction|BaseOEL56ServerTemplate|EoIB-wls-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.225.64,192.168.0.64,10.117.81.64,172.17.0.19
Production:Create|vServer|VS002|VSTProduction|BaseOEL56ServerTemplate|EoIB-wls-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.225.65,192.168.0.65,10.117.81.65,172.17.0.20
Production:Create|vServer|VS003|VSTProduction|BaseOEL56ServerTemplate|EoIB-wls-prod,vn-prod-web,IPoIB-default,IPoIB-vserver-shared-storage|10.51.225.66,192.168.0.66,10.117.81.66,172.17.0.21

Production:Create|Volume|VS006|50
Production:Create|Volume|VS007|50
Production:Create|Volume|VS008|50
Production:Create|Volume|VS009|50
Production:Create|Volume|VS000|50
Production:Create|Volume|VS001|50
Production:Create|Volume|VS002|50
Production:Create|Volume|VS003|50

Production:Attach|Volume|VS006|VS006
Production:Attach|Volume|VS007|VS007
Production:Attach|Volume|VS008|VS008
Production:Attach|Volume|VS009|VS009
Production:Attach|Volume|VS000|VS000
Production:Attach|Volume|VS001|VS001
Production:Attach|Volume|VS002|VS002
Production:Attach|Volume|VS003|VS003

Production:Disconnect

Development:Connect|exadev|welcome1

Development:Create|vServer|VS014|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.24,10.117.81.71,172.17.0.24
Development:Create|vServer|VS015|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.25,10.117.81.72,172.17.0.25
Development:Create|vServer|VS016|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.26,10.117.81.73,172.17.0.26
Development:Create|vServer|VS017|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.27,10.117.81.74,172.17.0.27
Development:Create|vServer|VS018|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.28,10.117.81.75,172.17.0.28
Development:Create|vServer|VS019|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.29,10.117.81.76,172.17.0.29
Development:Create|vServer|VS020|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.30,10.117.81.77,172.17.0.30
Development:Create|vServer|VS021|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.31,10.117.81.78,172.17.0.31
Development:Create|vServer|VS022|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.32,10.117.81.79,172.17.0.32
Development:Create|vServer|VS023|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.33,10.117.81.80,172.17.0.33
Development:Create|vServer|VS024|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.34,10.117.81.81,172.17.0.34
Development:Create|vServer|VS025|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.35,10.117.81.82,172.17.0.35
Development:Create|vServer|VS026|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.36,10.117.81.83,172.17.0.36
Development:Create|vServer|VS027|VSTDevelopment|BaseOEL56ServerTemplate|EoIB-development,IPoIB-default,IPoIB-vserver-shared-storage|10.51.224.37,10.117.81.84,172.17.0.37


Development:Create|Volume|VS014|50
Development:Create|Volume|VS015|50
Development:Create|Volume|VS016|50
Development:Create|Volume|VS017|50
Development:Create|Volume|VS018|50
Development:Create|Volume|VS019|50
Development:Create|Volume|VS020|50
Development:Create|Volume|VS021|50
Development:Create|Volume|VS022|50
Development:Create|Volume|VS023|50
Development:Create|Volume|VS024|50
Development:Create|Volume|VS025|50
Development:Create|Volume|VS026|50
Development:Create|Volume|VS027|50

Development:Attach|Volume|VS014|VS014
Development:Attach|Volume|VS015|VS015
Development:Attach|Volume|VS016|VS016
Development:Attach|Volume|VS017|VS017
Development:Attach|Volume|VS018|VS018
Development:Attach|Volume|VS019|VS019
Development:Attach|Volume|VS020|VS020
Development:Attach|Volume|VS021|VS021
Development:Attach|Volume|VS022|VS022
Development:Attach|Volume|VS023|VS023
Development:Attach|Volume|VS024|VS024
Development:Attach|Volume|VS025|VS025
Development:Attach|Volume|VS026|VS026
Development:Attach|Volume|VS027|VS027

Development:Disconnect


This entry was originally posted on the The Old Toxophilist Site.

© Oracle Blogs or respective owner

Related posts about /A-Team