1*** Settings *** 2Resource ../lib/utils.robot 3Resource ../lib/connection_client.robot 4Resource ../lib/boot_utils.robot 5Library ../lib/gen_misc.py 6Library ../lib/utils.py 7Library ../lib/bmc_network_utils.py 8 9*** Variables *** 10# MAC input from user. 11${MAC_ADDRESS} ${EMPTY} 12 13 14*** Keywords *** 15 16Check And Reset MAC 17 [Documentation] Update BMC with user input MAC address. 18 [Arguments] ${mac_address}=${MAC_ADDRESS} 19 20 # Description of argument(s): 21 # mac_address The mac address (e.g. 00:01:6c:80:02:28). 22 23 Should Not Be Empty ${mac_address} 24 Open Connection And Log In 25 ${bmc_mac_addr} ${stderr} ${rc}= BMC Execute Command 26 ... cat /sys/class/net/eth0/address 27 Run Keyword If '${mac_address.lower()}' != '${bmc_mac_addr.lower()}' 28 ... Set MAC Address 29 30 31Set MAC Address 32 [Documentation] Update eth0 with input MAC address. 33 [Arguments] ${mac_address}=${MAC_ADDRESS} 34 35 # Description of argument(s): 36 # mac_address The mac address (e.g. 00:01:6c:80:02:28). 37 38 Write fw_setenv ethaddr ${mac_address} 39 OBMC Reboot (off) 40 41 # Take SSH session post BMC reboot. 42 Open Connection And Log In 43 ${bmc_mac_addr} ${stderr} ${rc}= BMC Execute Command 44 ... cat /sys/class/net/eth0/address 45 Should Be Equal ${bmc_mac_addr} ${mac_address} ignore_case=True 46 47 48Get BMC IP Info 49 [Documentation] Get system IP address and prefix length. 50 51 52 # Get system IP address and prefix length details using "ip addr" 53 # Sample Output of "ip addr": 54 # 1: eth0: <BROADCAST,MULTIAST> mtu 1500 qdisc mq state UP qlen 1000 55 # link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff 56 # inet xx.xx.xx.xx/24 brd xx.xx.xx.xx scope global eth0 57 58 ${active_channel_config}= Get Active Channel Config 59 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 60 ${cmd_output} ${stderr} ${rc}= BMC Execute Command 61 ... /sbin/ip addr | grep ${ethernet_interface} 62 63 # Get line having IP address details. 64 ${lines}= Get Lines Containing String ${cmd_output} inet 65 66 # List IP address details. 67 @{ip_components}= Split To Lines ${lines} 68 69 @{ip_data}= Create List 70 71 # Get all IP addresses and prefix lengths on system. 72 FOR ${ip_component} IN @{ip_components} 73 @{if_info}= Split String ${ip_component} 74 ${ip_n_prefix}= Get From List ${if_info} 1 75 Append To List ${ip_data} ${ip_n_prefix} 76 END 77 78 [Return] ${ip_data} 79 80Get BMC Route Info 81 [Documentation] Get system route info. 82 83 84 # Sample output of "ip route": 85 # default via xx.xx.xx.x dev eth0 86 # xx.xx.xx.0/23 dev eth0 src xx.xx.xx.xx 87 # xx.xx.xx.0/24 dev eth0 src xx.xx.xx.xx 88 89 ${cmd_output} ${stderr} ${rc}= BMC Execute Command 90 ... /sbin/ip route 91 92 [Return] ${cmd_output} 93 94# TODO: openbmc/openbmc-test-automation#1331 95Get BMC MAC Address 96 [Documentation] Get system MAC address. 97 98 99 # Sample output of "ip addr | grep ether": 100 # link/ether xx.xx.xx.xx.xx.xx brd ff:ff:ff:ff:ff:ff 101 102 ${cmd_output} ${stderr} ${rc}= BMC Execute Command 103 ... /sbin/ip addr | grep ether 104 105 # Split the line and return MAC address. 106 # Split list data: 107 # link/ether | xx:xx:xx:xx:xx:xx | brd | ff:ff:ff:ff:ff:ff 108 109 @{words}= Split String ${cmd_output} 110 111 [Return] ${words[1]} 112 113 114Get BMC MAC Address List 115 [Documentation] Get system MAC address 116 117 # Sample output of "ip addr | grep ether": 118 # link/ether xx.xx.xx.xx.xx.xx brd ff:ff:ff:ff:ff:ff 119 120 ${cmd_output} ${stderr} ${rc}= BMC Execute Command 121 ... /sbin/ip addr | grep ether 122 123 # Split the line and return MAC address. 124 # Split list data: 125 # link/ether | xx:xx:xx:xx:xx:xx | brd | ff:ff:ff:ff:ff:ff 126 # link/ether | xx:xx:xx:xx:xx:xx | brd | ff:ff:ff:ff:ff:ff 127 128 ${mac_list}= Create List 129 @{lines}= Split To Lines ${cmd_output} 130 FOR ${line} IN @{lines} 131 @{words}= Split String ${line} 132 Append To List ${mac_list} ${words[1]} 133 END 134 135 [Return] ${mac_list} 136 137Get BMC Hostname 138 [Documentation] Get BMC hostname. 139 140 # Sample output of "hostname": 141 # test_hostname 142 143 ${output} ${stderr} ${rc}= BMC Execute Command hostname 144 145 [Return] ${output} 146 147Get List Of IP Address Via REST 148 [Documentation] Get list of IP address via REST. 149 [Arguments] @{ip_uri_list} 150 151 # Description of argument(s): 152 # ip_uri_list List of IP objects. 153 # Example: 154 # "data": [ 155 # "/xyz/openbmc_project/network/eth0/ipv4/e9767624", 156 # "/xyz/openbmc_project/network/eth0/ipv4/31f4ce8b" 157 # ], 158 159 ${ip_list}= Create List 160 161 FOR ${ip_uri} IN @{ip_uri_list} 162 ${ip_addr}= Read Attribute ${ip_uri} Address 163 Append To List ${ip_list} ${ip_addr} 164 END 165 166 [Return] @{ip_list} 167 168Delete IP And Object 169 [Documentation] Delete IP and object. 170 [Arguments] ${ip_addr} @{ip_uri_list} 171 172 # Description of argument(s): 173 # ip_addr IP address to be deleted. 174 # ip_uri_list List of IP object URIs. 175 176 # Find IP object having this IP address. 177 178 FOR ${ip_uri} IN @{ip_uri_list} 179 ${ip_addr1}= Read Attribute ${ip_uri} Address 180 Run Keyword If '${ip_addr}' == '${ip_addr1}' Exit For Loop 181 END 182 183 # If the given IP address is not configured, return. 184 # Otherwise, delete the IP and object. 185 186 Run Keyword And Return If '${ip_addr}' != '${ip_addr1}' 187 ... Pass Execution IP address to be deleted is not configured. 188 189 Run Keyword And Ignore Error OpenBMC Delete Request ${ip_uri} 190 191 # After any modification on network interface, BMC restarts network 192 # module, wait until it is reachable. Then wait 15 seconds for new 193 # configuration to be updated on BMC. 194 195 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 196 ... ${NETWORK_RETRY_TIME} 197 Sleep 15s 198 199 # Verify whether deleted IP address is removed from BMC system. 200 201 ${ip_data}= Get BMC IP Info 202 Should Not Contain Match ${ip_data} ${ip_addr}* 203 ... msg=IP address not deleted. 204 205Get First Non Pingable IP From Subnet 206 [Documentation] Find first non-pingable IP from the subnet and return it. 207 [Arguments] ${host}=${OPENBMC_HOST} 208 209 # Description of argument(s): 210 # host Any valid host name or IP address 211 # (e.g. "machine1" or "9.xx.xx.31"). 212 213 # Non-pingable IP is unused IP address in the subnet. 214 ${host_name} ${ip_addr}= Get Host Name IP 215 216 # Split IP address into network part and host part. 217 # IP address will have 4 octets xx.xx.xx.xx. 218 # Sample output after split: 219 # split_ip [xx.xx.xx, xx] 220 221 ${split_ip}= Split String From Right ${ip_addr} . 1 222 # First element in list is Network part. 223 ${network_part}= Get From List ${split_ip} 0 224 225 FOR ${octet4} IN RANGE 1 255 226 ${new_ip}= Catenate ${network_part}.${octet4} 227 ${status}= Run Keyword And Return Status Ping Host ${new_ip} 228 # If IP is non-pingable, return it. 229 Return From Keyword If '${status}' == 'False' ${new_ip} 230 END 231 232 Fail msg=No non-pingable IP could be found in subnet ${network_part}. 233 234 235Validate MAC On BMC 236 [Documentation] Validate MAC on BMC. 237 [Arguments] ${mac_addr} 238 239 # Description of argument(s): 240 # mac_addr MAC address of the BMC. 241 242 ${system_mac}= Get BMC MAC Address 243 244 ${status}= Compare MAC Address ${system_mac} ${mac_addr} 245 Should Be True ${status} 246 ... msg=MAC address ${system_mac} does not match ${mac_addr}. 247 248 249Run Build Net 250 [Documentation] Run build_net to preconfigure the ethernet interfaces. 251 252 OS Execute Command build_net help y y 253 # Run pingum to check if the "build_net" was run correctly done. 254 ${output} ${stderr} ${rc}= OS Execute Command pingum 255 Should Contain ${output} All networks ping Ok 256 257 258Configure Hostname 259 [Documentation] Configure hostname on BMC via Redfish. 260 [Arguments] ${hostname} 261 262 # Description of argument(s): 263 # hostname A hostname value which is to be configured on BMC. 264 265 ${data}= Create Dictionary HostName=${hostname} 266 Redfish.patch ${REDFISH_NW_PROTOCOL_URI} body=&{data} 267 ... valid_status_codes=[${HTTP_OK}, ${HTTP_NO_CONTENT}] 268 269 270Verify IP On BMC 271 [Documentation] Verify IP on BMC. 272 [Arguments] ${ip} 273 274 # Description of argument(s): 275 # ip IP address to be verified (e.g. "10.7.7.7"). 276 277 # Get IP address details on BMC using IP command. 278 @{ip_data}= Get BMC IP Info 279 Should Contain Match ${ip_data} ${ip}/* 280 ... msg=IP address does not exist. 281 282 283Verify Gateway On BMC 284 [Documentation] Verify gateway on BMC. 285 [Arguments] ${gateway_ip}=0.0.0.0 286 287 # Description of argument(s): 288 # gateway_ip Gateway IP address. 289 290 ${route_info}= Get BMC Route Info 291 292 # If gateway IP is empty or 0.0.0.0 it will not have route entry. 293 294 Run Keyword If '${gateway_ip}' == '0.0.0.0' 295 ... Pass Execution Gateway IP is "0.0.0.0". 296 ... ELSE 297 ... Should Contain ${route_info} ${gateway_ip} 298 ... msg=Gateway IP address not matching. 299 300 301Get BMC DNS Info 302 [Documentation] Get system DNS info. 303 304 305 # Sample output of "resolv.conf": 306 # ### Generated manually via dbus settings ### 307 # nameserver 8.8.8.8 308 309 ${cmd_output} ${stderr} ${rc}= BMC Execute Command 310 ... cat /etc/resolv.conf 311 312 [Return] ${cmd_output} 313 314 315CLI Get Nameservers 316 [Documentation] Get the nameserver IPs from /etc/resolv.conf and return as a list. 317 318 # Example of /etc/resolv.conf data: 319 # nameserver x.x.x.x 320 # nameserver y.y.y.y 321 322 ${stdout} ${stderr} ${rc}= BMC Execute Command egrep nameserver /etc/resolv.conf | cut -f2- -d ' ' 323 ${nameservers}= Split String ${stdout} 324 325 [Return] ${nameservers} 326 327 328Get Network Configuration 329 [Documentation] Get network configuration. 330 # Sample output: 331 #{ 332 # "@odata.context": "/redfish/v1/$metadata#EthernetInterface.EthernetInterface", 333 # "@odata.id": "/redfish/v1/Managers/bmc/EthernetInterfaces/eth0", 334 # "@odata.type": "#EthernetInterface.v1_2_0.EthernetInterface", 335 # "Description": "Management Network Interface", 336 # "IPv4Addresses": [ 337 # { 338 # "Address": "169.254.xx.xx", 339 # "AddressOrigin": "IPv4LinkLocal", 340 # "Gateway": "0.0.0.0", 341 # "SubnetMask": "255.255.0.0" 342 # }, 343 # { 344 # "Address": "xx.xx.xx.xx", 345 # "AddressOrigin": "Static", 346 # "Gateway": "xx.xx.xx.1", 347 # "SubnetMask": "xx.xx.xx.xx" 348 # } 349 # ], 350 # "Id": "eth0", 351 # "MACAddress": "xx:xx:xx:xx:xx:xx", 352 # "Name": "Manager Ethernet Interface", 353 # "SpeedMbps": 0, 354 # "VLAN": { 355 # "VLANEnable": false, 356 # "VLANId": 0 357 # } 358 359 360 ${active_channel_config}= Get Active Channel Config 361 ${resp}= Redfish.Get ${REDFISH_NW_ETH_IFACE}${active_channel_config['${CHANNEL_NUMBER}']['name']} 362 363 @{network_configurations}= Get From Dictionary ${resp.dict} IPv4StaticAddresses 364 [Return] @{network_configurations} 365 366 367Add IP Address 368 [Documentation] Add IP Address To BMC. 369 [Arguments] ${ip} ${subnet_mask} ${gateway} 370 ... ${valid_status_codes}=${HTTP_OK} 371 372 # Description of argument(s): 373 # ip IP address to be added (e.g. "10.7.7.7"). 374 # subnet_mask Subnet mask for the IP to be added 375 # (e.g. "255.255.0.0"). 376 # gateway Gateway for the IP to be added (e.g. "10.7.7.1"). 377 # valid_status_codes Expected return code from patch operation 378 # (e.g. "200"). See prolog of rest_request 379 # method in redfish_plus.py for details. 380 381 ${empty_dict}= Create Dictionary 382 ${ip_data}= Create Dictionary Address=${ip} 383 ... SubnetMask=${subnet_mask} Gateway=${gateway} 384 385 ${patch_list}= Create List 386 ${network_configurations}= Get Network Configuration 387 ${num_entries}= Get Length ${network_configurations} 388 389 FOR ${INDEX} IN RANGE 0 ${num_entries} 390 Append To List ${patch_list} ${empty_dict} 391 END 392 393 # We need not check for existence of IP on BMC while adding. 394 Append To List ${patch_list} ${ip_data} 395 ${data}= Create Dictionary IPv4StaticAddresses=${patch_list} 396 397 ${active_channel_config}= Get Active Channel Config 398 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 399 400 Redfish.patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} body=&{data} 401 ... valid_status_codes=[${valid_status_codes}] 402 403 Return From Keyword If '${valid_status_codes}' != '${HTTP_OK}' 404 405 # Note: Network restart takes around 15-18s after patch request processing. 406 Sleep ${NETWORK_TIMEOUT}s 407 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 408 409 Verify IP On BMC ${ip} 410 Validate Network Config On BMC 411 412 413Delete IP Address 414 [Documentation] Delete IP Address Of BMC. 415 [Arguments] ${ip} ${valid_status_codes}=${HTTP_OK} 416 417 # Description of argument(s): 418 # ip IP address to be deleted (e.g. "10.7.7.7"). 419 # valid_status_codes Expected return code from patch operation 420 # (e.g. "200"). See prolog of rest_request 421 # method in redfish_plus.py for details. 422 423 ${empty_dict}= Create Dictionary 424 ${patch_list}= Create List 425 426 @{network_configurations}= Get Network Configuration 427 FOR ${network_configuration} IN @{network_configurations} 428 Run Keyword If '${network_configuration['Address']}' == '${ip}' 429 ... Append To List ${patch_list} ${null} 430 ... ELSE Append To List ${patch_list} ${empty_dict} 431 END 432 433 ${ip_found}= Run Keyword And Return Status List Should Contain Value 434 ... ${patch_list} ${null} msg=${ip} does not exist on BMC 435 Pass Execution If ${ip_found} == ${False} ${ip} does not exist on BMC 436 437 # Run patch command only if given IP is found on BMC 438 ${data}= Create Dictionary IPv4StaticAddresses=${patch_list} 439 440 ${active_channel_config}= Get Active Channel Config 441 ${ethernet_interface}= Set Variable ${active_channel_config['${CHANNEL_NUMBER}']['name']} 442 443 Redfish.patch ${REDFISH_NW_ETH_IFACE}${ethernet_interface} body=&{data} 444 ... valid_status_codes=[${valid_status_codes}] 445 446 # Note: Network restart takes around 15-18s after patch request processing 447 Sleep ${NETWORK_TIMEOUT}s 448 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 449 450 ${delete_status}= Run Keyword And Return Status Verify IP On BMC ${ip} 451 Run Keyword If '${valid_status_codes}' == '${HTTP_OK}' 452 ... Should Be True '${delete_status}' == '${False}' 453 ... ELSE Should Be True '${delete_status}' == '${True}' 454 455 Validate Network Config On BMC 456 457 458Validate Network Config On BMC 459 [Documentation] Check that network info obtained via redfish matches info 460 ... obtained via CLI. 461 462 @{network_configurations}= Get Network Configuration 463 ${ip_data}= Get BMC IP Info 464 FOR ${network_configuration} IN @{network_configurations} 465 Should Contain Match ${ip_data} ${network_configuration['Address']}/* 466 ... msg=IP address does not exist. 467 END 468 469 470Create VLAN 471 [Documentation] Create a VLAN. 472 [Arguments] ${id} ${interface}=eth0 ${expected_result}=valid 473 474 # Description of argument(s): 475 # id The VLAN ID (e.g. '53'). 476 # interface The physical interface for the VLAN(e.g. 'eth0'). 477 # expected_result Expected status of VLAN configuration. 478 479 @{data_vlan_id}= Create List ${interface} ${id} 480 ${data}= Create Dictionary data=@{data_vlan_id} 481 ${resp}= OpenBMC Post Request ${vlan_resource} data=${data} 482 ${resp.status_code}= Convert To String ${resp.status_code} 483 ${status}= Run Keyword And Return Status 484 ... Valid Value resp.status_code ["${HTTP_OK}"] 485 486 Run Keyword If '${expected_result}' == 'error' 487 ... Should Be Equal ${status} ${False} 488 ... msg=Configuration of an invalid VLAN ID Failed. 489 ... ELSE 490 ... Should Be Equal ${status} ${True} 491 ... msg=Configuration of a valid VLAN ID Failed. 492 493 Sleep ${NETWORK_TIMEOUT}s 494 495 496Configure Network Settings On VLAN 497 [Documentation] Configure network settings. 498 [Arguments] ${id} ${ip_addr} ${prefix_len} ${gateway_ip}=${gateway} 499 ... ${expected_result}=valid ${interface}=eth0 500 501 # Description of argument(s): 502 # id The VLAN ID (e.g. '53'). 503 # ip_addr IP address of VLAN Interface. 504 # prefix_len Prefix length of VLAN Interface. 505 # gateway_ip Gateway IP address of VLAN Interface. 506 # expected_result Expected status of network setting configuration. 507 # interface Physical Interface on which the VLAN is defined. 508 509 @{ip_parm_list}= Create List ${network_resource} 510 ... ${ip_addr} ${prefix_len} ${gateway_ip} 511 512 ${data}= Create Dictionary data=@{ip_parm_list} 513 514 Run Keyword And Ignore Error OpenBMC Post Request 515 ... ${NETWORK_MANAGER}${interface}_${id}/action/IP data=${data} 516 517 # After any modification on network interface, BMC restarts network 518 # module, wait until it is reachable. Then wait 15 seconds for new 519 # configuration to be updated on BMC. 520 521 Wait For Host To Ping ${OPENBMC_HOST} ${NETWORK_TIMEOUT} 522 ... ${NETWORK_RETRY_TIME} 523 Sleep ${NETWORK_TIMEOUT}s 524 525 # Verify whether new IP address is populated on BMC system. 526 # It should not allow to configure invalid settings. 527 ${status}= Run Keyword And Return Status 528 ... Verify IP On BMC ${ip_addr} 529 530 Run Keyword If '${expected_result}' == 'error' 531 ... Should Be Equal ${status} ${False} 532 ... msg=Configuration of invalid IP Failed. 533 ... ELSE 534 ... Should Be Equal ${status} ${True} 535 ... msg=Configuration of valid IP Failed. 536 537 538Get BMC Default Gateway 539 [Documentation] Get system default gateway. 540 541 ${route_info}= Get BMC Route Info 542 543 ${lines}= Get Lines Containing String ${route_info} default via 544 @{gateway_list}= Split To Lines ${lines} 545 546 # Extract first default gateway and return. 547 @{default_gw}= Split String ${gateway_list[0]} 548 549 [Return] ${default_gw[2]} 550