mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	- Refactor IPv6 related tests - Adds smoke test for IPv4 network to IPv6 upgrade - Adds smoke test for IPv6 VPC Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
		
			
				
	
	
		
			217 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Licensed to the Apache Software Foundation (ASF) under one
 | |
| # or more contributor license agreements.  See the NOTICE file
 | |
| # distributed with this work for additional information
 | |
| # regarding copyright ownership.  The ASF licenses this file
 | |
| # to you under the Apache License, Version 2.0 (the
 | |
| # "License"); you may not use this file except in compliance
 | |
| # with the License.  You may obtain a copy of the License at
 | |
| #
 | |
| #   http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| # Unless required by applicable law or agreed to in writing,
 | |
| # software distributed under the License is distributed on an
 | |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 | |
| # KIND, either express or implied.  See the License for the
 | |
| # specific language governing permissions and limitations
 | |
| # under the License.
 | |
| 
 | |
| from paramiko import (BadHostKeyException,
 | |
|                       AuthenticationException,
 | |
|                       SSHException,
 | |
|                       SSHClient,
 | |
|                       AutoAddPolicy,
 | |
|                       Transport,
 | |
|                       SFTPClient)
 | |
| import socket
 | |
| import time
 | |
| from marvin.cloudstackException import (
 | |
|     internalError,
 | |
|     GetDetailExceptionInfo
 | |
| )
 | |
| import contextlib
 | |
| import logging
 | |
| from marvin.codes import (
 | |
|     SUCCESS, FAILED, INVALID_INPUT
 | |
| )
 | |
| 
 | |
| 
 | |
| class SshClient(object):
 | |
| 
 | |
|     '''
 | |
|     @Desc : SSH Library for Marvin.
 | |
|     Facilitates SSH,SCP services to marvin users
 | |
|     @Input: host: Host to connect
 | |
|             port: port on host to connect
 | |
|             user: Username to be used for connecting
 | |
|             passwd: Password for connection
 | |
|             retries and delay applies for establishing connection
 | |
|             timeout : Applies while executing command
 | |
|     '''
 | |
| 
 | |
|     def __init__(self, host, port, user, passwd, retries=60, delay=10,
 | |
|                  log_lvl=logging.DEBUG, keyPairFiles=None, timeout=10.0):
 | |
|         self.host = None
 | |
|         self.port = 22
 | |
|         self.user = user
 | |
|         self.passwd = passwd
 | |
|         self.keyPairFiles = keyPairFiles
 | |
|         self.ssh = SSHClient()
 | |
|         self.ssh.set_missing_host_key_policy(AutoAddPolicy())
 | |
|         self.logger = logging.getLogger('sshClient')
 | |
|         self.retryCnt = 0
 | |
|         self.delay = 0
 | |
|         self.timeout = 3.0
 | |
|         self.ch = logging.StreamHandler()
 | |
|         self.ch.setLevel(log_lvl)
 | |
|         self.logger.addHandler(self.ch)
 | |
| 
 | |
|         # Check invalid host value and raise exception
 | |
|         # Atleast host is required for connection
 | |
|         if host is not None and host != '':
 | |
|             self.host = host
 | |
|         if retries is not None and retries > 0:
 | |
|             self.retryCnt = retries
 | |
|         if delay is not None and delay > 0:
 | |
|             self.delay = delay
 | |
|         if timeout is not None and timeout > 0:
 | |
|             self.timeout = timeout
 | |
|         if port is not None and port >= 0:
 | |
|             self.port = port
 | |
|         if self.createConnection() == FAILED:
 | |
|             raise internalError("SSH Connection Failed")
 | |
| 
 | |
|     def execute(self, command):
 | |
|         stdin, stdout, stderr = self.ssh.exec_command(command)
 | |
|         output = stdout.readlines()
 | |
|         errors = stderr.readlines()
 | |
|         results = []
 | |
|         if output is not None and len(output) == 0:
 | |
|             if errors is not None and len(errors) > 0:
 | |
|                 for error in errors:
 | |
|                     results.append(error.rstrip())
 | |
| 
 | |
|         else:
 | |
|             for strOut in output:
 | |
|                 results.append(strOut.rstrip())
 | |
|         self.logger.debug("{Cmd: %s via Host: %s} {returns: %s}" %
 | |
|                           (command, str(self.host), results))
 | |
|         return results
 | |
| 
 | |
|     def createConnection(self):
 | |
|         '''
 | |
|         @Name: createConnection
 | |
|         @Desc: Creates an ssh connection for
 | |
|                retries mentioned,along with sleep mentioned
 | |
|         @Output: SUCCESS on successful connection
 | |
|                  FAILED If connection through ssh failed
 | |
|         '''
 | |
|         ret = FAILED
 | |
|         except_msg = ''
 | |
|         while self.retryCnt >= 0:
 | |
|             try:
 | |
