1
2 """
3 This library contains APIs for executing shell commands, for getting the exit status of
4 the executed command, and for allowing multiple commands to run conditional on that exit status.
5 It is initialized with a Shell Client, and then uses the client to run commands and get the results.
6 """
7 from com.hp.ucmdb.discovery.probe.services.dynamic.core import DynamicServiceFrameworkImpl
8 from com.hp.ucmdb.discovery.library.communication.downloader.cfgfiles import GeneralSettingsConfigFile
9
10 import modeling
11 import netutils
12 import logger
13 import errorcodes
14 import errorobject
15 import shell_interpreter
16 import re
17 import string
18 import sys
19 import codecs
20
21 from java.io import File
22 from java.util import Properties, WeakHashMap
23 from java.util import Locale
24 from java.nio.charset import Charset
25 from java.nio import ByteBuffer
26 from java.nio.charset import CodingErrorAction
27
28 from com.hp.ucmdb.discovery.library.common import CollectorsParameters
29 from com.hp.ucmdb.discovery.library.clients.agents import NTCmdSessionAgent
30 from com.hp.ucmdb.discovery.library.clients.agents.ssh import SSHAgent
31 from com.hp.ucmdb.discovery.library.clients.agents import AgentConstants
32 from com.hp.ucmdb.discovery.library.clients.agents import PowerShellAgent
33 from com.hp.ucmdb.discovery.library.clients.shell import PowerShellClient
34 from com.hp.ucmdb.discovery.library.clients.protocols.telnet import StreamReaderThread
35
36 from java.lang import String
37 from java.lang import Boolean
38
39
40 DDM_LINK_SYSTEM32_LOCATION = "%SystemDrive%"
41 DDM_LINK_SYSTEM32_NAME = "ddm_link_system32"
42
43
45 'Shell command base class'
46 - def __init__(self, line, output=None, returnCode=None):
47 '''@types: str, str, int -> None
48 @deprecated
49 '''
50 self.cmd = line
51
52 self.line = line
53 self.output = output
54 self.outputInBytes = []
55 self.returnCode = returnCode
56 self.executionTimeout = 0
57 self.waitForTimeout = 0
58 self.useSudo = 1
59 self.checkErrCode = 1
60 self.preserveSudoContext = 0
61
64
67
68
70 r'''Language describes localized system configuration: locale, character sets,
71 code pages etc'''
72 DEFAULT_CHARSET_OBJECT = Charset.defaultCharset()
73
74 - def __init__(self, locale, bundlePostfix, charsets, wmiCodes=None, codepage=None):
75 ''' Default constructor also performs initialization of supported
76 character sets on the probe machine
77 @types: java.util.Locale, str, str, list(int), int -> None'''
78 self.locale = locale
79 self.bundlePostfix = bundlePostfix
80 self.charsets = charsets
81 self.wmiCodes = wmiCodes
82 self.charsetNameToObject = {}
83 self.__initCharsets()
84 self.codepage = codepage
85
87 'Find supported character sets on the probe machine'
88 for charsetName in self.charsets:
89 try:
90 charset = Charset.forName(charsetName)
91 self.charsetNameToObject[charsetName] = charset
92 except:
93 logger.warn("Charset is not supported: %s." % charsetName)
94
95 LOCALE_SPANISH = Locale("es", "", "")
96 LOCALE_RUSSIAN = Locale("ru", "", "")
97 LOCALE_GERMAN = Locale("de", "", "")
98 LOCALE_FRENCH = Locale("fr", "", "")
99 LOCALE_ITALIAN = Locale("it", "", "")
100 LOCALE_PORTUGUESE = Locale("pt", "", "")
101 LOCALE_CHINESE = Locale("cn", "", "")
102 LOCALE_KOREAN = Locale("kr", "", "")
103 LOCALE_DUTCH = Locale("nl", "", "")
104
105 LANG_ENGLISH = Language(Locale.ENGLISH, 'eng', ('Cp1252',), (1033,), 437)
106 LANG_GERMAN = Language(Locale.GERMAN, 'ger', ('Cp1252', 'Cp850'), (1031,), 850)
107 LANG_SPANISH = Language(LOCALE_SPANISH, 'spa', ('Cp1252',), (1034, 3082,))
108 LANG_RUSSIAN = Language(LOCALE_RUSSIAN, 'rus', ('Cp866', 'Cp1251'), (1049,), 866)
109 LANG_JAPANESE = Language(Locale.JAPANESE, 'jap', ('MS932',), (1041,), 932)
110 LANG_FRENCH = Language(Locale.FRENCH, 'fra', ('Cp1252',), (1036,), 850)
111 LANG_ITALIAN = Language(Locale.ITALIAN, 'ita', ('Cp1252',), (1040,), 850)
112 LANG_DUTCH = Language(LOCALE_DUTCH, 'nld', ('Cp1252',), (1043,), 850)
113 LANG_PORTUGUESE = Language(LOCALE_PORTUGUESE, 'prt', ('Cp1252',), (1046,), 850)
114 LANG_CHINESE = Language(Locale.CHINESE, 'chn', ('MS936',), (2052,), 936)
115 LANG_KOREAN = Language(Locale.KOREAN, 'kor', ('MS949',), (1042,), 949)
116
117 LANGUAGES = (LANG_ENGLISH, LANG_GERMAN, LANG_SPANISH, LANG_RUSSIAN,
118 LANG_JAPANESE, LANG_FRENCH, LANG_ITALIAN, LANG_PORTUGUESE,
119 LANG_CHINESE, LANG_KOREAN, LANG_DUTCH)
120
121
122 DEFAULT_LANGUAGE = LANG_ENGLISH
123
124
126 'Discoverer determines language on destination system'
128 '@types: Shell -> None'
129 self.shell = shell
130
132 '@types: -> Language'
133 raise NotImplementedError()
134
135
137 'Windows specific discoverer'
141
143 ''' Determine language for Windows system.
144 @types: -> Language
145 @note: English will be used as default one if fails
146 to determine machine encoding
147 '''
148 language = self.getLanguageFromWmi()
149 if not language:
150 language = self.getLanguageFromChcp()
151 if not language:
152 logger.warn('Failed to determine machine encoding, using default %s' % DEFAULT_LANGUAGE.locale)
153 return DEFAULT_LANGUAGE
154 else:
155 return language
156
158 '''@types: -> shellutils.Language or None
159 @command: wmic OS Get CodeSet
160 '''
161 osLanguageOutput = self.shell.execAlternateCmds('wmic OS Get CodeSet < %SystemRoot%\win.ini', '%WINDIR%\system32\wbem\wmic OS Get CodeSet < %SystemRoot%\win.ini')
162 if osLanguageOutput and self.shell.getLastCmdReturnCode() == 0:
163 return self.__parseLanguageFromWmi(osLanguageOutput)
164
166 '''@types: -> shellutils.Language or None
167 @command: wmic OS Get OSLanguage
168 '''
169 osLanguageOutput = self.shell.execAlternateCmds('wmic OS Get OSLanguage < %SystemRoot%\win.ini', '%WINDIR%\system32\wbem\wmic OS Get OSLanguage < %SystemRoot%\win.ini')
170 if osLanguageOutput and self.shell.getLastCmdReturnCode() == 0:
171 return self.__parseLanguageFromWmi(osLanguageOutput)
172
174 '@types: str -> shellutils.Language or None'
175 if osLanguageOutput:
176 languageResult = None
177 matcher = re.search(r"(\d{4})", osLanguageOutput)
178 if matcher:
179 osLanguageCodeStr = matcher.group(1)
180 osLanguageCode = int(osLanguageCodeStr)
181 for lang in LANGUAGES:
182 if osLanguageCode in lang.wmiCodes:
183 logger.debug('Bundle postfix %s' % lang.bundlePostfix)
184 languageResult = lang
185 break
186 return languageResult
187
193
195 ''' Determine language executing chcp command
196 @types: -> Language or None
197 @command: chcp
198 '''
199 languageResult = None
200 codepage = int(self.shell.getCodePage())
201 for lang in LANGUAGES:
202 if codepage == lang.codepage:
203 logger.debug('Bundle postfix %s' % lang.bundlePostfix)
204 languageResult = lang
205 break
206 return languageResult
207
208
210 'For Unix destination localization is not supported. English language is used'
214
218
219
221 - def match(self, content):
222 '@types: str -> bool'
223 raise NotImplementedError()
224
225
228 '@types: str -> None'
229 self.keyword = keyword
230
231 - def match(self, content):
232 '@types: str -> bool'
233 logger.debug('Matching by keyword: %s' % self.keyword)
234
235 if self.keyword and content:
236 buffer = re.search(self.keyword, content, re.I)
237 if buffer:
238 return 1
239
240
242
243 - def __init__(self, bytesArray, language, framework):
244 '@types: jarray(byte), Language, Framework'
245 self.bytesArray = bytesArray
246 self.language = language
247 self.framework = framework
248 self.outputHandlers = []
249
250 - def addOutputHandler(self, handler):
251 '''@types: OutputHandler -> None'''
252 self.outputHandlers.append(handler)
253
254 - def getDecodedString(self, outputMatcher):
255 ''' Select such charset that decoded content using it will match using matcher
256 and return decoded content
257 @types: OutputMatcher -> tuple(str(decoded output), str(charset name))'''
258 charsetObjects = self.language.charsetNameToObject.values()
259 if charsetObjects:
260 for charset in charsetObjects:
261 decodedContent = self.decodeString(charset)
262 for outputHandler in self.outputHandlers:
263 decodedContent = outputHandler.handle(decodedContent)
264
265 decodedContentString = str(String(decodedContent))
266 if outputMatcher.match(decodedContentString):
267 return (decodedContentString, charset.name())
268
269 msg = "Command output verification has failed. Check whether the language is supported."
270 errobj = errorobject.createError(errorcodes.COMMAND_OUTPUT_VERIFICATION_FAILED, None, msg)
271 logger.reportWarningObject(errobj)
272 logger.debug(msg)
273
274 charset = Language.DEFAULT_CHARSET_OBJECT
275 decodedContent = str(String(self.decodeString(charset)))
276 return (decodedContent, charset.name())
277
278 - def decodeString(self, charsetObject):
279 ''' Decode string with specified charset
280 @types: java.nio.charset.Charset -> jarray(char)'''
281 decoder = charsetObject.newDecoder()
282 decoder.onMalformedInput(CodingErrorAction.REPLACE)
283 decoder.onUnmappableCharacter(CodingErrorAction.REPLACE)
284 charBuffer = decoder.decode(ByteBuffer.wrap(self.bytesArray))
285 return charBuffer.array()
286
287
290 '@types: jarray(char) -> jarray(char)'
291 return contents
292
293
304
306 '@types: jarray(char) -> str'
307 return SSHAgent.translateBackspace(String(contents))
308
310 '@types: str -> str'
311 return SSHAgent.removeMarkers(contents)
312
313
315 POWERSHELL_CMD_SUCCESS = 'True'
316 POWERSHELL_CMD_FAILED = 'False'
317
318 - def __init__(self, command=None, trimWS=None):
319 '@types: str, bool'
320 self.command = command
321 self.trimWS = trimWS
322
334
351
352 - def handle(self, contentChars):
353 '''@types: jarray(char) -> jarray(char)'''
354 cleanedOutput = PowerShellAgent.cleanupCommandOutput(self.command, String(contentChars), self.trimWS)
355 return String(cleanedOutput).toCharArray()
356
357
360 '@types: str, bool'
361 self.command = command
362 self.trimWS = trimWS
363
364 - def handle(self, contentChars):
365 '@types: jarray(char) -> jarray(char)'
366 cleanedOutput = NTCmdSessionAgent.cleanupCommandOutput(self.command, String(contentChars), self.trimWS)
367 return String(cleanedOutput).toCharArray()
368
369
372 '@types: jarray(char) -> jarray(char)'
373 return StreamReaderThread.translateBackspace(contents, len(contents)).toCharArray()
374
375
377 ''' Command transaction class.
378 Provides possibility to define alternative ways for determining command execution status
379 '''
380 - def __init__(self, cmd, expectedReturnCode=None, sucessString=None, failureString=None):
381 '''@types: str, int, str, str'''
382 self.cmd = cmd
383 self.expectedReturnCode = expectedReturnCode
384 self.sucessString = sucessString
385 self.failureString = failureString
386
387
388 -def ShellUtils(client, props=None, protocolName=None):
389 '''BaseClient or DynamicServiceFrameworkImpl, java.util.Properties, str -> Shell
390 This method play role of factory method for backward compatibility and will be removed in further releases
391 @deprecated: Use ShellFactory instead
392 @raise Exception: failed to detect OS
393 '''
394 if isinstance(client, DynamicServiceFrameworkImpl):
395 if not props:
396 props = Properties()
397 Framework = client
398 client = Framework.createClient(props)
399
400 return ShellFactory().createShell(client, protocolName)
401
402
404 '''This class manages shell creation for different shell protocols SSH, Telnet, or NTCMD.'''
430
432 ''' Check for cygwin shell. In cygwin shell it is possible to launch
433 windows command interpreter.
434 @types: Client -> bool
435 @command: cmd.exe /c ver
436 @raise Exception: Failed starting Windows Cmd Shell
437 '''
438 winOs = 0
439 logger.debug('Check for Cygwin installed on Windows')
440 buffer = shellClient.executeCmd('cmd.exe /c ver')
441 if self.__isWinDetectInVerOutput(buffer):
442 try:
443 logger.debug('Entering Windows CMD shell')
444 shellClient.executeCmd('cmd.exe', 10000, 1)
445 shellClient.getShellCmdSeperator()
446 except:
447 raise Exception("Failed starting Windows Cmd Shell")
448 winOs = 1
449 return winOs
450
452 ''' Determine windows shell trying to execute 'ver' command
453 @command: ver
454 @types: BaseClient -> bool
455 @raise Exception: Failed detecting OS type
456 '''
457 try:
458 osBuff = shellClient.executeCmd('ver')
459 if osBuff is None:
460 errMsg = 'Failed detecting OS type. command=\'ver\' returned with no output'
461 logger.error(errMsg)
462 raise Exception(errMsg)
463
464
465 winOs = self.__isWinDetectInVerOutput(osBuff)
466 return winOs
467 except:
468 errMsg = 'Failed detecting OS type. Exception received: %s' % (sys.exc_info()[1])
469 logger.error(errMsg)
470 raise Exception(errMsg)
471
473 '''Determine restricted shell of VIO server installed on AIX
474 @command: ioscli uname -a
475 @types: BaseClient -> bool'''
476 logger.debug("Check for IBM VIO Server Shell")
477 isVioServer = 0
478 try:
479 output = shellClient.executeCmd("ioscli uname -a")
480 if not output or output.count("ioscli"):
481 logger.debug('Failed detecting IBM VIO Server. %s' % output)
482 else:
483 isVioServer = 1
484 except:
485 logger.warnException('Failed detecting IBM VIO Server')
486 return isVioServer
487
489 try:
490 osBuff = shellClient.executeCmd('uname')
491 if osBuff and re.match("\s*Darwin", osBuff):
492 return 1
493 except:
494 logger.warn('Failed checking for MacOS')
495 logger.debugException('')
496
498 '@types: str -> bool'
499 return (buffer
500 and (buffer.lower().find('windows') > -1
501 or buffer.find('MS-DOS') > -1))
502
503
505 'Exception case when command does not exists or cannot be recognized'
506 pass
507
508
510 'Exception case when client has no permission to execute command'
511 pass
512
513
515 """
516 Class for managing Shell connections via SSH, Telnet, or NTCmd
517
518 B{Shell is not thread-safe.} Every thread must have its own instance.
519 """
520
521 NO_CMD_RETURN_CODE_ERR_NUMBER = -9999
522
524 '@types: Client'
525 self.cmdCache = WeakHashMap()
526
527 self.__client = client
528
529 self.osType = None
530
531 self.osVer = None
532 self.__lastCmdReturnCode = None
533 self.__alternateCmdList = []
534 self.__shellCmdSeparator = None
535
536
537 self.winOs = self.isWinOs()
538 self.getOsType()
539
540 self.getLastCommandOutputBytes = None
541
542 self.lastExecutedCommand = None
543
544 self.copiedFiles = []
545
546 self.osLanguage = None
547
548 self.charsetName = None
549 self.determineOsLanguage()
550
551 if self.osLanguage.charsets:
552 self.useCharset(self.osLanguage.charsets[0])
553
554 self.globalSettings = GeneralSettingsConfigFile.getInstance()
555 self.__defaultCommandTimeout = None
556 self.getDefaultCommandTimeout()
557
559 ''' Get default command timeout declared in globalSettings.xml
560 @types: -> number
561 '''
562 if not self.__defaultCommandTimeout:
563 self.__defaultCommandTimeout = self.globalSettings.getPropertyIntegerValue('shellGlobalCommandTimeout', 1)
564 return self.__defaultCommandTimeout
565
567 '@deprecated: Unix only dedicated'
568 pass
569
571 '@types: -> bool'
572 return NotImplementedError()
573
575 """Returns the type of the operating system running on the target host to which the shell client is connected
576 @types: -> str
577 @raise Exception: Failed getting machine OS type
578 """
579 if not self.osType:
580 try:
581 self.osType = self._getOsType()
582 except Exception, e:
583 logger.errorException(str(e))
584 raise Exception('Failed getting machine OS type')
585 return self.osType
586
588 ''' Template method for each derived class to get properly OS type
589 @types: -> str
590 @raise Exception: Failed getting machine OS type'''
591 return NotImplementedError()
592
594 ''' Indicates whether running commands in cygwin shell
595 @types: -> bool
596 @deprecated: will be removed from public access'''
597 return 0
598
600 """ Get version of the OS running on the target host to which the shell
601 client is connected
602 @types: -> str or None
603 @deprecated: should be moved to the OS discoverer (domain layer)
604 """
605 if not self.osVer:
606 try:
607 self.osVer = self._getOsVersion()
608 except Exception, e:
609 logger.warn(str(e))
610 return self.osVer
611
613 return self.osLanguage
614
618
620 ''' Template method to get OS version for derived shell
621 @types: -> str
622 @raise Exception: Failed to get OS version
623 '''
624 return NotImplemented
625
627 '@types: -> OsLanguageDiscoverer'
628 raise NotImplemented
629
631 ''' Use specified character set for command encoding and output decoding in raw client
632 @types: str
633 @raise IllegalCharsetNameException: The given charset name is illegal
634 @raise UnsupportedCharsetException: No support for the named charset is available in this instance of the JVM
635 '''
636 charset = Charset.forName(charsetName)
637 logger.debug('Using charset: %s' % charsetName)
638 logger.debug('Can encode: %s' % charset.canEncode())
639 self.__client.setCharset(charset)
640
642 """ Returns the shell command exit status code
643 @types: -> str
644 """
645 raise NotImplemented
646
648 ''' Get command separator depending on OS type
649 @types: -> str'''
650 return self.getShellCmdSeperator()
651
653 """
654 Returns the shell command separator character.
655 This is the character used between commands when more than one command
656 is passed on the same command line.
657 @types: -> str
658 @deprecated: Use getCommandSeparator instead
659 """
660 if (self.__shellCmdSeparator is None):
661 self.__shellCmdSeparator = self.__client.getShellCmdSeperator()
662 return self.__shellCmdSeparator
663
664 - def __addAlternateCmd(self, cmd, expectedReturnCode=None, sucessString=None, failureString=None):
665 '''Add alternative command to execute list
666 @types: str, int, str, str'''
667 self.__alternateCmdList.append(__CmdTransaction(cmd, expectedReturnCode, sucessString, failureString))
668
670 if (len(self.__alternateCmdList) > 0):
671 self.__alternateCmdList = []
672
674 ''' Go over all alternative commands list and execute each until the first successful command termination.
675 This method basically executes shell commands and retrieves terminate status of the executed command
676 until a command ended successfully.
677 command is successful when:
678 1. it returned the expected return code.
679 2. if no return code is given, the output of the command is compared against sucessString
680 to determine command success.
681 3. if failureString is given the output of the command is compared against failureString
682 to determine command failure
683 @types: int -> str
684 '''
685 err_output = ''
686 for cmdTrans in self.__alternateCmdList:
687 try:
688 output = self.execCmd(cmdTrans.cmd, timeout)
689 if (cmdTrans.expectedReturnCode is not None):
690 if (cmdTrans.expectedReturnCode == self.getLastCmdReturnCode()):
691 logger.debug('command=\'%s\' ended successfully' % cmdTrans.cmd)
692 return output
693 else:
694 err_output = '%s\n%s' % (err_output, output)
695 logger.debug('command=%s did not pass return code creteria. got rc=%d expected rc=%d' % (cmdTrans.cmd, self.getLastCmdReturnCode(), cmdTrans.expectedReturnCode))
696 continue
697 elif(cmdTrans.sucessString is not None):
698 if (output.find(cmdTrans.sucessString) > -1):
699
700 logger.debug('command=\'%s\' ended successfully' % cmdTrans.cmd)
701 return output
702 else:
703 err_output = '%s\n%s' % (err_output, output)
704 logger.debug('command=%s did not pass sucsess string creteria. got output string=%s expected=%s' % (cmdTrans.cmd, output, cmdTrans.sucessString))
705 continue
706 elif(cmdTrans.failureString is not None):
707 if (output.find(cmdTrans.sucessString) > -1):
708
709 logger.debug('command=\'%s\' did not pass failure string creteria. got output string=%s which contains failure string=%s' % (cmdTrans.cmd, output, cmdTrans.failureString))
710 err_output = '%s\n%s' % (err_output, output)
711 continue
712 else:
713
714 logger.debug('command=\'%s\' ended successfully' % cmdTrans.cmd)
715 return output
716 except:
717 logger.warnException('Failed to execute %s.' % cmdTrans.cmd)
718 return err_output
719
721 """
722 Executes the input list of shell commands until one of them succeeds.
723 @types: vararg(str) -> str or None
724 @return: output of the first successful command, otherwise None
725 """
726 return self.execAlternateCmdsList(commands)
727
729 """
730 Executes the input list of shell commands until one of them succeeds.
731 @types: list(str), int -> str or None
732 @param timeout: timeout for each command in milliseconds
733 @return: output of the first successesfull command, otherwise None
734 """
735 for cmd in commands:
736 logger.debug('adding alternate cmd=\'%s\'' % cmd)
737 self.__addAlternateCmd(cmd, 0)
738 output = self.__execCmdSet(timeout)
739 self.__removeAllAlternateCmds()
740 return output
741
743 """
744 Returns the exit status of the last shell command issued by execCmd or execAlternateCmds methods
745 @types: -> int
746 @return: exit status of the last command issued
747 @raise Exception: Cannot get last command return code: no command was issued
748 """
749 if (self.__lastCmdReturnCode is None):
750 raise Exception('Cannot get last command return code: no command was issued')
751 return self.__lastCmdReturnCode
752
754 """ Checks whether the file or directory exists on the File System
755 @types: str -> bool
756 @deprecated: Use FileSystem methods instead
757 """
758 raise NotImplemented
759
760 - def execCmd(self, cmdLine, timeout=0, waitForTimeout=0, useSudo=1, checkErrCode=1, useCache=0, preserveSudoContext=0):
761 """ Executes a shell command and sets the exit status of the command.
762 @types: str, int, int, bool, bool, bool -> str
763 Issue the given command followed by an echo of its return status, in the last line of the output
764 The exit status is an integer.
765 @param cmdLine: command to execute
766 @param timeout: time in ms or if < 1ms treated as coefficient for predefined timeout
767 @return: output of the executed shell command
768 @raise Exception: Command execution does not produced output nor return code
769 """
770
771 if useCache and self.cmdCache.containsKey(cmdLine):
772 command = self.cmdCache.get(cmdLine)
773 self.__lastCmdReturnCode = command.returnCode
774 self.getLastCommandOutputBytes = command.outputInBytes
775 return command.output
776
777 if timeout and timeout < 1000:
778 timeout = timeout * self.__defaultCommandTimeout
779
780 command = Command(cmdLine)
781 command.executionTimeout = timeout
782 command.waitForTimeout = waitForTimeout
783 command.useSudo = useSudo
784 command.checkErrCode = checkErrCode
785 command.preserveSudoContext = preserveSudoContext
786
787 command = self._execute(command)
788
789 self.__lastCmdReturnCode = command.returnCode
790 self.getLastCommandOutputBytes = command.outputInBytes
791
792 self.cmdCache.put(cmdLine, command)
793 return command.output
794
796 ''' Template method for derived shells for exact command execution
797 @types: Command -> Command
798 @raise Exception
799 @raise NoPermission
800 @raise CommandNotFound
801 '''
802 raise NotImplemented
803
804 - def execCmdAsBytes(self, cmdLine, timeout=0, waitForTimeout=0, useSudo=1):
805 ''' Get raw data as list of bytes.
806 @types: str, int, int, bool -> list(byte)'''
807 self.execCmd(cmdLine, timeout, waitForTimeout, useSudo)
808 return self.getLastCommandOutputBytes
809
810 - def resolveHost(self, hostName, nodeClassName='node'):
811 """ Create host CI with IP as key resolved by host name
812 @types: str -> ObjectStateHolder or None
813 @return: IP address or None if IP cannot be resolved or is local
814 @deprecated: Will be removed in further version
815 """
816 node_ip = None
817 dns_name = None
818 try:
819 node_ip = netutils.getHostAddress(hostName, None)
820 except:
821 node_ip = None
822 if (node_ip is None) or netutils.isLocalIp(node_ip):
823 try:
824 logger.debug('Trying to resolve ip for node %s by nslookup command' % hostName)
825 result = self.execCmd('nslookup %s' % hostName)
826 logger.debug('nslookup command returned result:', result)
827 m = re.search('(Name:)\s+(.+)\s+(Address:)\s+(\d+\.\d+\.\d+\.\d+)', result) or re.search('(Name:)\s+(.+)\s+(Addresses:)\s+(?:[0-9a-f:]*)\s+(\d+\.\d+\.\d+\.\d+)', result)
828 if m is not None:
829 node_ip = m.group(4).strip()
830 dns_name = m.group(2).strip()
831 else:
832 node_ip = None
833 except:
834 logger.debugException('Failed to resolve ip address of cluster node ', hostName)
835 node_ip = None
836 if (node_ip is None) or netutils.isLocalIp(node_ip):
837 return None
838 nodeHostOSH = modeling.createHostOSH(node_ip, nodeClassName)
839 if dns_name:
840 nodeHostOSH.setStringAttribute('host_dnsname', dns_name)
841 if hostName and not hostName.count('.'):
842 nodeHostOSH.setStringAttribute('host_hostname', hostName)
843 return nodeHostOSH
844
846 """ Resolve IP by host name
847 @types: str -> str or None
848 @return: IP address or None if IP cannot be resolved or is local
849 @deprecated: Use netutils.IpResolver instead
850 """
851 node_ip = None
852 try:
853 node_ip = netutils.getHostAddress(hostName, None)
854 except:
855 node_ip = None
856 if (node_ip is None) or (netutils.isLocalIp(node_ip)):
857 try:
858 logger.debug('Trying to resolve ip for node %s by nslookup command' % hostName)
859 result = self.execCmd('nslookup %s' % hostName)
860 logger.debug('nslookup command returned result:', result)
861 m = re.search('(Name:)\s+(.+)\s+(Address:)\s+(\d+\.\d+\.\d+\.\d+)', result) or re.search('(Name:)\s+(.+)\s+(Addresses:)\s+(?:[0-9a-f:]*)\s+(\d+\.\d+\.\d+\.\d+)', result)
862 if m is not None:
863 node_ip = m.group(4).strip()
864 else:
865 node_ip = None
866 except:
867 logger.debugException('Failed to resolve ip address of cluster node ', hostName)
868 node_ip = None
869 if (node_ip is None) or (netutils.isLocalIp(node_ip)):
870 return None
871 return node_ip
872
873 - def getXML(self, path, forceSudo=0):
874 ''' Get xml content with proper encoding
875 @types: str, bool -> str
876 @param forceSudo:if true, always uses sudo, if false first tries to run command without sudo
877 @deprecated: Use file system module for such purposes
878 '''
879 content = self.safecat(path, forceSudo)
880 if content:
881 match = re.search(r'encoding="(\S+.)"', content)
882 if match:
883 encoding = match.group(1)
884 encodedContent = String(self.getLastCommandOutputBytes, encoding)
885 handler = self.createOutputHandler(self.lastExecutedCommand)
886 output = handler.handle(encodedContent)
887 return str(String(output))
888 return content
889
890 - def safecat(self, path, forceSudo=0):
891 ''' Get file content by specified path
892 @types: str, bool -> str
893 @deprecated: Use methods from file system module instead
894 @param path:full path (including name) to the desired file
895 @param forceSudo:if true, always uses sudo, if false first tries to run command without sudo
896 @raise Exception: Redirection symbols used or getting content failed
897 '''
898 raise NotImplemented
899
901 '@types: -> str'
902
903 return self.__client.getClientType()
904
906 '@types: -> int'
907 return self.__client.getPort()
908
912
914 '''Perform cleaning of temporary data on destination system and close the client'''
915 self.__removeCopiedData()
916 self.__client and self.__client.close()
917
919 removeCopiedData = self.globalSettings.getPropertyStringValue('removeCopiedFiles', 'true')
920 if removeCopiedData and removeCopiedData.lower() == 'true':
921 for remoteFile in self.copiedFiles:
922 self.deleteFile(remoteFile)
923
925 '''Indicates whether client can copy files to the remote system
926 @types: -> bool'''
927 return self.__client.canCopyFile()
928
930 ''' Normalize path to one used in OS client connected to
931 @types: str -> str
932 @deprecated: Use methods from file system module instead
933 '''
934 raise NotImplemented
935
937 ''' Create output handler depending OS type
938 @types: str -> OutputHandler
939 @deprecated: Will be moved to the private scope
940 @raise ValueError: If decoding is not supported for used protocol type
941 '''
942 if self.getClientType() == 'ntadmin':
943 trimWSString = self.__client.getProperty(AgentConstants.PROP_NTCMD_AGENT_TRIM_WHITESPACE)
944 trimWS = 1
945
946 if trimWSString:
947 trimWS = Boolean.parseBoolean(trimWSString)
948
949 return NTCMDOutputHandler(cmd, trimWS)
950 elif self.getClientType() == 'ssh':
951 return SSHOutputHandler()
952 elif self.getClientType() == 'telnet':
953 return TelnetOutputHandler()
954 elif self.getClientType() == PowerShell.PROTOCOL_TYPE:
955 return PowerShellOutputHandler(cmd, 1)
956 else:
957 raise ValueError("Decoding is not supported for protocol type %s" % self.getClientType())
958
960 ''' Execute command and try to decode output using predefined charsets.
961 Decoded output considered as valid if it is matched by provided matcher.
962 @types: str, OutputMatcher, Framework, int, int, bool, Language -> str
963 @param matcher: defines matching case for valid character set
964 '''
965 language = language or self.osLanguage
966
967 commandBytes = self.execCmdAsBytes(cmd, timeout, waitForTimeout, useSudo)
968 encodingContext = EncodingContext(commandBytes, language, framework)
969
970 encodingContext.addOutputHandler(self.createOutputHandler(cmd))
971
972 (result, charsetName) = encodingContext.getDecodedString(matcher)
973 self.charsetName = charsetName
974 return result
975
976 - def executeCommandAndDecode(self, cmd, keyword, framework, timeout=0, waitForTimeout=0, useSudo=1, language=None):
977 ''' Execute command and try to decode output using predefined charsets.
978 Decoded output considered as valid if it is matched by KEYWORD matcher.
979 @types: str, str, Framework, int, int, bool, Language -> str'''
980 return self.executeCommandAndDecodeByMatcher(cmd, KeywordOutputMatcher(keyword), framework, timeout, waitForTimeout, useSudo, language)
981
983 ''' Get name of the character set for the latest command execution
984 @types: -> str or None
985 '''
986 return self.charsetName
987
988
990 'Basic class for Windows shell'
991
992 DEFAULT_ENGLISH_CODEPAGE = 437
993 DEFAULT_WIN_SHARE = 'admin$\\system32\\drivers\etc'
994 __DEFAULT_COMMAND_SEPARATOR = '&'
995
996 - def __init__(self, client, protocolName):
997 ''' @types: Client, str'''
998 self.__shellStatusVar = '%ERRORLEVEL%'
999 self.__protocolName = protocolName
1000 self.__osLanguageDiscoverer = WindowsLanguageDiscoverer(self)
1001 self.__client = client
1002 self.__pathAppended = 0
1003 self.__is64Bit = None
1004
1005
1006
1007 self.__ddm_link_system32 = None
1008 self.__system32 = None
1009
1010 Shell.__init__(self, client)
1011
1013 '@types: -> bool'
1014 return 1
1015
1017 '@types: -> OsLanguageDiscoverer'
1018 return self.__osLanguageDiscoverer
1019
1021 """ Get the shell command separator character.
1022 This is the character used between commands when more than one command is passed on the same command line.
1023 @types: -> str
1024 @deprecated: Use getCommandSeparator instead
1025 """
1026 return WinShell.__DEFAULT_COMMAND_SEPARATOR
1027
1028 - def getCodePage(self):
1029 """Get current codepage of remote Windows machine to which the shell client is connected or 437 if codepage was not resolved
1030 @types: -> Integer
1031 @command: chcp
1032 """
1033 codePage = WinShell.DEFAULT_ENGLISH_CODEPAGE
1034 try:
1035 chcpBuffer = self.execCmd('chcp')
1036 if chcpBuffer and self.getLastCmdReturnCode() == 0:
1037 cpMatch = re.search('(\d{3})',chcpBuffer)
1038 if cpMatch:
1039 codePage = int(cpMatch.group(1))
1040 except:
1041 logger.warn("Failed to detect codepage, assuming default: 437")
1042 return codePage
1043
1045 """Set new codepage on remote Windows machine to which the shell client is connected
1046 @Types: Integer -> Integer
1047 @command: chcp <codepage>
1048 """
1049 try:
1050 self.execCmd('chcp %s' % str(newCodePage))
1051 except:
1052 return 0
1053 else:
1054 return 1
1055
1057 '@types: -> str'
1058 return self.__shellStatusVar
1059
1061 """ Get the type of the OS running on the target host to which the shell client is connected.
1062 types: -> str
1063 @command: ver
1064 @raise Exception: Failed getting machine OS type.
1065 """
1066 osBuff = self.execCmd('ver', useCache=1)
1067 if (self.getLastCmdReturnCode() == self.NO_CMD_RETURN_CODE_ERR_NUMBER and self.__protocolName == 'sshprotocol'):
1068 self.__shellStatusVar = '$?'
1069 osBuff = self.execCmd('ver')
1070 if (self.getLastCmdReturnCode() != 0):
1071 logger.debug('failed getting os type. command=ver failed with rc=%d' % (self.getLastCmdReturnCode()) + ". Output buffer :" + osBuff)
1072 raise Exception('Failed getting machine OS type.')
1073 else:
1074 match = re.search('(.*)\s*\[', osBuff)
1075 if (match is None):
1076 logger.debug('failed getting os type. unrecognized ver command output')
1077 raise Exception('Failed getting machine OS type.')
1078 else:
1079 self.osType = match.group(1).strip()
1080 return self.osType
1081
1083 ''' Get OS Version
1084 @types: -> str
1085 @command: ver
1086 @raise Exception: Failed getting os type
1087 '''
1088 buffer = self.execCmd('ver')
1089 if (self.getLastCmdReturnCode() != 0):
1090 raise Exception('Failed getting os version. command=ver failed with rc=%d' % (self.getLastCmdReturnCode()))
1091 else:
1092 match = re.search('\[.*\s(.*)\]', buffer)
1093 if match:
1094 return match.group(1)
1095 else:
1096 raise Exception('Failed getting os type. unrecognized ver command output')
1097
1099 ''' Get the return code for the latest command execution
1100 @types: -> str
1101 @command: echo %ERRORLEVEL%
1102 @deprecated: Will be removed from the public access'''
1103 return self.__client.executeCmd('echo %ERRORLEVEL%')
1104
1106 '''@types: Command -> Command
1107 @raise Exception: Command execution does not produced output nor return code
1108 '''
1109 output = self.__client.executeCmd(cmd.line, cmd.executionTimeout, cmd.waitForTimeout)
1110 cmd.outputInBytes = self.__client.getLastCommandOutputBytes()
1111 try:
1112 cmd.returnCode = int(self.getWindowsErrorCode())
1113 except:
1114 cmd.returnCode = self.NO_CMD_RETURN_CODE_ERR_NUMBER
1115 if output is None:
1116 raise Exception('Executing command: "%s" failed. Command produced no output and no return status (we might be connected to an unstable agent)' % cmd.cmd)
1117 cmd.output = output
1118 return cmd
1119
1121 """ Delete directory
1122 @types: str
1123 @comamnd: rmdir "<dirPath>" /s /q
1124 @raise ValueError: Specified path is empty
1125 @raise ValueError: Failed deleting directory
1126 @deprecated: Use methods from file system module instead
1127 """
1128 if not dirPath:
1129 raise ValueError("dirPath is empty")
1130 self.execCmd("rmdir \"%s\" /s /q" % dirPath)
1131 if self.getLastCmdReturnCode() != 0:
1132 raise ValueError("Failed deleting directory '%s'" % dirPath)
1133
1135 """ Create directory
1136 @types: str
1137 @command: mkdir "<dirPath>"
1138 @raise ValueError: Specified path is empty
1139 @raise ValueError: Failed creating directory
1140 @deprecated: Use methods from file system module instead
1141 """
1142 if not dirPath:
1143 raise ValueError("dirPath is empty")
1144 self.execCmd("mkdir \"%s\"" % dirPath)
1145 if self.getLastCmdReturnCode() != 0:
1146 raise ValueError("Failed creating directory '%s'" % dirPath)
1147
1149 """ Copy file from the remote share resource
1150 @types: str, str -> None
1151 @deprecated: Use methods from file system module instead
1152 """
1153 return self.__client.getFile(remoteFileName, remoteShareName)
1154
1156 """ Delete file from the remote share resource
1157 @types: str, str -> None
1158 @deprecated: Use methods from file system module instead
1159 """
1160 return self.__client.deleteFile(remoteFile, remoteShare)
1161
1163 """ Copy file to the remote share. If file exists it will be rewritten.
1164 @types: str, str -> bool
1165 """
1166 if self.__client.putFile(localFilePath, share):
1167 remoteFile = self.__composeRemotePath(localFilePath, share)
1168 self.copiedFiles.append(remoteFile)
1169 logger.debug("Create file on destination: ", remoteFile)
1170 return 1
1171
1173 """ Delete remote file
1174 @types: str, str -> bool
1175 @deprecated: Use methods from file system module instead
1176 """
1177 isDeleted = self.__client.deleteFile(remoteFile, share)
1178 if not isDeleted:
1179 self.execCmd('del ' + remoteFile)
1180 isDeleted = not self.getLastCmdReturnCode()
1181 return isDeleted
1182
1184 '''@types: str, str -> str
1185 @return: String of format "\\<ip address>\<share>\<file name>
1186 '''
1187 file_ = File(localFilePath)
1188
1189
1190 ipAddress = self.__client.getIpAddress() or '127.0.0.1'
1191 remoteFile = '\\\\' + ipAddress + '\\' + share + '\\' + file_.getName()
1192 return remoteFile
1193
1195 """ Copy file to the share if it does not exist there
1196 @types: str, str -> str or None
1197 @command: dir \\ip_address\share\file_name
1198 @deprecated: Use methods from file system module instead
1199 @return: return None if file is not copied
1200 """
1201 remoteFile = self.__composeRemotePath(localFile, share)
1202 self.execCmd('dir ' + remoteFile)
1203
1204 if self.getLastCmdReturnCode() != 0:
1205 if self.__client.putFile(localFile, share):
1206 self.copiedFiles.append(remoteFile)
1207 logger.debug("Create file on destination: ", remoteFile)
1208 else:
1209 return None
1210
1211
1212 if not self.__pathAppended:
1213 try:
1214 interpreter = shell_interpreter.Factory().create(self)
1215 systemRoot = interpreter.getEnvironment().buildVarRepresentation('SystemRoot')
1216 interpreter.getEnvironment().appendPath('PATH', '%s\\system32\\drivers\\etc' % systemRoot,
1217 '%s\\SysWOW64' % systemRoot,
1218 '%s\\system32' % systemRoot)
1219 self.__pathAppended = 1
1220 except:
1221 logger.debugException('Failed to append path using shell_interpreter')
1222
1223 return remoteFile
1224
1226 """ Get case sensitive name of Windows %SystemRoot%
1227 @command: dir %SystemRoot% /O:-D | find /I "system32"
1228 @raise ValueError: Failed to find system32 folder inside the %SystemRoot%
1229 @deprecated: Use methods from file system module instead
1230 """
1231 system32Line = self.execCmd('dir %SystemRoot% /O:-D | find /I "system32"')
1232 system32Name = None
1233 if self.getLastCmdReturnCode() == 0:
1234 match = re.search(r'.*\s+(system32)$', system32Line, re.IGNORECASE)
1235 if match:
1236 system32Name = match.group(1)
1237
1238 if not system32Name:
1239 raise ValueError('Failed to find system32 folder inside the %SystemRoot%')
1240
1241 return system32Name
1242
1244 """ Creates, locks and returns NTFS junction point to %SystemRoot%\\System32
1245 using (in fallback order) linkd, mklink and junction commands.
1246 @types: str, bool, bool -> str or None
1247 @param lock: variable to control whether to lock or not the created junction point once it is created, default is 1 (meaning lock it)
1248 @param force: variable to control whether Universal Discovery should decide upon creation of junction point (WinOS + 64bit) or forcibly create it
1249 @raise ValueError: if creation or locking failed
1250 @command: linkd <src> <dest>
1251 @command: mklink /d <src> <dest>
1252 @command: junction <src> <dest> /accepteula
1253 @deprecated: Use methods from file system module instead
1254 """
1255 actualLinkFolder = None
1256 if (0 == force):
1257 if not (self.isWinOs() and self.is64BitMachine()):
1258 return
1259 if not self.__system32:
1260 self.__system32 = '%SystemRoot%' + '\\' + self.getSystem32DirectoryName()
1261 self.__ddm_link_system32 = "%s\\%s" % (DDM_LINK_SYSTEM32_LOCATION, DDM_LINK_SYSTEM32_NAME)
1262 if location:
1263 actualLinkFolder = location
1264 else:
1265 actualLinkFolder = self.__ddm_link_system32
1266 if not self.fsObjectExists(actualLinkFolder):
1267 self.execAlternateCmdsList(['linkd %s %s' % (actualLinkFolder, self.__system32), \
1268 'mklink /d %s %s' % (actualLinkFolder, self.__system32)])
1269 if self.getLastCmdReturnCode() != 0:
1270 localFile = CollectorsParameters.BASE_PROBE_MGR_DIR + CollectorsParameters.getDiscoveryResourceFolder() + \
1271 CollectorsParameters.FILE_SEPARATOR + 'junction.exe'
1272 self.copyFileIfNeeded(localFile)
1273 self.execCmd('junction %s %s /accepteula' % (actualLinkFolder, self.__system32))
1274
1275 if self.getLastCmdReturnCode() != 0:
1276 raise ValueError("Failed to create System32 junction point")
1277 if (lock != 0):
1278 self.execCmd('cd %s\\' % (actualLinkFolder))
1279 if self.getLastCmdReturnCode() == 0:
1280 return actualLinkFolder + '\\'
1281 else:
1282 raise ValueError('Unable to lock junction point')
1283 else:
1284 return actualLinkFolder + '\\'
1285
1287 """
1288 Unlocks and removes NTFS junction point previously created by @createSystem32Link().
1289 @types: str
1290 @command: cd %SystemDrive%\\
1291 @command: rd <location>
1292 @raise ValueError: Unable to delete or unlock junction point
1293 @deprecated: Use methods from file system module instead
1294 """
1295 location = location or self.__ddm_link_system32
1296 if not (self.isWinOs() and self.is64BitMachine() and location):
1297 return
1298 self.execCmd('cd %SystemDrive%\\')
1299 if self.getLastCmdReturnCode() == 0:
1300 self.execCmd('rd %s' % (location))
1301 if self.getLastCmdReturnCode() != 0:
1302 raise ValueError('Unable to delete junction point')
1303 else:
1304 raise ValueError('Unable to unlock junction point')
1305
1307 """ Checks is the discovered machine OS 64 bit.
1308 32 or 64 bit family detected by checking existence of %SystemRoot%\SysWOW64 folder
1309 @types: -> bool
1310 @command: (@if exist %SystemRoot%\SysWOW64 (echo SysWOW64) ELSE (echo FALSE))
1311 @deprecated: Will be removed from the public access
1312 """
1313 if self.__is64Bit is None:
1314 output = self.execCmd('(@if exist %SystemRoot%\SysWOW64 (echo SysWOW64) ELSE (echo FALSE))')
1315 self.__is64Bit = (output.find('SysWOW64') > -1)
1316 return self.__is64Bit
1317
1319 """ Indicates whether object by specified path exists on remote file system
1320 @types: str -> bool
1321 @command: (@if exist %s (echo TRUE) ELSE (echo FALSE))
1322 @deprecated: Use methods from file system module instead
1323 """
1324 if path:
1325 output = self.execCmd('(@if exist %s (echo TRUE) ELSE (echo FALSE))' % path)
1326 return output.find('TRUE') > -1
1327
1328 - def safecat(self, path, forceSudo=0):
1329 ''' Get file content by specified path
1330 @types: str, bool -> str
1331 @param forceSudo:if true, always uses sudo, if false first tries to run command without sudo
1332 @command: type
1333 @deprecated: Use file system module for such purposes
1334 @raise ValueError: Illegal type command, contains redirect
1335 @raise Exception: Failed getting contents of file
1336 '''
1337
1338 m = re.search('>', path)
1339 if m is not None:
1340
1341
1342 logger.warn('Illegal type command, contains redirect: [%s]' % path)
1343 raise ValueError('Illegal type command, contains redirect')
1344
1345 path = self.rebuildPath(path)
1346 if (path[0] != '"'):
1347 path = '"' + path + '"'
1348 cmd = 'type %s' % path
1349 self.lastExecutedCommand = cmd
1350 fileContents = self.execCmd(cmd)
1351 if not self.getLastCmdReturnCode():
1352 return fileContents
1353 logger.warn('Failed getting contents of %s file' % path)
1354 raise Exception('Failed getting contents of file')
1355
1357 ''' Normalize path to one used in OS client connected to
1358 @types: str -> str
1359 @deprecated: Use file system module for such purposes
1360 '''
1361 return re.sub('/', '\\\\', folder)
1362
1364 '''Perform cleaning of temporary data on destination system and close the client'''
1365 try:
1366 self.removeSystem32Link()
1367 finally:
1368 Shell.closeClient(self)
1369
1370
1372 'Cygwin Shell base class'
1373
1375 '@types: -> bool'
1376 return 1
1377
1378
1380 PROTOCOL_TYPE = PowerShellClient.POWERSHELL_PROTOCOL_NAME
1381 __DEFAULT_COMMAND_SEPARATOR = ';'
1382 __INVOKE_COMMAND_SCRIPT_BLOCK = (
1383 'Invoke-Command -ScriptBlock {%s ;$?} -Session $'
1384 + PowerShellAgent.REMOTE_SESSION_IDENTIFIER)
1385 __INVOKE_COMMAND_LOCAL_SCRIPT = (
1386 'Invoke-Command -FilePath %s -Session $'
1387 + PowerShellAgent.REMOTE_SESSION_IDENTIFIER
1388 + '; $?')
1389
1390 - def __init__(self, client, protocolName):
1391 '@types: PowerShellClient, str -> None'
1392 self.__client = client
1393 self.__is64Bit = None
1394 self.__outputHandler = PowerShellOutputHandler()
1395 self.__consoleCharsetName = self.__getRemoteConsoleEncoding()
1396 self.__powershellConsoleCharsetName = self.__getPowerShellEncoding()
1397
1398
1399 self.__consoleCommands = ['ver', 'type', 'wmic', 'chcp']
1400 consoleCommands = (GeneralSettingsConfigFile.getInstance().
1401 getPropertyTextValue('consoleCommands')
1402 or "")
1403 _isEmptyString = lambda s: s and s.strip()
1404 _normalize = lambda s: s.strip().lower()
1405 consoleCommands = filter(_isEmptyString, consoleCommands.split(','))
1406 consoleCommands = map(_normalize, consoleCommands)
1407 self.__consoleCommands.extend(consoleCommands)
1408 WinShell.__init__(self, client, protocolName)
1409 self.execCmd('$global:FormatEnumerationLimit = -1', pipeToOutString=0)
1410 self.useCharset('utf8')
1411
1422
1424 '''@types: ->str or None
1425 @command: [System.Console]::OutputEncoding.WebName
1426 '''
1427 cmd = '[System.Console]::OutputEncoding.WebName'
1428 cmd = PowerShell.__INVOKE_COMMAND_SCRIPT_BLOCK % cmd
1429 encodingName = self.__client.executeCmd(cmd)
1430 if self.__outputHandler.isCommandSucceeded(encodingName) == 0:
1431 return self.__outputHandler.cleanOutput(encodingName, 0).strip()
1432
1434 '''@types: str -> str or None
1435 @command: [System.Text.Encoding]::GetEncoding(<codePage>).WebName
1436 '''
1437 cmd = '[System.Text.Encoding]::GetEncoding(%s).WebName' % codePage
1438 cmd = PowerShell.__INVOKE_COMMAND_SCRIPT_BLOCK % cmd
1439 encodingName = self.__client.executeCmd(cmd)
1440 if self.__outputHandler.isCommandSucceeded(encodingName) == 0:
1441 return self.__outputHandler.cleanOutput(encodingName, 0).strip()
1442
1444 """ Checks is the discovered machine OS 64 bit. 32 or 64 bit family
1445 detected by checking existence of %SystemRoot%\SysWOW64 folder
1446 @types: -> bool
1447 @command: Test-Path $env:SystemRoot/SysWOW64
1448 """
1449 if self.__is64Bit is None:
1450 output = self.execCmd('Test-Path $env:SystemRoot/SysWOW64')
1451 self.__is64Bit = output.lower().count('true')
1452 return self.__is64Bit
1453
1455 raise NotImplemented
1456
1458 raise NotImplemented
1459
1465
1467 ''' If passed command is a windows batch command it should be called in
1468 batch command interpreter
1469 @types: str -> str'''
1470 return "cmd.exe /c '%s'" % cmdline.replace("'", "\\'")
1471
1473 '''Strip WMIC redirection part
1474 @types: str -> str
1475 '''
1476 if re.search('wmic\s', cmdline):
1477 cmdline = re.sub('\<\s* [\w\-\.\,\%\\\/\$]+\s*', '', cmdline)
1478 return cmdline
1479
1481 '''Indicates whether passed command line contains command of batch
1482 command interpreter
1483 @types: str -> bool'''
1484 cmd = cmdline.split()[0].lower()
1485 for consoleCmd in self.__consoleCommands:
1486 if re.match('(?<![\w\-])%s$' % consoleCmd, cmd):
1487 logger.debug('A console command')
1488 return 1
1489
1491 '@types: str, [int] -> str'
1492 return '%s | Out-String -width %d' % (cmd, lineWidth)
1493
1494 - def execCmd(self, cmdLine, timeout=0, waitForTimeout=0, useSudo=1,
1495 checkErrCode=1, useCache=0, lineWidth=80, pipeToOutString=1):
1496 ''' Execute command in powershell
1497 * If current command is cmdlet:
1498 1. Method passes output object to 'Out-String' cmdlet to get its
1499 string representation.
1500 * If current command is non-cmdlet command(console)
1501 1. Method prefixes current command with 'cmd.exe /c %cmd%' and
1502 no passing to 'Out-String' cmdlet performed.
1503 List of console commands is defined at globalSettings.xml file and
1504 defaults to ('ver', 'type', 'wmic', 'chcp') if 'consoleCommands'
1505 attribute is note set.
1506
1507 @types: str, int, bool, bool, bool, bool, int, bool -> str
1508 @param lineWidth: Attribute of the 'Out-String' cmdlet.
1509 From the msdn: Specifies the number of characters in each line
1510 of output. Any additional characters are truncated, not wrapped
1511 @see: Shell.execCmd for the param meaning and usage
1512 '''
1513
1514
1515 isConsoleCommand = self.__isConsoleCommand(cmdLine)
1516 if isConsoleCommand:
1517 cmdLine = self.__makePowerShellCompatible(cmdLine)
1518 elif pipeToOutString:
1519 cmdLine = self.__pipeToOutString(cmdLine, lineWidth)
1520 cmdLine = self.__makePowerShellCompatibleWmicQuery(cmdLine)
1521 cmdLine = PowerShell.__INVOKE_COMMAND_SCRIPT_BLOCK % cmdLine
1522 output = Shell.execCmd(self, cmdLine, timeout, waitForTimeout, useSudo,
1523 checkErrCode, useCache)
1524 if isConsoleCommand:
1525 output = self.__fixEncoding(self.__powershellConsoleCharsetName,
1526 self.__consoleCharsetName, output)
1527 return output
1528
1529 - def execLocalScript(self, path, timeout=0, waitForTimeout=0, useSudo=1,
1530 checkErrCode=1, useCache=0):
1531 ''' Execute script on the probe
1532 @types: str, int, bool, bool, bool, bool -> str
1533 '''
1534 cmd = PowerShell.__INVOKE_COMMAND_LOCAL_SCRIPT % path
1535 return Shell.execCmd(self, cmd, timeout, waitForTimeout, useSudo,
1536 checkErrCode, useCache)
1537
1538 - def execMultilinedCmd(self, cmdLine, timeout=0, waitForTimeout=0,
1539 useSudo=1, checkErrCode=1, useCache=0):
1540 '''Method intended to execute multiline scripts. It's output is not
1541 passed to 'Out-String' cmdlet, so all toString conversion should be
1542 done manually. Powershell remote console encoding used to decode output
1543 Use ';' to separate different commands.
1544 @types: str, int, bool, bool, bool, bool -> str
1545 @see: Shell.execCmd for the param meaning
1546 '''
1547 cmdLine = "".join(cmdLine.split('\n'))
1548 cmdLine = PowerShell.__INVOKE_COMMAND_SCRIPT_BLOCK % cmdLine
1549 return Shell.execCmd(self, cmdLine, timeout, waitForTimeout, useSudo,
1550 checkErrCode, useCache)
1551
1553 '''@types: Command -> Command
1554 @raise Exception: Command produced nor output nor return status
1555 '''
1556 output = self.__client.executeCmd(cmd.line, cmd.executionTimeout,
1557 cmd.waitForTimeout)
1558 cmd.outputInBytes = self.__client.getLastCommandOutputBytes()
1559 if output is None:
1560 raise Exception('Executing command: "%s" failed. '
1561 'Command produced nor output nor return status '
1562 '(we might be connected to an unstable agent)'
1563 % cmd.cmd)
1564 output = output.strip()
1565
1566 try:
1567 cmd.returnCode = self.__outputHandler.isCommandSucceeded(output)
1568 except:
1569 cmd.returnCode = self.NO_CMD_RETURN_CODE_ERR_NUMBER
1570 cmd.output = self.__outputHandler.cleanOutput(output, cmd.returnCode)
1571 return cmd
1572
1574 '''Method is intended to fix string encoding. The root problem comes
1575 from execution of console commands through the powershell.
1576 There are two variables defining encodings: $OutputEncoding
1577 and [Console]::OutputEncoding. The problem is that Exception is raised
1578 when one tries to set remote [Console]::OutputEncoding, so when chcp
1579 output differes from [Console]::OutputEncoding.CodePage value, we need
1580 to fix corrupted string. Fixing is done if passed encodings are
1581 different only
1582 @types: str, str -> str
1583 '''
1584 if (fromEncoding != toEncoding):
1585 logger.debug('Fixing encoding.. from :%s, to: %s' % (fromEncoding,
1586 toEncoding))
1587 bytes = String(targetStr).getBytes(fromEncoding)
1588 targetStr = String(bytes, toEncoding)
1589 logger.debug('Fixed string: %s' % targetStr)
1590 return str(targetStr)
1591
1592
1594 'Unix Shell base class'
1595 ONLY_SUDO_POLICY = 'sudo'
1596 ONLY_SU_POLICY = 'su'
1597 SUDO_SU_POLICY = 'sudo or su'
1598 ERROR_CODE_PREFIX = 'ERROR_CODE:'
1599
1601 self.__shellStatusVar = None
1602 self.__shell = None
1603 self.__client = client
1604 self.__sudoPath = None
1605 self.__sudoPathsArray = None
1606 self.__sudoCommandsArray = None
1607 self.__osLanguageDiscoverer = UnixLanguageDiscoverer(self)
1608 self.__sudoConfiguredCommands = None
1609 self.__sudoSuPolicy = None
1610 self.__sudoSplitPattern = "(%s|\s*nice(?:\s*-i\s*\d+)|\s*nice(?:\s*)|\|(?:\s*))"
1611
1612 sudoExcludeCommandsPattern = "\s*export\s+|\s*set\s+|\s*LC_ALL\s*=|\s*LANG\s*=|\s*ORACLE_HOME\s*=|\s*PATH\s*=|\s*DB2NODE\s*="
1613 self.__sudoExcludeCommandMatcher = re.compile(sudoExcludeCommandsPattern)
1614
1615 Shell.__init__(self, client)
1616
1617
1618 if self.__client.supportsSudo():
1619 self.__retrieveSudoDetails()
1620 self.setSessionLocale()
1621
1622
1623
1624 if self.__isLimitedCommandLength():
1625 client.setMaxCommandLength(256)
1626
1627 try:
1628 interpreter = shell_interpreter.Factory().create(self)
1629 interpreter.getEnvironment().appendPath('PATH', '/bin', '/usr/bin')
1630 except:
1631 logger.debugException('Failed to append path using shell_interpreter')
1632
1634 '@types: -> bool'
1635 return 0
1636
1642
1644 '@types: -> OsLanguageDiscoverer'
1645 return self.__osLanguageDiscoverer
1646
1648 ''' Get OS version
1649 @types: -> str
1650 @command: uname -r
1651 @raise Exception: Failed getting OS version
1652 '''
1653 buffer = self.execCmd('uname -r')
1654 if (self.getLastCmdReturnCode() == 0):
1655 return buffer
1656 raise Exception('Failed getting OS version. command="uname -r" failed with rc=%d' % (self.getLastCmdReturnCode()))
1657
1659 """ Get OS type
1660 @types: -> str
1661 @command: uname
1662 @raise Exception: Failed getting machine OS type.
1663 """
1664 osBuff = self.execCmd('uname')
1665 if (self.getLastCmdReturnCode() == 0):
1666 return osBuff.strip()
1667 raise Exception('Failed getting machine OS type.')
1668
1670 '@deprecated: will be removed from the public access'
1671 locale = self.getAvailableEngLocale()
1672 if locale:
1673 environment = shell_interpreter.Factory().create(self).getEnvironment()
1674 try:
1675 environment.setVariable('LANG', locale)
1676 environment.setVariable('LC_ALL', locale)
1677 except:
1678 logger.debugException('Failed to set new locale')
1679 else:
1680 logger.debug('Locale set to: %s' % locale)
1681
1683 '''Try to retrieve a shell path from Unix machines (like /bin/sh or /sbin/sh)
1684 @types: -> str
1685 @command: echo $SHELL
1686 '''
1687 if not self.__shell:
1688 logger.debug('determining shell:')
1689 cmd = 'echo $SHELL'
1690 logger.debug("trying: '%s'" % cmd)
1691 resLines = self.__client.executeCmd(cmd)
1692 logger.debug("res: '%s'" % resLines)
1693 if resLines:
1694 resLines = resLines.strip()
1695 logger.debug("response: '%s'" % resLines)
1696 if len(resLines) > 0:
1697 self.__shell = resLines
1698 return self.__shell
1699
1701 '@types: -> str'
1702 if not self.__shellStatusVar:
1703 logger.debug('Determining shell environment status variable...')
1704
1705
1706 shellName = str(self.getShell())
1707 if (shellName and shellName.endswith('csh')):
1708 self.__shellStatusVar = self.__getCommandExitStatus('$status')
1709 else:
1710 for statusVar in ["$?", "$status", "$STATUS"]:
1711 if (self.__getCommandExitStatus(statusVar) is not None):
1712 self.__shellStatusVar = statusVar
1713 break
1714 return self.__shellStatusVar
1715
1717 '''@types: -> str or None
1718 @command: locale -a | grep -E "en_US.*|^C|POSIX"
1719 @command: locale -a | /usr/xpg4/bin/grep -E "en_US.*|^C|POSIX"
1720 '''
1721 buff = self.execAlternateCmds('locale -a | grep -E "en_US.*|^C|POSIX"', 'locale -a | /usr/xpg4/bin/grep -E "en_US.*|^C|POSIX"')
1722 if buff:
1723 match = re.search(r'en_US\S+', buff)
1724 if match:
1725 return match.group(0).strip()
1726 match = re.search(r'(?<![\w])C\s+', buff)
1727 if match:
1728 return match.group(0).strip()
1729 match = re.search(r'POSIX\S+', buff)
1730 if match:
1731 return match.group(0).strip()
1732 return None
1733
1735 '''@types: str -> str or None
1736 @command: echo <env variable>
1737 '''
1738 cmd = 'echo %s' % statusVar
1739 logger.debug('trying: \'%s\'...' % cmd)
1740 resLines = self.__client.executeCmd(cmd)
1741 logger.debug('res: \'%s\'...' % resLines)
1742 if (resLines is not None):
1743 resLines = resLines.strip()
1744 logger.debug('response: \'%s\'' % resLines)
1745 resLinesCount = len(resLines)
1746 if ((resLinesCount > 0) and (resLines[resLinesCount - 1].isdigit())):
1747 logger.debug('found shell environment status variable=\'%s\'' % statusVar)
1748 return statusVar
1749 return None
1750
1752 ''' Specific for Sun OS where shell 'sh' has command length limitation
1753 @types: -> bool
1754 '''
1755
1756 return self.getOsType() == 'SunOS' and self.getShell() == '/sbin/sh'
1757
1759 '@types: Command -> Command'
1760 cmd = command.line
1761 separator = self.getShellCmdSeperator()
1762
1763 cmdWithRc = '%s %s echo %s%s' % (cmd, separator, self.ERROR_CODE_PREFIX, self.getShellStatusVar())
1764 buff = self.__client.executeCmd(cmdWithRc, command.executionTimeout, command.waitForTimeout)
1765 command.outputInBytes = self.__client.getLastCommandOutputBytes()
1766 if buff is not None:
1767 try:
1768 output, returnCode = _extractCommandOutputAndReturnCode(buff)
1769 except ValueError:
1770 command.returnCode = Shell.NO_CMD_RETURN_CODE_ERR_NUMBER
1771 logger.warn("Execution command: \'%s\' failed (we might be connected to an unstable agent)" % cmd)
1772 raise Exception("Command produced no return status")
1773 else:
1774 command.returnCode = returnCode
1775 command.output = output
1776 else:
1777 command.returnCode = self.NO_CMD_RETURN_CODE_ERR_NUMBER
1778 logger.warn("Executing command: \'%s\' failed (we might be connected to an unstable agent)" % cmd)
1779 raise Exception("Command produced no output and no return status")
1780 return command
1781
1783 self.__client.executeSuCommand()
1784 if not self.__client.isInSuMode():
1785 raise Exception('Failed to run command in su mode.')
1786 command = self.__executeCommand(command)
1787 self.__client.exitFromSu()
1788 return command
1789
1791 '@types: str, str -> bool'
1792 return (self.__sudoCommandsArray
1793 and self.__shouldRunAsSuperUser(originalCommand, 1))
1794
1796 separator = self.getShellCmdSeperator()
1797 splitPattern = self.__sudoSplitPattern % re.escape(separator)
1798 commandElements = re.split(splitPattern, originalCommand)
1799 for i in range(0, len(commandElements)):
1800 command = commandElements[i]
1801 if not command or re.match(splitPattern, command):
1802
1803 continue
1804 isDestinationConfigured = 1
1805 if checkDestinationConfiguration:
1806 isDestinationConfigured = self.__isCommandConfiguredOnDestination(command)
1807
1808 if isDestinationConfigured and self.__shouldCommandElemRunAsSuperUser(command):
1809 return 1
1810
1811 return None
1812
1820
1822 if self.__sudoCommandsArray:
1823 isConfiguredInCreds = 0
1824 for sudoCommandPattern in self.__sudoCommandsArray:
1825 if sudoCommandPattern and sudoCommandPattern.strip() == '.*':
1826 isConfiguredInCreds = 1
1827
1828 if isConfiguredInCreds:
1829 sudoConfiguredCommands = self.__getSudoConfiguredCommands()
1830 for sudoCommandPattern in sudoConfiguredCommands:
1831 if sudoCommandPattern and sudoCommandPattern.strip() == '.*':
1832 return 1
1833
1835 if self.__sudoCommandsArray:
1836 for sudoCommandPattern in self.__sudoCommandsArray:
1837 if re.match(sudoCommandPattern.lstrip(), command.strip()):
1838 logger.debug("Command %s is matched by privileged command pattern %s" % (command, sudoCommandPattern))
1839 return 1
1840
1842 try:
1843 return self.__client.isSuConfigured() and self.__shouldRunAsSuperUser(originalCommand)
1844 except:
1845 logger.error('Method isSuConfigured() is missing in client. Wrong content.jar used. Please update.')
1846
1848 from com.hp.ucmdb.discovery.library.credentials.dictionary import ProtocolManager
1849 return ProtocolManager
1850
1852 if self.__sudoSuPolicy is None:
1853 try:
1854 protocol = self.__getProtocolManager().getProtocolById(self.getCredentialId())
1855 protocolName = self.getClientType()
1856 sudoPolicy = None
1857 if protocolName in ['ssh', 'telnet']:
1858 sudoPolicy = protocol.getProtocolAttribute('%sprotocol_sudo_su_policy' % protocolName)
1859 self.__sudoSuPolicy = sudoPolicy or UnixShell.ONLY_SUDO_POLICY
1860 except:
1861 self.__sudoSuPolicy = UnixShell.ONLY_SUDO_POLICY
1862 return self.__sudoSuPolicy
1863
1879
1881 '''Get information about sudo paths and sudo enabled commands'''
1882 sudoPaths = self.__client.getSudoPaths()
1883 if sudoPaths:
1884 self.__sudoPathsArray = string.split(sudoPaths, ',')
1885 sudoCommands = self.__client.getSudoCommands()
1886 if sudoCommands:
1887 splitCommands = string.split(sudoCommands, ',')
1888 if '*' in splitCommands:
1889 self.__sudoCommandsArray = ['.*']
1890 else:
1891 self.__sudoCommandsArray = splitCommands
1892
1894 '@types: str -> str'
1895
1896 if not self.__sudoPathsArray:
1897 return cmd
1898
1899 if re.match('\S*sudo\s', cmd):
1900 return cmd
1901
1902 sudoPath = self.__getSudoPath()
1903
1904 if sudoPath and len(sudoPath) > 0:
1905 return self.__getSudoWithCmd(sudoPath, cmd, preserveSudoContext)
1906 else:
1907 return cmd
1908
1928
1945
1946 - def __getSudoWithCmd(self, sudoPath, originalCommand, preserveSudoContext = 0):
1947 '@types: str, str -> str'
1948 if not self.__sudoCommandsArray:
1949 logger.debug('No sudo commands specified.')
1950 return originalCommand
1951 else:
1952 sudoPathWithParams = sudoPath
1953 if preserveSudoContext:
1954 sudoPathWithParams = '%s %s' % (sudoPath, '-E')
1955 separator = self.getShellCmdSeperator()
1956
1957 if self.__shouldAllCommandsRunAsSuperUser():
1958 if self.__sudoExcludeCommandMatcher.match(originalCommand):
1959 logger.debug('Command is in excluded for sudo commands list. Sudo will not be added.')
1960 return originalCommand
1961 logger.debug('Both credentials and destination are configured to run all commands as Super User.')
1962 return '%s %s -c "%s"' % (sudoPathWithParams, self.getShell(), re.sub(r'(?<!\\)"', r'\\"', originalCommand))
1963
1964 splitPattern = self.__sudoSplitPattern % re.escape(separator)
1965 commandElements = re.split(splitPattern, originalCommand)
1966 for i in range(0, len(commandElements)):
1967 command = commandElements[i]
1968 if not command or re.match(splitPattern, command):
1969
1970 continue
1971 if self.__shouldCommandElemRunAsSuperUser(command):
1972 if self.__isCommandConfiguredOnDestination(command):
1973 logger.debug("Command %s will be prefixed with %s" % (command, sudoPathWithParams))
1974 command = "%s %s" % (sudoPathWithParams, command)
1975 else:
1976 logger.warn('Command %s matches the UCMDB privileged command patterns but is not in the sudo list on the destination.' % command)
1977 commandElements[i] = command
1978
1979 return ''.join(commandElements)
1980
1982 '@types: -> str'
1983 if self.__sudoPath is not None:
1984 return self.__sudoPath
1985 else:
1986 if (not self.__sudoPathsArray or not(len(self.__sudoPathsArray) > 0)):
1987 self.__sudoPath = ''
1988 else:
1989 for path in self.__sudoPathsArray:
1990 cmdWithRc = '%s%secho %s' % (path + ' -V', self.getShellCmdSeperator(), self.getShellStatusVar())
1991 logger.debug('__getSudoPath: checking "%s" command' % cmdWithRc)
1992 buff = self.__client.executeCmd(cmdWithRc, 0, 0)
1993 if (buff is None):
1994 logger.debug('__getSudoPath: execution of %s failed - command produced no output and no return status' % cmdWithRc)
1995 else:
1996 keepends = 1
1997 resLines = buff.strip().splitlines(keepends)
1998 lastLineNum = len(resLines) - 1
1999
2000 if (lastLineNum < 0):
2001 logger.debug('__getSudoPath: no output was received for %s - proceeding to check next path' % cmdWithRc)
2002 continue
2003 lastLine = resLines[lastLineNum].strip()
2004 try:
2005 lastCmdReturnCode = int(lastLine.strip())
2006
2007 if lastCmdReturnCode == 0:
2008 logger.debug("__getSudoPath: execution of '%s' succeeded - setting it as sudo path" % cmdWithRc)
2009 self.__sudoPath = path
2010 return self.__sudoPath
2011 except:
2012 logger.debug('__getSudoPath: error parsing return code for command: %s=> returned output: %s' % (cmdWithRc, lastLine))
2013 continue
2014 logger.debug('__getSudoPath: none of the supplied sudo paths is valid - proceeding without sudo support')
2015 self.__sudoPath = ''
2016 return self.__sudoPath
2017
2019 '''Indicates whether object by specified path exists on remote file system
2020 @types: str -> bool
2021 @command: if [ -d \"%s\" ]; then echo true ; else echo false; fi
2022 @command: if [ -f \"%s\" ]; then echo true ; else echo false; fi
2023 @deprecated: Use methods from file system module instead'''
2024 if path:
2025 output = self.execCmd("if [ -d \"%s\" ]; then echo true ; else echo false; fi" % path)
2026 if output.find('true') > -1:
2027 return 1
2028 output = self.execCmd("if [ -f \"%s\" ]; then echo true ; else echo false; fi" % path)
2029 if output.find('true') > -1:
2030 return 1
2031
2032 - def safecat(self, path, forceSudo=0):
2033 ''' Get content of file by specified path
2034 @types: str, bool -> str
2035 @param forceSudo:if true, always uses sudo, if false first tries to run command without sudo
2036 @command: cat <path>
2037 @raise ValueError: Illegal cat command, contains redirect
2038 @raise EnvironmentError: sudo for cat is not available on server
2039 @raise Exception: Failed getting contents of file
2040 '''
2041
2042 if re.search('>', path):
2043
2044 logger.error('Illegal cat command, contains redirect: [%s]' % path)
2045 raise ValueError('Illegal cat command, contains redirect')
2046
2047 path = self.rebuildPath(path)
2048
2049
2050 cmd = 'cat %s' % path
2051 self.lastExecutedCommand = cmd
2052 if not forceSudo:
2053 fileContents = self.execCmd(cmd, useSudo=0)
2054 if not self.getLastCmdReturnCode():
2055 return fileContents
2056 fileContents = self.execCmd(cmd)
2057 if not self.getLastCmdReturnCode():
2058 return fileContents
2059 else:
2060 m = re.search('you do not have access', fileContents.lower())
2061 if m is not None:
2062 raise EnvironmentError('sudo for cat is not implemented on server')
2063 elif re.search('not found', fileContents.lower()):
2064 raise EnvironmentError('sudo is not available on server')
2065 else:
2066 logger.warn('Failed getting contents of %s file' % path)
2067 raise Exception('Failed getting contents of file')
2068
2070 ''' Normalize path to one used in OS client connected to
2071 @types: str -> str
2072 @deprecated: Use file system module for such purposes
2073 '''
2074 return re.sub('\\\\', '/', folder)
2075
2076
2078 r''' Extract output and return code information by splitting output into
2079 two parts by ERROR_CODE_PREFIX substring, used in unix shell
2080 @types: str -> (str, int)
2081 @raise ValueError: No return code information found
2082 '''
2083 errCodeIndex = buffer.rfind(UnixShell.ERROR_CODE_PREFIX)
2084 if errCodeIndex != -1:
2085 output, errorCode = buffer, Shell.NO_CMD_RETURN_CODE_ERR_NUMBER
2086 output = buffer[:errCodeIndex]
2087 lastLine = buffer[errCodeIndex:].strip()
2088 returnCodeStr = lastLine[len(UnixShell.ERROR_CODE_PREFIX):]
2089 try:
2090 errorCode = int(returnCodeStr)
2091 except:
2092 logger.debug("Failed to process errorcode value: %s" % returnCodeStr)
2093 return (output, errorCode)
2094 raise ValueError("No return code information found")
2095
2096
2103
2104
2106 '''Shell for Virtual I/O Server
2107 ( part of the IBM eServer p5 Advanced Power Virtualization hardware feature)'''
2108
2110 ''' Prepare passed command line to run as padmin user
2111 @types: str -> str'''
2112 return 'ioscli %s' % cmdLine
2113
2115 ''' Run command as padmin user, using command ioscli
2116 @types: str -> str'''
2117 return self.execCmd(self.__prepareCmd(cmdLine), *args, **kwargs)
2118
2120 """ Get OS type
2121 @types: -> str
2122 @command: uname
2123 @raise Exception: Failed getting machine OS type.
2124 """
2125
2126 osBuff = self.execIoscliCmd('uname')
2127 if (self.getLastCmdReturnCode() == 0):
2128 return osBuff.strip()
2129 raise Exception('Failed getting machine OS type.')
2130
2132 ''' Get OS version
2133 @types: -> str
2134 @command: uname -r
2135 @raise Exception: Failed getting OS version.
2136 '''
2137 buffer = self.execIoscliCmd('uname -r')
2138 if (self.getLastCmdReturnCode() == 0):
2139 return buffer
2140 raise Exception('Failed getting os version. command="ioscli uname -r" failed with rc=%d' % (self.getLastCmdReturnCode()))
2141
2142
2144 '@types: str, str, Framework -> bundle'
2145 languageName = language.bundlePostfix
2146 return framework.getEnvironmentInformation().getBundle(baseName, languageName)
2147
2148
2150 ''' Read file on the probe machine by the specified path
2151 @types: str, str -> str or None
2152 @deprecated: Use methods from file system module instead
2153 @raise ValueError: specified localFilePath is empty
2154 '''
2155 if not localFilePath:
2156 raise ValueError("localFilePath is empty")
2157 fileObject = None
2158 try:
2159 fileObject = codecs.open(localFilePath, "r", encoding)
2160 return fileObject.read()
2161 finally:
2162 if fileObject is not None:
2163 try:
2164 fileObject.close()
2165 except:
2166 pass
2167
2168
2170 ''' Delete file on the probe machine by the specified path
2171 @types: str -> bool
2172 @deprecated: Use methods from file system module instead
2173 @raise ValueError: specified localFilePath is empty
2174 '''
2175 if not localFilePath:
2176 raise ValueError("localFilePath is empty")
2177 try:
2178 file_ = File(localFilePath)
2179 return file_.delete()
2180 except:
2181 logger.debugException("Failed deleting file '%s'\n" % localFilePath)
2182