* Added deelemc_idrac_server_config_profile
* Update dellemc_idrac_server_config_profile.py
numbering for string concat
* Update dellemc_idrac_server_config_profile.py
git comments corrected
* Update dellemc_idrac_server_config_profile.py
contribution review comments
* Update dellemc_idrac_server_config_profile.py
updated correct version
* Update dellemc_idrac_server_config_profile.py
short description updated with term iDRAC
* Update dellemc_idrac_server_config_profile.py
pwd to password
* removed prefix dellemc_
* revereted password to pwd
idrac_password to idrac_pwd
* changed pwd to password
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,304 @@ |
0 |
+#!/usr/bin/python |
|
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+# |
|
4 |
+# Dell EMC OpenManage Ansible Modules |
|
5 |
+# Version 1.3 |
|
6 |
+# Copyright (C) 2019 Dell Inc. |
|
7 |
+ |
|
8 |
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) |
|
9 |
+# All rights reserved. Dell, EMC, and other trademarks are trademarks of Dell Inc. or its subsidiaries. |
|
10 |
+# Other trademarks may be trademarks of their respective owners. |
|
11 |
+# |
|
12 |
+ |
|
13 |
+ |
|
14 |
+from __future__ import (absolute_import, division, print_function) |
|
15 |
+__metaclass__ = type |
|
16 |
+ |
|
17 |
+ANSIBLE_METADATA = {'metadata_version': '1.1', |
|
18 |
+ 'status': ['preview'], |
|
19 |
+ 'supported_by': 'community'} |
|
20 |
+ |
|
21 |
+DOCUMENTATION = r''' |
|
22 |
+--- |
|
23 |
+module: idrac_server_config_profile |
|
24 |
+short_description: Export or Import iDRAC Server Configuration Profile (SCP). |
|
25 |
+version_added: "2.8" |
|
26 |
+description: |
|
27 |
+ - Export the Server Configuration Profile (SCP) from the iDRAC or Import from a network share or a local file. |
|
28 |
+options: |
|
29 |
+ idrac_ip: |
|
30 |
+ description: iDRAC IP Address. |
|
31 |
+ type: str |
|
32 |
+ required: True |
|
33 |
+ idrac_user: |
|
34 |
+ description: iDRAC username. |
|
35 |
+ type: str |
|
36 |
+ required: True |
|
37 |
+ idrac_password: |
|
38 |
+ description: iDRAC user password. |
|
39 |
+ type: str |
|
40 |
+ required: True |
|
41 |
+ idrac_port: |
|
42 |
+ description: iDRAC port. |
|
43 |
+ type: int |
|
44 |
+ default: 443 |
|
45 |
+ command: |
|
46 |
+ description: |
|
47 |
+ - If C(import), will perform SCP import operations. |
|
48 |
+ - If C(export), will perform SCP export operations. |
|
49 |
+ choices: ['import', 'export'] |
|
50 |
+ default: 'export' |
|
51 |
+ job_wait: |
|
52 |
+ description: Whether to wait for job completion or not. |
|
53 |
+ type: bool |
|
54 |
+ required: True |
|
55 |
+ share_name: |
|
56 |
+ description: CIFS or NFS Network Share or a local path. |
|
57 |
+ type: str |
|
58 |
+ required: True |
|
59 |
+ share_user: |
|
60 |
+ description: Network share user in the format 'user@domain' or 'domain\\user' if user is |
|
61 |
+ part of a domain else 'user'. This option is mandatory for CIFS Network Share. |
|
62 |
+ type: str |
|
63 |
+ share_password: |
|
64 |
+ description: Network share user password. This option is mandatory for CIFS Network Share. |
|
65 |
+ type: str |
|
66 |
+ scp_file: |
|
67 |
+ description: Server Configuration Profile file name. This option is mandatory for C(import) command. |
|
68 |
+ type: str |
|
69 |
+ scp_components: |
|
70 |
+ description: |
|
71 |
+ - If C(ALL), this module will import all components configurations from SCP file. |
|
72 |
+ - If C(IDRAC), this module will import iDRAC configuration from SCP file. |
|
73 |
+ - If C(BIOS), this module will import BIOS configuration from SCP file. |
|
74 |
+ - If C(NIC), this module will import NIC configuration from SCP file. |
|
75 |
+ - If C(RAID), this module will import RAID configuration from SCP file. |
|
76 |
+ choices: ['ALL', 'IDRAC', 'BIOS', 'NIC', 'RAID'] |
|
77 |
+ default: 'ALL' |
|
78 |
+ shutdown_type: |
|
79 |
+ description: |
|
80 |
+ - This option is applicable for C(import) command. |
|
81 |
+ - If C(Graceful), it gracefully shuts down the server. |
|
82 |
+ - If C(Forced), it forcefully shuts down the server. |
|
83 |
+ - If C(NoReboot), it does not reboot the server. |
|
84 |
+ choices: ['Graceful', 'Forced', 'NoReboot'] |
|
85 |
+ default: 'Graceful' |
|
86 |
+ end_host_power_state: |
|
87 |
+ description: |
|
88 |
+ - This option is applicable for C(import) command. |
|
89 |
+ - If C(On), End host power state is on. |
|
90 |
+ - If C(Off), End host power state is off. |
|
91 |
+ choices: ['On' ,'Off'] |
|
92 |
+ default: 'On' |
|
93 |
+ export_format: |
|
94 |
+ description: Specify the output file format. This option is applicable for C(export) command. |
|
95 |
+ choices: ['JSON', 'XML'] |
|
96 |
+ default: 'XML' |
|
97 |
+ export_use: |
|
98 |
+ description: Specify the type of server configuration profile (SCP) to be exported. |
|
99 |
+ This option is applicable for C(export) command. |
|
100 |
+ choices: ['Default', 'Clone', 'Replace'] |
|
101 |
+ default: 'Default' |
|
102 |
+ |
|
103 |
+requirements: |
|
104 |
+ - "omsdk" |
|
105 |
+ - "python >= 2.7.5" |
|
106 |
+author: "Jagadeesh N V(@jagadeeshnv)" |
|
107 |
+ |
|
108 |
+''' |
|
109 |
+ |
|
110 |
+EXAMPLES = r''' |
|
111 |
+--- |
|
112 |
+- name: Import Server Configuration Profile from a network share |
|
113 |
+ idrac_server_config_profile: |
|
114 |
+ idrac_ip: "192.168.0.1" |
|
115 |
+ idrac_user: "user_name" |
|
116 |
+ idrac_password: "user_password" |
|
117 |
+ command: "import" |
|
118 |
+ share_name: "192.168.0.2:/share" |
|
119 |
+ share_user: "share_user_name" |
|
120 |
+ share_password: "share_user_password" |
|
121 |
+ scp_file: "scp_filename.xml" |
|
122 |
+ scp_components: "ALL" |
|
123 |
+ job_wait: True |
|
124 |
+ |
|
125 |
+- name: Import Server Configuration Profile from a local path |
|
126 |
+ idrac_server_config_profile: |
|
127 |
+ idrac_ip: "192.168.0.1" |
|
128 |
+ idrac_user: "user_name" |
|
129 |
+ idrac_password: "user_password" |
|
130 |
+ command: "import" |
|
131 |
+ share_name: "/scp_folder" |
|
132 |
+ share_user: "share_user_name" |
|
133 |
+ share_password: "share_user_password" |
|
134 |
+ scp_file: "scp_filename.xml" |
|
135 |
+ scp_components: "ALL" |
|
136 |
+ job_wait: True |
|
137 |
+ |
|
138 |
+- name: Export Server Configuration Profile to a network share |
|
139 |
+ idrac_server_config_profile: |
|
140 |
+ idrac_ip: "192.168.0.1" |
|
141 |
+ idrac_user: "user_name" |
|
142 |
+ idrac_password: "user_password" |
|
143 |
+ share_name: "192.168.0.2:/share" |
|
144 |
+ share_user: "share_user_name" |
|
145 |
+ share_password: "share_user_password" |
|
146 |
+ job_wait: False |
|
147 |
+ |
|
148 |
+- name: Export Server Configuration Profile to a local path |
|
149 |
+ idrac_server_config_profile: |
|
150 |
+ idrac_ip: "192.168.0.1" |
|
151 |
+ idrac_user: "user_name" |
|
152 |
+ idrac_password: "user_password" |
|
153 |
+ share_name: "/scp_folder" |
|
154 |
+ share_user: "share_user_name" |
|
155 |
+ share_password: "share_user_password" |
|
156 |
+ job_wait: False |
|
157 |
+''' |
|
158 |
+ |
|
159 |
+RETURN = r''' |
|
160 |
+--- |
|
161 |
+msg: |
|
162 |
+ type: str |
|
163 |
+ description: Status of the import or export SCP job. |
|
164 |
+ returned: always |
|
165 |
+ sample: "Successfully imported the Server Configuration Profile" |
|
166 |
+scp_status: |
|
167 |
+ type: dict |
|
168 |
+ description: SCP operation job and progress details from the iDRAC. |
|
169 |
+ returned: success |
|
170 |
+ sample: |
|
171 |
+ { |
|
172 |
+ "Id": "JID_XXXXXXXXX", |
|
173 |
+ "JobState": "Completed", |
|
174 |
+ "JobType": "ImportConfiguration", |
|
175 |
+ "Message": "Successfully imported and applied Server Configuration Profile.", |
|
176 |
+ "MessageArgs": [], |
|
177 |
+ "MessageId": "XXX123", |
|
178 |
+ "Name": "Import Configuration", |
|
179 |
+ "PercentComplete": 100, |
|
180 |
+ "StartTime": "TIME_NOW", |
|
181 |
+ "Status": "Success", |
|
182 |
+ "TargetSettingsURI": null, |
|
183 |
+ "retval": true |
|
184 |
+ } |
|
185 |
+''' |
|
186 |
+ |
|
187 |
+import os |
|
188 |
+from ansible.module_utils.remote_management.dellemc.dellemc_idrac import iDRACConnection |
|
189 |
+from ansible.module_utils.basic import AnsibleModule |
|
190 |
+try: |
|
191 |
+ from omsdk.sdkfile import file_share_manager |
|
192 |
+ from omsdk.sdkcreds import UserCredentials |
|
193 |
+ from omdrivers.enums.iDRAC.iDRACEnums import (SCPTargetEnum, EndHostPowerStateEnum, |
|
194 |
+ ShutdownTypeEnum, ExportFormatEnum, ExportUseEnum) |
|
195 |
+except ImportError: |
|
196 |
+ pass |
|
197 |
+ |
|
198 |
+ |
|
199 |
+def run_import_server_config_profile(idrac, module): |
|
200 |
+ """Import Server Configuration Profile from a network share.""" |
|
201 |
+ target = SCPTargetEnum[module.params['scp_components']] |
|
202 |
+ job_wait = module.params['job_wait'] |
|
203 |
+ end_host_power_state = EndHostPowerStateEnum[module.params['end_host_power_state']] |
|
204 |
+ shutdown_type = ShutdownTypeEnum[module.params['shutdown_type']] |
|
205 |
+ idrac.use_redfish = True |
|
206 |
+ |
|
207 |
+ try: |
|
208 |
+ myshare = file_share_manager.create_share_obj( |
|
209 |
+ share_path="{0}{1}{2}".format(module.params['share_name'], os.sep, module.params['scp_file']), |
|
210 |
+ creds=UserCredentials(module.params['share_user'], |
|
211 |
+ module.params['share_password']), isFolder=False) |
|
212 |
+ import_status = idrac.config_mgr.scp_import(myshare, |
|
213 |
+ target=target, shutdown_type=shutdown_type, |
|
214 |
+ end_host_power_state=end_host_power_state, |
|
215 |
+ job_wait=job_wait) |
|
216 |
+ if not import_status or import_status.get('Status') != "Success": |
|
217 |
+ module.fail_json(msg='Failed to import scp.', scp_status=import_status) |
|
218 |
+ except RuntimeError as e: |
|
219 |
+ module.fail_json(msg=str(e)) |
|
220 |
+ return import_status |
|
221 |
+ |
|
222 |
+ |
|
223 |
+def run_export_server_config_profile(idrac, module): |
|
224 |
+ """Export Server Configuration Profile to a network share.""" |
|
225 |
+ export_format = ExportFormatEnum[module.params['export_format']] |
|
226 |
+ scp_file_name_format = "%ip_%Y%m%d_%H%M%S_scp.{0}".format(module.params['export_format'].lower()) |
|
227 |
+ target = SCPTargetEnum[module.params['scp_components']] |
|
228 |
+ export_use = ExportUseEnum[module.params['export_use']] |
|
229 |
+ idrac.use_redfish = True |
|
230 |
+ |
|
231 |
+ try: |
|
232 |
+ myshare = file_share_manager.create_share_obj(share_path=module.params['share_name'], |
|
233 |
+ creds=UserCredentials(module.params['share_user'], |
|
234 |
+ module.params['share_password']), |
|
235 |
+ isFolder=True) |
|
236 |
+ scp_file_name = myshare.new_file(scp_file_name_format) |
|
237 |
+ export_status = idrac.config_mgr.scp_export(scp_file_name, |
|
238 |
+ target=target, |
|
239 |
+ export_format=export_format, |
|
240 |
+ export_use=export_use, |
|
241 |
+ job_wait=module.params['job_wait']) |
|
242 |
+ if not export_status or export_status.get('Status') != "Success": |
|
243 |
+ module.fail_json(msg='Failed to export scp.', scp_status=export_status) |
|
244 |
+ except RuntimeError as e: |
|
245 |
+ module.fail_json(msg=str(e)) |
|
246 |
+ return export_status |
|
247 |
+ |
|
248 |
+ |
|
249 |
+def main(): |
|
250 |
+ module = AnsibleModule( |
|
251 |
+ argument_spec={ |
|
252 |
+ "idrac_ip": {"required": True, "type": 'str'}, |
|
253 |
+ "idrac_user": {"required": True, "type": 'str'}, |
|
254 |
+ "idrac_password": {"required": True, "type": 'str', "no_log": True}, |
|
255 |
+ "idrac_port": {"required": False, "default": 443, "type": 'int'}, |
|
256 |
+ |
|
257 |
+ "command": {"required": False, "type": 'str', |
|
258 |
+ "choices": ['export', 'import'], "default": 'export'}, |
|
259 |
+ "job_wait": {"required": True, "type": 'bool'}, |
|
260 |
+ |
|
261 |
+ "share_name": {"required": True, "type": 'str'}, |
|
262 |
+ "share_user": {"required": False, "type": 'str'}, |
|
263 |
+ "share_password": {"required": False, "type": 'str', "no_log": True}, |
|
264 |
+ "scp_components": {"required": False, |
|
265 |
+ "choices": ['ALL', 'IDRAC', 'BIOS', 'NIC', 'RAID'], |
|
266 |
+ "default": 'ALL'}, |
|
267 |
+ |
|
268 |
+ "scp_file": {"required": False, "type": 'str'}, |
|
269 |
+ "shutdown_type": {"required": False, |
|
270 |
+ "choices": ['Graceful', 'Forced', 'NoReboot'], |
|
271 |
+ "default": 'Graceful'}, |
|
272 |
+ "end_host_power_state": {"required": False, |
|
273 |
+ "choices": ['On', 'Off'], |
|
274 |
+ "default": 'On'}, |
|
275 |
+ |
|
276 |
+ "export_format": {"required": False, "type": 'str', |
|
277 |
+ "choices": ['JSON', 'XML'], "default": 'XML'}, |
|
278 |
+ "export_use": {"required": False, "type": 'str', |
|
279 |
+ "choices": ['Default', 'Clone', 'Replace'], "default": 'Default'} |
|
280 |
+ }, |
|
281 |
+ required_if=[ |
|
282 |
+ ["command", "import", ["scp_file"]] |
|
283 |
+ ], |
|
284 |
+ supports_check_mode=False) |
|
285 |
+ |
|
286 |
+ try: |
|
287 |
+ changed = False |
|
288 |
+ with iDRACConnection(module.params) as idrac: |
|
289 |
+ command = module.params['command'] |
|
290 |
+ if command == 'import': |
|
291 |
+ scp_status = run_import_server_config_profile(idrac, module) |
|
292 |
+ if "No changes were applied" not in scp_status.get('Message', ""): |
|
293 |
+ changed = True |
|
294 |
+ else: |
|
295 |
+ scp_status = run_export_server_config_profile(idrac, module) |
|
296 |
+ module.exit_json(changed=changed, msg="Successfully {0}ed the Server Configuration Profile.".format(command), |
|
297 |
+ scp_status=scp_status) |
|
298 |
+ except (ImportError, ValueError, RuntimeError) as e: |
|
299 |
+ module.fail_json(msg=str(e)) |
|
300 |
+ |
|
301 |
+ |
|
302 |
+if __name__ == '__main__': |
|
303 |
+ main() |