Dev compute script generation
[osm/openvim.git] / scripts / host-add-develop.sh
1
2 #!/bin/bash
3
4 ##
5 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6 # This file is part of openvim
7 # All Rights Reserved.
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
12 #
13 # http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
19 # under the License.
20 #
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact with: nfvlabs@tid.es
23 ##
24
25 #Get configuration of a host for using it as a compute node
26
27 function usage(){
28
29 echo -e "\nUsage: $0 --user <user> --ip=<X.X.X.X> --cores=<core_number> --huge-pages-1G=<huga_pages_number> --nb-10GB-interfaces==<interface_number>"
30 echo -e "Generate a develop host yaml to be used for openvim host-add\n"
31 echo -e " --user -u <user> Server OAM Ip"
32 echo -e " --ip -i <ip> Server hostname"
33 echo -e " --cores -c <cores> Numa Cores available must be an odd number and bigger or equal to 4."
34 echo -e " --huge-pages-1G -hp <huge_pages_number> Must be an odd number and bigger or equal to 16. 4GiB of memory will be reserved for the host OS, the rest will be used by VM."
35 echo -e " --nb-10GB-interfaces -ni <nb-10GB-interfaces> Dataplane interfaces must be an odd number and bigger or equal to 4."
36 echo -e "\n"
37 echo -e "The output will be a server descriptor with two numas and resources (memory, cores and interfaces) equally distributed between them."
38 echo -e "Each interface (physical funtion) will have defined 8 SR-IOV (virtual functions)."
39 echo -e "\n"
40 exit 1
41 }
42
43 function get_hash_value() { echo `eval echo $\{\`echo $USER[$IP]\`\}`; }
44
45 function get_mac(){
46 seed=$1
47 b1=$((seed%16)); seed=$((seed/16))
48 b2=$((seed%16)); seed=$((seed/16))
49 b3=$((seed%16)); seed=$((seed/16))
50 b4=$((seed%16)); seed=$((seed/16))
51 b5=$((seed%16)); seed=$((seed/16))
52 mac=`printf "%02X:%02X:%02X:%02X:%02X:%02X" 2 $b5 $b4 $b3 $b2 $b1`
53 echo $mac
54 }
55
56 function _parse_opts(){
57
58 #help argument
59 if [ -n "$option_help" ];
60 then
61 usage
62 fi
63
64 #User argument
65 [ -z "$option_user" ] && echo -e "ERROR: User argument is mandatory, --user=<user>\n" && usage
66 USER=${option_user}
67
68 [ -z "$option_ip" ] && echo -e "ERROR: OAM IP argument is mandatory, --ip=<X.X.X.X>\n" && usage
69 IP=${option_ip}
70
71 #TODO to be checl diference between real cores an numa cores
72 #cores argument
73 REAL_CORES=$(grep -c "^processor" "/proc/cpuinfo")
74 if [ -z "$option_cores" ] ; then
75 CORES=REAL_CORES
76 else
77 CORES=${option_cores}
78 fi
79
80 #Ensure the core user input is big enough
81 ([ $((CORES%2)) -ne 0 ]) && echo -e "ERROR: Wrong number of cores\n" && usage
82
83 MEMORY=$(($(grep MemTotal /proc/meminfo | awk '{print $2}') /1024/1024))
84 if [ -z "$option_huge_pages_1G" ] ; then
85 HUGE_PAGES_MEMORY=0
86 else
87 HUGE_PAGES_MEMORY=${option_huge_pages_1G}
88 fi
89 #Ensure the memory user input is big enough
90 #([ $((MEMORY%2)) -ne 0 ] || [ $MEMORY -lt 16 ] ) && echo -e "ERROR: Wrong number of memory\n" && usage
91
92 #nb_10GB_interfaces argument
93 if [ -z "$nb_10GB_interfaces" ] ; then
94 INTERFACES=8
95 else
96 INTERFACES=${nb_10GB_interfaces}
97 fi
98 ([ $((INTERFACES%2)) -ne 0 ] || [ $INTERFACES -lt 4 ] ) && echo -e "ERROR: Wrong number of interfaces\n" && usage
99
100 # Parameter by default
101 NUMAS=1
102 ([ $((NUMAS%2)) -ne 0 ]) && NUMAS=1
103 }
104
105 function _generate_compute_develope_yaml(){
106
107 _yaml_init
108
109 FEATURES_LIST="lps,dioc,hwsv,tlbps,ht,lps,64b,iommu"
110
111 #Generate a cpu topology for 4 numas with hyperthreading
112 #in this developing/fake server all cores can be used
113 #TODO check if this calculation is correct
114 echo2file "#This file was created by $0"
115 echo2file "#for adding this compute node to openvim"
116 echo2file "#copy this file to openvim controller and run"
117 echo2file "#openvim host-add <this>"
118 echo2file
119 echo2file "host:"
120 echo2file " name: $HOST_NAME"
121 echo2file " user: $USER"
122 echo2file " ip_name: $IP"
123 echo2file "host-data:"
124 echo2file " name: $HOST_NAME"
125 echo2file " user: $USER"
126 echo2file " ip_name: $IP"
127 echo2file " ranking: 100"
128 echo2file " description: $HOST_NAME"
129 echo2file " features: $FEATURES_LIST"
130 echo2file " numas:"
131
132 numa=0
133 last_iface=0
134 iface_counter=0
135
136 while [ $numa -lt $NUMAS ]
137 do
138
139 HUGE_PAGES=$((HUGE_PAGES_MEMORY/2-2))
140 ([ ${HUGE_PAGES} -lt -1 ]) && HUGE_PAGES=0
141
142 echo2file " - numa_socket: $numa"
143 #MEMORY
144 echo2file " hugepages: $((HUGE_PAGES))"
145 echo2file " memory: $((MEMORY/$NUMAS))"
146 #CORES
147 echo2file " cores:"
148
149 for((n_core=0;n_core<$REAL_CORES;n_core++))
150 do
151 THREAD_ID=$(($n_core+1))
152 CORE_ID=$(($((${n_core}+${numa}))/2))
153 echo2file " - core_id: ${CORE_ID}"
154 echo2file " thread_id: ${THREAD_ID}"
155 [ $CORE_ID -eq 0 ] && echo2file " status: noteligible"
156
157 thread_counter=$((thread_counter+1))
158 done
159 # GENERATE INTERFACES INFORMATION AND PRINT IT
160 seed=$RANDOM
161 echo2file " interfaces:"
162 for ((iface=0;iface<$INTERFACES;iface+=2))
163 do
164 name="iface$iface_counter"
165 bus=$((iface+last_iface))
166 bus=$((iface))
167 pci=`printf "0000:%02X:00.0" $bus`
168 mac=`get_mac $seed`
169 seed=$((seed+1))
170
171 echo2file " - source_name: $name"
172 echo2file " Mbps: 10000"
173 echo2file " pci: \"$pci\""
174 echo2file " mac: \"$mac\""
175 echo2file " sriovs:"
176
177 PCI_COUNTER=0
178 for((nb_sriov=0;nb_sriov<8;nb_sriov++))
179 do
180 #PCI_COUNTER=$((PCI_COUNTER+2))
181 #echo2file "nb_sriov "$nb_sriov
182 #echo2file "PCI_COUNTER "$PCI_COUNTER
183
184 pci=`printf "0000:%02X:10.%i" $bus $nb_sriov`
185 mac=`get_mac $seed`
186 seed=$((seed+1))
187 echo2file " - source_name: eth$nb_sriov"
188 echo2file " mac: \"$mac\""
189 echo2file " pci: \"$pci\""
190 done
191 iface_counter=$((iface_counter+1))
192 done
193 last_iface=$(((numa+1)*127/NUMAS+5)) #made-up formula for more realistic pci numbers
194 numa=$((numa+1))
195 done
196 }
197
198 function _yaml_init(){
199 echo -n > host-develope.yaml
200 }
201
202 function echo2file(){
203 echo "${1}"
204 echo "${1}" >> host-develope.yaml
205 }
206
207 function _get_opts()
208 {
209 [[ ${BASH_SOURCE[0]} != $0 ]] && ___exit="return" || ___exit="exit"
210
211 options="$1"
212 shift
213
214 get_argument=""
215 #reset variables
216 params=""
217 for option_group in $options
218 do
219 _name=${option_group%%:*}
220 _name=${_name%=}
221 _name=${_name//-/_}
222 eval option_${_name}='""'
223 done
224
225 while [[ $# -gt 0 ]]
226 do
227 argument="$1"
228 shift
229 if [[ -n $get_argument ]]
230 then
231 [[ ${argument:0:1} == "-" ]] && echo "option '-$option' requires an argument" >&2 && $___exit 1
232 eval ${get_argument}='"$argument"'
233 #echo option $get_argument with argument
234 get_argument=""
235 continue
236 fi
237
238
239 #short options
240 if [[ ${argument:0:1} == "-" ]] && [[ ${argument:1:1} != "-" ]] && [[ ${#argument} -ge 2 ]]
241 then
242 index=0
243 while index=$((index+1)) && [[ $index -lt ${#argument} ]]
244 do
245 option=${argument:$index:1}
246 bad_option=y
247 for option_group in $options
248 do
249 _name=""
250 for o in $(echo $option_group | tr ":=" " ")
251 do
252 [[ -z "$_name" ]] && _name=${o//-/_}
253 #echo option $option versus $o
254 if [[ "$option" == "${o}" ]]
255 then
256 eval option_${_name}='${option_'${_name}'}-'
257 bad_option=n
258 if [[ ${option_group:${#option_group}-1} != "=" ]]
259 then
260 continue
261 fi
262 if [[ ${#argument} -gt $((index+1)) ]]
263 then
264 eval option_${_name}='"${argument:$((index+1))}"'
265 index=${#argument}
266 else
267 get_argument=option_${_name}
268 #echo next should be argument $argument
269 fi
270
271 break
272 fi
273 done
274 done
275 [[ $bad_option == y ]] && echo "invalid argument '-$option'? Type -h for help" >&2 && $___exit 1
276 done
277 elif [[ ${argument:0:2} == "--" ]] && [[ ${#argument} -ge 3 ]]
278 then
279 option=${argument:2}
280 option_argument=${option#*=}
281 option_name=${option%%=*}
282 [[ "$option_name" == "$option" ]] && option_argument=""
283 bad_option=y
284 for option_group in $options
285 do
286 _name=""
287 for o in $(echo $option_group | tr ":=" " ")
288 do
289 [[ -z "$_name" ]] && _name=${o//-/_}
290 #echo option $option versus $o
291 if [[ "$option_name" == "${o}" ]]
292 then
293 bad_option=n
294 if [[ ${option_group:${#option_group}-1} != "=" ]]
295 then #not an argument
296 [[ -n "${option_argument}" ]] && echo "option '--${option%%=*}' do not accept an argument " >&2 && $___exit 1
297 eval option_${_name}='"${option_'${_name}'}-"'
298 elif [[ -n "${option_argument}" ]]
299 then
300 eval option_${_name}='"${option_argument}"'
301 else
302 get_argument=option_${_name}
303 #echo next should be argument $argument
304 fi
305 break
306 fi
307 done
308 done
309 [[ $bad_option == y ]] && echo "invalid argument '-$option'? Type -h for help" >&2 && $___exit 1
310 elif [[ ${argument:0:2} == "--" ]]
311 then
312 option__="$*"
313 bad_option=y
314 for o in $options
315 do
316 if [[ "$o" == "--" ]]
317 then
318 bad_option=n
319 option__=" $*"
320 break
321 fi
322 done
323 [[ $bad_option == y ]] && echo "invalid argument '--'? Type -h for help" >&2 && $___exit 1
324 break
325 else
326 params="$params ${argument}"
327 fi
328
329 done
330
331 [[ -n "$get_argument" ]] && echo "option '-$option' requires an argument" >&2 && $___exit 1
332 $___exit 0
333
334 }
335
336 #check root privileges and non a root user behind
337 [ "${USER}" != "root" ] && echo "Needed root privileges" && _usage && exit -1
338
339 #process options
340 DIRNAME=$(readlink -f ${BASH_SOURCE[0]})
341 DIRNAME=$(dirname $DIRNAME)
342
343 #source ${DIRNAME}/get-options.sh "help:h user:u= ip:i= cores:c= huge-pages-1G:hp= nb-10GB-interfaces:ni=" $*
344 _get_opts "help:h user:u= ip:i= cores:c= huge-pages-1G:hp= nb-10GB-interfaces:ni=" $*
345 _parse_opts
346
347 HOST_NAME=`cat /etc/hostname`
348
349 _generate_compute_develope_yaml
350