def test_smtp_login_expect_reject(self): message = EmailMessage() message["From"] = "*****@*****.**" message["To"] = "*****@*****.**" message["Subject"] = "Test" machine: pb.SshMachine = pb.SshMachine(host="remote.example.com", user="******", keyfile="~/.ssh/id_rsa") server = DeployedServer(machine) connection: rpyc.Connection = server.classic_connect() with connection.modules.smtplib.SMTP("mail.example.com") as smtp: with self.assertRaises(smtplib.SMTPNotSupportedError) as e: smtp.login(user="******", password="******") smtp.send_message(message, from_addr="*****@*****.**", to_addrs="*****@*****.**") self.assertIn("SMTP AUTH extension not supported by server", str(e.exception), msg=str(e.exception)) connection.close() server.close() machine.close()
def test_login_mailaddress_starttls_wrong_credentials_expect_rejected( self): message = EmailMessage() message["From"] = "*****@*****.**" message["To"] = "*****@*****.**" message["Subject"] = "Test" machine: pb.SshMachine = pb.SshMachine(host="remote.example.com", user="******", keyfile="~/.ssh/id_rsa") server = DeployedServer(machine) connection: rpyc.Connection = server.classic_connect() with connection.modules.smtplib.SMTP("mail.example.com", 587) as smtp: smtp.starttls() with self.assertRaises(smtplib.SMTPAuthenticationError) as e: smtp.login(user="******", password="******") self.assertIn("Error: authentication failed", str(e.exception), msg=str(e.exception)) connection.close() server.close() machine.close()
def mapleDeployment(host, loacalMaple, loaclMapleHandler, loaclMapleDataMerger, loaclGetDestination): # create the deployment mach = SshMachine(host, user="******", keyfile="/home/zitongc2/.ssh/id_rsa") server = DeployedServer(mach) # and now you can connect to it the usual way conn = server.classic_connect() print("[INFO] Connected to ", host) conn._config['sync_request_timeout'] = None def getResult(string): print(string) remoteMaple = conn.teleport(loacalMaple) remoteMapleHandler = teleport_function(conn, loaclMapleHandler) remoteMapleHandler(remoteMaple, "/home/zitongc2/test/phase0/input", getResult) # print("[INFO] Done processing, now sendind result to desinated location") remoteMapleDataMerger = teleport_function(conn, loaclMapleDataMerger) remoteMapleDataMerger(loaclGetDestination) # when you're done - close the server and everything will disappear print("[INFO] done") server.close()
class SshHost(BaseHost): def __init__(self, **kwargs): BaseHost.__init__(self, **kwargs) self._mach = None self.deployment = None def connect(self): if self.deployment is None: self._mach = SshMachine(**self.kwargs) self.deployment = DeployedServer(self._mach) return self.deployment.classic_connect() def close(self): if self.deployment is not None: self.deployment.close() self._mach.close()
def create_remote_node(self, hostname, username, keyfile, ntype, addr, config=None): if config is None: config = {} remote_machine = SshMachine(host=hostname, user=username, keyfile=keyfile) remote_server = DeployedServer(remote_machine) conn = remote_server.classic_connect() site = conn.modules.site python_pkg_path = site.getsitepackages()[0] # if `asgrids` wasn't available remotely, now we installed it # but we need to reconnect to get an updated conn.modules # TODO Might not be needed if using execute/eval if not self.check_remote(remote_server, python_pkg_path): remote_server.close() remote_server = DeployedServer(remote_machine) self.remote_machines.append(remote_machine) self.remote_servers.append(remote_server) conn = remote_server.classic_connect() serving_thread = BgServingThread(conn) self.server_threads.append(serving_thread) self.conns[addr] = conn # Using execute/eval allows working on a remote single namespace # useful when teleporting functions that need using remote object names # as using conn.modules create a locate but not a remote namespace member if ntype is 'load': conn.execute("from asgrids import NetworkLoad") conn.execute("node=NetworkLoad()") conn.execute("node.local='{}'".format(addr)) node = conn.namespace['node'] elif ntype is 'allocator': conn.execute("from asgrids import NetworkAllocator") conn.execute("node=NetworkAllocator()") node = conn.namespace['node'] else: raise ValueError("Can't handle ntype == {}".format(ntype)) self.nodes[addr] = node # Return node netref object and rpyc connection return node, conn
class RPyCConnection(BaseConnection): """RPyC wrapper for component connection. In case the machine doesn't already run SlaveService, we will try to use SSH to upload and deploy RPyC SlaveService. """ def __init__(self, hostname: str, username: Optional[str] = None, password: Optional[str] = None) -> None: """Connects (or start with SSH if needed) to RPyC remote SlaveService. Connect to RPyC SlaveService on remote machine. If the service isn't running, try to deploy it with SSHConnection and RPyC zero deploy library. Args: hostname: The hostname of the component we want to connect to. username: Username for SSH login (if needed). password: Password for SSH login (if needed). """ self._server = None try: # Checks if the machine already runs RPyC SlaveService. self._connection = rpyc.classic.connect(hostname, keepalive=True) except ConnectionRefusedError: if username is None or password is None: # Not given necessary SSH credentials. raise with SSHConnection(hostname, username, password) as ssh: # Upload RPyC and start SlaveService in a temporarily directory. self._server = DeployedServer(ssh.shell) # pylint: disable=no-member self._connection = self._server.classic_connect() @property def rpyc(self) -> rpyc.Connection: """The RPyc connection to component.""" return self._connection def close(self) -> None: """Closes RPyC connections.""" self._connection.close() if self._server is not None: self._server.close()
def test_login_username_smtps_expect_pass(self): message = EmailMessage() message["From"] = "*****@*****.**" message["To"] = "*****@*****.**" message["Subject"] = "Test" machine: pb.SshMachine = pb.SshMachine(host="remote.example.com", user="******", keyfile="~/.ssh/id_rsa") server = DeployedServer(machine) connection: rpyc.Connection = server.classic_connect() with connection.modules.smtplib.SMTP_SSL("mail.example.com", 465) as smtp: smtp.login(user="******", password="******") connection.close() server.close() machine.close()
def juiceDeployment(host, loacalJuice, loaclJuiceHandler, localJuiceDataMerger): # create the deployment mach = SshMachine(host, user="******", keyfile="/home/zitongc2/.ssh/id_rsa") server = DeployedServer(mach) # and now you can connect to it the usual way conn = server.classic_connect() print("[INFO] Connected to ", host) conn._config['sync_request_timeout'] = None remoteJuice = conn.teleport(loacalJuice) remoteMapleHandler = teleport_function(conn, loaclJuiceHandler) remoteMapleHandler(remoteJuice) print("[INFO] Done processing, now sendind result to desinated location") remoteJuiceDataMerger = teleport_function(conn, localJuiceDataMerger) remoteJuiceDataMerger(socket.gethostbyname(socket.gethostname())) # when you're done - close the server and everything will disappear server.close()
def test_logged_out_starttls_expect_client_host_rejected(self): message = EmailMessage() message["From"] = "*****@*****.**" message["To"] = "*****@*****.**" message["Subject"] = "Test" machine: pb.SshMachine = pb.SshMachine(host="remote.example.com", user="******", keyfile="~/.ssh/id_rsa") server = DeployedServer(machine) connection: rpyc.Connection = server.classic_connect() with connection.modules.smtplib.SMTP("mail.example.com", 587) as smtp: smtp.starttls() with self.assertRaises(smtplib.SMTPRecipientsRefused) as e: smtp.send_message(message, from_addr="*****@*****.**", to_addrs="*****@*****.**") self.assertIn("Client host rejected: Access denied", str(e.exception)) connection.close() server.close() machine.close()
class Controller: """ Stores connection variables and perfoms monitoring and data syncing functions """ def __init__(self, username, ipaddress): # Connection Parameters self.user = username self.ip = ipaddress # Connection Resources self.nxTunnel = None self.nxServer = None self.nxConnA = None self.nxConnB = None self.rest = vellosREST(ipaddress) # Extend logger of parent script importing this module self.logger = logging.getLogger('vBrokerLog.controller.Controller') # Resources local to controller self.pdb = '/var/lib/pdb/pdb-rest.db' # Flag when monitored proc/s or system has failed self.has_failed = Event() def __enter__(self): self.connect() def __exit__(self, exc_type, exc_value, traceback): self.close() def to_dict(self): """Return dict of crucial attributes""" controller_dict = { 'user_name' : self.user, 'ip_address': self.ip } return controller_dict def _execute(self, cmd): """Execute shell command """ try: if self.is_connected(): self.nxConnA.modules.subprocess.check_call(cmd) else: return False except subprocess.CalledProcessError: return False return True def connect(self): """Initiate ssh tunnel & rpyc server""" self.logger.info('Opening connection @%s'%self.ip) try: with RLock(): self.nxTunnel = SshMachine(self.ip,self.user) self.nxServer = DeployedServer(self.nxTunnel) self.nxConnA = self.nxServer.classic_connect() self.nxConnB = self.nxServer.classic_connect() except Exception: self.logger.error('Failed opening @%s' % self.ip) self.logger.info('Successfully connected @%s'%self.ip) def close(self): """Close ssh tunnel % destroy rpyc server""" self.logger.info('Closing connection @%s'%self.ip) try: self.nxServer.close() except Exception as e: self.logger.error('Failed closing @%s - %s'%(self.ip,e)) def is_connected(self): """Test if ssh tunnel & rpyc connection is active""" try: with RLock(): self.nxConnA.ping() #self.nxConnB.ping() except: return False return True def ping(self): """Ping controller""" cmd = ['ping','-c','1',self.ip] try: self.logger.info('Pinging @%s'%self.ip) with open(os.devnull, 'w') as devnull: subprocess.check_call(cmd,stdout=devnull) except: self.logger.error('Failed to ping @%s'%self.ip) return False return True def assert_connection(self): """Monitor connection, attempt reconnect if down""" if not self.is_connected(): self.logger.error('lost connection @%s'%self.ip) if self.ping(): self.logger.info('ping @%s succeeded'% self.ip) try: if not self.is_connected(): self.logger.debug('still not connected') self.close() self.connect() self.logger.debug('connection found') self.control_plane_down() except: with RLock(): self.has_failed.set() return False self.logger.error('reconnect @%s fail'% self.ip) else: with RLock(): self.has_failed.set() return False else: return True def monitor(self, procs, interval, kill_monitor): """Monitor processes and exit if failure""" watch = Watch( self, procs, interval, kill_monitor, self.has_failed ) watch.run() def sync(self, dst, event): """Sync pdb-rest.db to to local target""" pdbsync = Sync( self, dst, event) pdbsync.run() def restore(self, nodes, flows): """Install data using REST, ignore if error""" self.logger.info('Restoring nodes @%s'%self.ip) for node_id, node in nodes.iteritems(): snode = json.dumps(node) try: self.logger.debug('Installing node: %s'%snode) self.rest.putNode(node_id, snode) except Exception as e: self.logger.debug('%s - %s'%(node_id,e)) pass self.logger.info('Restoring flows @%s'%self.ip) for flow_id, flow in flows.iteritems(): sflow = json.dumps(flow) try: self.logger.debug('Installing flow: %s'%sflow) self.rest.putFlow(flow_id, json.dumps(flow)) except Exception as e: self.logger.error('%s - %s'%(flow_id,e)) pass return True def remove(self, nodes, flows): """Remove data using REST, ignore if error""" self.logger.info('Removing data @%s'%self.ip) for flow_id, flow in flows.iteritems(): sflow = json.dumps(flow) try: self.logger.debug('Removing flow: %s'%sflow) self.rest.deleteFlow(flow_id) except Exception as e: self.logger.error('%s - %s'%(flow_id,e)) pass for node_id, node in nodes.iteritems(): snode = json.dumps(node) try: self.logger.debug('Removing node: %s'%snode) self.rest.deleteNode(node_id) except Exception as e: self.logger.error('%s - %s'%(node_id,e)) pass return True def diff_switches(self, switches): """Diff passed in switches with ones in inventory""" self.logger.info('Diffing Switches @%s'%self.ip) try: active_switches = self.rest.getSwitchNames()['items'] except Exception as e: self.logger.error('Could not get switches: %s'%e) return set(switches) <= set(active_switches) def control_plane_up(self): """Bring control plane interface up""" self.logger.info('Bringing up br0 @%s'%self.ip) up_cmd = ['/sbin/ifconfig', 'br0', 'up'] return self._execute(up_cmd) def control_plane_down(self): """Bring control plane interface down""" self.logger.info('Bringing down br0 @%s'%self.ip) down_cmd = ['/sbin/ifconfig', 'br0', 'down'] return self._execute(down_cmd)