From 8dc0edb319b5d7fa2d5310dc672f92c3cfa9cd7b Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Fri, 20 Jul 2018 16:19:58 +0530 Subject: [PATCH 01/13] Bug 140983 - Run LXCA Python cmd disconnect return failed --- pylxca/pylxca_api/lxca_api.py | 45 ++++++++++++++++++++++++---- pylxca/pylxca_api/lxca_connection.py | 6 +++- pylxca/pylxca_cmd/lxca_cmd.py | 2 +- pylxca/pylxca_cmd/lxca_cmd_data.json | 6 ++-- pylxca/pylxca_cmd/lxca_pyshell.py | 41 +++++++++++++++++-------- setup.py | 2 +- 6 files changed, 80 insertions(+), 22 deletions(-) diff --git a/pylxca/pylxca_api/lxca_api.py b/pylxca/pylxca_api/lxca_api.py index dc6f3ef..9dfb5ca 100644 --- a/pylxca/pylxca_api/lxca_api.py +++ b/pylxca/pylxca_api/lxca_api.py @@ -50,6 +50,7 @@ def __init__(self): self.con = None self.func_dict = {'connect':self.connect, + 'disconnect':self.disconnect, 'chassis':self.get_chassis, 'nodes':self.get_nodes, 'switches':self.get_switches, @@ -89,13 +90,17 @@ def api( self, object_name, dict_handler = None, con = None ): # If Any connection is establibshed if con == None and self.con and isinstance(self.con,lxca_connection): con = self.con - + + if object_name == "disconnect": + dict_handler['orig_con'] = self.con + if object_name != "connect": if con and isinstance(con,lxca_connection): self.con = con else: raise ConnectionError("Invalid Connection Object") + return self.func_dict[object_name](dict_handler) except ConnectionError as re: logger.error("Connection Exception: Exception = %s", re) @@ -140,13 +145,43 @@ def connect( self, dict_handler = None ): self.con = None return self.con - def disconnect( self ): + def disconnect( self, dict_handler=None): + """ + this method perform disconnect operation + it also reset current connection to original connection this is used in api version + to retain origianal connection if we are disconnecting other than current connection + + i.e + con1 = connect(...) + con2 = connect(...) + con3 = connect(...) + con4 = connect(...) + + disconnect(con2) will keep current connection to con4 + disconnect(con4) or disconnect() will set current connection to None + + :param dict_handler: orig_con have original connection before call of disconnect() + :return: + """ if not self.con: raise ConnectionError("Connection is not Initialized.") - self.con.disconnect() - self.con = None + + reset_conn_to_orig = False + if dict_handler and dict_handler.has_key("orig_con"): + if self.con != dict_handler['orig_con']: + reset_conn_to_orig = True + try: + self.con.disconnect() + except Exception as e: + if reset_conn_to_orig: + self.con = dict_handler['orig_con'] + raise + if reset_conn_to_orig: + self.con = dict_handler['orig_con'] + else: + self.con = None return True - + def get_log_level(self, dict_handler=None): lvl = None if dict_handler: diff --git a/pylxca/pylxca_api/lxca_connection.py b/pylxca/pylxca_api/lxca_connection.py index 029c0ce..6c99273 100644 --- a/pylxca/pylxca_api/lxca_connection.py +++ b/pylxca/pylxca_api/lxca_connection.py @@ -130,7 +130,11 @@ def disconnect(self): self.user = None self.passwd = None self.debug = False - self.session.close() + try: + self.session.close() + except Exception as e: + logger.debug("Connection with invalid session = %s", e) + raise Exception("Invalid connection: Connection is not Initialized") self.session = None def ping(self, host): diff --git a/pylxca/pylxca_cmd/lxca_cmd.py b/pylxca/pylxca_cmd/lxca_cmd.py index 4a86444..71ac2d0 100644 --- a/pylxca/pylxca_cmd/lxca_cmd.py +++ b/pylxca/pylxca_cmd/lxca_cmd.py @@ -91,7 +91,7 @@ class disconnect(InteractiveCommand): disconnect -h | --help disconnect """ - def handle_no_input(self): + def handle_no_input(self, con_obj = None): api = pylxca.pylxca_api.lxca_api() if api.disconnect() == True: self.sprint("Connection with LXCA closed successfully " ) diff --git a/pylxca/pylxca_cmd/lxca_cmd_data.json b/pylxca/pylxca_cmd/lxca_cmd_data.json index 2157f05..fb1118a 100644 --- a/pylxca/pylxca_cmd/lxca_cmd_data.json +++ b/pylxca/pylxca_cmd/lxca_cmd_data.json @@ -100,8 +100,10 @@ "Get/set log level of Python LXCA" ], "disconnect": [ - "h", - [], + "c:h", + [ + "con=" + ], "Disconnect LXCA" ], "ostream": [ diff --git a/pylxca/pylxca_cmd/lxca_pyshell.py b/pylxca/pylxca_cmd/lxca_pyshell.py index bab1ca2..f483011 100644 --- a/pylxca/pylxca_cmd/lxca_pyshell.py +++ b/pylxca/pylxca_cmd/lxca_pyshell.py @@ -111,7 +111,21 @@ def disconnect(*args, **kwargs): @summary: Use this function to disconnect from Lenovo XClarity Administrator run this function as - disconnect() + disconnect() + + + it also reset internal current connection to original connection this is used in api version + to retain origianal connection if we are disconnecting other than current connection + + i.e + con1 = connect(...) + con2 = connect(...) + con3 = connect(...) + con4 = connect(...) current internal connection is con4 + + disconnect(con2) will keep current connection to con4 + disconnect(con4) or disconnect() will set current connection to None + @param The parameters for this command are as follows @@ -121,20 +135,23 @@ def disconnect(*args, **kwargs): @example disconnect() ''' - global shell_obj + command_name = sys._getframe().f_code.co_name + param_dict = {} + con = None + + long_short_key_map = {} keylist = ['con'] - if len(args) == 0 and len(kwargs) == 0: - return - - for i in range(len(args)): - #print args[i] - kwargs[keylist[i]]= args[i] - - con = shell_obj.handle_input_args(command_name, args=args, kwargs=kwargs) - - return con + optional_keylist = ['con'] + mutually_exclusive_keys = [] + mandatory_options_list = {} + + con = _validate_param(keylist, long_short_key_map, mandatory_options_list, optional_keylist, mutually_exclusive_keys, + param_dict, *args, **kwargs) + + out_obj = shell_obj.handle_input_dict(command_name, con, param_dict) + return out_obj def cmms(*args, **kwargs): ''' diff --git a/setup.py b/setup.py index 4a401d8..7c9696a 100755 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ def read(fname): classifiers = [ "Development Status :: 3 - Alpha", "Topic :: Utilities", - "License :: Lenovo License", + "License :: License :: OSI Approved :: Apache Software License ", ], ) else: From 39ce8507d0ef6cdc195b03dab339213a6351a9d5 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Tue, 24 Jul 2018 12:00:36 +0530 Subject: [PATCH 02/13] Created branch pylxca_v220_maint --- pylxca/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylxca/__init__.py b/pylxca/__init__.py index 7687909..2d44dcd 100644 --- a/pylxca/__init__.py +++ b/pylxca/__init__.py @@ -1,6 +1,6 @@ # Version of the pylxca package -__version__ = '2.99.99' +__version__ = '2.2.0' # There are submodules, but clients shouldn't need to know about them. From 15d2b144c2f7e207b2332f75cf5d1ef781c0beb0 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Thu, 26 Jul 2018 17:30:59 +0530 Subject: [PATCH 03/13] Bug 140983 - Call delete on session to see effect on UI --- pylxca/pylxca_api/lxca_api.py | 5 +++-- pylxca/pylxca_api/lxca_connection.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pylxca/pylxca_api/lxca_api.py b/pylxca/pylxca_api/lxca_api.py index 9dfb5ca..53db08a 100644 --- a/pylxca/pylxca_api/lxca_api.py +++ b/pylxca/pylxca_api/lxca_api.py @@ -163,6 +163,7 @@ def disconnect( self, dict_handler=None): :param dict_handler: orig_con have original connection before call of disconnect() :return: """ + resp = False if not self.con: raise ConnectionError("Connection is not Initialized.") @@ -171,7 +172,7 @@ def disconnect( self, dict_handler=None): if self.con != dict_handler['orig_con']: reset_conn_to_orig = True try: - self.con.disconnect() + resp = self.con.disconnect() except Exception as e: if reset_conn_to_orig: self.con = dict_handler['orig_con'] @@ -180,7 +181,7 @@ def disconnect( self, dict_handler=None): self.con = dict_handler['orig_con'] else: self.con = None - return True + return resp def get_log_level(self, dict_handler=None): lvl = None diff --git a/pylxca/pylxca_api/lxca_connection.py b/pylxca/pylxca_api/lxca_connection.py index 6c99273..d996bae 100644 --- a/pylxca/pylxca_api/lxca_connection.py +++ b/pylxca/pylxca_api/lxca_connection.py @@ -126,6 +126,17 @@ def disconnect(self): ''' session Disconnection ''' + result = False + try: + delete_url = self.url + '/sessions' + resp = self.session.delete(delete_url, verify=False, timeout=3) + py_obj = json.loads(resp.text) + logger.debug("Deleted session on lxca = %s", py_obj) + result = True + except Exception as e: + logger.debug("Unable to delete session on lxca = %s", e) + raise ConnectionError("Invalid connection: Connection is not Initialized") + self.url = None self.user = None self.passwd = None @@ -136,6 +147,7 @@ def disconnect(self): logger.debug("Connection with invalid session = %s", e) raise Exception("Invalid connection: Connection is not Initialized") self.session = None + return result def ping(self, host): """ From 181e88230e0859c6551c2cbe75c3b3f5c2fce599 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Tue, 21 Aug 2018 15:24:21 +0530 Subject: [PATCH 04/13] LXCA-13028 Added option prioritized for mode in updatecomp --- pylxca/pylxca_api/lxca_rest.py | 4 ++-- pylxca/pylxca_cmd/lxca_cmd.py | 2 ++ pylxca/pylxca_cmd/lxca_pyshell.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pylxca/pylxca_api/lxca_rest.py b/pylxca/pylxca_api/lxca_rest.py index cf0420a..7ad3712 100644 --- a/pylxca/pylxca_api/lxca_rest.py +++ b/pylxca/pylxca_api/lxca_rest.py @@ -847,7 +847,7 @@ def do_updatecomp(self, url, session, query, mode, action, server, switch, stora url= url + "?action=" + action - if not mode == None and mode == "immediate" or mode == "delayed" : + if not mode == None and mode == "immediate" or mode == "delayed" or mode == "prioritized": url= url + "&activationMode=" + mode else: raise Exception("Invalid argument mode") @@ -927,7 +927,7 @@ def do_updatecomp_all(self, url, session, action, mode,dev_list): if action == "apply" or action == "cancelApply": url = url + "?action=" + action - if not mode == None and mode == "immediate" or mode == "delayed": + if not mode == None and mode == "immediate" or mode == "delayed" or mode == "prioritized": url = url + "&activationMode=" + mode else: raise Exception("Invalid argument mode") diff --git a/pylxca/pylxca_cmd/lxca_cmd.py b/pylxca/pylxca_cmd/lxca_cmd.py index 71ac2d0..47c01b4 100644 --- a/pylxca/pylxca_cmd/lxca_cmd.py +++ b/pylxca/pylxca_cmd/lxca_cmd.py @@ -620,6 +620,8 @@ class updatecomp(InteractiveCommand): -m, --mode Indicates when to activate the update. This can be one of the following values. immediate - Uses Immediate Activation mode when applying firmware updates to the selected endpoints. delayed - Uses Delayed Activation mode when applying firmware updates to the selected endpoints. + prioritized - Firmware updates on the baseboard management controller are activated immediately + -a, --action The action to take. This can be one of the following values. apply - Applies the associated firmware to the submitted components. power - Perform power action on selected endpoint. diff --git a/pylxca/pylxca_cmd/lxca_pyshell.py b/pylxca/pylxca_cmd/lxca_pyshell.py index f483011..d3c4aec 100644 --- a/pylxca/pylxca_cmd/lxca_pyshell.py +++ b/pylxca/pylxca_cmd/lxca_pyshell.py @@ -929,6 +929,7 @@ def updatecomp(*args, **kwargs): mode Indicates when to activate the update. This can be one of the following values. immediate - Uses Immediate Activaton mode when applying firmware updates to the selected endpoints. delayed - Uses Delayed Activaton mode when applying firmware updates to the selected endpoints. + prioritized. Firmware updates on the baseboard management controller are activated immediately action The action to take. This can be one of the following values. apply - Applies the associated firmware to the submitted components. From a7cba4f13069dac7fee0b638036ff5826427824f Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Mon, 3 Sep 2018 14:13:51 +0530 Subject: [PATCH 05/13] Changed License to Appache 2.0 --- LICENSE | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- README | 8 --- setup.py | 4 +- 3 files changed, 203 insertions(+), 15 deletions(-) diff --git a/LICENSE b/LICENSE index 9a9ef35..8dada3e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,201 @@ -(C) Copyright Lenovo 2015. -LIMITED AND RESTRICTED RIGHTS NOTICE: -If data or software is delivered pursuant a General Services -Administration (GSA) contract, use, reproduction, or disclosure -is subject to restrictions set forth in Contract No. GS-35F-05925. \ No newline at end of file + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README b/README index 9dcd835..1fc3206 100644 --- a/README +++ b/README @@ -83,11 +83,3 @@ The sample scripts are location in the following directory: lib/python2.7/site-packages/pylxca-1.0-py2.7.egg/pylxca\test -License -------- - -(C) Copyright Lenovo 2015. -LIMITED AND RESTRICTED RIGHTS NOTICE: -If data or software is delivered pursuant a General Services -Administration (GSA) contract, use, reproduction, or disclosure -is subject to restrictions set forth in Contract No. GS-35F-05925. \ No newline at end of file diff --git a/setup.py b/setup.py index 7c9696a..ad01ba6 100755 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ def read(fname): classifiers = [ "Development Status :: 3 - Alpha", "Topic :: Utilities", - "License :: License :: OSI Approved :: Apache Software License ", + "License :: Apache License 2.0 ", ], ) else: @@ -69,6 +69,6 @@ def read(fname): classifiers=[ "Development Status :: 3 - Alpha", "Topic :: Utilities", - "License :: Lenovo License", + "License :: Apache License 2.0", ], ) From b76d6dac8b022d8ee5c71a0083ff8d1238deea50 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Mon, 3 Sep 2018 15:32:24 +0530 Subject: [PATCH 06/13] Bug145265 Update license to Apache 2.0 --- README | 4 +++- setup.py | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README b/README index 1fc3206..e379641 100644 --- a/README +++ b/README @@ -82,4 +82,6 @@ Several sample scripts are also available to help you to quickly begin using the The sample scripts are location in the following directory: lib/python2.7/site-packages/pylxca-1.0-py2.7.egg/pylxca\test - +License +------- +Apache Software License (http://www.apache.org/licenses/LICENSE-2.0) diff --git a/setup.py b/setup.py index ad01ba6..3d2a457 100755 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ def read(fname): author = "Girish Kumar, Prashant Bhosle", author_email = "gkumar1@lenovo.com, pbhosle@lenovo.com", description = ("It is tool/api to connect LXCA from command line"), - license = "LENOVO", + license = "Apache License 2.0", keywords = "PYLXCA", url = "http://www.lenovo.com", packages = ['pylxca','pylxca.pylxca_api','pylxca.pylxca_cmd'], @@ -47,7 +47,7 @@ def read(fname): classifiers = [ "Development Status :: 3 - Alpha", "Topic :: Utilities", - "License :: Apache License 2.0 ", + "License :: OSI Approved :: Apache Software License", ], ) else: @@ -57,7 +57,7 @@ def read(fname): author="Girish Kumar, Prashant Bhosle", author_email="gkumar1@lenovo.com, pbhosle@lenovo.com", description=("It is tool/api to connect LXCA from command line"), - license="LENOVO", + license = "Apache License 2.0", keywords="PYLXCA", url="http://www.lenovo.com", packages=['pylxca', 'pylxca.pylxca_api', 'pylxca.pylxca_cmd'], @@ -69,6 +69,6 @@ def read(fname): classifiers=[ "Development Status :: 3 - Alpha", "Topic :: Utilities", - "License :: Apache License 2.0", + "License :: OSI Approved :: Apache Software License", ], ) From e3e1521c0cbe11f4e546048ad749bc5deb274555 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Wed, 19 Sep 2018 16:03:02 +0530 Subject: [PATCH 07/13] Ported to python 2.6 --- pylxca/pylxca_api/lxca_rest.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pylxca/pylxca_api/lxca_rest.py b/pylxca/pylxca_api/lxca_rest.py index 7ad3712..b2dc3e2 100644 --- a/pylxca/pylxca_api/lxca_rest.py +++ b/pylxca/pylxca_api/lxca_rest.py @@ -1272,8 +1272,8 @@ def get_osimage(self, osimages_info, **kwargs): session = kwargs['session'] # url = baseurl + '/osImages' url = '' - kwargs = {key: kwargs[key] for key in kwargs if key not in ['url', 'session']} - + kwargs.pop("url", None) + kwargs.pop("session", None) if not osimages_info and ('id' not in kwargs or 'fileName' not in kwargs): url = baseurl + '/osImages' if 'hostPlatforms' in osimages_info: @@ -1309,7 +1309,8 @@ def set_osimage(self, osimages_info, **kwargs): baseurl = kwargs['url'] session = kwargs['session'] url = baseurl + '/osImages' - kwargs = {key: kwargs[key] for key in kwargs if key not in ['url', 'session']} + kwargs.pop("url", None) + kwargs.pop("session", None) payload = dict() # print "i'm in lxca_rest, set_osimage args,kwargs", args, kwargs From 1e91a58022eb6fdd24dedea1a332b95f92ae5c9e Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Fri, 28 Sep 2018 12:32:48 +0530 Subject: [PATCH 08/13] BUG147875 In lxca_shell, run ffdc return failed --- pylxca/pylxca_cmd/lxca_cmd.py | 2 +- pylxca/pylxca_cmd/lxca_pyshell.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pylxca/pylxca_cmd/lxca_cmd.py b/pylxca/pylxca_cmd/lxca_cmd.py index 47c01b4..e26effe 100644 --- a/pylxca/pylxca_cmd/lxca_cmd.py +++ b/pylxca/pylxca_cmd/lxca_cmd.py @@ -513,7 +513,7 @@ class ffdc(InteractiveCommand): Retrieve and Manage information about ffdc USAGE: - ffdc [-u ] + ffdc -u OPTIONS: -u, --uuid diff --git a/pylxca/pylxca_cmd/lxca_pyshell.py b/pylxca/pylxca_cmd/lxca_pyshell.py index d3c4aec..aa31f9b 100644 --- a/pylxca/pylxca_cmd/lxca_pyshell.py +++ b/pylxca/pylxca_cmd/lxca_pyshell.py @@ -1035,9 +1035,10 @@ def ffdc(*args, **kwargs): @param The parameters for this command are as follows - uuid UUID of the target endpoint + uuid UUID of the target endpoint this is manadatory parameter -@example +@example + ffdc(con = lxca_con, uuid='UUID of endpoint") ''' global shell_obj From 4e89217ca096571f83628ec27bf038308ea98143 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Fri, 28 Sep 2018 15:03:40 +0530 Subject: [PATCH 09/13] BUG147872 The behaviors are different when run unsupported parmeter in lxca_shell and script --- pylxca/pylxca_cmd/lxca_pyshell.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pylxca/pylxca_cmd/lxca_pyshell.py b/pylxca/pylxca_cmd/lxca_pyshell.py index aa31f9b..61dab23 100644 --- a/pylxca/pylxca_cmd/lxca_pyshell.py +++ b/pylxca/pylxca_cmd/lxca_pyshell.py @@ -1379,6 +1379,11 @@ def _validate_param(keylist, long_short_key_map, mandatory_options_list, optiona me_key, str(mutually_exclusive_keys))) raise AttributeError("Invalid command invocation") me_key_found = True + + if not set(keylist).issuperset(set(kwargs.keys())): + logger.error(" Invalid Input args: %s unsupported argument passed" % list(set(kwargs.keys()).difference(set(keylist)))) + raise ValueError("Invalid Input Arguments") + return con def osimages(*args, **kwargs): @@ -1447,6 +1452,7 @@ def osimages(*args, **kwargs): con = None param_dict = {} param_dict = kwargs + kwargs = {} # this is required to avoid invalid argument error in _validate_param command_name = sys._getframe().f_code.co_name long_short_key_map = {'osimages_info':'i'} From 6c50f87d2501cab37a1c3210332a1a4f21dd883e Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Sat, 29 Sep 2018 12:07:59 +0530 Subject: [PATCH 10/13] Bug 147879 - The behaviors are different when run log in lxca_shell and script --- pylxca/pylxca_api/lxca_api.py | 2 +- pylxca/pylxca_api/lxca_rest.py | 5 ++++- pylxca/pylxca_cmd/lxca_cmd.py | 4 ++-- pylxca/pylxca_cmd/lxca_pyshell.py | 29 ++++++++++++++++++++++------- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/pylxca/pylxca_api/lxca_api.py b/pylxca/pylxca_api/lxca_api.py index 53db08a..8ca48af 100644 --- a/pylxca/pylxca_api/lxca_api.py +++ b/pylxca/pylxca_api/lxca_api.py @@ -186,7 +186,7 @@ def disconnect( self, dict_handler=None): def get_log_level(self, dict_handler=None): lvl = None if dict_handler: - lvl = dict_handler['l'] or dict_handler['lvl'] + lvl = next((item for item in [dict_handler.get('l') , dict_handler.get('lvl')] if item is not None),None) if lvl == None: lvl = lxca_rest().get_log_level() else: diff --git a/pylxca/pylxca_api/lxca_rest.py b/pylxca/pylxca_api/lxca_rest.py index b2dc3e2..e8a16ab 100644 --- a/pylxca/pylxca_api/lxca_rest.py +++ b/pylxca/pylxca_api/lxca_rest.py @@ -225,10 +225,13 @@ def set_log_config(self): def get_log_level(self): logger.debug("Current Log Level is: " + str(logger.getEffectiveLevel())) - return logger.getEffectiveLevel() + return logging.getLevelName(logger.getEffectiveLevel()) def set_log_level(self,log_value): logger.setLevel(log_value) + for handler in logger.handlers: + handler.setLevel(log_value) + logger.debug("Current Log Level is: " + str(logger.getEffectiveLevel())) return def do_discovery(self,url, session, ip_addr,jobid): diff --git a/pylxca/pylxca_cmd/lxca_cmd.py b/pylxca/pylxca_cmd/lxca_cmd.py index e26effe..c9635c4 100644 --- a/pylxca/pylxca_cmd/lxca_cmd.py +++ b/pylxca/pylxca_cmd/lxca_cmd.py @@ -115,7 +115,7 @@ class log(InteractiveCommand): """ def handle_no_input(self,con_obj = None): api = pylxca.pylxca_api.lxca_api() - self.sprint("Current Log Level is set to " + str(logging.getLevelName(api.get_log_level()))) + self.sprint("Current Log Level is set to " + str(api.get_log_level())) message = """ Possible Log Levels, Please use following values to set desired log level. @@ -132,7 +132,7 @@ def handle_no_input(self,con_obj = None): def handle_output(self, out_obj): api = pylxca.pylxca_api.lxca_api() if out_obj == True: - self.sprint("Current Log Level is set to " + logging.getLevelName(api.get_log_level())) + self.sprint("Current Log Level is set to " + api.get_log_level()) else: self.sprint("Fail to set Log Level") message = """ diff --git a/pylxca/pylxca_cmd/lxca_pyshell.py b/pylxca/pylxca_cmd/lxca_pyshell.py index 61dab23..372f523 100644 --- a/pylxca/pylxca_cmd/lxca_pyshell.py +++ b/pylxca/pylxca_cmd/lxca_pyshell.py @@ -1070,25 +1070,40 @@ def log(*args, **kwargs): Where KeyList is as follows - keylist = ['con','filter'] + keylist = ['con','lvl'] @param The parameters for this command are as follows - filter filter for the event + lvl log level to be set + Possible Log Levels, Please use following values to set desired log level. + + DEBUG: Detailed information, typically of interest only when diagnosing problems. + INFO: Confirmation that things are working as expected. + WARNING: An indication that something unexpected happened, or indicative of some problem in the near future. + ERROR: Due to a more serious problem, the software has not been able to perform some function. + CRITICAL: A serious error, indicating that the program itself may be unable to continue running. @example ''' global shell_obj command_name = sys._getframe().f_code.co_name - keylist = ['lvl'] - for i in range(len(args)): - kwargs[keylist[i]] = args[i] + param_dict = {} + con = None + + long_short_key_map = {'lvl':'l'} + keylist = ['con','lvl'] + optional_keylist = ['con', 'lvl'] + mutually_exclusive_keys = [] + mandatory_options_list = {} - ch = shell_obj.handle_input_args(command_name, args=args, kwargs=kwargs) - return ch + con = _validate_param(keylist, long_short_key_map, mandatory_options_list, optional_keylist, mutually_exclusive_keys, + param_dict, *args, **kwargs) + + out_obj = shell_obj.handle_input_dict(command_name, con, param_dict) + return out_obj def lxcalog(*args, **kwargs): ''' From c48dff56c0bbe8b37c481b3521e3358e040273f8 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Sat, 29 Sep 2018 12:23:52 +0530 Subject: [PATCH 11/13] Bug 147872 corrected for handling short parameters --- pylxca/pylxca_cmd/lxca_pyshell.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pylxca/pylxca_cmd/lxca_pyshell.py b/pylxca/pylxca_cmd/lxca_pyshell.py index 372f523..1dcdef5 100644 --- a/pylxca/pylxca_cmd/lxca_pyshell.py +++ b/pylxca/pylxca_cmd/lxca_pyshell.py @@ -1395,8 +1395,9 @@ def _validate_param(keylist, long_short_key_map, mandatory_options_list, optiona raise AttributeError("Invalid command invocation") me_key_found = True - if not set(keylist).issuperset(set(kwargs.keys())): - logger.error(" Invalid Input args: %s unsupported argument passed" % list(set(kwargs.keys()).difference(set(keylist)))) + if not set(keylist + long_short_key_map.values()).issuperset(set(kwargs.keys())): + logger.error(" Invalid Input args: %s unsupported argument passed" + % list(set(kwargs.keys()).difference(set(keylist + long_short_key_map.values())))) raise ValueError("Invalid Input Arguments") return con From c08824f6a71a8cd3ac3caf264edf6e86b8920ce6 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Mon, 22 Oct 2018 14:03:03 +0530 Subject: [PATCH 12/13] Bug 150096 - In lxca_shell, cannot get specific jobs detail --- pylxca/pylxca_api/lxca_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pylxca/pylxca_api/lxca_api.py b/pylxca/pylxca_api/lxca_api.py index 8ca48af..d224316 100644 --- a/pylxca/pylxca_api/lxca_api.py +++ b/pylxca/pylxca_api/lxca_api.py @@ -581,6 +581,7 @@ def get_jobs( self, dict_handler = None ): try: if jobid: py_obj = json.loads(resp.text) + return py_obj if canceljobid or deletejobid: return resp else: From 9ffd59faf625174b0bc9a3f31d8148e7872b64c5 Mon Sep 17 00:00:00 2001 From: Naval Patel Date: Mon, 22 Oct 2018 15:25:39 +0530 Subject: [PATCH 13/13] Bug150096 modified to return jobsList even for specific jobs --- pylxca/pylxca_api/lxca_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pylxca/pylxca_api/lxca_api.py b/pylxca/pylxca_api/lxca_api.py index d224316..0d40456 100644 --- a/pylxca/pylxca_api/lxca_api.py +++ b/pylxca/pylxca_api/lxca_api.py @@ -581,6 +581,7 @@ def get_jobs( self, dict_handler = None ): try: if jobid: py_obj = json.loads(resp.text) + py_obj = {'jobsList': [py_obj]} return py_obj if canceljobid or deletejobid: return resp