1 | # Licensed to the StackStorm, Inc ('StackStorm') under one or more |
||
2 | # contributor license agreements. See the NOTICE file distributed with |
||
3 | # this work for additional information regarding copyright ownership. |
||
4 | # The ASF licenses this file to You under the Apache License, Version 2.0 |
||
5 | # (the "License"); you may not use this file except in compliance with |
||
6 | # the License. You may obtain a copy of the License at |
||
7 | # |
||
8 | # http://www.apache.org/licenses/LICENSE-2.0 |
||
9 | # |
||
10 | # Unless required by applicable law or agreed to in writing, software |
||
11 | # distributed under the License is distributed on an "AS IS" BASIS, |
||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
13 | # See the License for the specific language governing permissions and |
||
14 | # limitations under the License. |
||
15 | |||
16 | from __future__ import absolute_import |
||
17 | |||
18 | import abc |
||
19 | from distutils.spawn import find_executable |
||
20 | |||
21 | import six |
||
22 | |||
23 | from st2common.runners.base import ActionRunner |
||
24 | |||
25 | __all__ = [ |
||
26 | 'BaseWindowsRunner', |
||
27 | |||
28 | 'WINEXE_EXISTS', |
||
29 | 'SMBCLIENT_EXISTS' |
||
30 | ] |
||
31 | |||
32 | WINEXE_EXISTS = find_executable('winexe') is not None |
||
33 | SMBCLIENT_EXISTS = find_executable('smbclient') is not None |
||
34 | |||
35 | # Constants which map winexe error codes to user-friendly error messages |
||
36 | ERROR_CODE_TO_MESSAGE_MAP = { |
||
37 | 'NT_STATUS_LOGON_FAILURE': 'Invalid or missing authentication credentials.', |
||
38 | 'NT_STATUS_IO_TIMEOUT': 'Connection timeout.', |
||
39 | 'NT_STATUS_NETWORK_UNREACHABLE': 'Network unavailable, unable to connect.', |
||
40 | 'NT_STATUS_NO_MEMORY': 'Failed to run the command.' |
||
41 | } |
||
42 | |||
43 | |||
44 | @six.add_metaclass(abc.ABCMeta) |
||
45 | class BaseWindowsRunner(ActionRunner): |
||
46 | def _verify_winexe_exists(self): |
||
47 | if not WINEXE_EXISTS: |
||
48 | msg = ('Could not find "winexe" binary. Make sure it\'s installed and available' |
||
49 | 'in $PATH') |
||
50 | raise Exception(msg) |
||
51 | |||
52 | def _verify_smbclient_exists(self): |
||
53 | if not SMBCLIENT_EXISTS: |
||
54 | msg = ('Could not find "smbclient" binary. Make sure it\'s installed and available' |
||
55 | 'in $PATH') |
||
56 | raise Exception(msg) |
||
57 | |||
58 | def _get_winexe_command_args(self, host, username, password, command, domain=None): |
||
59 | args = ['winexe'] |
||
60 | |||
61 | # Disable interactive mode |
||
62 | args += ['--interactive', '0'] |
||
63 | |||
64 | if domain: |
||
65 | args += ['-U', '%s\%s%%%s' % (domain, username, password)] |
||
0 ignored issues
–
show
|
|||
66 | else: |
||
67 | args += ['-U', '%s%%%s' % (username, password)] |
||
68 | |||
69 | args += ['//%s' % (host)] |
||
70 | args += [command] |
||
71 | |||
72 | return args |
||
73 | |||
74 | def _get_smbclient_command_args(self, host, username, password, command, share='C$', |
||
75 | domain=None): |
||
76 | """ |
||
77 | :param command: Samba command string. |
||
78 | :type command: ``str`` |
||
79 | |||
80 | :param share: Samba share name. |
||
81 | :type share: ``str`` |
||
82 | """ |
||
83 | args = ['smbclient'] |
||
84 | |||
85 | values = {'domain': domain, 'username': username, 'password': password} |
||
86 | if domain: |
||
87 | auth_string = '%(domain)s\%(username)s%%%(password)s' % values |
||
88 | else: |
||
89 | auth_string = '%(username)s%%%(password)s' % values |
||
90 | |||
91 | # Authentication info |
||
92 | args += ['-U', auth_string] |
||
93 | |||
94 | # Host and share |
||
95 | args += ['//%(host)s/%(share)s' % {'host': host, 'share': share}] |
||
96 | |||
97 | # Command |
||
98 | args += ['-c', command] |
||
99 | return args |
||
100 | |||
101 | def _parse_winexe_error(self, stdout, stderr): |
||
102 | for code, message in ERROR_CODE_TO_MESSAGE_MAP.items(): |
||
103 | if code in stdout: |
||
104 | return message |
||
105 | |||
106 | return None |
||
107 |
Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with
r
orR
are they interpreted as regular expressions.The escape sequence that was used indicates that you might have intended to write a regular expression.
Learn more about the available escape sequences. in the Python documentation.