blob: 5dd0ca78e61e36f6bc9c3377f0184069b1b1ff57 [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]))
45 taken_priorities[image_priority] = image
46
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 Hofer9f74d3a2017-08-18 09:54:28 -050068 if image_properties['Purpose'] != var.VERSION_PURPOSE_HOST \
69 and image_properties['Version'] != cur_img_version:
Charles Paul Hoferda24d0a2017-08-09 15:03:40 -050070 return image_name
71 BuiltIn().fail("Did not find any non-running BMC images.")
72
73###############################################################################
74
75
76###############################################################################
Charles Paul Hoferde7d4082017-08-08 14:41:01 -050077def delete_all_pnor_images():
78
79 r"""
80 Delete all PNOR images from the BMC.
81 """
82
83 status, images = keyword.run_key("Read Properties "
84 + var.SOFTWARE_VERSION_URI + "enumerate")
85 for image_name in images:
86 image_id = image_name.split('/')[-1]
87 image_purpose = images[image_name]["Purpose"]
88 if var.VERSION_PURPOSE_HOST == image_purpose:
89 # Delete twice, in case the image is in the /tmp/images directory
90 keyword.run_key("Call Method " + var.SOFTWARE_VERSION_URI
91 + image_id + " delete data={\"data\":[]}")
92 keyword.run_key("Call Method " + var.SOFTWARE_VERSION_URI
93 + image_id + " delete data={\"data\":[]}")
94
95###############################################################################
96
97
98###############################################################################
99def wait_for_activation_state_change(version_id, initial_state):
100
101 r"""
102 Wait for the current activation state of ${version_id} to
103 change from the state provided by the calling function.
104
105 Description of argument(s):
106 version_id The version ID whose state change we are waiting for.
107 initial_state The activation state we want to wait for.
108 """
109
110 keyword.run_key_u("Open Connection And Log In")
111 retry = 0
112 while (retry < 20):
113 status, software_state = keyword.run_key("Read Properties " +
114 var.SOFTWARE_VERSION_URI + str(version_id))
115 current_state = (software_state)["Activation"]
116 if (initial_state == current_state):
117 time.sleep(60)
118 retry += 1
119 else:
120 return
121 return
122
123###############################################################################
124
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500125
126###############################################################################
127def get_latest_file(dir_path):
128
129 r"""
130 Get the path to the latest uploaded file.
131
132 Description of argument(s):
133 dir_path Path to the dir from which the name of the last
134 updated file or folder will be returned to the
135 calling function.
136 """
137
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500138 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500139 status, ret_values =\
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500140 keyword.run_key("Execute Command On BMC cd " + dir_path
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500141 + "; stat -c '%Y %n' * | sort -k1,1nr | head -n 1", ignore=1)
142 return ret_values.split(" ")[-1]
143
144###############################################################################
145
146
147###############################################################################
148def get_version_tar(tar_file_path):
149
150 r"""
151 Read the image version from the MANIFEST inside the tarball.
152
153 Description of argument(s):
154 tar_file_path The path to a tar file that holds the image
155 version inside the MANIFEST.
156 """
157
158 tar = tarfile.open(tar_file_path)
159 for member in tar.getmembers():
160 f=tar.extractfile(member)
161 content=f.read()
162 if "version=" in content:
163 content = content.split("\n")
164 content = [x for x in content if "version=" in x]
165 version = content[0].split("=")[-1]
166 break
167 tar.close()
168 return version
169
170###############################################################################
171
172
173###############################################################################
174def get_image_version(file_path):
175
176 r"""
177 Read the file for a version object.
178
179 Description of argument(s):
180 file_path The path to a file that holds the image version.
181 """
182
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500183 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500184 status, ret_values =\
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500185 keyword.run_key("Execute Command On BMC cat "
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500186 + file_path + " | grep \"version=\"", ignore=1)
187 return (ret_values.split("\n")[0]).split("=")[-1]
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500188
189###############################################################################
190
191
192###############################################################################
193def get_image_purpose(file_path):
194
195 r"""
196 Read the file for a purpose object.
197
198 Description of argument(s):
199 file_path The path to a file that holds the image purpose.
200 """
201
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500202 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500203 status, ret_values =\
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500204 keyword.run_key("Execute Command On BMC cat "
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500205 + file_path + " | grep \"purpose=\"", ignore=1)
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500206 return ret_values.split("=")[-1]
207
208###############################################################################
209
210
211###############################################################################
212def get_image_path(image_version):
213
214 r"""
215 Query the upload image dir for the presence of image matching
216 the version that was read from the MANIFEST before uploading
217 the image. Based on the purpose verify the activation object
218 exists and is either READY or INVALID.
219
220 Description of argument(s):
221 image_version The version of the image that should match one
222 of the images in the upload dir.
223 """
224
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500225 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500226 status, image_list =\
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500227 keyword.run_key("Execute Command On BMC ls -d "
228 + var.IMAGE_UPLOAD_DIR_PATH + "*/")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500229
230 image_list = image_list.split("\n")
231 retry = 0
232 while (retry < 10):
233 for i in range(0, len(image_list)):
234 version = get_image_version(image_list[i] + "MANIFEST")
235 if (version == image_version):
236 return image_list[i]
237 time.sleep(10)
238 retry += 1
239
240###############################################################################
241
242
243###############################################################################
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500244def verify_image_upload(image_version,
245 timeout=3):
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500246
247 r"""
248 Verify the image was uploaded correctly and that it created
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500249 a valid d-bus object. If the first check for the image
250 fails, try again until we reach the timeout.
251
252 Description of argument(s):
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500253 image_version The version from the image's manifest file
254 (e.g. "IBM-witherspoon-redbud-ibm-OP9_v1.17_1.68").
255 timeout How long, in minutes, to keep trying to find the
256 image on the BMC. Default is 3 minutes.
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500257 """
258
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500259 image_path = get_image_path(image_version)
260 image_version_id = image_path.split("/")[-2]
261
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500262 keyword.run_key_u("Open Connection And Log In")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500263 image_purpose = get_image_purpose(image_path + "MANIFEST")
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500264 if (image_purpose == var.VERSION_PURPOSE_BMC or
265 image_purpose == var.VERSION_PURPOSE_HOST):
George Keishingff1e3ec2017-07-20 01:58:21 -0500266 uri = var.SOFTWARE_VERSION_URI + image_version_id
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500267 ret_values = ""
268 for itr in range(timeout * 2):
269 status, ret_values = \
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500270 keyword.run_key("Read Attribute " + uri + " Activation")
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500271
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500272 if ((ret_values == var.READY) or (ret_values == var.INVALID)
273 or (ret_values == var.ACTIVE)):
Charles Paul Hofercef61992017-08-18 10:14:18 -0500274 return True, image_version_id
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500275 else:
276 time.sleep(30)
277
278 # If we exit the for loop, the timeout has been reached
279 gp.print_var(ret_values)
Charles Paul Hofercef61992017-08-18 10:14:18 -0500280 return False, None
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500281 else:
Saqib Khanbb8b63f2017-05-24 10:58:01 -0500282 gp.print_var(image_purpose)
Charles Paul Hofercef61992017-08-18 10:14:18 -0500283 return False, None
Saqib Khanfb1f6ae2017-04-26 13:24:41 -0500284
285###############################################################################
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500286
287
288###############################################################################
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500289def verify_image_not_in_bmc_uploads_dir(image_version, timeout=3):
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500290
291 r"""
292 Check that an image with the given version is not unpacked inside of the
293 BMCs image uploads directory. If no image is found, retry every 30 seconds
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500294 until the given timeout is hit, in case the BMC takes time
295 unpacking the image.
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500296
297 Description of argument(s):
298 image_version The version of the image to look for on the BMC.
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500299 timeout How long, in minutes, to try to find an image on the BMC.
300 Default is 3 minutes.
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500301 """
302
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500303 keyword.run_key('Open Connection And Log In')
Charles Paul Hofer6b972682017-07-20 11:36:56 -0500304 for i in range(timeout * 2):
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500305 stat, grep_res = keyword.run_key('Execute Command On BMC '
Charles Paul Hofer9f74d3a2017-08-18 09:54:28 -0500306 + 'ls ' + var.IMAGE_UPLOAD_DIR_PATH + '*/MANIFEST 2>/dev/null '
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500307 + '| xargs grep -rl "version=' + image_version + '"')
308 image_dir = os.path.dirname(grep_res.split('\n')[0])
309 if '' != image_dir:
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500310 keyword.run_key('Execute Command On BMC rm -rf ' + image_dir)
Charles P. Hofer1d20acd2017-07-05 15:24:40 -0500311 BuiltIn().fail('Found invalid BMC Image: ' + image_dir)
312 time.sleep(30)
313
Charles Paul Hoferde7d4082017-08-08 14:41:01 -0500314###############################################################################