2 ##############################################################################
3 # Copyright (c) 2015 Ericsson AB and others.
4 # stefan.k.berg@ericsson.com
5 # jonas.bjurel@ericsson.com
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10 ##############################################################################
14 ########################################################################
15 # Internal functions BEGIN
27 echo "Exit with code $rc" >&2
36 if [ $rc -ne 0 ]; then
37 dha_f_err $rc "running $@" >&2
55 ipmiIp=$($DHAPARSE $DHAFILE getNodeProperty $nodeId ipmiIp)
56 ipmiUser=$($DHAPARSE $DHAFILE getNodeProperty $nodeId ipmiUser)
57 ipmiPass=$($DHAPARSE $DHAFILE getNodeProperty $nodeId ipmiPass)
59 test -n "$ipmiIp" || error_exit "Could not get IPMI IP"
60 test -n "$ipmiUser" || error_exit "Could not get IPMI username"
61 test -n "$ipmiPass" || error_exit "Could not get IPMI password"
63 # Repeat three times for good measure (some hardware seems
67 ipmitool -I lanplus -A password -H $ipmiIp -U $ipmiUser -P $ipmiPass \
71 ipmitool -I lanplus -A password -H $ipmiIp -U $ipmiUser -P $ipmiPass \
75 # Internal functions END
76 ########################################################################
82 # API: Get the DHA API version supported by this adapter
88 # API: Get the name of this adapter
94 # API: ### Node identity functions ###
95 # API: Node numbering is sequential.
97 # API: Get a list of all defined node ids, sorted in ascending order
100 dha_f_run $DHAPARSE $DHAFILE getNodes | sort -n
104 # API: Get ID for Fuel node ID
107 for node in `dha_getAllNodeIds`
109 if [ -n "`dha_f_run $DHAPARSE $DHAFILE getNodeProperty $node isFuel`" ]
116 # API: Get node property
117 # API: Argument 1: node id
118 # API: Argument 2: Property
119 dha_getNodeProperty()
121 dha_f_run $DHAPARSE $DHAFILE getNodeProperty $1 $2
125 # API: Get MAC address for the PXE interface of this node. If not
126 # API: defined, an empty string will be returned.
127 # API: Argument 1: Node id
130 dha_getNodeProperty $1 pxeMac
134 ### Node operation functions ###
136 # API: Use custom installation method for Fuel master?
137 # API: Returns 0 if true, 1 if false
138 dha_useFuelCustomInstall()
140 $DHAPARSE $DHAFILE get fuelCustomInstall | grep -qi true
145 # API: Fuel custom installation method
146 # API: Leaving the Fuel master powered on and booting from ISO at exit
147 # API: Argument 1: Full path to ISO file to install
148 dha_fuelCustomInstall()
151 error_exit "Could not access ISO file $1"
154 dha_useFuelCustomInstall || dha_f_err 1 "dha_fuelCustomInstall not supported"
156 fuelIp=`dea getFuelIp` || error_exit "Could not get fuel IP"
157 fuelNodeId=`dha getFuelNodeId` || error_exit "Could not get fuel node id"
158 virtName=`$DHAPARSE $DHAFILE getNodeProperty $fuelNodeId libvirtName`
161 virsh destroy $virtName
165 fueldisk=`virsh dumpxml $virtName | \
166 grep "<source file" | grep raw | sed "s/.*'\(.*\)'.*/\1/"`
167 disksize=`ls -l $fueldisk | awk '{ print $5 }'`
169 fallocate -l $disksize $fueldisk
172 for order in disk iso
174 if [ "$order" == "pxe" ]; then
175 bootline+="<boot dev='network'\/>\n"
176 elif [ "$order" == "disk" ]; then
177 bootline+="<boot dev='hd'/\>\n"
178 elif [ "$order" == "iso" ]; then
179 bootline+="<boot dev='cdrom'/\>\n"
181 error_exit "Unknown boot type: $order"
185 virsh dumpxml $virtName | grep -v "<boot dev.*>" | \
187 ${bootline}" > $tmpdir/vm.xml || error_exit "Could not set bootorder"
188 virsh define $tmpdir/vm.xml || error_exit "Could not set bootorder"
191 # Get name of CD device
192 cdDev=`virsh domblklist $virtName | tail -n +3 | awk '{ print $1 }' | grep ^hd`
194 # Eject and insert ISO
195 virsh change-media $virtName --config --eject $cdDev
197 virsh change-media $virtName --config --insert $cdDev $1 || error_exit "Could not insert CD $1"
200 virsh start $virtName || error_exit "Could not start $virtName"
204 echo "Waiting for Fuel master to accept SSH"
207 ssh root@${fuelIp} date 2>/dev/null
208 if [ $? -eq 0 ]; then
214 # Wait until fuelmenu is up
215 echo "Waiting for fuelmenu to come up"
217 while [ -z "$menuPid" ]
219 menuPid=`ssh root@${fuelIp} "ps -ef" 2>&1 | grep fuelmenu | grep -v grep | awk '{ print $2 }'`
223 # This is where we inject our own astute.yaml settings
224 scp -q $deafile root@${fuelIp}:. || error_exit "Could not copy DEA file to Fuel"
225 echo "Uploading build tools to Fuel server"
226 ssh root@${fuelIp} rm -rf tools || error_exit "Error cleaning old tools structure"
227 scp -qrp $topdir/tools root@${fuelIp}:. || error_exit "Error copying tools"
228 echo "Running transplant #0"
229 ssh root@${fuelIp} "cd tools; ./transplant0.sh ../`basename $deafile`" \
230 || error_exit "Error running transplant sequence #0"
234 # Let the Fuel deployment continue
235 echo "Found menu as PID $menuPid, now killing it"
236 ssh root@${fuelIp} "kill $menuPid" 2>/dev/null
238 # Wait until installation complete
239 echo "Waiting for bootstrap of Fuel node to complete"
242 ssh root@${fuelIp} "ps -ef" 2>/dev/null \
243 | grep -q /usr/local/sbin/bootstrap_admin_node
244 if [ $? -ne 0 ]; then
250 echo "Waiting for one minute for Fuel to stabilize"
255 # API: Get power on strategy from DHA
256 # API: Returns one of two values:
257 # API: all: Power on all nodes simultaneously
258 # API: sequence: Power on node by node, wait for Fuel detection
259 dha_getPowerOnStrategy()
263 strategy=`$DHAPARSE $DHAFILE get powerOnStrategy`
265 if [ "$strategy" == "all" ]; then
268 [ "$strategy" == "sequence" ]; then
271 dha_f_err 1 "Could not parse strategy from DHA, got $strategy"
276 # API: Argument 1: node id
282 state=$(dha_f_ipmi $1 chassis power status) || error_exit "Could not get IPMI power status"
286 if [ "$(echo $state | sed 's/.* //')" == "off" ]; then
287 dha_f_ipmi $1 chassis power on
291 # API: Power off node
292 # API: Argument 1: node id
298 state=$(dha_f_ipmi $1 chassis power status) || error_exit "Could not get IPMI power status"
302 if [ "$(echo $state | sed 's/.* //')" != "off" ]; then
303 dha_f_ipmi $1 chassis power off
308 # API: Argument 1: node id
314 state=$(dha_f_ipmi $1 chassis power reset) || error_exit "Could not get IPMI power status"
318 if [ "$(echo $state | sed 's/.* //')" != "off" ]; then
319 dha_f_ipmi $1 chassis power reset
323 # Boot order and ISO boot file
325 # API: Is the node able to commit boot order without power toggle?
326 # API: Argument 1: node id
327 # API: Returns 0 if true, 1 if false
328 dha_nodeCanSetBootOrderLive()
333 # API: Set node boot order
334 # API: Argument 1: node id
335 # API: Argument 2: Space separated line of boot order - boot ids are "pxe", "disk" and "iso"
336 # Strategy for IPMI: Always set boot order to persistent except in the case of CDROM.
337 dha_nodeSetBootOrder()
346 if [ "$order" == "pxe" ]; then
347 dha_f_ipmi $id chassis bootdev pxe options=persistent || error_exit "Could not get IPMI power status"
348 elif [ "$order" == "iso" ]; then
349 dha_f_ipmi $id chassis bootdev cdrom || error_exit "Could not get IPMI power status"
350 elif [ "$order" == "disk" ]; then
351 dha_f_ipmi $id chassis bootdev disk options=persistent || error_exit "Could not get IPMI power status"
353 error_exit "Unknown boot type: $order"
357 # API: Is the node able to operate on ISO media?
358 # API: Argument 1: node id
359 # API: Returns 0 if true, 1 if false
365 # API: Is the node able to insert add eject ISO files without power toggle?
366 # API: Argument 1: node id
367 # API: Returns 0 if true, 1 if false
368 dha_nodeCanHandeIsoLive()
373 # API: Insert ISO into virtualDVD
374 # API: Argument 1: node id
375 # API: Argument 2: iso file
378 error_exit "Node can not handle InsertIso"
381 # API: Eject ISO from virtual DVD
382 # API: Argument 1: node id
385 error_exit "Node can not handle InsertIso"
388 # API: Wait until a suitable time to change the boot order to
389 # API: "disk iso" when ISO has been booted. Can't be too long, nor
391 # API: We should make a smart trigger for this somehow...
394 echo "waitForIsoBoot: Not used by ipmi"
397 # API: Is the node able to reset its MBR?
398 # API: Returns 0 if true, 1 if false
404 # API: Reset the node's MBR
407 error_exit "Node $1 does not support ZeroMBR"
411 # API: Entry point for dha functions
412 # API: Typically do not call "dha_node_zeroMBR" but "dha node_ZeroMBR"
414 # API: Before calling dha, the adapter file must gave been sourced with
415 # API: the DHA file name as argument
418 if [ -z "$DHAFILE" ]; then
419 error_exit "dha_setup has not been run"
423 if type dha_$1 &>/dev/null; then
429 error_exit "No such function dha_$1 defined"
433 if [ "$1" == "api" ]; then
434 egrep "^# API: |dha.*\(\)" $0 | sed 's/^# API: /# /' | grep -v dha_f_ | sed 's/)$/)\n/'
436 dhatopdir=$(dirname $(readlink -f $BASH_SOURCE))
437 DHAPARSE="$dhatopdir/dhaParse.py"
440 if [ ! -f $DHAFILE ]; then
441 error_exit "No such DHA file: $DHAFILE"
445 echo "DHAPARSE: $DHAPARSE"
446 echo "DHAFILE: $DHAFILE"