blob: f56941022e671c84a414508baf0f716e9812612a [file] [log] [blame]
Saqib Khanfb1f6ae2017-04-26 13:24:41 -05001#!/usr/bin/env python
2
3r"""
Charles Paul Hoferde7d4082017-08-08 14:41:01 -05004This module provides utilities for code updates.
Saqib Khanfb1f6ae2017-04-26 13:24:41 -05005"""
6
7import os
Saqib Khanfb1f6ae2017-04-26 13:24:41 -05008import re
Charles Paul Hoferde7d4082017-08-08 14:41:01 -05009import sys
Saqib Khanfb1f6ae2017-04-26 13:24:41 -050010import tarfile
11import time
12
13robot_pgm_dir_path = os.path.dirname(__file__) + os.sep
Charles Paul Hoferde7d4082017-08-08 14:41:01 -050014repo_data_path = re.sub('/lib', '/data', robot_pgm_dir_path)
Saqib Khanfb1f6ae2017-04-26 13:24:41 -050015sys.path.append(repo_data_path)
16
Charles Paul Hoferde7d4082017-08-08 14:41:01 -050017import gen_robot_keyword as keyword
Saqib Khanfb1f6ae2017-04-26 13:24:41 -050018import gen_print as gp
19import variables as var
20from robot.libraries.BuiltIn import BuiltIn
21
Charles Paul Hoferde7d4082017-08-08 14:41:01 -050022###############################################################################
Charles Paul Hoferc1fa2bc2017-08-18 16:44:03 -050023def 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]))
Charles Paul Hofera5673162017-08-30 09:49:16 -050045 taken_priorities[image_priority] = image
Charles Paul Hoferc1fa2bc2017-08-18 16:44:03 -050046
47###############################################################################
48
49
50###############################################################################
Charles Paul Hoferda24d0a2017-08-09 15:03:40 -050051def 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)
Charles Paul Hofer1e487272017-09-14 12:55:11 -050068 if 'Purpose' in image_properties and 'Version' in image_properties \
69 and image_properties['Purpose'] != var.VERSION_PURPOSE_HOST \
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -050070 and image_properties['Version'] != cur_img_version:
Charles Paul Hoferda24d0a2017-08-09 15:03:40 -050071 return image_name
72 BuiltIn().fail("Did not find any non-running BMC images.")
73
74###############################################################################
75
76
77###############################################################################
Charles Paul Hoferde7d4082017-08-08 14:41:01 -050078def delete_all_pnor_images():
79
80 r"""
81 Delete all PNOR images from the BMC.
82 """
83
George Keishing8e984782017-08-30 14:16:18 -050084 status, images = keyword.run_key("Get Software Objects "
85 + var.VERSION_PURPOSE_HOST)
Charles Paul Hoferde7d4082017-08-08 14:41:01 -050086 for image_name in images:
George Keishing8e984782017-08-30 14:16:18 -050087 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\":[]}")
Charles Paul Hoferde7d4082017-08-08 14:41:01 -050093
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
Charles Paul Hofer290b8bd2017-09-26 10:02:22 -0500111 num_read_errors = 0
112 read_fail_threshold = 1
Charles Paul Hofer4d26c002017-09-27 08:39:29 -0500113 while (retry < 30):
Charles Paul Hofer290b8bd2017-09-26 10:02:22 -0500114 # TODO: Use retry option in run_key when available.
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500115 status, software_state = keyword.run_key("Read Properties " +
Charles Paul Hofer290b8bd2017-09-26 10:02:22 -0500116 var.SOFTWARE_VERSION_URI + str(version_id),
117 ignore=1)
118 if status == 'FAIL':
119 num_read_errors += 1
120 if num_read_errors > read_fail_threshold:
121 message = "Read errors exceeds threshold:\n " \
122 + gp.sprint_vars(num_read_errors, read_fail_threshold)
123 BuiltIn().fail(message)
Charles Paul Hofer4d26c002017-09-27 08:39:29 -0500124 time.sleep(10)
Charles Paul Hofer290b8bd2017-09-26 10:02:22 -0500125 continue
126
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500127 current_state = (software_state)["Activation"]
128 if (initial_state == current_state):
Charles Paul Hofer4d26c002017-09-27 08:39:29 -0500129 time.sleep(10)
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500130 retry += 1
Charles Paul Hofer290b8bd2017-09-26 10:02:22 -0500131 num_read_errors = 0
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500132 else:
133 return
134 return
135
136###############################################################################
137
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500138
139###############################################################################
140def get_latest_file(dir_path):
141
142 r"""
143 Get the path to the latest uploaded file.
144
145 Description of argument(s):
146 dir_path Path to the dir from which the name of the last
147 updated file or folder will be returned to the
148 calling function.
149 """
150
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500151 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500152 status, ret_values =\
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500153 keyword.run_key("Execute Command On BMC cd " + dir_path
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500154 + "; stat -c '%Y %n' * | sort -k1,1nr | head -n 1", ignore=1)
155 return ret_values.split(" ")[-1]
156
157###############################################################################
158
159
160###############################################################################
161def get_version_tar(tar_file_path):
162
163 r"""
164 Read the image version from the MANIFEST inside the tarball.
165
166 Description of argument(s):
167 tar_file_path The path to a tar file that holds the image
168 version inside the MANIFEST.
169 """
170
171 tar = tarfile.open(tar_file_path)
172 for member in tar.getmembers():
173 f=tar.extractfile(member)
174 content=f.read()
175 if "version=" in content:
176 content = content.split("\n")
177 content = [x for x in content if "version=" in x]
178 version = content[0].split("=")[-1]
179 break
180 tar.close()
181 return version
182
183###############################################################################
184
185
186###############################################################################
187def get_image_version(file_path):
188
189 r"""
190 Read the file for a version object.
191
192 Description of argument(s):
193 file_path The path to a file that holds the image version.
194 """
195
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500196 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500197 status, ret_values =\
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500198 keyword.run_key("Execute Command On BMC cat "
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500199 + file_path + " | grep \"version=\"", ignore=1)
200 return (ret_values.split("\n")[0]).split("=")[-1]
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500201
202###############################################################################
203
204
205###############################################################################
206def get_image_purpose(file_path):
207
208 r"""
209 Read the file for a purpose object.
210
211 Description of argument(s):
212 file_path The path to a file that holds the image purpose.
213 """
214
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500215 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500216 status, ret_values =\
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500217 keyword.run_key("Execute Command On BMC cat "
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500218 + file_path + " | grep \"purpose=\"", ignore=1)
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500219 return ret_values.split("=")[-1]
220
221###############################################################################
222
223
224###############################################################################
225def get_image_path(image_version):
226
227 r"""
228 Query the upload image dir for the presence of image matching
229 the version that was read from the MANIFEST before uploading
230 the image. Based on the purpose verify the activation object
231 exists and is either READY or INVALID.
232
233 Description of argument(s):
234 image_version The version of the image that should match one
235 of the images in the upload dir.
236 """
237
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500238 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500239 status, image_list =\
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500240 keyword.run_key("Execute Command On BMC ls -d "
241 + var.IMAGE_UPLOAD_DIR_PATH + "*/")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500242
243 image_list = image_list.split("\n")
244 retry = 0
245 while (retry < 10):
246 for i in range(0, len(image_list)):
247 version = get_image_version(image_list[i] + "MANIFEST")
248 if (version == image_version):
249 return image_list[i]
250 time.sleep(10)
251 retry += 1
252
253###############################################################################
254
255
256###############################################################################
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500257def verify_image_upload(image_version,
258 timeout=3):
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500259
260 r"""
261 Verify the image was uploaded correctly and that it created
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500262 a valid d-bus object. If the first check for the image
263 fails, try again until we reach the timeout.
264
265 Description of argument(s):
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500266 image_version The version from the image's manifest file
267 (e.g. "IBM-witherspoon-redbud-ibm-OP9_v1.17_1.68").
268 timeout How long, in minutes, to keep trying to find the
269 image on the BMC. Default is 3 minutes.
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500270 """
271
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500272 image_path = get_image_path(image_version)
273 image_version_id = image_path.split("/")[-2]
274
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500275 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500276 image_purpose = get_image_purpose(image_path + "MANIFEST")
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500277 if (image_purpose == var.VERSION_PURPOSE_BMC or
278 image_purpose == var.VERSION_PURPOSE_HOST):
George Keishingff1e3ec2017-07-20 01:58:21 -0500279 uri = var.SOFTWARE_VERSION_URI + image_version_id
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500280 ret_values = ""
281 for itr in range(timeout * 2):
282 status, ret_values = \
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500283 keyword.run_key("Read Attribute " + uri + " Activation")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500284
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500285 if ((ret_values == var.READY) or (ret_values == var.INVALID)
286 or (ret_values == var.ACTIVE)):
Charles Paul Hofercef61992017-08-18 10:14:18 -0500287 return True, image_version_id
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500288 else:
289 time.sleep(30)
290
291 # If we exit the for loop, the timeout has been reached
292 gp.print_var(ret_values)
Charles Paul Hofercef61992017-08-18 10:14:18 -0500293 return False, None
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500294 else:
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500295 gp.print_var(image_purpose)
Charles Paul Hofercef61992017-08-18 10:14:18 -0500296 return False, None
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500297
298###############################################################################
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500299
300
301###############################################################################
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500302def verify_image_not_in_bmc_uploads_dir(image_version, timeout=3):
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500303
304 r"""
305 Check that an image with the given version is not unpacked inside of the
306 BMCs image uploads directory. If no image is found, retry every 30 seconds
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500307 until the given timeout is hit, in case the BMC takes time
308 unpacking the image.
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500309
310 Description of argument(s):
311 image_version The version of the image to look for on the BMC.
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500312 timeout How long, in minutes, to try to find an image on the BMC.
313 Default is 3 minutes.
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500314 """
315
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500316 keyword.run_key('Open Connection And Log In')
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500317 for i in range(timeout * 2):
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500318 stat, grep_res = keyword.run_key('Execute Command On BMC '
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500319 + 'ls ' + var.IMAGE_UPLOAD_DIR_PATH + '*/MANIFEST 2>/dev/null '
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500320 + '| xargs grep -rl "version=' + image_version + '"')
321 image_dir = os.path.dirname(grep_res.split('\n')[0])
322 if '' != image_dir:
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500323 keyword.run_key('Execute Command On BMC rm -rf ' + image_dir)
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500324 BuiltIn().fail('Found invalid BMC Image: ' + image_dir)
325 time.sleep(30)
326
George Keishing8e984782017-08-30 14:16:18 -0500327###############################################################################