1de7d408dSCharles Paul Hofer#!/usr/bin/env python 2de7d408dSCharles Paul Hofer 3de7d408dSCharles Paul Hoferr""" 4de7d408dSCharles Paul HoferThis module provides utilities for code updates. 5de7d408dSCharles Paul Hofer""" 6de7d408dSCharles Paul Hofer 7de7d408dSCharles Paul Hoferimport os 8de7d408dSCharles Paul Hoferimport re 9de7d408dSCharles Paul Hoferimport sys 10de7d408dSCharles Paul Hoferimport tarfile 11de7d408dSCharles Paul Hoferimport time 12de7d408dSCharles Paul Hofer 13de7d408dSCharles Paul Hoferrobot_pgm_dir_path = os.path.dirname(__file__) + os.sep 14de7d408dSCharles Paul Hoferrepo_data_path = re.sub('/lib', '/data', robot_pgm_dir_path) 15de7d408dSCharles Paul Hofersys.path.append(repo_data_path) 16de7d408dSCharles Paul Hofer 17de7d408dSCharles Paul Hoferimport gen_robot_keyword as keyword 18de7d408dSCharles Paul Hoferimport gen_print as gp 19de7d408dSCharles Paul Hoferimport variables as var 20de7d408dSCharles Paul Hoferfrom robot.libraries.BuiltIn import BuiltIn 21de7d408dSCharles Paul Hofer 22de7d408dSCharles Paul Hofer############################################################################### 23da24d0a0SCharles Paul Hoferdef get_non_running_bmc_software_object(): 24da24d0a0SCharles Paul Hofer 25da24d0a0SCharles Paul Hofer r""" 26da24d0a0SCharles Paul Hofer Get the URI to a BMC image from software that is not running on the BMC. 27da24d0a0SCharles Paul Hofer """ 28da24d0a0SCharles Paul Hofer 29da24d0a0SCharles Paul Hofer # Get the version of the image currently running on the BMC. 30da24d0a0SCharles Paul Hofer _, cur_img_version = keyword.run_key("Get BMC Version") 31da24d0a0SCharles Paul Hofer # Remove the surrounding double quotes from the version. 32da24d0a0SCharles Paul Hofer cur_img_version = cur_img_version.replace('"', '') 33da24d0a0SCharles Paul Hofer 34da24d0a0SCharles Paul Hofer _, images = keyword.run_key("Read Properties " 35da24d0a0SCharles Paul Hofer + var.SOFTWARE_VERSION_URI + "enumerate") 36da24d0a0SCharles Paul Hofer 37da24d0a0SCharles Paul Hofer for image_name in images: 38da24d0a0SCharles Paul Hofer _, image_properties = keyword.run_key( 39da24d0a0SCharles Paul Hofer "Get Host Software Property " + image_name) 40*9f74d3afSCharles Paul Hofer if image_properties['Purpose'] != var.VERSION_PURPOSE_HOST \ 41*9f74d3afSCharles Paul Hofer and image_properties['Version'] != cur_img_version: 42da24d0a0SCharles Paul Hofer return image_name 43da24d0a0SCharles Paul Hofer BuiltIn().fail("Did not find any non-running BMC images.") 44da24d0a0SCharles Paul Hofer 45da24d0a0SCharles Paul Hofer############################################################################### 46da24d0a0SCharles Paul Hofer 47da24d0a0SCharles Paul Hofer 48da24d0a0SCharles Paul Hofer############################################################################### 49de7d408dSCharles Paul Hoferdef delete_all_pnor_images(): 50de7d408dSCharles Paul Hofer 51de7d408dSCharles Paul Hofer r""" 52de7d408dSCharles Paul Hofer Delete all PNOR images from the BMC. 53de7d408dSCharles Paul Hofer """ 54de7d408dSCharles Paul Hofer 55de7d408dSCharles Paul Hofer status, images = keyword.run_key("Read Properties " 56de7d408dSCharles Paul Hofer + var.SOFTWARE_VERSION_URI + "enumerate") 57de7d408dSCharles Paul Hofer for image_name in images: 58de7d408dSCharles Paul Hofer image_id = image_name.split('/')[-1] 59de7d408dSCharles Paul Hofer image_purpose = images[image_name]["Purpose"] 60de7d408dSCharles Paul Hofer if var.VERSION_PURPOSE_HOST == image_purpose: 61de7d408dSCharles Paul Hofer # Delete twice, in case the image is in the /tmp/images directory 62de7d408dSCharles Paul Hofer keyword.run_key("Call Method " + var.SOFTWARE_VERSION_URI 63de7d408dSCharles Paul Hofer + image_id + " delete data={\"data\":[]}") 64de7d408dSCharles Paul Hofer keyword.run_key("Call Method " + var.SOFTWARE_VERSION_URI 65de7d408dSCharles Paul Hofer + image_id + " delete data={\"data\":[]}") 66de7d408dSCharles Paul Hofer 67de7d408dSCharles Paul Hofer############################################################################### 68de7d408dSCharles Paul Hofer 69de7d408dSCharles Paul Hofer 70de7d408dSCharles Paul Hofer############################################################################### 71de7d408dSCharles Paul Hoferdef wait_for_activation_state_change(version_id, initial_state): 72de7d408dSCharles Paul Hofer 73de7d408dSCharles Paul Hofer r""" 74de7d408dSCharles Paul Hofer Wait for the current activation state of ${version_id} to 75de7d408dSCharles Paul Hofer change from the state provided by the calling function. 76de7d408dSCharles Paul Hofer 77de7d408dSCharles Paul Hofer Description of argument(s): 78de7d408dSCharles Paul Hofer version_id The version ID whose state change we are waiting for. 79de7d408dSCharles Paul Hofer initial_state The activation state we want to wait for. 80de7d408dSCharles Paul Hofer """ 81de7d408dSCharles Paul Hofer 82de7d408dSCharles Paul Hofer keyword.run_key_u("Open Connection And Log In") 83de7d408dSCharles Paul Hofer retry = 0 84de7d408dSCharles Paul Hofer while (retry < 20): 85de7d408dSCharles Paul Hofer status, software_state = keyword.run_key("Read Properties " + 86de7d408dSCharles Paul Hofer var.SOFTWARE_VERSION_URI + str(version_id)) 87de7d408dSCharles Paul Hofer current_state = (software_state)["Activation"] 88de7d408dSCharles Paul Hofer if (initial_state == current_state): 89de7d408dSCharles Paul Hofer time.sleep(60) 90de7d408dSCharles Paul Hofer retry += 1 91de7d408dSCharles Paul Hofer else: 92de7d408dSCharles Paul Hofer return 93de7d408dSCharles Paul Hofer return 94de7d408dSCharles Paul Hofer 95de7d408dSCharles Paul Hofer############################################################################### 96de7d408dSCharles Paul Hofer 97de7d408dSCharles Paul Hofer 98de7d408dSCharles Paul Hofer############################################################################### 99de7d408dSCharles Paul Hoferdef get_latest_file(dir_path): 100de7d408dSCharles Paul Hofer 101de7d408dSCharles Paul Hofer r""" 102de7d408dSCharles Paul Hofer Get the path to the latest uploaded file. 103de7d408dSCharles Paul Hofer 104de7d408dSCharles Paul Hofer Description of argument(s): 105de7d408dSCharles Paul Hofer dir_path Path to the dir from which the name of the last 106de7d408dSCharles Paul Hofer updated file or folder will be returned to the 107de7d408dSCharles Paul Hofer calling function. 108de7d408dSCharles Paul Hofer """ 109de7d408dSCharles Paul Hofer 110de7d408dSCharles Paul Hofer keyword.run_key_u("Open Connection And Log In") 111de7d408dSCharles Paul Hofer status, ret_values =\ 112de7d408dSCharles Paul Hofer keyword.run_key("Execute Command On BMC cd " + dir_path 113de7d408dSCharles Paul Hofer + "; stat -c '%Y %n' * | sort -k1,1nr | head -n 1", ignore=1) 114de7d408dSCharles Paul Hofer return ret_values.split(" ")[-1] 115de7d408dSCharles Paul Hofer 116de7d408dSCharles Paul Hofer############################################################################### 117de7d408dSCharles Paul Hofer 118de7d408dSCharles Paul Hofer 119de7d408dSCharles Paul Hofer############################################################################### 120de7d408dSCharles Paul Hoferdef get_version_tar(tar_file_path): 121de7d408dSCharles Paul Hofer 122de7d408dSCharles Paul Hofer r""" 123de7d408dSCharles Paul Hofer Read the image version from the MANIFEST inside the tarball. 124de7d408dSCharles Paul Hofer 125de7d408dSCharles Paul Hofer Description of argument(s): 126de7d408dSCharles Paul Hofer tar_file_path The path to a tar file that holds the image 127de7d408dSCharles Paul Hofer version inside the MANIFEST. 128de7d408dSCharles Paul Hofer """ 129de7d408dSCharles Paul Hofer 130de7d408dSCharles Paul Hofer tar = tarfile.open(tar_file_path) 131de7d408dSCharles Paul Hofer for member in tar.getmembers(): 132de7d408dSCharles Paul Hofer f=tar.extractfile(member) 133de7d408dSCharles Paul Hofer content=f.read() 134de7d408dSCharles Paul Hofer if "version=" in content: 135de7d408dSCharles Paul Hofer content = content.split("\n") 136de7d408dSCharles Paul Hofer content = [x for x in content if "version=" in x] 137de7d408dSCharles Paul Hofer version = content[0].split("=")[-1] 138de7d408dSCharles Paul Hofer break 139de7d408dSCharles Paul Hofer tar.close() 140de7d408dSCharles Paul Hofer return version 141de7d408dSCharles Paul Hofer 142de7d408dSCharles Paul Hofer############################################################################### 143de7d408dSCharles Paul Hofer 144de7d408dSCharles Paul Hofer 145de7d408dSCharles Paul Hofer############################################################################### 146de7d408dSCharles Paul Hoferdef get_image_version(file_path): 147de7d408dSCharles Paul Hofer 148de7d408dSCharles Paul Hofer r""" 149de7d408dSCharles Paul Hofer Read the file for a version object. 150de7d408dSCharles Paul Hofer 151de7d408dSCharles Paul Hofer Description of argument(s): 152de7d408dSCharles Paul Hofer file_path The path to a file that holds the image version. 153de7d408dSCharles Paul Hofer """ 154de7d408dSCharles Paul Hofer 155de7d408dSCharles Paul Hofer keyword.run_key_u("Open Connection And Log In") 156de7d408dSCharles Paul Hofer status, ret_values =\ 157de7d408dSCharles Paul Hofer keyword.run_key("Execute Command On BMC cat " 158de7d408dSCharles Paul Hofer + file_path + " | grep \"version=\"", ignore=1) 159de7d408dSCharles Paul Hofer return (ret_values.split("\n")[0]).split("=")[-1] 160de7d408dSCharles Paul Hofer 161de7d408dSCharles Paul Hofer############################################################################### 162de7d408dSCharles Paul Hofer 163de7d408dSCharles Paul Hofer 164de7d408dSCharles Paul Hofer############################################################################### 165de7d408dSCharles Paul Hoferdef get_image_purpose(file_path): 166de7d408dSCharles Paul Hofer 167de7d408dSCharles Paul Hofer r""" 168de7d408dSCharles Paul Hofer Read the file for a purpose object. 169de7d408dSCharles Paul Hofer 170de7d408dSCharles Paul Hofer Description of argument(s): 171de7d408dSCharles Paul Hofer file_path The path to a file that holds the image purpose. 172de7d408dSCharles Paul Hofer """ 173de7d408dSCharles Paul Hofer 174de7d408dSCharles Paul Hofer keyword.run_key_u("Open Connection And Log In") 175de7d408dSCharles Paul Hofer status, ret_values =\ 176de7d408dSCharles Paul Hofer keyword.run_key("Execute Command On BMC cat " 177de7d408dSCharles Paul Hofer + file_path + " | grep \"purpose=\"", ignore=1) 178de7d408dSCharles Paul Hofer return ret_values.split("=")[-1] 179de7d408dSCharles Paul Hofer 180de7d408dSCharles Paul Hofer############################################################################### 181de7d408dSCharles Paul Hofer 182de7d408dSCharles Paul Hofer 183de7d408dSCharles Paul Hofer############################################################################### 184de7d408dSCharles Paul Hoferdef get_image_path(image_version): 185de7d408dSCharles Paul Hofer 186de7d408dSCharles Paul Hofer r""" 187de7d408dSCharles Paul Hofer Query the upload image dir for the presence of image matching 188de7d408dSCharles Paul Hofer the version that was read from the MANIFEST before uploading 189de7d408dSCharles Paul Hofer the image. Based on the purpose verify the activation object 190de7d408dSCharles Paul Hofer exists and is either READY or INVALID. 191de7d408dSCharles Paul Hofer 192de7d408dSCharles Paul Hofer Description of argument(s): 193de7d408dSCharles Paul Hofer image_version The version of the image that should match one 194de7d408dSCharles Paul Hofer of the images in the upload dir. 195de7d408dSCharles Paul Hofer """ 196de7d408dSCharles Paul Hofer 197de7d408dSCharles Paul Hofer keyword.run_key_u("Open Connection And Log In") 198de7d408dSCharles Paul Hofer status, image_list =\ 199*9f74d3afSCharles Paul Hofer keyword.run_key("Execute Command On BMC ls -d " 200*9f74d3afSCharles Paul Hofer + var.IMAGE_UPLOAD_DIR_PATH + "*/") 201de7d408dSCharles Paul Hofer 202de7d408dSCharles Paul Hofer image_list = image_list.split("\n") 203de7d408dSCharles Paul Hofer retry = 0 204de7d408dSCharles Paul Hofer while (retry < 10): 205de7d408dSCharles Paul Hofer for i in range(0, len(image_list)): 206de7d408dSCharles Paul Hofer version = get_image_version(image_list[i] + "MANIFEST") 207de7d408dSCharles Paul Hofer if (version == image_version): 208de7d408dSCharles Paul Hofer return image_list[i] 209de7d408dSCharles Paul Hofer time.sleep(10) 210de7d408dSCharles Paul Hofer retry += 1 211de7d408dSCharles Paul Hofer 212de7d408dSCharles Paul Hofer############################################################################### 213de7d408dSCharles Paul Hofer 214de7d408dSCharles Paul Hofer 215de7d408dSCharles Paul Hofer############################################################################### 216*9f74d3afSCharles Paul Hoferdef verify_image_upload(image_version, 217*9f74d3afSCharles Paul Hofer timeout=3): 218de7d408dSCharles Paul Hofer 219de7d408dSCharles Paul Hofer r""" 220de7d408dSCharles Paul Hofer Verify the image was uploaded correctly and that it created 221de7d408dSCharles Paul Hofer a valid d-bus object. If the first check for the image 222de7d408dSCharles Paul Hofer fails, try again until we reach the timeout. 223de7d408dSCharles Paul Hofer 224de7d408dSCharles Paul Hofer Description of argument(s): 225*9f74d3afSCharles Paul Hofer image_version The version from the image's manifest file 226*9f74d3afSCharles Paul Hofer (e.g. "IBM-witherspoon-redbud-ibm-OP9_v1.17_1.68"). 227de7d408dSCharles Paul Hofer timeout How long, in minutes, to keep trying to find the 228de7d408dSCharles Paul Hofer image on the BMC. Default is 3 minutes. 229de7d408dSCharles Paul Hofer """ 230de7d408dSCharles Paul Hofer 231de7d408dSCharles Paul Hofer image_path = get_image_path(image_version) 232de7d408dSCharles Paul Hofer image_version_id = image_path.split("/")[-2] 233de7d408dSCharles Paul Hofer 234de7d408dSCharles Paul Hofer keyword.run_key_u("Open Connection And Log In") 235de7d408dSCharles Paul Hofer image_purpose = get_image_purpose(image_path + "MANIFEST") 236de7d408dSCharles Paul Hofer if (image_purpose == var.VERSION_PURPOSE_BMC or 237de7d408dSCharles Paul Hofer image_purpose == var.VERSION_PURPOSE_HOST): 238de7d408dSCharles Paul Hofer uri = var.SOFTWARE_VERSION_URI + image_version_id 239de7d408dSCharles Paul Hofer ret_values = "" 240de7d408dSCharles Paul Hofer for itr in range(timeout * 2): 241de7d408dSCharles Paul Hofer status, ret_values = \ 242de7d408dSCharles Paul Hofer keyword.run_key("Read Attribute " + uri + " Activation") 243de7d408dSCharles Paul Hofer 244de7d408dSCharles Paul Hofer if ((ret_values == var.READY) or (ret_values == var.INVALID) 245de7d408dSCharles Paul Hofer or (ret_values == var.ACTIVE)): 246cef6199aSCharles Paul Hofer return True, image_version_id 247de7d408dSCharles Paul Hofer else: 248de7d408dSCharles Paul Hofer time.sleep(30) 249de7d408dSCharles Paul Hofer 250de7d408dSCharles Paul Hofer # If we exit the for loop, the timeout has been reached 251de7d408dSCharles Paul Hofer gp.print_var(ret_values) 252cef6199aSCharles Paul Hofer return False, None 253de7d408dSCharles Paul Hofer else: 254de7d408dSCharles Paul Hofer gp.print_var(image_purpose) 255cef6199aSCharles Paul Hofer return False, None 256de7d408dSCharles Paul Hofer 257de7d408dSCharles Paul Hofer############################################################################### 258de7d408dSCharles Paul Hofer 259de7d408dSCharles Paul Hofer 260de7d408dSCharles Paul Hofer############################################################################### 261de7d408dSCharles Paul Hoferdef verify_image_not_in_bmc_uploads_dir(image_version, timeout=3): 262de7d408dSCharles Paul Hofer 263de7d408dSCharles Paul Hofer r""" 264de7d408dSCharles Paul Hofer Check that an image with the given version is not unpacked inside of the 265de7d408dSCharles Paul Hofer BMCs image uploads directory. If no image is found, retry every 30 seconds 266de7d408dSCharles Paul Hofer until the given timeout is hit, in case the BMC takes time 267de7d408dSCharles Paul Hofer unpacking the image. 268de7d408dSCharles Paul Hofer 269de7d408dSCharles Paul Hofer Description of argument(s): 270de7d408dSCharles Paul Hofer image_version The version of the image to look for on the BMC. 271de7d408dSCharles Paul Hofer timeout How long, in minutes, to try to find an image on the BMC. 272de7d408dSCharles Paul Hofer Default is 3 minutes. 273de7d408dSCharles Paul Hofer """ 274de7d408dSCharles Paul Hofer 275de7d408dSCharles Paul Hofer keyword.run_key('Open Connection And Log In') 276de7d408dSCharles Paul Hofer for i in range(timeout * 2): 277de7d408dSCharles Paul Hofer stat, grep_res = keyword.run_key('Execute Command On BMC ' 278*9f74d3afSCharles Paul Hofer + 'ls ' + var.IMAGE_UPLOAD_DIR_PATH + '*/MANIFEST 2>/dev/null ' 279de7d408dSCharles Paul Hofer + '| xargs grep -rl "version=' + image_version + '"') 280de7d408dSCharles Paul Hofer image_dir = os.path.dirname(grep_res.split('\n')[0]) 281de7d408dSCharles Paul Hofer if '' != image_dir: 282de7d408dSCharles Paul Hofer keyword.run_key('Execute Command On BMC rm -rf ' + image_dir) 283de7d408dSCharles Paul Hofer BuiltIn().fail('Found invalid BMC Image: ' + image_dir) 284de7d408dSCharles Paul Hofer time.sleep(30) 285de7d408dSCharles Paul Hofer 286de7d408dSCharles Paul Hofer###############################################################################