|
| 1 | +#!/usr/bin/python |
| 2 | + |
| 3 | +# Copyright: (c) 2022, Rainer Leber [email protected], [email protected], |
| 4 | +# Robert Kraemer @rkpobe, [email protected] |
| 5 | +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) |
| 6 | +from __future__ import (absolute_import, division, print_function) |
| 7 | +__metaclass__ = type |
| 8 | + |
| 9 | +DOCUMENTATION = r''' |
| 10 | +--- |
| 11 | +module: sapcontrol |
| 12 | +
|
| 13 | +short_description: Manages SAPCONTROL |
| 14 | +
|
| 15 | +version_added: "1.1.0" |
| 16 | +
|
| 17 | +description: |
| 18 | + - Provides support for sapstartsrv formaly known as sapcontrol |
| 19 | + - A complete information of all functions and the parameters can be found here |
| 20 | + U(https://www.sap.com/documents/2016/09/0a40e60d-8b7c-0010-82c7-eda71af511fa.html) |
| 21 | +
|
| 22 | +options: |
| 23 | + sysnr: |
| 24 | + description: |
| 25 | + - The system number of the instance. |
| 26 | + required: false |
| 27 | + type: str |
| 28 | + port: |
| 29 | + description: |
| 30 | + - The port number of the sapstartsrv. |
| 31 | + required: false |
| 32 | + type: int |
| 33 | + username: |
| 34 | + description: |
| 35 | + - The username to connect to the sapstartsrv. |
| 36 | + required: false |
| 37 | + type: str |
| 38 | + password: |
| 39 | + description: |
| 40 | + - The password to connect to the sapstartsrv. |
| 41 | + required: false |
| 42 | + type: str |
| 43 | + hostname: |
| 44 | + description: |
| 45 | + - The hostname to connect to the sapstartsrv. |
| 46 | + - Could be an IP address, FQDN or hostname. |
| 47 | + required: false |
| 48 | + default: localhost |
| 49 | + type: str |
| 50 | + function: |
| 51 | + description: |
| 52 | + - The function to execute. |
| 53 | + required: true |
| 54 | + choices: |
| 55 | + - Start |
| 56 | + - Stop |
| 57 | + - RestartInstance |
| 58 | + - Shutdown |
| 59 | + - InstanceStart |
| 60 | + - GetProcessList |
| 61 | + - Bootstrap |
| 62 | + - InstanceStop |
| 63 | + - StopService |
| 64 | + - StartService |
| 65 | + - RestartService |
| 66 | + - ParameterValue |
| 67 | + - GetStartProfile |
| 68 | + - GetTraceFile |
| 69 | + - GetAlertTree |
| 70 | + - GetAlerts |
| 71 | + - GetEnvironment |
| 72 | + - GetVersionInfo |
| 73 | + - GetQueueStatistic |
| 74 | + - GetInstanceProperties |
| 75 | + - ListDeveloperTraces |
| 76 | + - ReadDeveloperTrace |
| 77 | + - ListLogFiles |
| 78 | + - ReadLogFile |
| 79 | + - AnalyseLogFiles |
| 80 | + - ConfigureLogFileList |
| 81 | + - GetLogFileList |
| 82 | + - CreateSnapshot |
| 83 | + - ReadSnapshot |
| 84 | + - ListSnapshots |
| 85 | + - DeleteSnapshots |
| 86 | + - GetAccessPointList |
| 87 | + - GetProcessParameter |
| 88 | + - SetProcessParameter |
| 89 | + - SetProcessParameter2 |
| 90 | + - CheckParameter |
| 91 | + - OSExecute |
| 92 | + - SendSignal |
| 93 | + - GetCallstack |
| 94 | + - GetSystemInstanceList |
| 95 | + - StartSystem |
| 96 | + - StopSystem |
| 97 | + - RestartSystem |
| 98 | + - GetSystemUpdateList |
| 99 | + - UpdateSystem |
| 100 | + - UpdateSCSInstance |
| 101 | + - CheckUpdateSystem |
| 102 | + - AccessCheck |
| 103 | + - GetSecNetworkId |
| 104 | + - GetNetworkId |
| 105 | + - RequestLogonFile |
| 106 | + - UpdateSystemPKI |
| 107 | + - UpdateInstancePSE |
| 108 | + - StorePSE |
| 109 | + - DeletePSE |
| 110 | + - CheckPSE |
| 111 | + - CreatePSECredential |
| 112 | + - HACheckConfig |
| 113 | + - HACheckFailoverConfig |
| 114 | + - HAGetFailoverConfig |
| 115 | + - HAFailoverToNode |
| 116 | + - HASetMaintenanceMode |
| 117 | + - HACheckMaintenanceMode |
| 118 | + - ABAPReadSyslog |
| 119 | + - ABAPReadRawSyslog |
| 120 | + - ABAPGetWPTable |
| 121 | + - ABAPGetComponentList |
| 122 | + - ABAPCheckRFCDestinations |
| 123 | + - ABAPGetSystemWPTable |
| 124 | + - J2EEControlProcess |
| 125 | + - J2EEControlCluster |
| 126 | + - J2EEEnableDbgSession |
| 127 | + - J2EEDisableDbgSession |
| 128 | + - J2EEGetProcessList |
| 129 | + - J2EEGetProcessList2 |
| 130 | + - J2EEGetThreadList |
| 131 | + - J2EEGetThreadList2 |
| 132 | + - J2EEGetThreadCallStack |
| 133 | + - J2EEGetThreadTaskStack |
| 134 | + - J2EEGetSessionList |
| 135 | + - J2EEGetCacheStatistic |
| 136 | + - J2EEGetCacheStatistic2 |
| 137 | + - J2EEGetApplicationAliasList |
| 138 | + - J2EEGetComponentList |
| 139 | + - J2EEControlComponents |
| 140 | + - J2EEGetWebSessionList |
| 141 | + - J2EEGetWebSessionList2 |
| 142 | + - J2EEGetEJBSessionList |
| 143 | + - J2EEGetRemoteObjectList |
| 144 | + - J2EEGetVMGCHistory |
| 145 | + - J2EEGetVMGCHistory2 |
| 146 | + - J2EEGetVMHeapInfo |
| 147 | + - J2EEGetClusterMsgList |
| 148 | + - J2EEGetSharedTableInfo |
| 149 | + - ICMGetThreadList |
| 150 | + - ICMGetConnectionList |
| 151 | + - ICMGetProxyConnectionList |
| 152 | + - ICMGetCacheEntries |
| 153 | + - WebDispGetServerList |
| 154 | + - WebDispGetGroupList |
| 155 | + - WebDispGetVirtHostList |
| 156 | + - WebDispGetUrlPrefixList |
| 157 | + - EnqGetStatistic |
| 158 | + - EnqGetLockTable |
| 159 | + - EnqRemoveUserLocks |
| 160 | + - StartWait |
| 161 | + - StopWait |
| 162 | + - WaitforStarted |
| 163 | + - WaitforStopped |
| 164 | + - RestartServiceWait |
| 165 | + - WaitforServiceStarted |
| 166 | + - CheckHostAgent |
| 167 | + type: str |
| 168 | + parameter: |
| 169 | + description: |
| 170 | + - The parameter to pass to the function. |
| 171 | + required: false |
| 172 | + type: str |
| 173 | + force: |
| 174 | + description: |
| 175 | + - Forces the execution of the function C(Stop). |
| 176 | + required: false |
| 177 | + default: false |
| 178 | + type: bool |
| 179 | +author: |
| 180 | + - Rainer Leber (@RainerLeber) |
| 181 | + - Robert Kraemer (@rkpobe) |
| 182 | +notes: |
| 183 | + - Does not support C(check_mode). |
| 184 | +''' |
| 185 | + |
| 186 | +EXAMPLES = r""" |
| 187 | +- name: GetProcessList with sysnr |
| 188 | + community.sap_libs.sapcontrol: |
| 189 | + hostname: 192.168.8.15 |
| 190 | + sysnr: "01" |
| 191 | + function: GetProcessList |
| 192 | +
|
| 193 | +- name: GetProcessList with custom port |
| 194 | + community.sap_libs.sapcontrol: |
| 195 | + hostname: 192.168.8.15 |
| 196 | + function: GetProcessList |
| 197 | + port: 50113 |
| 198 | +
|
| 199 | +- name: ParameterValue |
| 200 | + community.sap_libs.sapcontrol: |
| 201 | + hostname: 192.168.8.15 |
| 202 | + sysnr: "01" |
| 203 | + username: hdbadm |
| 204 | + password: test1234# |
| 205 | + function: ParameterValue |
| 206 | + parameter: ztta |
| 207 | +""" |
| 208 | + |
| 209 | +RETURN = r''' |
| 210 | +msg: |
| 211 | + description: Success-message with functionname. |
| 212 | + type: str |
| 213 | + returned: always |
| 214 | + sample: 'Succesful execution of: GetProcessList' |
| 215 | +out: |
| 216 | + description: The full output of the required function. |
| 217 | + type: list |
| 218 | + elements: dict |
| 219 | + returned: always |
| 220 | + sample: [{ |
| 221 | + "item": [ |
| 222 | + { |
| 223 | + "description": "MessageServer", |
| 224 | + "dispstatus": "SAPControl-GREEN", |
| 225 | + "elapsedtime": "412:30:50", |
| 226 | + "name": "msg_server", |
| 227 | + "pid": 70643, |
| 228 | + "starttime": "2022 03 13 15:22:42", |
| 229 | + "textstatus": "Running" |
| 230 | + }, |
| 231 | + { |
| 232 | + "description": "EnqueueServer", |
| 233 | + "dispstatus": "SAPControl-GREEN", |
| 234 | + "elapsedtime": "412:30:50", |
| 235 | + "name": "enserver", |
| 236 | + "pid": 70644, |
| 237 | + "starttime": "2022 03 13 15:22:42", |
| 238 | + "textstatus": "Running" |
| 239 | + }, |
| 240 | + { |
| 241 | + "description": "Gateway", |
| 242 | + "dispstatus": "SAPControl-GREEN", |
| 243 | + "elapsedtime": "412:30:50", |
| 244 | + "name": "gwrd", |
| 245 | + "pid": 70645, |
| 246 | + "starttime": "2022 03 13 15:22:42", |
| 247 | + "textstatus": "Running" |
| 248 | + } |
| 249 | + ] |
| 250 | + }] |
| 251 | +''' |
| 252 | + |
| 253 | +from ansible.module_utils.basic import AnsibleModule, missing_required_lib |
| 254 | +import traceback |
| 255 | +try: |
| 256 | + from suds.client import Client |
| 257 | + from suds.sudsobject import asdict |
| 258 | +except ImportError: |
| 259 | + HAS_SUDS_LIBRARY = False |
| 260 | + SUDS_LIBRARY_IMPORT_ERROR = traceback.format_exc() |
| 261 | +else: |
| 262 | + HAS_SUDS_LIBRARY = True |
| 263 | + |
| 264 | + |
| 265 | +def choices(): |
| 266 | + retlist = ["Start", "Stop", "RestartInstance", "Shutdown", "InstanceStart", 'GetProcessList', |
| 267 | + 'Bootstrap', 'InstanceStop', 'StopService', 'StartService', 'RestartService', 'ParameterValue', |
| 268 | + 'GetStartProfile', 'GetTraceFile', 'GetAlertTree', 'GetAlerts', 'GetEnvironment', 'GetVersionInfo', |
| 269 | + 'GetQueueStatistic', 'GetInstanceProperties', 'ListDeveloperTraces', 'ReadDeveloperTrace', |
| 270 | + 'ListLogFiles', 'ReadLogFile', 'AnalyseLogFiles', 'ConfigureLogFileList', 'GetLogFileList', 'CreateSnapshot', 'ReadSnapshot', |
| 271 | + 'ListSnapshots', 'DeleteSnapshots', 'GetAccessPointList', 'GetProcessParameter', 'SetProcessParameter', |
| 272 | + 'SetProcessParameter2', 'CheckParameter', 'OSExecute', 'SendSignal', 'GetCallstack', 'GetSystemInstanceList', |
| 273 | + 'StartSystem', 'StopSystem', 'RestartSystem', 'GetSystemUpdateList', 'UpdateSystem', 'UpdateSCSInstance', |
| 274 | + 'CheckUpdateSystem', 'AccessCheck', 'GetSecNetworkId', 'GetNetworkId', 'RequestLogonFile', |
| 275 | + 'UpdateSystemPKI', 'UpdateInstancePSE', 'StorePSE', 'DeletePSE', 'CheckPSE', 'CreatePSECredential', |
| 276 | + 'HACheckConfig', 'HACheckFailoverConfig', 'HAGetFailoverConfig', 'HAFailoverToNode', |
| 277 | + 'HASetMaintenanceMode', 'HACheckMaintenanceMode', 'ABAPReadSyslog', 'ABAPReadRawSyslog', |
| 278 | + 'ABAPGetWPTable', 'ABAPGetComponentList', 'ABAPCheckRFCDestinations', |
| 279 | + 'ABAPGetSystemWPTable', 'J2EEControlProcess', 'J2EEControlCluster', 'J2EEEnableDbgSession', |
| 280 | + 'J2EEDisableDbgSession', 'J2EEGetProcessList', 'J2EEGetProcessList2', 'J2EEGetThreadList', 'J2EEGetThreadList2', |
| 281 | + 'J2EEGetThreadCallStack', 'J2EEGetThreadTaskStack', 'J2EEGetSessionList', 'J2EEGetCacheStatistic', |
| 282 | + 'J2EEGetCacheStatistic2', 'J2EEGetApplicationAliasList', 'J2EEGetComponentList', |
| 283 | + 'J2EEControlComponents', 'J2EEGetWebSessionList', 'J2EEGetWebSessionList2', 'J2EEGetEJBSessionList', 'J2EEGetRemoteObjectList', |
| 284 | + 'J2EEGetVMGCHistory', 'J2EEGetVMGCHistory2', 'J2EEGetVMHeapInfo', 'J2EEGetClusterMsgList', 'J2EEGetSharedTableInfo', |
| 285 | + 'ICMGetThreadList', 'ICMGetConnectionList', 'ICMGetProxyConnectionList', 'ICMGetCacheEntries', 'WebDispGetServerList', |
| 286 | + 'WebDispGetGroupList', 'WebDispGetVirtHostList', 'WebDispGetUrlPrefixList', 'EnqGetStatistic', 'EnqGetLockTable', |
| 287 | + 'EnqRemoveUserLocks', 'StartWait', 'StopWait', 'WaitforStarted', 'WaitforStopped', 'RestartServiceWait', |
| 288 | + 'WaitforServiceStarted', 'CheckHostAgent'] |
| 289 | + return retlist |
| 290 | + |
| 291 | + |
| 292 | +# converts recursively the suds object to a dictionary e.g. {'item': [{'name': hdbdaemon, 'value': '1'}]} |
| 293 | +def recursive_dict(suds_object): |
| 294 | + out = {} |
| 295 | + if isinstance(suds_object, str): |
| 296 | + return suds_object |
| 297 | + for k, v in asdict(suds_object).items(): |
| 298 | + if hasattr(v, '__keylist__'): |
| 299 | + out[k] = recursive_dict(v) |
| 300 | + elif isinstance(v, list): |
| 301 | + out[k] = [] |
| 302 | + for item in v: |
| 303 | + if hasattr(item, '__keylist__'): |
| 304 | + out[k].append(recursive_dict(item)) |
| 305 | + else: |
| 306 | + out[k].append(item) |
| 307 | + else: |
| 308 | + out[k] = v |
| 309 | + return out |
| 310 | + |
| 311 | + |
| 312 | +def connection(hostname, port, username, password, function, parameter): |
| 313 | + url = 'http://{0}:{1}/sapcontrol?wsdl'.format(hostname, port) |
| 314 | + client = Client(url, username=username, password=password) |
| 315 | + _function = getattr(client.service, function) |
| 316 | + if parameter is not None: |
| 317 | + result = _function(parameter) |
| 318 | + else: |
| 319 | + result = _function() |
| 320 | + |
| 321 | + return result |
| 322 | + |
| 323 | + |
| 324 | +def main(): |
| 325 | + module = AnsibleModule( |
| 326 | + argument_spec=dict( |
| 327 | + sysnr=dict(type='str', required=False), |
| 328 | + port=dict(type='int', required=False), |
| 329 | + username=dict(type='str', required=False), |
| 330 | + password=dict(type='str', no_log=True, required=False), |
| 331 | + hostname=dict(type='str', default="localhost"), |
| 332 | + function=dict(type='str', required=True, choices=choices()), |
| 333 | + parameter=dict(type='str', required=False), |
| 334 | + force=dict(type='bool', default=False), |
| 335 | + ), |
| 336 | + required_one_of=[('sysnr', 'port')], |
| 337 | + mutually_exclusive=[('sysnr', 'port')], |
| 338 | + supports_check_mode=False, |
| 339 | + ) |
| 340 | + result = dict(changed=False, msg='', out={}, error='') |
| 341 | + params = module.params |
| 342 | + |
| 343 | + sysnr = params['sysnr'] |
| 344 | + port = params['port'] |
| 345 | + username = params['username'] |
| 346 | + password = params['password'] |
| 347 | + hostname = params['hostname'] |
| 348 | + function = params['function'] |
| 349 | + parameter = params['parameter'] |
| 350 | + force = params['force'] |
| 351 | + |
| 352 | + if not HAS_SUDS_LIBRARY: |
| 353 | + module.fail_json( |
| 354 | + msg=missing_required_lib('suds'), |
| 355 | + exception=SUDS_LIBRARY_IMPORT_ERROR) |
| 356 | + |
| 357 | + if function == "Stop": |
| 358 | + if force is False: |
| 359 | + module.fail_json(msg="Stop function requires force: True") |
| 360 | + |
| 361 | + if port is None: |
| 362 | + try: |
| 363 | + try: |
| 364 | + conn = connection(hostname, "5{0}14".format((sysnr).zfill(2)), username, password, function, parameter) |
| 365 | + except Exception: |
| 366 | + conn = connection(hostname, "5{0}13".format((sysnr).zfill(2)), username, password, function, parameter) |
| 367 | + except Exception as err: |
| 368 | + result['error'] = str(err) |
| 369 | + else: |
| 370 | + try: |
| 371 | + conn = connection(hostname, port, username, password, function, parameter) |
| 372 | + except Exception as err: |
| 373 | + result['error'] = str(err) |
| 374 | + |
| 375 | + if result['error'] != '': |
| 376 | + result['msg'] = 'Something went wrong connecting to the SAPCONTROL SOAP API.' |
| 377 | + module.fail_json(**result) |
| 378 | + |
| 379 | + returned_data = recursive_dict(conn) |
| 380 | + |
| 381 | + result['changed'] = True |
| 382 | + result['msg'] = "Succesful execution of: " + function |
| 383 | + result['out'] = [returned_data] |
| 384 | + |
| 385 | + module.exit_json(**result) |
| 386 | + |
| 387 | + |
| 388 | +if __name__ == '__main__': |
| 389 | + main() |
0 commit comments