| Leonardo | d9cd596 | 2016-11-17 14:33:07 +0100 | [diff] [blame^] | 1 | |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 2 | #!/bin/bash |
| 3 | |
| 4 | ## |
| 5 | # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U. |
| tierno | 9a61c6b | 2016-09-08 10:57:02 +0200 | [diff] [blame] | 6 | # This file is part of openvim |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 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(){ |
| Leonardo | d9cd596 | 2016-11-17 14:33:07 +0100 | [diff] [blame^] | 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" |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 40 | exit 1 |
| 41 | } |
| 42 | |
| Leonardo | d9cd596 | 2016-11-17 14:33:07 +0100 | [diff] [blame^] | 43 | function get_hash_value() { echo `eval echo $\{\`echo $USER[$IP]\`\}`; } |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 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 | |
| Leonardo | d9cd596 | 2016-11-17 14:33:07 +0100 | [diff] [blame^] | 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 | } |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 335 | |
| 336 | #check root privileges and non a root user behind |
| Leonardo | d9cd596 | 2016-11-17 14:33:07 +0100 | [diff] [blame^] | 337 | [ "${USER}" != "root" ] && echo "Needed root privileges" && _usage && exit -1 |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 338 | |
| Leonardo | d9cd596 | 2016-11-17 14:33:07 +0100 | [diff] [blame^] | 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 | |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 347 | HOST_NAME=`cat /etc/hostname` |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 348 | |
| Leonardo | d9cd596 | 2016-11-17 14:33:07 +0100 | [diff] [blame^] | 349 | _generate_compute_develope_yaml |
| tierno | f7aa8c4 | 2016-09-06 16:43:04 +0200 | [diff] [blame] | 350 | |