Skip to content

Commit ce1facc

Browse files
authored
add sapcontrol (#2)
* add sapcontrol
1 parent bcf6e6d commit ce1facc

File tree

3 files changed

+519
-0
lines changed

3 files changed

+519
-0
lines changed

plugins/modules/sapcontrol.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
system/sapcontrol.py
Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
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

Comments
 (0)