├── library ├── __init__.py └── pylxca_module.py ├── files ├── compliance_plugins │ ├── __init__.py │ └── test_plugin │ │ ├── __init__.py │ │ └── test_plugin.py └── resource_groups.json ├── site.yml ├── playbooks ├── uhm │ ├── pylxca.yml │ ├── thinkagile.yml │ ├── fw_update.yml │ ├── compliance.yml │ └── manifests.yml ├── config │ ├── config.yml │ └── firmware_update_all_dev.yml └── inventory │ └── inventory.yml ├── docs └── LXCA_Ansible_User_Guide.pdf ├── roles └── pre │ └── tasks │ └── main.yml ├── .gitmodules ├── LICENSE.BSD ├── test ├── test_config_playbooks.sh └── test_pylxca_module.py ├── ansible.cfg └── README.md /library/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /files/compliance_plugins/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /files/compliance_plugins/test_plugin/__init__.py: -------------------------------------------------------------------------------- 1 | from test_plugin import * -------------------------------------------------------------------------------- /site.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # file: site.yml 3 | - include: playbooks/inventory/inventory.yml -------------------------------------------------------------------------------- /playbooks/uhm/pylxca.yml: -------------------------------------------------------------------------------- 1 | hosts: localhost 2 | connection: local 3 | - easy_install: 4 | name: pip 5 | -------------------------------------------------------------------------------- /docs/LXCA_Ansible_User_Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lenovo/ansible.lenovo-lxca/HEAD/docs/LXCA_Ansible_User_Guide.pdf -------------------------------------------------------------------------------- /playbooks/uhm/thinkagile.yml: -------------------------------------------------------------------------------- 1 | - name: Calling UHM Role 2 | hosts: localhost 3 | connection: local 4 | roles: 5 | - { role: lenovo.lxca-uhm } 6 | -------------------------------------------------------------------------------- /playbooks/uhm/fw_update.yml: -------------------------------------------------------------------------------- 1 | - name: Do Firmware update 2 | hosts: localhost 3 | connection: local 4 | roles: 5 | - { role: lenovo.lxca-config } 6 | -------------------------------------------------------------------------------- /playbooks/config/config.yml: -------------------------------------------------------------------------------- 1 | - name: Calling Config Role 2 | hosts: localhost 3 | connection: local 4 | roles: 5 | - pre 6 | - lenovo.lxca-config 7 | -------------------------------------------------------------------------------- /playbooks/inventory/inventory.yml: -------------------------------------------------------------------------------- 1 | - name: Calling Inventory Role 2 | hosts: localhost 3 | connection: local 4 | roles: 5 | - pre 6 | - lenovo.lxca-inventory 7 | -------------------------------------------------------------------------------- /playbooks/uhm/compliance.yml: -------------------------------------------------------------------------------- 1 | - name: Executing Compliance Engine 2 | hosts: localhost 3 | connection: local 4 | gather_facts: no 5 | 6 | roles: 7 | - { role: lenovo.lxca-compliance } -------------------------------------------------------------------------------- /roles/pre/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # Installs the pylxca python library that is going to be used by the pylxca_module 2 | - name: Install PyLXCA dependency 3 | pip: 4 | name: pylxca 5 | name: jsonpath-ng 6 | tags: always 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "roles/lenovo.lxca-inventory"] 2 | path = roles/lenovo.lxca-inventory 3 | url = https://github.com/lenovo/ansible-role-lxca-inventory.git 4 | [submodule "roles/lenovo.lxca-config"] 5 | path = roles/lenovo.lxca-config 6 | url = https://github.com/lenovo/ansible-role-lxca-config.git 7 | -------------------------------------------------------------------------------- /files/compliance_plugins/test_plugin/test_plugin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ''' 3 | @since: 09 Sep 2017 4 | @author: Prashant Bhosale 5 | @license: Lenovo License 6 | @copyright: Copyright 2017, Lenovo 7 | @organization: Lenovo 8 | @summary: Test Plugin for Test compliance through dynamic script 9 | ''' 10 | 11 | 12 | def validate_compliance(): 13 | return True -------------------------------------------------------------------------------- /files/resource_groups.json: -------------------------------------------------------------------------------- 1 | { 2 | 'lxca_user': 'USERID', 3 | 'lxca_password': 'Passw0rd', 4 | 'lxca_url': 'https://10.240.29.217', 5 | 'resource_group_name': 'TEST4', 6 | 'description': 'TestGroup', 7 | 'type': 'solution', 8 | 'solutionVPD': { 9 | 'id': '59A54997C18DCF0594A8CCD2', 10 | 'machineType': 'TESTMTM', 11 | 'model': 'TESTMODEL', 12 | 'serialNumber': 'TESTSERIAL', 13 | 'manufacturer': 'LENOVO' 14 | }, 15 | 'members': [], 16 | 'criteria': [] 17 | } 18 | -------------------------------------------------------------------------------- /playbooks/uhm/manifests.yml: -------------------------------------------------------------------------------- 1 | - name: send solution manifest to LXCA 2 | hosts: localhost 3 | connection: local 4 | tasks: 5 | - name: manifests 6 | pylxca_module: 7 | command_options: manifests 8 | login_user: "{{ lxca_user }}" 9 | login_password: "{{ lxca_password }}" 10 | auth_url: "{{ lxca_url }}" 11 | sol_id: "{{ sol_id }}" 12 | manifest_path: "{{ manifest_path }}" 13 | register: conn 14 | - debug: 15 | var: conn 16 | 17 | -------------------------------------------------------------------------------- /LICENSE.BSD: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019-present Lenovo. All Rights Reserved 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /playbooks/config/firmware_update_all_dev.yml: -------------------------------------------------------------------------------- 1 | - name: Firmware update of all devices 2 | hosts: localhost 3 | connection: local 4 | 5 | tasks: 6 | - name: calling role main 7 | include_role: 8 | name: lenovo.lxca-config 9 | tasks_from: query_update_comp 10 | register: rslt 11 | 12 | - debug: 13 | var: rslt 14 | 15 | - name: Doing something else 16 | include_role: 17 | name: lenovo.lxca-inventory 18 | tasks_from: wait_for_task 19 | vars: 20 | id: 677 21 | 22 | # - name: Polling for Status of firmware update Operation 23 | # pylxca_module: 24 | # command_options: tasks 25 | # login_user: "{{ lxca_user }}" 26 | # login_password: "{{ lxca_password }}" 27 | # auth_url: "{{ lxca_url }}" 28 | # id: 677 29 | # register: result 30 | # until: result.result.TaskList[0].percentage == 100.0 31 | # retries: 40 32 | # delay: 15 33 | # 34 | # - debug: 35 | # var: result.result.TaskList[0] 36 | # 37 | # - name: Check firmware update job completion status 38 | # assert: 39 | # that: 40 | # - " 'Complete' in result.result.TaskList[0].status" 41 | # - " 'CompleteWithErrors' not in result.result.TaskList[0].status" 42 | 43 | # - name: Doing something else 44 | # include_role: 45 | # name: lenovo.lxca-config 46 | # tasks_from: update_firmware_all 47 | # vars: 48 | # dev_list: [{'CMMList':[{'UUID':'37C7341F6C5111E480C08D031750448E','Components': [{'Component': 'MM40F2E9BF5A1A'}]}]}] 49 | # action: 'apply' 50 | # mode: 'immediate' 51 | 52 | # post_tasks: 53 | # - debug: 54 | # msg: 'goodbye' 55 | # tags: post_tasks 56 | -------------------------------------------------------------------------------- /test/test_config_playbooks.sh: -------------------------------------------------------------------------------- 1 | rm -rf playbooks/config/pylxca.log 2 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 repo_key=importDir" playbooks/config/config.yml -v --tag query_update_comp 3 | 4 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 repo_key=lastRefreshed" playbooks/config/config.yml -v --tag query_update_status 5 | 6 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=publicKeys update_policy_info=RESULTS" playbooks/config/config.yml -v --tag updatepolicy 7 | 8 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=importDir" playbooks/config/config.yml -v --tag updatepolicy 9 | 10 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=lastRefreshed policy_info=FIRMWARE" playbooks/config/config.yml -v --tag updatepolicy 11 | 12 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=publicKeys update_policy_info=RESULTS" playbooks/config/config.yml -v --tag updatepolicy 13 | 14 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=importDir" playbooks/config/config.yml -v --tag updaterepo 15 | 16 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=lastRefreshed" playbooks/config/config.yml -v --tag updaterepo 17 | 18 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=publicKeys" playbooks/config/config.yml -v --tag updaterepo 19 | 20 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=size" playbooks/config/config.yml -v --tag updaterepo 21 | 22 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=supportedMts" playbooks/config/config.yml -v --tag updaterepo 23 | 24 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=updates" playbooks/config/config.yml -v --tag updaterepo 25 | 26 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=updatesByMt" playbooks/config/config.yml -v --tag updaterepo 27 | 28 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=query repo_key=updatesByMtByComp" playbooks/config/config.yml -v --tag updaterepo 29 | 30 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=list" playbooks/config/config.yml -v --tag configprofiles 31 | 32 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=list" playbooks/config/config.yml -v --tag get_configpatterns 33 | 34 | ansible-playbook -e "{'lxca_user':'USERID', 'lxca_password':'Passw0rd', 'lxca_url':'https://10.240.197.119', 'subcmd':'query', 'update_key':'importDir'}" playbooks/config/config.yml -v --tag get_managementserver_pkg 35 | 36 | ansible-playbook -e "{'lxca_user':'USERID', 'lxca_password':'Passw0rd', 'lxca_url':'https://10.240.197.119', 'subcmd':'query', 'update_key':'size'}" playbooks/config/config.yml -v --tag get_managementserver_pkg 37 | 38 | ansible-playbook -e "{'lxca_user':'USERID', 'lxca_password':'Passw0rd', 'lxca_url':'https://10.240.197.119', 'subcmd':'query', 'update_key':'updates'}" playbooks/config/config.yml -v --tag get_managementserver_pkg 39 | 40 | ansible-playbook -e "lxca_user=USERID lxca_password=Passw0rd lxca_url=https://10.240.197.119 subcmd=list" playbooks/config/config.yml -v --tag osimages 41 | 42 | grep -rni "error" playbooks/config/pylxca.log 43 | -------------------------------------------------------------------------------- /test/test_pylxca_module.py: -------------------------------------------------------------------------------- 1 | import mock 2 | from nose.tools import assert_equals 3 | from nose.tools import assert_not_equal 4 | from library import pylxca_module 5 | 6 | 7 | # this dict is used to get command_options 8 | func_dict = { 9 | 'connect': pylxca_module._get_connect_lxca, 10 | 'chassis': pylxca_module._get_chassis_inventory, 11 | 'cmms': pylxca_module._get_cmms_inventory, 12 | 'get_configpatterns': pylxca_module._get_configpatterns, 13 | 'get_particular_configpattern': pylxca_module._get_particular_configpattern, 14 | 'import_configpatterns': pylxca_module._import_configpatterns, 15 | 'apply_configpatterns': pylxca_module._apply_configpatterns, 16 | 'configprofiles': pylxca_module._get_configprofiles, 17 | 'configtargets': pylxca_module._get_configtargets, 18 | 'get_configstatus': pylxca_module._get_configstatus, 19 | 'discover': pylxca_module._get_discover, 20 | 'fans': pylxca_module._get_fans, 21 | 'fanmuxes': pylxca_module._get_fanmuxes, 22 | 'ffdc': pylxca_module._get_ffdc, 23 | 'jobs': pylxca_module._get_jobs, 24 | 'lxcalog': pylxca_module._get_lxcalog, 25 | 'manage': pylxca_module._manage_endpoint, 26 | 'unmanage': pylxca_module._unmanage_endpoint, 27 | 'manage_status': pylxca_module._manage_status, 28 | 'unmanage_status': pylxca_module._unmanage_status, 29 | 'nodes': pylxca_module._get_nodes, 30 | 'osimages': pylxca_module._get_osimages, 31 | 'powersupplies': pylxca_module._get_powersupplies, 32 | 'scalablesystem': pylxca_module._get_scalablesystem, 33 | 'switches': pylxca_module._get_switches_inventory, 34 | 'tasks': pylxca_module._get_tasks, 35 | 'updaterepo': pylxca_module._get_updaterepo_info, 36 | 'update_firmware': pylxca_module._update_firmware, 37 | 'update_firmware_all': pylxca_module._update_firmware_all, 38 | 'update_firmware_query_status':pylxca_module._update_firmware_query_status, 39 | 'update_firmware_query_comp':pylxca_module._update_firmware_query_comp, 40 | 'get_managementserver_pkg': pylxca_module._get_managementserver_pkg, 41 | 'update_managementserver_pkg': pylxca_module._update_managementserver_pkg, 42 | 'import_managementserver_pkg': pylxca_module._import_managementserver_pkg, 43 | 'updatepolicy': pylxca_module._get_updatepolicy, 44 | 'users': pylxca_module._get_users, 45 | 46 | } 47 | 48 | expected_arguments_spec = dict( 49 | login_user=dict(default=None, required=False), 50 | login_password=dict(default=None, required=False), 51 | connobject=dict(default=None), 52 | command_options=dict(choises=list(func_dict)), 53 | lxca_action=dict(default=None), 54 | auth_url=dict(default=None), 55 | uuid=dict(default=None), 56 | id=dict(default=None), 57 | endpoint_ip=dict(default=None), 58 | jobid=dict(default=None), 59 | user=dict(default=None, required=False), 60 | password=dict(default=None, required=False), 61 | force=dict(default=None), 62 | percentage=dict(default=None), 63 | state=dict(default=None), 64 | sol_id=dict(default=None), 65 | description=dict(default=None), 66 | solutionVPD=dict(default=None, type=('dict')), 67 | members=dict(default=None, type=('list')), 68 | criteria=dict(default=None, type=('list')), 69 | recovery_password=dict(default=None), 70 | repo_key=dict(default=None), 71 | mode=dict(default=None), 72 | server=dict(default=None), 73 | storage=dict(default=None), 74 | switch=dict(default=None), 75 | cmm=dict(default=None), 76 | policy_info=dict(default=None), 77 | policy_name=dict(default=None), 78 | policy_type=dict(default=None), 79 | update_list=dict(default=None, type=('list')), 80 | fact_dict=dict(default=None, type=('dict')), 81 | machine_type=dict(default=None), 82 | fixids=dict(default=None), 83 | scope=dict(default=None), 84 | file_type=dict(default=None), 85 | endpoint=dict(default=None), 86 | restart=dict(default=None), 87 | type=dict(default=None), 88 | config_pattern_name=dict(default=None), 89 | config_profile_name=dict(default=None), 90 | resource_group_name=dict(default=None), 91 | delete_profile=dict(default=None), 92 | unassign=dict(default=None), 93 | powerdown=dict(default=None), 94 | resetimm=dict(default=None), 95 | pattern_update_dict=dict(default=None, type=('dict')), 96 | includeSettings=dict(default=None), 97 | osimages_info=dict(default=None), 98 | osimages_dict=dict(default=None, type=('dict')), 99 | update_key=dict(default=None), 100 | files=dict(default=None), 101 | unittest=dict(default=None), 102 | uuid_list=dict(default=None, type=('list')), 103 | storedcredential_id=dict(default=None) 104 | ) 105 | 106 | 107 | class TestPylxcaMod: 108 | ''' 109 | this test shows how to mock AnsibleModule and set args for return value 110 | it calls nodes to gett actual nodes from LXCA 111 | ''' 112 | 113 | @mock.patch("library.pylxca_module.AnsibleModule", autospec=True) 114 | def test__main__success(self, ansible_mod_cls): 115 | mod_obj = ansible_mod_cls.return_value 116 | args = { 117 | "auth_url": "https://10.243.12.139", 118 | "login_user": "USERID", 119 | "login_password": "CME44ibm", 120 | "command_options": "connect", 121 | "unittest": None, 122 | } 123 | mod_obj.params = args 124 | connection_obj = pylxca_module.main() 125 | print(" Return from main") 126 | print connection_obj 127 | 128 | assert_equals(mock.call(argument_spec=expected_arguments_spec, 129 | check_invalid_arguments=False,supports_check_mode = False), ansible_mod_cls.call_args) 130 | 131 | #assert_not_equal(connection_obj.exit_json.result, []) 132 | ''' 133 | This test mocks AnsibleModule and _get_nodes also 134 | call to pylxca_module.main will not fetch data from LXCA 135 | ''' 136 | @mock.patch("library.pylxca_module._get_nodes", autospec=True) 137 | @mock.patch("library.pylxca_module.AnsibleModule", autospec=True) 138 | def test__main_nodes(self, ansible_mod_cls,_get_nodes): 139 | mod_obj = ansible_mod_cls.return_value 140 | args = { 141 | "auth_url": "https://10.243.12.139", 142 | "login_user": "USERID", 143 | "login_password": "CME44ibm", 144 | "command_options": "nodes", 145 | "unittest": "True", 146 | } 147 | mod_obj.params = args 148 | #pylxca_module.main() 149 | 150 | empty_nodes_list = [] 151 | _get_nodes.return_value = empty_nodes_list 152 | ret_nodes = pylxca_module.main() 153 | print("main nodes output ") 154 | print ret_nodes 155 | #assert(mock.call(argument_spec=expected_arguments_spec) != ansible_mod_cls.call_args) 156 | assert_equals(mock.call(argument_spec=expected_arguments_spec, 157 | check_invalid_arguments=False, supports_check_mode=False), ansible_mod_cls.call_args) 158 | assert_not_equal(mock.call(mod_obj, mod_obj.params),_get_nodes.call_args) 159 | #assert(_get_nodes.return_value, ret_nodes) 160 | 161 | 162 | ''' 163 | This test mocks AnsibleModule and _get_nodes also 164 | call to _get_nodes will not fetch data from LXCA 165 | ''' 166 | @mock.patch("library.pylxca_module._get_nodes", autospec=True) 167 | @mock.patch("library.pylxca_module.AnsibleModule", autospec=True) 168 | def test__nodes(self, ansible_mod_cls,_get_nodes): 169 | mod_obj = ansible_mod_cls.return_value 170 | args = { 171 | "auth_url": "https://10.243.12.139", 172 | "login_user": "USERID", 173 | "login_password": "CME44ibm", 174 | "command_options": "nodes", 175 | } 176 | mod_obj.params = args 177 | #pylxca_module.main() 178 | expected_arguments_spec=dict( 179 | login_user = dict(default=None, required=False), 180 | login_password = dict(default=None, required=False), 181 | connobject = dict(default=None), 182 | command_options = dict( choises=list(func_dict) ), 183 | action = dict(default=None), 184 | auth_url = dict(default=None), 185 | uuid = dict(default=None), 186 | ) 187 | 188 | empty_nodes_list = [] 189 | _get_nodes.return_value = empty_nodes_list 190 | ret_nodes = _get_nodes(mod_obj, args) 191 | print("nodes output ") 192 | print ret_nodes 193 | #assert(mock.call(argument_spec=expected_arguments_spec) != ansible_mod_cls.call_args) 194 | # Assert call to _get_connect_lxca 195 | assert(mock.call(mod_obj, mod_obj.params) == _get_nodes.call_args) 196 | assert_equals(_get_nodes.return_value, ret_nodes) 197 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | # config file for ansible -- https://ansible.com/ 2 | # =============================================== 3 | 4 | # nearly all parameters can be overridden in ansible-playbook 5 | # or with command line flags. ansible will read ANSIBLE_CONFIG, 6 | # ansible.cfg in the current working directory, .ansible.cfg in 7 | # the home directory or /etc/ansible/ansible.cfg, whichever it 8 | # finds first 9 | 10 | [defaults] 11 | 12 | # some basic default values... 13 | 14 | #inventory = /etc/ansible/hosts 15 | library = ./library 16 | #module_utils = /usr/share/my_module_utils/ 17 | #remote_tmp = ~/.ansible/tmp 18 | #local_tmp = ~/.ansible/tmp 19 | remote_tmp = $HOME/.ansible/tmp 20 | local_tmp = $HOME/.ansible/tmp 21 | #forks = 5 22 | #poll_interval = 15 23 | #sudo_user = root 24 | #ask_sudo_pass = True 25 | #ask_pass = True 26 | #transport = smart 27 | #remote_port = 22 28 | #module_lang = C 29 | #module_set_locale = False 30 | 31 | # plays will gather facts by default, which contain information about 32 | # the remote system. 33 | # 34 | # smart - gather by default, but don't regather if already gathered 35 | # implicit - gather by default, turn off with gather_facts: False 36 | # explicit - do not gather by default, must say gather_facts: True 37 | #gathering = implicit 38 | 39 | # This only affects the gathering done by a play's gather_facts directive, 40 | # by default gathering retrieves all facts subsets 41 | # all - gather all subsets 42 | # network - gather min and network facts 43 | # hardware - gather hardware facts (longest facts to retrieve) 44 | # virtual - gather min and virtual facts 45 | # facter - import facts from facter 46 | # ohai - import facts from ohai 47 | # You can combine them using comma (ex: network,virtual) 48 | # You can negate them using ! (ex: !hardware,!facter,!ohai) 49 | # A minimal set of facts is always gathered. 50 | #gather_subset = all 51 | 52 | # some hardware related facts are collected 53 | # with a maximum timeout of 10 seconds. This 54 | # option lets you increase or decrease that 55 | # timeout to something more suitable for the 56 | # environment. 57 | # gather_timeout = 10 58 | 59 | # additional paths to search for roles in, colon separated 60 | roles_path = ./roles 61 | 62 | # uncomment this to disable SSH key host checking 63 | #host_key_checking = False 64 | 65 | # change the default callback 66 | #stdout_callback = skippy 67 | # enable additional callbacks 68 | #callback_whitelist = timer, mail 69 | 70 | # Determine whether includes in tasks and handlers are "static" by 71 | # default. As of 2.0, includes are dynamic by default. Setting these 72 | # values to True will make includes behave more like they did in the 73 | # 1.x versions. 74 | #task_includes_static = True 75 | #handler_includes_static = True 76 | 77 | # Controls if a missing handler for a notification event is an error or a warning 78 | #error_on_missing_handler = True 79 | 80 | # change this for alternative sudo implementations 81 | #sudo_exe = sudo 82 | 83 | # What flags to pass to sudo 84 | # WARNING: leaving out the defaults might create unexpected behaviours 85 | #sudo_flags = -H -S -n 86 | 87 | # SSH timeout 88 | #timeout = 10 89 | 90 | # default user to use for playbooks if user is not specified 91 | # (/usr/bin/ansible will use current user as default) 92 | #remote_user = root 93 | 94 | # logging is off by default unless this path is defined 95 | # if so defined, consider logrotate 96 | #log_path = /var/log/ansible.log 97 | 98 | # default module name for /usr/bin/ansible 99 | #module_name = command 100 | 101 | # use this shell for commands executed under sudo 102 | # you may need to change this to bin/bash in rare instances 103 | # if sudo is constrained 104 | #executable = /bin/sh 105 | 106 | # if inventory variables overlap, does the higher precedence one win 107 | # or are hash values merged together? The default is 'replace' but 108 | # this can also be set to 'merge'. 109 | #hash_behaviour = replace 110 | 111 | # by default, variables from roles will be visible in the global variable 112 | # scope. To prevent this, the following option can be enabled, and only 113 | # tasks and handlers within the role will see the variables there 114 | #private_role_vars = yes 115 | 116 | # list any Jinja2 extensions to enable here: 117 | #jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n 118 | 119 | # if set, always use this private key file for authentication, same as 120 | # if passing --private-key to ansible or ansible-playbook 121 | #private_key_file = /path/to/file 122 | 123 | # If set, configures the path to the Vault password file as an alternative to 124 | # specifying --vault-password-file on the command line. 125 | #vault_password_file = /path/to/vault_password_file 126 | 127 | # format of string {{ ansible_managed }} available within Jinja2 128 | # templates indicates to users editing templates files will be replaced. 129 | # replacing {file}, {host} and {uid} and strftime codes with proper values. 130 | #ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host} 131 | # {file}, {host}, {uid}, and the timestamp can all interfere with idempotence 132 | # in some situations so the default is a static string: 133 | #ansible_managed = Ansible managed 134 | 135 | # by default, ansible-playbook will display "Skipping [host]" if it determines a task 136 | # should not be run on a host. Set this to "False" if you don't want to see these "Skipping" 137 | # messages. NOTE: the task header will still be shown regardless of whether or not the 138 | # task is skipped. 139 | #display_skipped_hosts = True 140 | 141 | # by default, if a task in a playbook does not include a name: field then 142 | # ansible-playbook will construct a header that includes the task's action but 143 | # not the task's args. This is a security feature because ansible cannot know 144 | # if the *module* considers an argument to be no_log at the time that the 145 | # header is printed. If your environment doesn't have a problem securing 146 | # stdout from ansible-playbook (or you have manually specified no_log in your 147 | # playbook on all of the tasks where you have secret information) then you can 148 | # safely set this to True to get more informative messages. 149 | #display_args_to_stdout = False 150 | 151 | # by default (as of 1.3), Ansible will raise errors when attempting to dereference 152 | # Jinja2 variables that are not set in templates or action lines. Uncomment this line 153 | # to revert the behavior to pre-1.3. 154 | #error_on_undefined_vars = False 155 | 156 | # by default (as of 1.6), Ansible may display warnings based on the configuration of the 157 | # system running ansible itself. This may include warnings about 3rd party packages or 158 | # other conditions that should be resolved if possible. 159 | # to disable these warnings, set the following value to False: 160 | #system_warnings = True 161 | 162 | # by default (as of 1.4), Ansible may display deprecation warnings for language 163 | # features that should no longer be used and will be removed in future versions. 164 | # to disable these warnings, set the following value to False: 165 | #deprecation_warnings = True 166 | 167 | # (as of 1.8), Ansible can optionally warn when usage of the shell and 168 | # command module appear to be simplified by using a default Ansible module 169 | # instead. These warnings can be silenced by adjusting the following 170 | # setting or adding warn=yes or warn=no to the end of the command line 171 | # parameter string. This will for example suggest using the git module 172 | # instead of shelling out to the git command. 173 | # command_warnings = False 174 | 175 | 176 | # set plugin path directories here, separate with colons 177 | #action_plugins = /usr/share/ansible/plugins/action 178 | #cache_plugins = /usr/share/ansible/plugins/cache 179 | #callback_plugins = /usr/share/ansible/plugins/callback 180 | #connection_plugins = /usr/share/ansible/plugins/connection 181 | #lookup_plugins = /usr/share/ansible/plugins/lookup 182 | #inventory_plugins = /usr/share/ansible/plugins/inventory 183 | #vars_plugins = /usr/share/ansible/plugins/vars 184 | #filter_plugins = /usr/share/ansible/plugins/filter 185 | #test_plugins = /usr/share/ansible/plugins/test 186 | #terminal_plugins = /usr/share/ansible/plugins/terminal 187 | #strategy_plugins = /usr/share/ansible/plugins/strategy 188 | 189 | 190 | # by default, ansible will use the 'linear' strategy but you may want to try 191 | # another one 192 | #strategy = free 193 | 194 | # by default callbacks are not loaded for /bin/ansible, enable this if you 195 | # want, for example, a notification or logging callback to also apply to 196 | # /bin/ansible runs 197 | #bin_ansible_callbacks = False 198 | 199 | 200 | # don't like cows? that's unfortunate. 201 | # set to 1 if you don't want cowsay support or export ANSIBLE_NOCOWS=1 202 | #nocows = 1 203 | 204 | # set which cowsay stencil you'd like to use by default. When set to 'random', 205 | # a random stencil will be selected for each task. The selection will be filtered 206 | # against the `cow_whitelist` option below. 207 | #cow_selection = default 208 | #cow_selection = random 209 | 210 | # when using the 'random' option for cowsay, stencils will be restricted to this list. 211 | # it should be formatted as a comma-separated list with no spaces between names. 212 | # NOTE: line continuations here are for formatting purposes only, as the INI parser 213 | # in python does not support them. 214 | #cow_whitelist=bud-frogs,bunny,cheese,daemon,default,dragon,elephant-in-snake,elephant,eyes,\ 215 | # hellokitty,kitty,luke-koala,meow,milk,moofasa,moose,ren,sheep,small,stegosaurus,\ 216 | # stimpy,supermilker,three-eyes,turkey,turtle,tux,udder,vader-koala,vader,www 217 | 218 | # don't like colors either? 219 | # set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1 220 | #nocolor = 1 221 | 222 | # if set to a persistent type (not 'memory', for example 'redis') fact values 223 | # from previous runs in Ansible will be stored. This may be useful when 224 | # wanting to use, for example, IP information from one group of servers 225 | # without having to talk to them in the same playbook run to get their 226 | # current IP information. 227 | #fact_caching = memory 228 | 229 | 230 | # retry files 231 | # When a playbook fails by default a .retry file will be created in ~/ 232 | # You can disable this feature by setting retry_files_enabled to False 233 | # and you can change the location of the files by setting retry_files_save_path 234 | 235 | #retry_files_enabled = False 236 | #retry_files_save_path = ~/.ansible-retry 237 | 238 | # squash actions 239 | # Ansible can optimise actions that call modules with list parameters 240 | # when looping. Instead of calling the module once per with_ item, the 241 | # module is called once with all items at once. Currently this only works 242 | # under limited circumstances, and only with parameters named 'name'. 243 | #squash_actions = apk,apt,dnf,homebrew,pacman,pkgng,yum,zypper 244 | 245 | # prevents logging of task data, off by default 246 | #no_log = False 247 | 248 | # prevents logging of tasks, but only on the targets, data is still logged on the master/controller 249 | #no_target_syslog = False 250 | 251 | # controls whether Ansible will raise an error or warning if a task has no 252 | # choice but to create world readable temporary files to execute a module on 253 | # the remote machine. This option is False by default for security. Users may 254 | # turn this on to have behaviour more like Ansible prior to 2.1.x. See 255 | # https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user 256 | # for more secure ways to fix this than enabling this option. 257 | #allow_world_readable_tmpfiles = False 258 | 259 | # controls the compression level of variables sent to 260 | # worker processes. At the default of 0, no compression 261 | # is used. This value must be an integer from 0 to 9. 262 | #var_compression_level = 9 263 | 264 | # controls what compression method is used for new-style ansible modules when 265 | # they are sent to the remote system. The compression types depend on having 266 | # support compiled into both the controller's python and the client's python. 267 | # The names should match with the python Zipfile compression types: 268 | # * ZIP_STORED (no compression. available everywhere) 269 | # * ZIP_DEFLATED (uses zlib, the default) 270 | # These values may be set per host via the ansible_module_compression inventory 271 | # variable 272 | #module_compression = 'ZIP_DEFLATED' 273 | 274 | # This controls the cutoff point (in bytes) on --diff for files 275 | # set to 0 for unlimited (RAM may suffer!). 276 | #max_diff_size = 1048576 277 | 278 | # This controls how ansible handles multiple --tags and --skip-tags arguments 279 | # on the CLI. If this is True then multiple arguments are merged together. If 280 | # it is False, then the last specified argument is used and the others are ignored. 281 | #merge_multiple_cli_flags = False 282 | 283 | # Controls showing custom stats at the end, off by default 284 | #show_custom_stats = True 285 | 286 | # Controlls which files to ignore when using a directory as inventory with 287 | # possibly multiple sources (both static and dynamic) 288 | #inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo 289 | 290 | # This family of modules use an alternative execution path optimized for network appliances 291 | # only update this setting if you know how this works, otherwise it can break module execution 292 | #network_group_modules=['eos', 'nxos', 'ios', 'iosxr', 'junos', 'vyos'] 293 | 294 | [privilege_escalation] 295 | #become=True 296 | #become_method=sudo 297 | #become_user=root 298 | #become_ask_pass=False 299 | 300 | [paramiko_connection] 301 | 302 | # uncomment this line to cause the paramiko connection plugin to not record new host 303 | # keys encountered. Increases performance on new host additions. Setting works independently of the 304 | # host key checking setting above. 305 | #record_host_keys=False 306 | 307 | # by default, Ansible requests a pseudo-terminal for commands executed under sudo. Uncomment this 308 | # line to disable this behaviour. 309 | #pty=False 310 | 311 | # paramiko will default to looking for SSH keys initially when trying to 312 | # authenticate to remote devices. This is a problem for some network devices 313 | # that close the connection after a key failure. Uncomment this line to 314 | # disable the Paramiko look for keys function 315 | #look_for_keys = False 316 | 317 | # When using persistent connections with Paramiko, the connection runs in a 318 | # background process. If the host doesn't already have a valid SSH key, by 319 | # default Ansible will prompt to add the host key. This will cause connections 320 | # running in background processes to fail. Uncomment this line to have 321 | # Paramiko automatically add host keys. 322 | #host_key_auto_add = True 323 | 324 | [ssh_connection] 325 | 326 | # ssh arguments to use 327 | # Leaving off ControlPersist will result in poor performance, so use 328 | # paramiko on older platforms rather than removing it, -C controls compression use 329 | #ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s 330 | 331 | # The base directory for the ControlPath sockets. 332 | # This is the "%(directory)s" in the control_path option 333 | # 334 | # Example: 335 | # control_path_dir = /tmp/.ansible/cp 336 | #control_path_dir = ~/.ansible/cp 337 | 338 | # The path to use for the ControlPath sockets. This defaults to a hashed string of the hostname, 339 | # port and username (empty string in the config). The hash mitigates a common problem users 340 | # found with long hostames and the conventional %(directory)s/ansible-ssh-%%h-%%p-%%r format. 341 | # In those cases, a "too long for Unix domain socket" ssh error would occur. 342 | # 343 | # Example: 344 | # control_path = %(directory)s/%%h-%%r 345 | #control_path = 346 | 347 | # Enabling pipelining reduces the number of SSH operations required to 348 | # execute a module on the remote server. This can result in a significant 349 | # performance improvement when enabled, however when using "sudo:" you must 350 | # first disable 'requiretty' in /etc/sudoers 351 | # 352 | # By default, this option is disabled to preserve compatibility with 353 | # sudoers configurations that have requiretty (the default on many distros). 354 | # 355 | #pipelining = False 356 | 357 | # Control the mechanism for transferring files (old) 358 | # * smart = try sftp and then try scp [default] 359 | # * True = use scp only 360 | # * False = use sftp only 361 | #scp_if_ssh = smart 362 | 363 | # Control the mechanism for transferring files (new) 364 | # If set, this will override the scp_if_ssh option 365 | # * sftp = use sftp to transfer files 366 | # * scp = use scp to transfer files 367 | # * piped = use 'dd' over SSH to transfer files 368 | # * smart = try sftp, scp, and piped, in that order [default] 369 | #transfer_method = smart 370 | 371 | # if False, sftp will not use batch mode to transfer files. This may cause some 372 | # types of file transfer failures impossible to catch however, and should 373 | # only be disabled if your sftp version has problems with batch mode 374 | #sftp_batch_mode = False 375 | 376 | [persistent_connection] 377 | 378 | # Configures the persistent connection timeout value in seconds. This value is 379 | # how long the persistent connection will remain idle before it is destroyed. 380 | # If the connection doesn't receive a request before the timeout value 381 | # expires, the connection is shutdown. The default value is 30 seconds. 382 | connect_timeout = 30 383 | 384 | # Configures the persistent connection retries. This value configures the 385 | # number of attempts the ansible-connection will make when trying to connect 386 | # to the local domain socket. The default value is 30. 387 | connect_retries = 30 388 | 389 | # Configures the amount of time in seconds to wait between connection attempts 390 | # to the local unix domain socket. This value works in conjunction with the 391 | # connect_retries value to define how long to try to connect to the local 392 | # domain socket when setting up a persistent connection. The default value is 393 | # 1 second. 394 | connect_interval = 1 395 | 396 | [accelerate] 397 | #accelerate_port = 5099 398 | #accelerate_timeout = 30 399 | #accelerate_connect_timeout = 5.0 400 | 401 | # The daemon timeout is measured in minutes. This time is measured 402 | # from the last activity to the accelerate daemon. 403 | #accelerate_daemon_timeout = 30 404 | 405 | # If set to yes, accelerate_multi_key will allow multiple 406 | # private keys to be uploaded to it, though each user must 407 | # have access to the system via SSH to add a new key. The default 408 | # is "no". 409 | #accelerate_multi_key = yes 410 | 411 | [selinux] 412 | # file systems that require special treatment when dealing with security context 413 | # the default behaviour that copies the existing context or uses the user default 414 | # needs to be changed to use the file system dependent context. 415 | #special_context_filesystems=nfs,vboxsf,fuse,ramfs,9p 416 | 417 | # Set this to yes to allow libvirt_lxc connections to work without SELinux. 418 | #libvirt_lxc_noseclabel = yes 419 | 420 | [colors] 421 | #highlight = white 422 | #verbose = blue 423 | #warn = bright purple 424 | #error = red 425 | #debug = dark gray 426 | #deprecate = purple 427 | #skip = cyan 428 | #unreachable = red 429 | #ok = green 430 | #changed = yellow 431 | #diff_add = green 432 | #diff_remove = red 433 | #diff_lines = cyan 434 | 435 | 436 | [diff] 437 | # Always print diff when running ( same as always running with -D/--diff ) 438 | # always = no 439 | 440 | # Set how many context lines to show in diff 441 | # context = 3 442 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Lenovo Ansible 3 | -------------- 4 | This project contains Ansible Playbooks, Roles and Modules for LXCA and can be used collectively to implement various use cases. 5 | Project cotains following Ansible Roles 6 | - Inventory : Role to get all inventory from LXCA. 7 | - Configuration i: Role to do config operation, firmware update, apply patterns, os deploy. 8 | 9 | Dependencies 10 | ------------ 11 | -python3 version 3.10.4 12 | -pip version 22.0.2 13 | -ansible [core 2.12.5] 14 | 15 | Installation 16 | ------------ 17 | ansible-galaxy install lenovo.lxca-inventory 18 | ansible-galaxy install lenovo.lxca-config 19 | 20 | Pre-requisite 21 | Ansible Role requires LXCA Python Client and LXCA Ansible module installed. 22 | 23 | ### Example for calling LXCA Playbook 24 | ###### Stored Credentials 25 | ``` 26 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL " playbooks/config/config.yml -vvvv --tag get_all_storedcredentials 27 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL storedcredential_id=402" playbooks/config/config.yml -vvvv --tag get_particular_storedcredentials 28 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL description='desc of user' user=USER password=PASSWORD" playbooks/config/config.yml -vvvv --tag create_storedcredentials 29 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL storedcredential_id=412 user=USER password=PASSWORD" playbooks/config/config.yml -vvvv --tag update_storedcredentials 30 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL storedcredential_id=407" playbooks/config/config.yml -vvvv --tag delete_particular_storedcredentials 31 | 32 | ``` 33 | 34 | 35 | ###### Manage / Unmanage endpoint 36 | ``` 37 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL endpoint_ip=ENDPOINT_IP user=USER password=PASSWORD recovery_password=RECOVERY_PASSWORD force=True" playbooks/config/config.yml -vvvv --tag manage 38 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL endpoint_ip=ENDPOINT_IP storedcredential_id=STORED_CREDENTIAL_ID force=True" playbooks/config/config.yml -vvvv --tag 39 | manage 40 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL endpoint_ip=ENDPOINT_IP;UUID;Chassis force=True" playbooks/config/config.yml -v --tag unmanage 41 | ``` 42 | 43 | ###### Collect inventory in LXCA 44 | ``` 45 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" site.yml -vvvv 46 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" site.yml -vvvv --tag users 47 | ``` 48 | ###### Update Firmware 49 | ``` 50 | List all policy 51 | ---------------- 52 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=list" playbooks/config/config.yml -vvvv --tag updatepolicy 53 | 54 | Get List of Applicable Frimware policies 55 | ---------------- 56 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query policy_info=FIRMWARE" playbooks/config/config.yml -vvvv --tag updatepolicy 57 | 58 | List the persisted compare result for servers to which a policy is assigned 59 | ---------------- 60 | 61 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query update_policy_info=RESULTS" playbooks/config/config.yml -vvvv --tag updatepolicy 62 | 63 | Check compliant with the assigned compliance policy using the job or task ID that was returned when the compliance policy was assigned. 64 | ---------------- 65 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=status uuid=EF362CF0FB4511E397AB40F2E9AF01D0 jobid=2" playbooks/config/config.yml -vvvv --tag updatepolicy 66 | 67 | Assign policy to Endpoint 68 | ---------------- 69 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=assign policy_name=x220_imm2 policy_type=SERVER uuid=UUID" playbooks/config/config.yml -vvvv --tag updatepolicy 70 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=status jobid=16" playbooks/config/config.yml -vvvv --tag updatepolicy 71 | 72 | Update endpoint Firmware 73 | ================ 74 | 75 | Query Updatable components 76 | ---------------- 77 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" playbooks/config/config.yml -v --tag query_update_comp 78 | 79 | Query Firmware Update Status 80 | ---------------- 81 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" playbooks/config/config.yml -vvvv --tag query_update_status 82 | 83 | Applying Firmware with policy 84 | ---------------- 85 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL mode=immediate lxca_action=apply server='UUID,IMM2 (Primary)'" playbooks/config/config.yml -vvvv --tag update_firmware 86 | 87 | Applying Firmware with policy for specified updateable components 88 | ---------------- 89 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL mode=immediate lxca_action=apply uuid_list=['UUID1','UUID2']" playbooks/config/config.yml -vvvv --tag update_all_firmware_withpolicy 90 | 91 | Applying Firmware with policy for all updateable components 92 | ---------------- 93 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL mode=immediate lxca_action=apply uuid_list=[]" playbooks/config/config.yml -vvvv --tag update_all_firmware_withpolicy 94 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL mode=immediate lxca_action=apply" playbooks/config/config.yml -vvvv --tag update_all_firmware_withpolicy 95 | 96 | Update Repostory commands 97 | ================ 98 | Queries 99 | ---------------- 100 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=importDir" playbooks/config/config.yml -vvvv --tag updaterepo 101 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=lastRefreshed" playbooks/config/config.yml -vvvv --tag updaterepo 102 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=publicKeys" playbooks/config/config.yml -vvvv --tag updaterepo 103 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=size" playbooks/config/config.yml -vvvv --tag updaterepo 104 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=supportedMts" playbooks/config/config.yml -vvvv --tag updaterepo 105 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=updates" playbooks/config/config.yml -vvvv --tag updaterepo 106 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=updatesByMt" playbooks/config/config.yml -vvvv --tag updaterepo 107 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=query repo_key=updatesByMtByComp" playbooks/config/config.yml -vvvv --tag updaterepo 108 | 109 | Action 110 | ---------------- 111 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=read lxca_action=read" playbooks/config/config.yml -vvvv --tag updaterepo 112 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=refresh lxca_action=refresh machine_type=7903" playbooks/config/config.yml -vvvv --tag updaterepo 113 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=delete lxca_action=delete machine_type=7903 file_type=payloads fixids=ibm_fw_imm2_1aoo78j-6.20_anyos_noarch" playbooks/config/config.yml -vvvv --tag updaterepo 114 | ansible-playbook -e "lxca_user=TEST lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=acquire lxca_action=acquire machine_type=7903 scope=payloads fixids=ibm_fw_imm2_1aoo78j-6.20_anyos_noarch" playbooks/config/config.yml -vvvv --tag updaterepo 115 | ``` 116 | 117 | ###### Config Profile operations 118 | ``` 119 | get all profiles 120 | ---------------- 121 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=list" playbooks/config/config.yml -v --tag configprofiles 122 | 123 | get specified profile with id 124 | ---------------- 125 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=list id=69 " playbooks/config/config.yml -vvvv --tag configprofiles 126 | 127 | Change profile name of id 128 | ---------------- 129 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=rename id=69 config_profile_name='changed name 3' " playbooks/config/config.yml -vvvv --tag configprofiles 130 | 131 | Activate profile for endpoint 132 | ---------------- 133 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=activate id=69 endpoint=UUID restart=immediate " playbooks/config/config.yml -vvvv --tag configprofiles 134 | 135 | Unassign profile 136 | ---------------- 137 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL subcmd=unassign id=69" playbooks/config/config.yml -vvvv --tag configprofiles 138 | 139 | Delete profile 140 | ---------------- 141 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL id=69 subcmd=delete" playbooks/config/config.yml -vvvv --tag configprofiles 142 | ``` 143 | 144 | ###### Config Patterns operations 145 | ``` 146 | Get All config patterns 147 | ---------------- 148 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" playbooks/config/config.yml -vvvv --tag get_configpatterns 149 | 150 | Get specified config pattern with id 151 | ---------------- 152 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL id=52" playbooks/config/config.yml -vvvv --tag get_particular_configpattern 153 | 154 | Get specified config pattern for id with includeSettings 155 | ---------------- 156 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL id=52 includeSettings=True" playbooks/config/config.yml -vvvv --tag get_particular_configpattern 157 | 158 | Apply pattern to endpoint 159 | ---------------- 160 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL id=65 endpoint=UUID restart=pending type=node" playbooks/config/config.yml -vvvv --tag apply_configpatterns 161 | using name 162 | ---------- 163 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL config_pattern_name=From_abcdef endpoint=UUID restart=pending type=node" playbooks/config/config.yml -vvvv --tag apply_configpatterns 164 | Import SystemInfo pattern 165 | ---------------- 166 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL pattern_update_dict={'template_type':'SystemInfo','template':{'contact':'contact','description':'Pattern created by test API ','location':'location','name':'Learned-System_Info-99','systemName':{'autogen':'Disable','hyphenChecked':False},'type':'SystemInfo','uri':'\/config\/template\/61','userDefined':True}}" playbooks/config/config.yml -vvvv --tag import_configpatterns 167 | 168 | Import Pattern from file 169 | ------------------------ 170 | Read config pattern data from config_pattern_import.yml file in vars folder of config 171 | roles 172 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL pattern_file=config_pattern_import.yml pattern_from_file=true" playbooks/config/config.yml -vvvv --tag import_configpatterns 173 | 174 | config status 175 | ------------ 176 | get config status 177 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL endpoint=UUID" playbooks/config/config.yml -vvvv --tag get_configstatus 178 | ``` 179 | 180 | ###### osimages operations 181 | ``` 182 | get all osimages 183 | ----------------- 184 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'list'}" playbooks/config/config.yml -v --tag osimages 185 | 186 | delete osimages with id 187 | ----------------- 188 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'delete','id':'20190227190109_trail.py'}" playbooks/config/config.yml -vvvv --tag osimages 189 | 190 | get globalSetting for osimages 191 | ----------------- 192 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'globalsettings'}" playbooks/config/config.yml -vvvv --tag osimages 193 | 194 | set globalSetting for osimages 195 | ----------------- 196 | for setting globalSetting get detail from get golbalSetting and change the 197 | parameter you want to change. This example set LINUX default password. 198 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'globalsettings', 'osimages_dict':{'activeDirectory':{'allDomains': [],'defaultDomain':None}, 'credentials':[{'name': 'root', 'password':'Test1234', 'passwordChanged':True, 'type': 'LINUX'}, {'type': "WINDOWS", 'name': 'Administrator', password: None, 'passwordChanged': False}],'ipAssignment':'dhcpv4', 'isVLANMode': 'false', 'licenseKeys': {'win2012r1': {'dataCenterLicenseKey': '','standardLicenseKey': '',},'win2012r2':{'dataCenterLicenseKey': '', 'standardLicenseKey': ''}, 'win2016r1': {'dataCenterLicenseKey': '', 'standardLicenseKey': ''}, 'win2019r1': {'dataCenterLicenseKey': '','standardLicenseKey': ''}}}}" playbooks/config/config.yml -vvvv --tag osimages 199 | 200 | get hostSetting for osimages 201 | ----------------- 202 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'hostsettings'}" playbooks/config/config.yml -vvvv --tag osimages 203 | 204 | create hostSetting for osimages 205 | ----------------- 206 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'hostsettings', 'osimages_dict':{\"action\": \"create\", \"hosts\": [{\"storageSettings\": {\"targetDevice\": \"localdisk\"}, \"uuid\": \"UUID\", \"networkSettings\": {\"dns2\": \"\", \"dns1\": \"DNS1\", \"hostname\": \"nodeundefined\", \"vlanId\": 0, \"selectedMAC\": \"AUTO\", \"gateway\": \"GATEWAY_IP\", \"subnetMask\": \"255.255.240.0\", \"mtu\": 1500, \"prefixLength\": 64, \"ipAddress\": \"10.243.9.79\"}}, {\"storageSettings\": {\"targetDevice\": \"localdisk\"}, \"uuid\": \"UUID\", \"networkSettings\": {\"dns2\": \"\", \"dns1\": \"DNS1\", \"hostname\": \"proton1\", \"vlanId\": 0, \"selectedMAC\": \"AUTO\", \"gateway\": \"GATEWAY_IP\", \"subnetMask\": \"255.255.240.0\", \"mtu\": 1500, \"prefixLength\": 64, \"ipAddress\": \"IP_ADDRESS\"}}]}}" playbooks/config/config.yml -vvvv --tag osimages 207 | 208 | 209 | update hostSetting for osimages 210 | ----------------- 211 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'hostsettings', 'osimages_dict':{'action': 'update', 'hosts': [{'storageSettings': {'targetDevice': 'localdisk'}, 'uuid': 'UUID', 'networkSettings': {'dns2': '', 'dns1': 'DNS1', 'hostname': 'nodeundefined', 'vlanId': 0, 'selectedMAC': 'AUTO', 'gateway': 'GATEWAY_IP', 'subnetMask': '255.255.240.0', 'mt': 1500, 'prefixLength': 64, 'ipAddress': '10.243.9.79'}}, {'storageSettings': {'targetDevice': 'localdisk'}, 'uuid': 'UUID', 'networkSettings': {'dns2': '', 'dns1': 'DNS1', 'hostname': 'proton1', 'vlanId': 0, 'selectedMAC': 'AUTO', 'gateway': 'GATEWAY_IP', 'subnetMask': '255.255.240.0', 'mt': 1500, 'prefixLength': 64, 'ipAddress': 'IP_ADDRESS'}}]}}" playbooks/config/config.yml -vvvv --tag osimages 212 | 213 | 214 | delete hostSetting for osimages 215 | ----------------- 216 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'hostsettings', 'osimages_dict':{'action': 'delete', 'uuid': 'UUID'}}" playbooks/config/config.yml -vvvv --tag osimages 217 | 218 | import osimage file from remote server 219 | ------------------------------------- 220 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'osimages_imagetype_dict':{'imageType':'OS'}, 'import_dict':{'imageType':'OS','os':'rhels','imageName':'fixed','path':'iso/rhel73.iso','serverId':'1'}}" playbooks/config/config.yml -vvvv --tag import_osimages 221 | 222 | 223 | import osimage script file from local 224 | ------------------------------------- 225 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'osimages_imagetype_dict':{'imageType':'SCRIPT'}, 'import_dict':{'imageType':'SCRIPT', "imageName":"trail.py", "os":"rhels", "description":"test_python_file", "file": "/home/naval/trail.py" }}" playbooks/config/config.yml -vvvv --tag import_osimages 226 | 227 | get hostplatforms detail for osimages 228 | ------------------------------------ 229 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'hostplatforms'}" playbooks/config/config.yml -vvvv --tag osimages 230 | 231 | deploy osimage to node 232 | ---------------------- 233 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'hostplatforms','osimages_dict':{'networkSettings':{'dns1': 'DNS1','dns2':'10.240.0.11','gateway':'10.240.28.1','ipAddress':'10.240.29.226','mtu':1500,'prefixLength':64,'selectedMac':'AUTO','subnetMask':'255.255.252.0','vlanId':521},'selectedImage':'rhels7.3|rhels7.3-x86_64-install-Minimal','storageSettings':{'targetDevice':'localdisk'},'uuid':'UUID'}}" playbooks/config/config.yml -vvvv --tag osimages 234 | 235 | get all remoteFileServers 236 | ------------------------- 237 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'remotefileservers'}" playbooks/config/config.yml -vvvv --tag osimages 238 | 239 | Get Specific remoteFileServers 240 | ------------------------------ 241 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'remotefileservers', 'osimages_dict':{'id':'1'}}" playbooks/config/config.yml -vvvv --tag osimages 242 | 243 | Delete Specific Remote File Server 244 | --------------------------------- 245 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'remotefileservers', 'osimages_dict':{'deleteid':'2'}}" playbooks/config/config.yml -vvvv --tag osimages 246 | 247 | Add Remote File Server 248 | ---------------------- 249 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'remotefileservers', 'osimages_dict':{'displayName':'TEST99','address': '192.168.1.10','keyPassphrase': 'KEY_PASSPHRASE','keyType': 'RSA-2048','port': 8080,'protocol': 'HTTPS'}}" playbooks/config/config.yml -vvvv --tag osimages 250 | ``` 251 | 252 | ###### managementserver operations 253 | ``` 254 | get managementserver with different key options 255 | ----------------------------------------------- 256 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'query', 'update_key':'importDir'}" playbooks/config/config.yml -vvvv --tag get_managementserver_pkg 257 | 258 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'query', 'update_key':'size'}" playbooks/config/config.yml -vvvv --tag get_managementserver_pkg 259 | 260 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'query', 'update_key':'updates'}" playbooks/config/config.yml -vvvv --tag get_managementserver_pkg 261 | 262 | get particular details with fixids 263 | ---------------------------------- 264 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'query_fixids', 'update_key':'filetypes', 'fixids':'lnvgy_sw_lxca-fw-repository-pack_1-1.0.1_anyos_noarch'}" playbooks/config/config.yml -vvvv --tag get_particular_managementserver_pkg 265 | 266 | nsible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'query_fixids', 'fixids':'lnvgy_sw_lxca-fw-repository-pack_1-1.0.1_anyos_noarch','type':'readme'}" playbooks/config/config.yml -vvvv --tag get_particular_managementserver_pkg 267 | 268 | Update options for managementserver 269 | ---------------------------------- 270 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'subcmd':'refresh'}" playbooks/config/config.yml -vvvv --tag update_managementserver_pkg 271 | 272 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'fixids':'lnvgy_sw_lxca-fw-repository-pack_1-1.0.1_anyos_noarch','subcmd':'acquire'}" playbooks/config/config.yml -vvvv --tag update_managementserver_pkg 273 | 274 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'fixids':'lnvgy_sw_lxca-fw-repository-pack_1-1.0.1_anyos_noarch','subcmd':'apply'}" playbooks/config/config.yml -vvvv --tag update_managementserver_pkg 275 | 276 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'fixids':'lnvgy_sw_lxca-fw-repository-pack_1-1.0.1_anyos_noarch','subcmd':'delete'}" playbooks/config/config.yml -vvvv --tag update_managementserver_pkg 277 | 278 | Import local files to managementserver 279 | -------------------------------------- 280 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'import', 'files':'/path/to/lnvgy_sw_lxca_thinksystemrepo1-1.3.2_anyos_noarch.txt,/path/to/lnvgy_sw_lxca_thinksystemrepo1-1.3.2_anyos_noarch.chg,/path/to/lnvgy_sw_lxca_thinksystemrepo1-1.3.2_anyos_noarch.xml'}" playbooks/config/config.yml -vvvv --tag import_managementserver_pkg 281 | 282 | files specified with relative to playbook file 283 | ---------------------------------------------- 284 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL','subcmd':'import', 'files':'/path/to/lnvgy_sw_lxca_thinksystemrepo1-1.3.2_anyos_noarch.xml'}" playbooks/config/config.yml -vvvv --tag import_managementserver_pkg 285 | 286 | ``` 287 | 288 | ###### Resource Group operations 289 | ``` 290 | Sending Solution Manifest to LXCA 291 | ------------------- 292 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL sol_id=1 manifest_path=/tmp/test.manifest" playbooks/uhm/manifests.yml -vvvv 293 | 294 | Create Resource Groups 295 | ---------------------- 296 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL resource_group_name='TEST2' description='TestGroup' resource_type='solution' solutionVPD={'id':'ID','machineType':'TESTMTM','model':'TESTMODEL','serialNumber':'TESTSERIAL','manufacturer':'LENOVO'} members=[] criteria=[]" playbooks/uhm/thinkagile.yml -vvvv --tag create_resourcegroups 297 | 298 | Create Resource Groups extra_vars as JSON 299 | --------------------------- 300 | ansible-playbook -e "{'lxca_user':'LXCA_USER', 'lxca_password':'LXCA_PASSWORD', 'lxca_url':'LXCA_URL', 'resource_group_name':'TEST3', 'description':'TestGroup', 'resource_type':'solution', 'solutionVPD':{'id':'ID','machineType':'TESTMTM','model':'TESTMODEL','serialNumber':'TESTSERIAL','manufacturer':'LENOVO'}, 'members':[], 'criteria':[]}" playbooks/uhm/thinkagile.yml -vvvv --tag create_resourcegroups 301 | 302 | Create dynamic resource group 303 | ------------------------------ 304 | ansible-playbook -e '{"lxca_user":"LXCA_USER", "lxca_password":"LXCA_PASSWORD", "lxca_url":"LXCA_URL", "resource_group_name":"TEST3", "description":"TestGroup", "resource_type":"dynamic", "criteria":{"parent":"root", "value":None, "criteria":[{"operator":"contains","value":"test", "property":"hostname", "id":"1001", "parent":"lxca_customUI_resourceViews_allGroupsPage_editGroupDynamicPage_2"}], "operator":"AND", "property": None, "id":"root"}}' playbooks/uhm/thinkagile.yml -vvvv --tag create_dynamic_resourcegroups 305 | 306 | Create Resource Groups extra_vars as JSON file 307 | --------------------------- 308 | ansible-playbook -e "@files/resource_groups.json" playbooks/uhm/thinkagile.yml -vvvv --tag create_resourcegroups 309 | 310 | Add Resource Groups members 311 | --------------------------- 312 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL uuid=ID members=['nodes/9C4D0000B22E44F1A0000A1D85B4ECD0','switches/38D9D7DBCB713C12A210E60C74A0E931']" playbooks/uhm/thinkagile.yml -vvvv --tag add_group_members 313 | 314 | Get all Resource Groups 315 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL " playbooks/uhm/thinkagile.yml -vvvv --tag get_resourcegroups 316 | 317 | Get specific Resource Groups 318 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL uuid=ID" playbooks/uhm/thinkagile.yml -vvvv --tag get_resourcegroups 319 | 320 | ``` 321 | ###### compliance rules operations 322 | ``` 323 | get all compliance rules 324 | ------------------- 325 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" playbooks/uhm/thinkagile.yml -vvvv --tag get_compliance_rules 326 | 327 | get specific rule 328 | ------------------- 329 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL id=5a2a2d8df9a2f31486aa8b83" playbooks/uhm/thinkagile.yml -vvvv --tag get_compliance_rules 330 | 331 | import compliance rules from files of compliance_rules.yaml at uhm roles vars folder 332 | ------------------- 333 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" playbooks/uhm/thinkagile.yml -vvvv --tag import_compliance_rules 334 | 335 | Get compositeResults 336 | ------------------- 337 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" playbooks/uhm/thinkagile.yml -vvvv --tag get_compositeresults 338 | 339 | get specific compositeResults 340 | ------------------- 341 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL id=5a0eec085ababd3b02cc04a2" playbooks/uhm/thinkagile.yml -vvvv --tag get_compositeresults 342 | 343 | update composit results 344 | ------------------- 345 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL solutionGroups=5a0eec085ababd3b02cc04a2" playbooks/uhm/thinkagile.yml -vvvv --tag update_solutiongroup_compositeresults 346 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL targetResources=[u'nodes/4C7D5FD237D411E2875EE4C686742121', u'nodes/1B247BCC918311E2B0703440B5EFBAB8' ]" playbooks/uhm/thinkagile.yml -vvvv --tag update_targetresources_compositeresults 347 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL all_rules=True" playbooks/uhm/thinkagile.yml -vvvv --tag process_all_rules_compositeresults 348 | 349 | Executing Compliance Validation in LXCA 350 | ------------------- 351 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL" playbooks/uhm/compliance.yml --tag gather_server_facts,validate_basic_server_facts -vvvv 352 | ansible-playbook -e "plugin_name=test_plugin plugin_location=/home/prashant/git/ansible.lenovo-lxca/files/compliance_plugins" playbooks/uhm/compliance.yml --tag validate_plugin_compliance -vvvv 353 | ansible-playbook -e "lxca_user=LXCA_USER lxca_password=LXCA_PASSWORD lxca_url=LXCA_URL RESOURCE_UUID=RESOURCE_UUID RESOURCE_TYPE=Server BASIC_RULES=[{'property':'powerStatus','ref_value':8}]" playbooks/uhm/compliance.yml --tag gather_server_facts,validate_basic_server_facts -vvvv 354 | 355 | ``` 356 | 357 | ###### unittest cases 358 | ``` 359 | It uses mock and nose modules. For coverage it uses coverage module. 360 | run unittest from root folder of this repo 361 | 362 | nosetests -v -s test/test_pylxca_module.py 363 | nosetests -v -s test/test_pylxca_module.py --with-coverage 364 | nosetests -v -s test/test_pylxca_module.py --with-coverage --cover-package=pylxca 365 | ``` 366 | -------------------------------------------------------------------------------- /library/pylxca_module.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019 - present Lenovo. All Rights Reserved. 2 | # Licensed under: BSD-3 License See License.BSD file for more information. 3 | 4 | from __future__ import (absolute_import, division, print_function) 5 | __metaclass__ = type 6 | 7 | 8 | ANSIBLE_METADATA = { 9 | 'metadata_version': '1.1', 10 | 'supported_by': 'community', 11 | 'status': ['preview'] 12 | } 13 | 14 | 15 | DOCUMENTATION = ''' 16 | --- 17 | version_added: "1.1" 18 | author: 19 | - Prashant Bhosale 20 | - Naval Patel (@navalkp) 21 | module: pylxca_module 22 | short_description: custom module for pylxca utility 23 | description: 24 | - This module returns/displays a inventory details of chassis, cmms, nodes, 25 | switches, fans, powersupplies, fanmuxes etc. 26 | 27 | - It also displays/perform config operations like manage, unmanage, 28 | config pattern, config profile, config targets, update firmware, update policy, 29 | update management server, update osimamge and os deployment. 30 | options: 31 | login_user: 32 | description: 33 | The username for use in HTTP basic authentication. 34 | 35 | required: true 36 | 37 | login_password: 38 | description: 39 | The password for use in HTTP basic authentication. 40 | required: true 41 | 42 | auth_url: 43 | description: 44 | lxca https full web address 45 | required: true 46 | 47 | command_options: 48 | description: 49 | there are three types of commands inventory, config and others 50 | required: true 51 | choices: 52 | - chassis 53 | - cmms 54 | - nodes 55 | - discover 56 | - fans 57 | - fanmuxes 58 | - ffdc 59 | - jobs 60 | - lxcalog 61 | - powersupplies 62 | - scalablesystem 63 | - switches 64 | - tasks 65 | - users 66 | - get_configpatterns 67 | - get_particular_configpattern 68 | - import_configpatterns 69 | - apply_configpatterns 70 | - get_configstatus 71 | - configprofiles 72 | - configtargets 73 | - manage 74 | - unmanage 75 | - manage_status 76 | - unmanage_status 77 | - manifests 78 | - osimages 79 | - updaterepo 80 | - update_firmware 81 | - update_firmware_all 82 | - update_firmware_query_status 83 | - update_firmware_query_comp 84 | - get_managementserver_pkg 85 | - update_managementserver_pkg 86 | - import_managementserver_pkg 87 | - updatepolicy 88 | - get_storedcredentials 89 | - create_storedcredentials 90 | - update_storedcredentials 91 | - delete_storedcredentials 92 | - connect 93 | 94 | subcmd: 95 | description: subcmd for some of configuration command 96 | 97 | lxca_action: 98 | description: 99 | - action performed on lxca, Used with following commands with option for lxca_action 100 | - "update_firmware, update_all_firmware_withpolicy 101 | (apply Applies the associated firmware to the submitted components. 102 | power Perform power action on selected endpoint. 103 | cancelApply Cancels the firmware update request to the selected components.)" 104 | - "updaterepo 105 | read - Reloads the repository files. The clears the update information in cache and 106 | reads the update file again from the repository. 107 | refresh - Retrieves information about the latest available firmware updates from 108 | the Lenovo Support website, and stores the information to 109 | the firmware-updates repository. 110 | acquire - Downloads the specified firmware updates from Lenovo Support website, 111 | and stores the updates to the firmware-updates repository. 112 | delete - Deletes the specified firmware updates from the firmware-updates 113 | repository." 114 | - "configprofiles 115 | delete - delete profile 116 | unassign - unassign profile" 117 | 118 | - "update_managementserver_pkg 119 | apply - install a management-server update. 120 | refresh - Retrieves information (metadata) about the latest available 121 | management-server updates from the Lenovo XClarity Support website. 122 | acquire - Downloads the specified management-server update packages from the 123 | Lenovo XClarity Support website." 124 | 125 | - "import_managementserver_pkg 126 | import - import management package" 127 | 128 | 129 | choices: 130 | - None 131 | - apply 132 | - power 133 | - cancelApply 134 | - read 135 | - refresh 136 | - acquire 137 | - delete 138 | - unassign 139 | - import 140 | 141 | uuid: 142 | description: 143 | of device, this is string with length greater than 16. 144 | 145 | id: 146 | description: 147 | this is numeric string 148 | 149 | endpoint_ip: 150 | description: 151 | - Used with following command 152 | - "manage - ip of endpoint to be managed 153 | i.e 10.240.72.172" 154 | - "unmanage - combination of ip,uuid of device and type of device 155 | i.e 10.240.72.172;46920C143355486F97C19A34ABC7D746;Chassis 156 | type have following options 157 | Chassis 158 | ThinkServer 159 | Storage 160 | Rackswitch 161 | Rack-Tower" 162 | 163 | jobid: 164 | description: 165 | Id of job, to get status of it 166 | 167 | user: 168 | description: 169 | credential for login to device 170 | 171 | password: 172 | description: 173 | for login to device 174 | 175 | recovery_password: 176 | description: 177 | recovery password to be set in device 178 | 179 | force: 180 | description: 181 | Perform force operation. set to 'True'. 182 | 183 | description: 184 | description: 185 | detail about storedcredential. 186 | 187 | storedcredential_id: 188 | description: 189 | stored credential id to be used for operation 190 | 191 | 192 | repo_key: 193 | description: 194 | - used with updaterepo command following values are used. 195 | - "supportedMts - Returns a list of supported machine types" 196 | - "size - Returns the repository size" 197 | - "lastRefreshed - Returns the timestamp of the last repository refresh" 198 | - "importDir - Returns the import directory for the repository." 199 | - "publicKeys - Returns the supported signed keys" 200 | - "updates - Returns information about all firmware updates" 201 | - "updatesByMt - Returns information about firmware updates for the specified 202 | machine type" 203 | - "updatesByMtByComp - Returns the update component names for the specified 204 | machine type" 205 | choices: 206 | - None 207 | - supportedMts 208 | - size 209 | - lastRefreshed 210 | - importDir 211 | - publicKeys 212 | - updates 213 | - updatesByMt 214 | - updatesByMtByComp 215 | 216 | mode: 217 | description: 218 | - "used with command update_firmware, update_all_firmware_withpolicy 219 | Indicates when to activate the update. This can be one of the following values." 220 | - "immediate - Uses Immediate Activaton mode when applying firmware updates to 221 | the selected endpoints." 222 | - "delayed - Uses Delayed Activaton mode when applying firmware updates to the 223 | selected endpoints." 224 | - "prioritized - Firmware updates on the baseboard management controller 225 | are activated immediately." 226 | 227 | choices: 228 | - None 229 | - immediate 230 | - delayed 231 | - prioritized 232 | 233 | server: 234 | description: 235 | - used with command update_firmware 236 | - "string of format uuid,mt or uuid,fixids,mt 237 | fixid: lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch 238 | Component name 239 | name: IMM2 (Backup)" 240 | 241 | - "Example '7C5E041E3CCA11E18B715CF3FC112D8A,IMM2 (Backup)' or 242 | '7C5E041E3CCA11E18B715CF3FC112D8A,lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch,IMM2 (Backup)'" 243 | 244 | storage: 245 | description: 246 | - used with command update_firmware 247 | - "string of format uuid,mt or uuid,fixids,mt 248 | fixid: lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch 249 | Component name 250 | name: IMM2 (Backup)" 251 | 252 | - "Example '7C5E041E3CCA11E18B715CF3FC112D8A,IMM2 (Backup)' or 253 | '7C5E041E3CCA11E18B715CF3FC112D8A,lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch,IMM2 (Backup)'" 254 | 255 | cmm: 256 | description: 257 | - used with command update_firmware 258 | - "string of format uuid,mt or uuid,fixids,mt 259 | fixid: lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch 260 | Component name 261 | name: IMM2 (Backup)" 262 | 263 | - "Example '7C5E041E3CCA11E18B715CF3FC112D8A,IMM2 (Backup)' or 264 | '7C5E041E3CCA11E18B715CF3FC112D8A,lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch,IMM2 (Backup)'" 265 | 266 | switch: 267 | description: 268 | - used with command update_firmware 269 | - "string of format uuid,mt or uuid,fixids,mt 270 | fixid: lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch 271 | Component name 272 | name: IMM2 (Backup)" 273 | 274 | - "Example '7C5E041E3CCA11E18B715CF3FC112D8A,IMM2 (Backup)' or 275 | '7C5E041E3CCA11E18B715CF3FC112D8A,lnvgy_fw_imm2_tcoo15m-2.50_anyos_noarch,IMM2 (Backup)'" 276 | 277 | uuid_list: 278 | description: 279 | - used with command update_all_firmware_withpolicy. Apply firmware to uuid in list 280 | - "example ['38D9D7DBCB713C12A210E60C74A0E931','00000000000010008000542AA2D3CB00']" 281 | 282 | policy_info: 283 | description: 284 | - used with command updatepolicy following values are possible 285 | - "FIRMWARE - Get List of Applicable Frimware policies" 286 | - "RESULTS - List the persisted compare result for servers to which a policy is assigned" 287 | - "COMPARE_RESULTS -Check compliant with the assigned compliance policy using the job or task ID 288 | that was returned when the compliance policy was assigned." 289 | - "NAMELIST - Returns the available compliance policies" 290 | 291 | choices: 292 | - None 293 | - FIRMWARE 294 | - RESULTS 295 | - COMPARE_RESULTS 296 | - NAMELIST 297 | 298 | policy_name: 299 | description: 300 | used with command updatepolicy, name of policy to be applied 301 | 302 | policy_type: 303 | description: 304 | - used with command updatepolicy, policy applied to value specified it can have following value 305 | - CMM - Chassis Management Module 306 | - IOSwitch - Flex switch 307 | - RACKSWITCH - RackSwitch switch 308 | - STORAGE - Lenovo Storage system 309 | - SERVER - Compute node or rack server 310 | choices: 311 | - None 312 | - CMM 313 | - IOSwitch 314 | - RACKSWITCH 315 | - STORAGE 316 | - SERVER 317 | 318 | update_list: 319 | description: 320 | - used with command task to update task status this is used with action=update 321 | - example 322 | [{'jobUID':'9','percentage':50},{'jobUID':'8','percentage':50}]" 323 | 324 | machine_type: 325 | description: 326 | - used with command updaterepo 327 | - its string with value like '7903' 328 | 329 | fixids: 330 | description: 331 | - used with command updaterepo , get_particular_managementserver_pkg and update_managementserver_pkg 332 | - its string with value like 'lnvgy_sw_lxca-fw-repository-pack_1-1.0.1_anyos_noarch' 333 | 334 | scope: 335 | description: 336 | - used with command updaterepo, following are possible values 337 | - all - When lxca_action=refresh is specified, this parameter returns information about all versions of all 338 | firmware updates that are available for all supported devices. 339 | - latest - When lxca_action=refresh is specified, this parameter returns information about the most current 340 | version of all firmware updates for all supported devices. 341 | - payloads - When lxca_action=acquire is specified, this parameter returns information about specific 342 | firmware updates. 343 | choices: 344 | - None 345 | - all 346 | - latest 347 | - payloads 348 | 349 | file_type: 350 | description: 351 | - used with command updaterepo, When lxca_action=delete or lxca_action=export is specified, this parameter 352 | is used. You can specify one of the following values 353 | - all - Deletes selected update-package files (payload, change history, readme, and metadata files) 354 | - payloads - Deletes only the selected payload image files 355 | choices: 356 | - None 357 | - all 358 | - payloads 359 | 360 | endpoint: 361 | description: 362 | - used with command configprofiles, apply_configpatterns and get_configstatus, 363 | - its uuid of deivce for node, rack, tower 364 | - endpointdid for flex 365 | 366 | restart: 367 | description: 368 | - used with command configprofiles and apply_configpatterns 369 | - when to activate the configurations. This can be one of the following values 370 | - defer - Activate IMM settings but do not restart the server. 371 | - immediate - Activate all settings and restart the server immediately 372 | - pending - Manually activate the server profile and restart the server. this can be used 373 | with apply_configpatterns only. 374 | choices: 375 | - None 376 | - defer 377 | - immediate 378 | - pending 379 | 380 | type: 381 | description: 382 | - used with apply_configpatterns valid values are 383 | choices: 384 | - None 385 | - node 386 | - rack 387 | - tower 388 | - flex 389 | 390 | powerdown: 391 | description: 392 | used with command configprofiles to power down server 393 | 394 | resetimm: 395 | description: 396 | used with command configprofiles to reset imm 397 | 398 | pattern_update_dict: 399 | description: 400 | used with command import_configpatterns to import pattern specified in this variable as dict. 401 | 402 | includeSettings: 403 | description: 404 | used with command get_configpatterns to get detailed settings of configpattern set this to 'True' 405 | 406 | config_pattern_name: 407 | description: 408 | name of config pattern 409 | 410 | config_profile_name: 411 | description: 412 | name of config profile 413 | 414 | update_key: 415 | description: 416 | - Used with managementserver commands following are valid options 417 | Returns the specified type of update. This can be one of the following values. 418 | - C(all) - Returns all information. This is the default value. 419 | - C(currentVersion) - Returns the current version of Lenovo XClarity Administrator. 420 | - C(history) Returns the history of management-server updates. 421 | - C(importDir) Returns the directory for the management-server updates repository. 422 | - C(size) - Returns the repository size (in bytes). 423 | - C(updates) - Returns information about all updates packages. 424 | - C(updatedDate) - Returns the date when the last update was performed. 425 | 426 | choices: 427 | - None 428 | - all 429 | - currentVersion 430 | - history 431 | - importDir 432 | - size 433 | - updates 434 | - updatedDate 435 | 436 | files: 437 | description: 438 | - Used with managementserver commands to import files to LXCA file can be specified as comma separated string 439 | - example 440 | - '/home/naval/updates/updates/lnvgy_sw_lxca_thinksystemrepo1-1.3.2_anyos_noarch.txt, 441 | /home/naval/updates/updates/lnvgy_sw_lxca_thinksystemrepo1-1.3.2_anyos_noarch.chg, 442 | /home/naval/updates/updates/lnvgy_sw_lxca_thinksystemrepo1-1.3.2_anyos_noarch.xml' 443 | 444 | imagetype: 445 | description: 446 | - Used with osimage import type of files. 447 | choices: 448 | - BUNDLE 449 | - BOOT 450 | - DUD 451 | - OS 452 | - OSPROFILE 453 | - SCRIPT 454 | - CUSTOM_CONFIG 455 | - UNATTEND 456 | 457 | osimages_dict: 458 | type: 459 | dict 460 | description: 461 | Used with osimage it is used for setting osimage and os deployment parameters. 462 | 463 | requirements: 464 | - pylxca 465 | ''' 466 | 467 | EXAMPLES = ''' 468 | # Following links have example tasks using this module 469 | # for Inventory operations 470 | # U(https://github.com/lenovo/ansible.lenovo-lxca/tree/master/roles/lenovo.lxca-inventory/tasks) 471 | 472 | # for config operations 473 | # U(https://github.com/lenovo/ansible.lenovo-lxca/tree/master/roles/lenovo.lxca-config/tasks) 474 | # get cmms info 475 | - name: get cmms data from LXCA 476 | pylxca_module: 477 | command_options: cmms 478 | login_userr: USERID 479 | login_password: CME44ibm 480 | auth_url: "https://10.243.15.168" 481 | ''' 482 | 483 | import os 484 | import imp 485 | import json 486 | from jsonpath_ng.ext import parse 487 | 488 | try: 489 | from pylxca import chassis 490 | from pylxca import cmms 491 | from pylxca import nodes 492 | from pylxca import discover 493 | from pylxca import fans 494 | from pylxca import fanmuxes 495 | from pylxca import ffdc 496 | from pylxca import jobs 497 | from pylxca import lxcalog 498 | from pylxca import powersupplies 499 | from pylxca import scalablesystem 500 | from pylxca import switches 501 | from pylxca import tasks 502 | from pylxca import users 503 | from pylxca import configpatterns 504 | from pylxca import configprofiles 505 | from pylxca import configtargets 506 | from pylxca import manage 507 | from pylxca import unmanage 508 | from pylxca import osimages 509 | from pylxca import updaterepo 510 | from pylxca import updatecomp 511 | from pylxca import managementserver 512 | from pylxca import updatepolicy 513 | from pylxca import storedcredentials 514 | from pylxca import connect 515 | from pylxca import disconnect 516 | HAS_PYLXCA = True 517 | except Exception: 518 | HAS_PYLXCA = False 519 | 520 | from ansible.module_utils.basic import AnsibleModule 521 | 522 | 523 | __ip_map__ = dict() 524 | __changed__ = False 525 | 526 | 527 | class connection_object: 528 | def __init__(self, module, kwargs): 529 | self.module = module 530 | self.kwargs = kwargs 531 | 532 | def __enter__(self): 533 | return _get_connect_lxca(self.module, self.kwargs) 534 | 535 | def __exit__(self, type, value, traceback): 536 | disconnect() 537 | 538 | 539 | def find_conn_obj(kwargs): 540 | """ 541 | Find connection object in map and return if its already there for url 542 | :param kwargs: uses url from this dict 543 | :return: connection if already exist. 544 | """ 545 | global __ip_map__ 546 | 547 | if __ip_map__.get(kwargs.get('url')) is not None: 548 | return __ip_map__.get(kwargs.get('url')) 549 | return None 550 | 551 | 552 | def _get_connect_lxca(module, kwargs): 553 | global __ip_map__ 554 | 555 | _conn_lxca = None 556 | try: 557 | _conn_lxca = find_conn_obj(kwargs) 558 | if _conn_lxca is None: 559 | _conn_lxca = connect(kwargs.get('auth_url'), kwargs.get( 560 | 'login_user'), kwargs.get('login_password'), "True") 561 | __ip_map__.update({kwargs.get('auth_url'): _conn_lxca}) 562 | if _conn_lxca is None: 563 | module.fail_json(msg="Error connecting with: %s" % 564 | kwargs.get('auth_url')) 565 | except Exception: 566 | module.fail_json( 567 | msg="Error authenticating with provided credentials: %s" % kwargs.get('auth_url')) 568 | return _conn_lxca 569 | 570 | 571 | def _get_chassis_inventory(module, kwargs): 572 | result = None 573 | try: 574 | with connection_object(module, kwargs) as con: 575 | result = chassis(con) 576 | except Exception as err: 577 | module.fail_json(msg="Error getting chassis inventory" + str(err)) 578 | return result 579 | 580 | 581 | def _get_cmms_inventory(module, kwargs): 582 | result = None 583 | try: 584 | with connection_object(module, kwargs) as con: 585 | result = cmms(con, kwargs.get('uuid')) 586 | except Exception as err: 587 | module.fail_json(msg="Error getting cmms inventory" + str(err)) 588 | return result 589 | 590 | 591 | def _get_configstatus(module, kwargs): 592 | result = None 593 | try: 594 | with connection_object(module, kwargs) as con: 595 | result = configpatterns(con, subcmd='status', endpoint=kwargs.get( 596 | 'endpoint')) 597 | if 'items' in result and len(result['items']) and result['items'][0]: 598 | result = result['items'][0] 599 | except Exception as err: 600 | module.fail_json(msg="Error in configstatus " + str(err)) 601 | return result 602 | 603 | 604 | def _get_configpatterns(module, kwargs): 605 | result = None 606 | try: 607 | with connection_object(module, kwargs) as con: 608 | result = configpatterns(con, subcmd='list') 609 | except Exception as err: 610 | module.fail_json(msg="Error in configpatterns " + str(err)) 611 | return result 612 | 613 | 614 | def _get_particular_configpattern(module, kwargs): 615 | result = None 616 | try: 617 | with connection_object(module, kwargs) as con: 618 | pattern_dict = {} 619 | pattern_dict['id'] = kwargs.get('id') 620 | pattern_dict['includeSettings'] = kwargs.get('includeSettings') 621 | result = configpatterns(con, subcmd='list', **pattern_dict) 622 | except Exception as err: 623 | module.fail_json( 624 | msg="Error in getting particular configpattern " + str(err)) 625 | return result 626 | 627 | 628 | def _apply_configpatterns(module, kwargs): 629 | global __changed__ 630 | result = None 631 | try: 632 | with connection_object(module, kwargs) as con: 633 | pattern_dict = {} 634 | pattern_dict['id'] = kwargs.get('id') 635 | pattern_dict['name'] = kwargs.get('config_pattern_name') 636 | pattern_dict['endpoint'] = kwargs.get('endpoint') 637 | pattern_dict['restart'] = kwargs.get('restart') 638 | pattern_dict['type'] = kwargs.get('type') 639 | result = configpatterns(con, subcmd='apply', **pattern_dict) 640 | __changed__ = True 641 | except Exception as err: 642 | module.fail_json(msg="Error in applying configpatterns" + str(err)) 643 | return result 644 | 645 | 646 | def _import_configpatterns(module, kwargs): 647 | global __changed__ 648 | result = None 649 | try: 650 | with connection_object(module, kwargs) as con: 651 | pattern_dict = {} 652 | json_str = json.dumps(kwargs.get('pattern_update_dict')) 653 | pattern_dict['pattern_update_dict'] = json_str 654 | result = configpatterns(con, subcmd='import', **pattern_dict) 655 | __changed__ = True 656 | except Exception as err: 657 | module.fail_json(msg="Error in import configpatterns" + str(err)) 658 | return result 659 | 660 | 661 | def _get_configprofiles(module, kwargs): 662 | global __changed__ 663 | result = None 664 | try: 665 | with connection_object(module, kwargs) as con: 666 | subcmd = kwargs.get("subcmd") 667 | if subcmd: 668 | if subcmd.lower() in ['delete', 'unassign']: 669 | __changed__ = True 670 | result = configprofiles(con, 671 | kwargs.get('subcmd'), 672 | kwargs.get('id'), 673 | kwargs.get('config_profile_name'), 674 | kwargs.get('endpoint'), 675 | kwargs.get('restart'), 676 | kwargs.get('powerdown'), 677 | kwargs.get('resetimm'), 678 | kwargs.get('force'),) 679 | except Exception as err: 680 | module.fail_json(msg="Error getting configprofiles" + str(err)) 681 | return result 682 | 683 | 684 | def _get_configtargets(module, kwargs): 685 | result = None 686 | try: 687 | with connection_object(module, kwargs) as con: 688 | result = configtargets(con, kwargs.get('id')) 689 | except Exception as err: 690 | module.fail_json(msg="Error getting configtargets" + str(err)) 691 | return result 692 | 693 | 694 | def _get_discover(module, kwargs): 695 | result = None 696 | try: 697 | with connection_object(module, kwargs) as con: 698 | result = discover(con, kwargs.get('discovery_ip')) 699 | except Exception as err: 700 | module.fail_json(msg="Error discovery " + str(err)) 701 | return result 702 | 703 | 704 | def _get_fans(module, kwargs): 705 | result = None 706 | try: 707 | with connection_object(module, kwargs) as con: 708 | result = fans(con, kwargs.get('uuid')) 709 | except Exception as err: 710 | module.fail_json(msg="Error getting fans inventory " + str(err)) 711 | return result 712 | 713 | 714 | def _get_fanmuxes(module, kwargs): 715 | result = None 716 | try: 717 | with connection_object(module, kwargs) as con: 718 | result = fanmuxes(con, kwargs.get('uuid')) 719 | except Exception as err: 720 | module.fail_json(msg="Error getting fanmuxes inventory " + str(err)) 721 | return result 722 | 723 | 724 | def _get_ffdc(module, kwargs): 725 | result = None 726 | try: 727 | with connection_object(module, kwargs) as con: 728 | result = ffdc(con, kwargs.get('uuid')) 729 | except Exception as err: 730 | module.fail_json(msg="Error getting ffdc inventory " + str(err)) 731 | return result 732 | 733 | 734 | def _get_jobs(module, kwargs): 735 | result = None 736 | try: 737 | with connection_object(module, kwargs) as con: 738 | result = jobs(con, kwargs.get('id')) 739 | except Exception as err: 740 | module.fail_json(msg="Error getting jobs inventory " + str(err)) 741 | return result 742 | 743 | 744 | # TODO filter 745 | def _get_lxcalog(module, kwargs): 746 | result = None 747 | try: 748 | with connection_object(module, kwargs) as con: 749 | result = lxcalog(con) 750 | except Exception as err: 751 | module.fail_json(msg="Error getting lxcalog " + str(err)) 752 | return result 753 | 754 | 755 | def _manage_endpoint(module, kwargs): 756 | global __changed__ 757 | result = None 758 | 759 | try: 760 | with connection_object(module, kwargs) as con: 761 | result = manage(con, 762 | 'device', 763 | kwargs.get('endpoint_ip'), 764 | kwargs.get('user'), 765 | kwargs.get('password'), 766 | kwargs.get('recovery_password'), 767 | None, kwargs.get('force'), 768 | kwargs.get('storedcredential_id')) 769 | __changed__ = True 770 | except Exception as err: 771 | module.fail_json(msg=" Fail to manage the endpoint" + str(err)) 772 | return result 773 | 774 | 775 | def _manage_status(module, kwargs): 776 | result = None 777 | try: 778 | with connection_object(module, kwargs) as con: 779 | result = manage(con, 'job_status', None, 780 | None, None, None, kwargs.get('jobid')) 781 | except Exception as err: 782 | module.fail_json(msg="Error getting info abt jobid" + str(err)) 783 | return result 784 | 785 | 786 | def _unmanage_endpoint(module, kwargs): 787 | global __changed__ 788 | result = None 789 | 790 | try: 791 | with connection_object(module, kwargs) as con: 792 | result = unmanage(con, 793 | 'device', 794 | kwargs.get('endpoint_ip'), 795 | kwargs.get('force'), 796 | None) 797 | __changed__ = True 798 | except Exception as err: 799 | module.fail_json(msg=" Fail to unmanage the endpoint" + str(err)) 800 | return result 801 | 802 | 803 | def _unmanage_status(module, kwargs): 804 | result = None 805 | try: 806 | with connection_object(module, kwargs) as con: 807 | result = unmanage(con, 'job_status', None, None, kwargs.get('jobid')) 808 | except Exception as err: 809 | module.fail_json(msg="Error getting info abt jobid" + str(err)) 810 | return result 811 | 812 | 813 | # TODO chassis , status 814 | 815 | 816 | def _get_nodes(module, kwargs): 817 | result = None 818 | try: 819 | with connection_object(module, kwargs) as con: 820 | result = nodes( 821 | con, 822 | kwargs.get('uuid'), 823 | kwargs.get('chassis'), 824 | kwargs.get('status'), 825 | json.dumps(kwargs.get('modify')), 826 | ) 827 | except Exception as err: 828 | module.fail_json(msg="Error getting nodes inventory " + str(err)) 829 | return result 830 | 831 | 832 | def _get_powersupplies(module, kwargs): 833 | result = None 834 | try: 835 | with connection_object(module, kwargs) as con: 836 | result = powersupplies(con, kwargs.get('uuid')) 837 | except Exception as err: 838 | module.fail_json(msg="Error getting powersupplies inventory " + str(err)) 839 | return result 840 | 841 | # TODO type 842 | 843 | 844 | def _get_scalablesystem(module, kwargs): 845 | result = None 846 | try: 847 | with connection_object(module, kwargs) as con: 848 | result = scalablesystem(con, kwargs.get('id')) 849 | except Exception as err: 850 | module.fail_json( 851 | msg="Error getting scalablesystem inventory " + str(err)) 852 | return result 853 | 854 | # TODO chassis, ports, action 855 | 856 | 857 | def _get_switches_inventory(module, kwargs): 858 | result = None 859 | try: 860 | with connection_object(module, kwargs) as con: 861 | result = switches(con, kwargs.get('uuid')) 862 | except Exception as err: 863 | module.fail_json(msg="Error getting switches " + str(err)) 864 | return result 865 | 866 | 867 | def _get_tasks(module, kwargs): 868 | global __changed__ 869 | result = None 870 | tasks_dict = {} 871 | job_uid = kwargs.get("id") 872 | action = kwargs.get("lxca_action") 873 | if action in ['cancel', 'delete']: 874 | tasks_dict['jobUID'] = job_uid 875 | tasks_dict['action'] = action 876 | __changed__ = True 877 | elif action in ['update']: 878 | tasks_dict['action'] = action 879 | update_list = kwargs.get("update_list") 880 | tasks_dict['updateList'] = update_list 881 | __changed__ = True 882 | else: 883 | tasks_dict['jobUID'] = job_uid 884 | try: 885 | with connection_object(module, kwargs) as con: 886 | result = tasks(con, **tasks_dict) 887 | except Exception as err: 888 | module.fail_json(msg="Error getting tasks " + str(err)) 889 | return result 890 | 891 | 892 | def _get_updaterepo_info(module, kwargs): 893 | result = None 894 | try: 895 | with connection_object(module, kwargs) as con: 896 | result = updaterepo(con, 897 | kwargs.get('subcmd'), 898 | kwargs.get('repo_key'), 899 | kwargs.get('lxca_action'), 900 | kwargs.get('machine_type'), 901 | kwargs.get('scope'), 902 | kwargs.get('fixids'), 903 | kwargs.get('file_type')) 904 | except Exception as err: 905 | module.fail_json(msg="Error retriving firmware info." + str(err)) 906 | return result 907 | 908 | 909 | def _update_firmware(module, kwargs): 910 | global __changed__ 911 | result = None 912 | try: 913 | with connection_object(module, kwargs) as con: 914 | cmm_json_str = json.dumps(kwargs.get('cmm')) 915 | switch_json_str = json.dumps(kwargs.get('switch')) 916 | server_json_str = json.dumps(kwargs.get('server')) 917 | storage_json_str = json.dumps(kwargs.get('storage')) 918 | result = updatecomp(con, 'apply', mode=kwargs.get('mode'), 919 | action=kwargs.get('lxca_action'), 920 | cmm=cmm_json_str, 921 | switch=switch_json_str, 922 | server=server_json_str, 923 | storage=storage_json_str) 924 | __changed__ = True 925 | except Exception as err: 926 | module.fail_json(msg="Error updating firmware " + str(err)) 927 | return result 928 | 929 | 930 | def _transform_devicelist(devicelist, uuid_list): 931 | ret_device_list = [] 932 | for dev in devicelist: 933 | new_dict = {} 934 | for dev_type in dev.keys(): # SwitchList 935 | new_list = [] 936 | for sw_dev in dev[dev_type]: 937 | if not sw_dev['UUID'] in uuid_list: 938 | continue 939 | cm_list = [] 940 | for cm_dev in sw_dev['Components']: 941 | cm_list.append({'Component': cm_dev}) 942 | sw_dev['Components'] = cm_list 943 | new_list.append(sw_dev) 944 | if len(new_list) > 0: 945 | new_dict[dev_type] = new_list 946 | if len(new_dict) > 0: 947 | ret_device_list.append(new_dict) 948 | return ret_device_list 949 | 950 | 951 | def _valid_compliance_policies(policy_list): 952 | uuid_list = [] 953 | for comp_policy in policy_list: 954 | if 'uuid' in comp_policy.keys(): 955 | if 'currentPolicy' in comp_policy.keys() and len(comp_policy['currentPolicy']) > 0: 956 | uuid_list.append(comp_policy['uuid']) 957 | 958 | return uuid_list 959 | 960 | 961 | def _get_do_not_update_components(module, policies): 962 | skip_components_dict = {} 963 | server_list = [] 964 | cmm_list = [] 965 | storage_list = [] 966 | switch_list = [] 967 | 968 | # This dict can be updated based as you found type which are not covered here 969 | type_to_name_dict = {"XCC-BACKUP": ["XCC (Backup)"], 970 | "IMM-BACKUP": ["IMM (Backup)"], 971 | "IMM2-BACKUP": ["IMM2 (Backup)"], 972 | "UEFI-BACKUP": ["UEFI (Backup)"], 973 | "XCC": ["XCC"], 974 | "IMM": ["IMM"], 975 | "IMM2": ["IMM2"], 976 | "UEFI": ["UEFI"]} 977 | for policy in policies: 978 | 979 | if len(policy['deviceslist']) > 0: 980 | uuids = policy['deviceslist'] 981 | comp_details = policy['details'] 982 | components_list = [] 983 | 984 | for comp in comp_details: 985 | for c in comp['components']: 986 | type = c['type'].upper() 987 | if c['targetVersion'].find('DoNotUpdate') == 0 and type: 988 | if type not in type_to_name_dict: 989 | module.fail_json(msg="Following type is missing from type_to_name_dict " + type) 990 | else: 991 | for component in type_to_name_dict[type]: 992 | comp_dict = {"Component": component} 993 | components_list.append(comp_dict) 994 | 995 | if components_list: 996 | for uuid_dict in uuids: 997 | skip_dict = {} 998 | skip_dict['uuid'] = uuid_dict['uuid'] 999 | skip_dict['Components'] = components_list 1000 | if uuid_dict['type'] == 'SERVER': 1001 | server_list.append(skip_dict) 1002 | elif uuid_dict['type'] == 'CMM': 1003 | cmm_list.append(skip_dict) 1004 | elif uuid_dict['type'] == 'Storage': 1005 | storage_list.append(skip_dict) 1006 | elif uuid_dict['type'] == 'Switch': 1007 | switch_list.append(skip_dict) 1008 | 1009 | skip_components_dict['ServerList'] = server_list 1010 | skip_components_dict['CMMList'] = cmm_list 1011 | skip_components_dict['StorageList'] = storage_list 1012 | skip_components_dict['SwitchList'] = switch_list 1013 | 1014 | return skip_components_dict 1015 | 1016 | 1017 | def _remove_components(device_list, dev_type_list, del_uuid, del_component): 1018 | del_component_bool = False 1019 | del_uuid_bool = False 1020 | for dev_dict in device_list: 1021 | if dev_type_list in dev_dict: 1022 | if len(dev_dict[dev_type_list]) > 0: 1023 | for sev_dict in dev_dict[dev_type_list]: 1024 | if del_uuid == sev_dict['UUID']: 1025 | len_of_components = len(sev_dict['Components']) 1026 | ### 1027 | new_Compnents = [x for x in sev_dict['Components'] if not (del_component == x.get('Component'))] 1028 | sev_dict['Components'] = new_Compnents 1029 | if len(new_Compnents) < len_of_components: 1030 | del_component_bool = True 1031 | if del_component_bool: 1032 | if len(new_Compnents) == 0: 1033 | del_uuid_bool = True 1034 | if del_uuid_bool: 1035 | new_dev_list = [x for x in dev_dict[dev_type_list] if not (del_uuid == x.get('UUID'))] 1036 | dev_dict[dev_type_list] = new_dev_list 1037 | 1038 | 1039 | def _call_remove_components(skip_dict, from_device_list): 1040 | for dev_type_list in ['ServerList', 'CMMList', 'StorageList', 'SwtichList']: 1041 | if dev_type_list in skip_dict: 1042 | if len(skip_dict[dev_type_list]) > 0: 1043 | for sev_dict in skip_dict[dev_type_list]: 1044 | for comp_dict in sev_dict['Components']: 1045 | _remove_components(from_device_list, dev_type_list, sev_dict['uuid'], comp_dict['Component']) 1046 | 1047 | 1048 | def _update_firmware_all(module, kwargs): 1049 | global __changed__ 1050 | result = None 1051 | try: 1052 | with connection_object(module, kwargs) as con: 1053 | rep = updatepolicy(con, 'query', info="NAMELIST") 1054 | uuid_list = _valid_compliance_policies(rep['policies']) 1055 | if len(uuid_list) == 0: 1056 | module.fail_json(msg="No policy assigned to any device") 1057 | return result 1058 | 1059 | dev_uuid_list = [] 1060 | if 'uuid_list' in kwargs: 1061 | dev_uuid_list = kwargs.get('uuid_list') 1062 | if len(dev_uuid_list) > 0: 1063 | # getting common uuid of two list 1064 | uuid_list = list(set(dev_uuid_list).intersection(uuid_list)) 1065 | 1066 | rep = updatecomp(con, 'info', query='components') 1067 | ret_dev_list = rep['DeviceList'] 1068 | mod_dev_list = _transform_devicelist(ret_dev_list, uuid_list) 1069 | if len(mod_dev_list) == 0: 1070 | module.fail_json( 1071 | msg="No updateable component with assigned policy found") 1072 | return result 1073 | 1074 | # removing component with DoNotUpdate 1075 | rep = updatepolicy(con, 'query', info="RESULT") 1076 | skip_components = _get_do_not_update_components(module, rep['policies']) 1077 | _call_remove_components(skip_components, mod_dev_list) 1078 | 1079 | final_dev = {} 1080 | final_dev['DeviceList'] = mod_dev_list 1081 | dev_json_str = json.dumps(final_dev) 1082 | result = updatecomp(con, 'apply', mode=kwargs.get( 1083 | 'mode'), action=kwargs.get('lxca_action'), dev_list=dev_json_str) 1084 | __changed__ = True 1085 | except Exception as err: 1086 | module.fail_json(msg="Error updating all device firmware " + str(err)) 1087 | return result 1088 | 1089 | 1090 | def _update_firmware_query_status(module, kwargs): 1091 | result = None 1092 | try: 1093 | with connection_object(module, kwargs) as con: 1094 | result = updatecomp(con, 'info', query='status') 1095 | except Exception as err: 1096 | module.fail_json(msg="Error updating firmware " + str(err)) 1097 | return result 1098 | 1099 | 1100 | def _update_firmware_query_comp(module, kwargs): 1101 | result = None 1102 | try: 1103 | with connection_object(module, kwargs) as con: 1104 | result = updatecomp(con, 'info', query='components') 1105 | except Exception as err: 1106 | module.fail_json(msg="Error updating firmware " + str(err)) 1107 | return result 1108 | 1109 | 1110 | def _get_managementserver_pkg(module, kwargs): 1111 | result = None 1112 | try: 1113 | with connection_object(module, kwargs) as con: 1114 | result = managementserver(con, 1115 | kwargs.get('subcmd'), 1116 | kwargs.get('update_key'), 1117 | kwargs.get('fixids'), 1118 | kwargs.get('type')) 1119 | except Exception as err: 1120 | module.fail_json(msg="Error retriving managementserver info." + str(err)) 1121 | return result 1122 | 1123 | 1124 | def _update_managementserver_pkg(module, kwargs): 1125 | global __changed__ 1126 | result = None 1127 | try: 1128 | with connection_object(module, kwargs) as con: 1129 | result = managementserver(con, 1130 | kwargs.get('subcmd'), 1131 | kwargs.get('update_key'), 1132 | kwargs.get('fixids'), 1133 | kwargs.get('type')) 1134 | __changed__ = True 1135 | except Exception as err: 1136 | module.fail_json( 1137 | msg="Error retriving update managementserver." + str(err)) 1138 | return result 1139 | 1140 | 1141 | def _import_managementserver_pkg(module, kwargs): 1142 | global __changed__ 1143 | result = None 1144 | try: 1145 | with connection_object(module, kwargs) as con: 1146 | result = managementserver(con, 1147 | kwargs.get('subcmd'), 1148 | kwargs.get('update_key'), 1149 | kwargs.get('fixids'), 1150 | kwargs.get('type'), 1151 | kwargs.get('files'), 1152 | kwargs.get('jobid')) 1153 | __changed__ = True 1154 | except Exception as err: 1155 | module.fail_json(msg="Error import managementserver ." + str(err)) 1156 | return result 1157 | 1158 | 1159 | def _get_updatepolicy(module, kwargs): 1160 | result = None 1161 | try: 1162 | with connection_object(module, kwargs) as con: 1163 | result = updatepolicy(con, 1164 | kwargs.get('subcmd'), 1165 | kwargs.get('policy_info'), 1166 | kwargs.get('jobid'), 1167 | kwargs.get('uuid'), 1168 | kwargs.get('policy_name'), 1169 | kwargs.get('policy_type')) 1170 | except Exception as err: 1171 | module.fail_json(msg="Error getting updatepolicy " + str(err)) 1172 | return result 1173 | 1174 | 1175 | def _get_osimages(module, kwargs): 1176 | result = None 1177 | try: 1178 | with connection_object(module, kwargs) as con: 1179 | subcmd = kwargs.get('subcmd') 1180 | osimages_dict = kwargs.get('osimages_dict') 1181 | if subcmd and osimages_dict: 1182 | json_str = json.dumps(osimages_dict) 1183 | if subcmd in ['import']: 1184 | result = osimages(con, 1185 | subcmd, imagetype=kwargs.get('imagetype'), 1186 | osimages_dict=json_str) 1187 | elif subcmd in ['hostsettings']: 1188 | result = osimages(con, 1189 | subcmd, action=osimages_dict['action'], 1190 | osimages_dict=json_str) 1191 | else: 1192 | result = osimages(con, 1193 | subcmd, 1194 | osimages_dict=json_str) 1195 | elif subcmd in ['delete']: 1196 | result = osimages(con, 1197 | subcmd, id=kwargs.get('id')) 1198 | elif subcmd in ['import']: 1199 | result = osimages(con, 1200 | subcmd, imagetype=kwargs.get('imagetype')) 1201 | elif subcmd: 1202 | result = osimages(con, 1203 | subcmd) 1204 | except Exception as err: 1205 | module.fail_json(msg="Error processing osimages " + str(err)) 1206 | return result 1207 | 1208 | 1209 | def _get_users(module, kwargs): 1210 | result = None 1211 | try: 1212 | with connection_object(module, kwargs) as con: 1213 | result = users(con, kwargs.get('id')) 1214 | except Exception as err: 1215 | module.fail_json(msg="Error getting users " + str(err)) 1216 | return result 1217 | 1218 | 1219 | def _get_storedcredentials(module, kwargs): 1220 | result = None 1221 | try: 1222 | with connection_object(module, kwargs) as con: 1223 | result = storedcredentials(con, kwargs.get('storedcredential_id')) 1224 | except Exception as err: 1225 | disconnect() 1226 | module.fail_json(msg="Error getting stored credential " + str(err)) 1227 | return result 1228 | 1229 | 1230 | def _create_storedcredentials(module, kwargs): 1231 | global __changed__ 1232 | result = None 1233 | try: 1234 | with connection_object(module, kwargs) as con: 1235 | result = storedcredentials(con, 1236 | user_name=kwargs.get('user'), 1237 | password=kwargs.get('password'), 1238 | description=kwargs.get('description'),) 1239 | __changed__ = True 1240 | except Exception as err: 1241 | module.fail_json(msg="Error create stored credential " + str(err)) 1242 | return result 1243 | 1244 | 1245 | def _update_storedcredentials(module, kwargs): 1246 | global __changed__ 1247 | result = None 1248 | try: 1249 | with connection_object(module, kwargs) as con: 1250 | result = storedcredentials(con, 1251 | id=kwargs.get('storedcredential_id'), 1252 | user_name=kwargs.get('user'), 1253 | password=kwargs.get('password'), 1254 | description=kwargs.get('description'),) 1255 | __changed__ = True 1256 | except Exception as err: 1257 | module.fail_json(msg="Error getting stored credential " + str(err)) 1258 | return result 1259 | 1260 | 1261 | def _delete_storedcredentials(module, kwargs): 1262 | global __changed__ 1263 | result = None 1264 | try: 1265 | with connection_object(module, kwargs) as con: 1266 | result = storedcredentials(con, 1267 | delete_id=kwargs.get('storedcredential_id')) 1268 | __changed__ = True 1269 | except Exception as err: 1270 | module.fail_json(msg="Error getting stored credential " + str(err)) 1271 | return result 1272 | 1273 | 1274 | FUNC_DICT = { 1275 | 'connect': _get_connect_lxca, 1276 | 'chassis': _get_chassis_inventory, 1277 | 'cmms': _get_cmms_inventory, 1278 | 'get_configpatterns': _get_configpatterns, 1279 | 'get_particular_configpattern': _get_particular_configpattern, 1280 | 'import_configpatterns': _import_configpatterns, 1281 | 'apply_configpatterns': _apply_configpatterns, 1282 | 'get_configstatus': _get_configstatus, 1283 | 'configprofiles': _get_configprofiles, 1284 | 'configtargets': _get_configtargets, 1285 | 'discover': _get_discover, 1286 | 'fans': _get_fans, 1287 | 'fanmuxes': _get_fanmuxes, 1288 | 'ffdc': _get_ffdc, 1289 | 'jobs': _get_jobs, 1290 | 'lxcalog': _get_lxcalog, 1291 | 'manage': _manage_endpoint, 1292 | 'unmanage': _unmanage_endpoint, 1293 | 'manage_status': _manage_status, 1294 | 'unmanage_status': _unmanage_status, 1295 | 'nodes': _get_nodes, 1296 | 'osimages': _get_osimages, 1297 | 'powersupplies': _get_powersupplies, 1298 | 'scalablesystem': _get_scalablesystem, 1299 | 'switches': _get_switches_inventory, 1300 | 'tasks': _get_tasks, 1301 | 'updaterepo': _get_updaterepo_info, 1302 | 'update_firmware': _update_firmware, 1303 | 'update_firmware_all': _update_firmware_all, 1304 | 'update_firmware_query_status': _update_firmware_query_status, 1305 | 'update_firmware_query_comp': _update_firmware_query_comp, 1306 | 'get_managementserver_pkg': _get_managementserver_pkg, 1307 | 'update_managementserver_pkg': _update_managementserver_pkg, 1308 | 'import_managementserver_pkg': _import_managementserver_pkg, 1309 | 'updatepolicy': _get_updatepolicy, 1310 | 'users': _get_users, 1311 | 'get_storedcredentials': _get_storedcredentials, 1312 | 'create_storedcredentials': _create_storedcredentials, 1313 | 'update_storedcredentials': _update_storedcredentials, 1314 | 'delete_storedcredentials': _delete_storedcredentials 1315 | 1316 | } 1317 | 1318 | 1319 | # =========================================== 1320 | # Main 1321 | # 1322 | def main(): 1323 | """ 1324 | Main entry point for this module 1325 | :return: 1326 | """ 1327 | module = AnsibleModule( 1328 | argument_spec=dict( 1329 | login_user=dict(default=None, required=False), 1330 | login_password=dict(default=None, required=False, no_log=True), 1331 | command_options=dict(choices=list(FUNC_DICT)), 1332 | subcmd=dict(default=None), 1333 | lxca_action=dict( 1334 | default=None, 1335 | choices=['apply', 'power', 'cancelApply', 'read', 'refresh', 1336 | 'acquire', 'delete', 'unassign', 'import', None]), 1337 | auth_url=dict(default=None), 1338 | uuid=dict(default=None), 1339 | id=dict(default=None), 1340 | endpoint_ip=dict(default=None), 1341 | jobid=dict(default=None), 1342 | user=dict(default=None, required=False), 1343 | password=dict(default=None, required=False, no_log=True), 1344 | force=dict(default=None), 1345 | description=dict(default=None), 1346 | recovery_password=dict(default=None, no_log=True), 1347 | repo_key=dict(default=None, 1348 | choices=[None, 'supportedMts', 'size', 'lastRefreshed', 1349 | 'importDir', 'publicKeys', 'updates', 1350 | 'updatesByMt', 'updatesByMtByComp']), 1351 | mode=dict(default=None, 1352 | choices=[None, 'immediate', 'delayed', 'prioritized']), 1353 | server=dict(default=None), 1354 | storage=dict(default=None), 1355 | switch=dict(default=None), 1356 | cmm=dict(default=None), 1357 | policy_info=dict(default=None, 1358 | choices=[None, 'FIRMWARE', 'RESULTS', 1359 | 'COMPARE_RESULTS', 'NAMELIST']), 1360 | policy_name=dict(default=None), 1361 | policy_type=dict(default=None, 1362 | choices=['CMM', 'IOSwitch', 'RACKSWITCH', 1363 | 'STORAGE', 'SERVER', None]), 1364 | update_list=dict(default=None, type=('list')), 1365 | machine_type=dict(default=None), 1366 | fixids=dict(default=None), 1367 | scope=dict(default=None, 1368 | choices=['all', 'latest', 'payloads', None]), 1369 | file_type=dict(default=None, choices=[None, 'all', 'payloads']), 1370 | endpoint=dict(default=None), 1371 | restart=dict(default=None, 1372 | choices=[None, 'defer', 'immediate', 'pending']), 1373 | type=dict(default=None, 1374 | choices=[None, 'node', 'rack', 'tower', 'flex']), 1375 | config_pattern_name=dict(default=None), 1376 | config_profile_name=dict(default=None), 1377 | powerdown=dict(default=None), 1378 | resetimm=dict(default=None), 1379 | pattern_update_dict=dict(default=None, type=('dict')), 1380 | includeSettings=dict(default=None), 1381 | imagetype=dict(default=None, 1382 | choices=["BUNDLE", "BOOT", "DUD", "OS", "OSPROFILE", "SCRIPT", "CUSTOM_CONFIG", "UNATTEND"]), 1383 | osimages_dict=dict(default=None, type=('dict')), 1384 | update_key=dict(default=None, 1385 | choices=['all', 'currentVersion', 'history', 'importDir', 1386 | 'size', 'updates', 'updatedDate', None]), 1387 | files=dict(default=None), 1388 | storedcredential_id=dict(default=None), 1389 | uuid_list=dict(default=None, type=('list')), 1390 | unittest=dict(default=None), 1391 | 1392 | ), 1393 | supports_check_mode=False, 1394 | ) 1395 | 1396 | if not HAS_PYLXCA: 1397 | module.fail_json(changed=False, msg="Install pylxca") 1398 | 1399 | rslt = None 1400 | command_options = module.params['command_options'] 1401 | 1402 | rslt = FUNC_DICT[command_options](module, module.params) 1403 | if module.params['unittest']: 1404 | return rslt 1405 | 1406 | if command_options == "connect": 1407 | if rslt: 1408 | disconnect() 1409 | module.exit_json(changed=False, msg="Success %s result" % 1410 | command_options, result="Connected successfully") 1411 | 1412 | if not rslt: 1413 | module.fail_json(changed=False, msg="Fail to get %s result" % 1414 | command_options, result=rslt) 1415 | else: 1416 | module.exit_json(changed=__changed__, msg="Success %s result" % 1417 | command_options, result=rslt) 1418 | 1419 | 1420 | if __name__ == '__main__': 1421 | main() 1422 | --------------------------------------------------------------------------------