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###############################################################################