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