|                 self.logger.debug("====Trying SSH Connection: Host:%s User:%s\
 | |
|                                    Port:%s RetryCnt:%s===" %
 | |
|                                   (self.host, self.user, str(self.port),
 | |
|                                    str(self.retryCnt)))
 | |
|                 if self.keyPairFiles is None:
 | |
|                     self.ssh.connect(hostname=self.host,
 | |
|                                      port=self.port,
 | |
|                                      username=self.user,
 | |
|                                      password=self.passwd,
 | |
|                                      timeout=self.timeout,
 | |
|                                      allow_agent=False)
 | |
|                 else:
 | |
|                     self.ssh.connect(hostname=self.host,
 | |
|                                      port=self.port,
 | |
|                                      username=self.user,
 | |
|                                      password=self.passwd,
 | |
|                                      key_filename=self.keyPairFiles,
 | |
|                                      timeout=self.timeout,
 | |
|                                      look_for_keys=False
 | |
|                                      )
 | |
|                 self.logger.debug("===SSH to Host %s port : %s SUCCESSFUL==="
 | |
|                                   % (str(self.host), str(self.port)))
 | |
|                 ret = SUCCESS
 | |
|                 break
 | |
|             except BadHostKeyException as e:
 | |
|                 except_msg = GetDetailExceptionInfo(e)
 | |
|             except AuthenticationException as e:
 | |
|                 except_msg = GetDetailExceptionInfo(e)
 | |
|             except SSHException as e:
 | |
|                 except_msg = GetDetailExceptionInfo(e)
 | |
|             except socket.error as e:
 | |
|                 except_msg = GetDetailExceptionInfo(e)
 | |
|             except Exception as e:
 | |
|                 except_msg = GetDetailExceptionInfo(e)
 | |
|             finally:
 | |
|                 if self.retryCnt == 0 or ret == SUCCESS:
 | |
|                     break
 | |
|                 if except_msg != '':
 | |
|                     self.logger.\
 | |
|                         exception("SshClient: Exception under "
 | |
|                                   "createConnection: %s" % except_msg)
 | |
|                 self.retryCnt -= 1
 | |
|                 time.sleep(self.delay)
 | |
|         return ret
 | |
| 
 | |
|     def runCommand(self, command):
 | |
|         '''
 | |
|         @Name: runCommand
 | |
|         @Desc: Runs a command over ssh and
 | |
|                returns the result along with status code
 | |
|         @Input: command to execute
 | |
|         @Output: 1: status of command executed.
 | |
|                  SUCCESS : If command execution is successful
 | |
|                  FAILED    : If command execution has failed
 | |
|                  2: stdin,stdout,stderr values of command output
 | |
|         '''
 | |
|         ret = {"status": FAILED, "stdin": None, "stdout": None,
 | |
|                "stderr": INVALID_INPUT}
 | |
|         if command is None or command == '':
 | |
|             return ret
 | |
|         try:
 | |
|             status_check = 1
 | |
|             stdin, stdout, stderr = self.ssh.\
 | |
|                 exec_command(command, timeout=self.timeout)
 | |
|             if stdout is not None:
 | |
|                 status_check = stdout.channel.recv_exit_status()
 | |
|                 if status_check == 0:
 | |
|                     ret["status"] = SUCCESS
 | |
|                 ret["stdout"] = stdout.readlines()
 | |
|                 if stderr is not None:
 | |
|                     ret["stderr"] = stderr.readlines()
 | |
|         except Exception as e:
 | |
|             ret["stderr"] = GetDetailExceptionInfo(e)
 | |
|             self.logger.exception("SshClient: Exception under runCommand :%s" %
 | |
|                                   GetDetailExceptionInfo(e))
 | |
|         finally:
 | |
|             self.logger.debug(" Host: %s Cmd: %s Output:%s" %
 | |
|                               (self.host, command, str(ret)))
 | |
|             return ret
 | |
| 
 | |
|     def scp(self, srcFile, destPath):
 | |
|         transport = Transport((self.host, int(self.port)))
 | |
|         transport.connect(username=self.user, password=self.passwd)
 | |
|         sftp = SFTPClient.from_transport(transport)
 | |
|         try:
 | |
|             sftp.put(srcFile, destPath)
 | |
|         except IOError as e:
 | |
|             raise e
 | |
| 
 | |
|     def __del__(self):
 | |
|         self.close()
 | |
| 
 | |
|     def close(self):
 | |
|         if self.ssh is not None:
 | |
|             self.ssh.close()
 | |
|             self.ssh = None
 | |
|         if self.ch is not None:
 | |
|             self.logger.removeHandler(self.ch)
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     with contextlib.closing(SshClient("127.0.0.1", 22, "root",
 | |
|                                       "asdf!@34")) as ssh:
 | |
|         ret = ssh.runCommand("ls -l")
 | |
|         print(ret)
 |