From 72324c513db7ec0f5338a1abe04d85642587e618 Mon Sep 17 00:00:00 2001 From: Luciano Resende Date: Mon, 23 Jan 2017 19:57:25 -0800 Subject: Python doc for classes and methods --- python/config.py | 10 ++++++++++ python/lifecycle.py | 34 ++++++++++++++++++++++++++++++---- python/toree_manager.py | 45 ++++++++++++++++++++++++++++++++++----------- python/toree_profile.py | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 15 deletions(-) diff --git a/python/config.py b/python/config.py index e7e69ea..479f165 100644 --- a/python/config.py +++ b/python/config.py @@ -19,6 +19,16 @@ import os.path import configparser class ConfigManager: + """ + Simple configuration manager + + This expects TOREE_GATEWAY_HOME environment variable + to be set and will look for the config file in + TOREE_GATEWAY_HOME/conf/toree-gateway.properties + + In dev environment, it will fallback to reading + the config file + """ config = configparser.RawConfigParser() homePath = os.getcwd()[:-7] configPath = None diff --git a/python/lifecycle.py b/python/lifecycle.py index 39e1638..bbc58d2 100644 --- a/python/lifecycle.py +++ b/python/lifecycle.py @@ -22,6 +22,15 @@ from config import * from toree_manager import * class LifecycleManager: + """ + A Orchestrator for Toree Lifecycle which select an available + toree sloot, reserv it and start/stop when notebooks are + started/stopped. + + Open slots are identified by a not having a toree.pid. In case + of corruption or a requirement to kill the toree process, one + should also remove the toree.id from the specific Toree slot. + """ configManager = None toreeManager = None @@ -31,8 +40,9 @@ class LifecycleManager: def _reserve_profile(self): """ - Tries to reserv a profile configuration to access Toree - :return: the reserved profile folder location, or None + Tries to reserve an available toree slot + + :return: the reserved Toree slot or None """ profilesFolder = self.configManager.getProfilesFolder() profile = None @@ -53,12 +63,23 @@ class LifecycleManager: return profile def _release_profile(self, profile): + """ + Release the provided Toree slot + + :param profile: the Toree slot that was previously reserved + :return: None + """ profile.release() def start_toree(self): """ - Reserve a profile to use, and start a remote Toree instance with that configuration - :return: the path to the configuration file (profile.json) to use when connecting + Reserve a open Toree slot, and start a remote Toree + instance with the configuration provided + + :return: the path to the Toree configuration file + (profile.json) which was used to start Toree. A + runtime error is thrown in case of no more available + Toree slots. """ profile = self._reserve_profile() if profile is None: @@ -68,6 +89,11 @@ class LifecycleManager: return profile def stop_toree(self, profile): + """ + Stop remote Toree instance and release Toree slot + :param profile: the toree slot that was previously reserved + :return: None + """ self.toreeManager.stop_toree(profile) self._release_profile(profile) diff --git a/python/toree_manager.py b/python/toree_manager.py index 996ad9e..2784067 100644 --- a/python/toree_manager.py +++ b/python/toree_manager.py @@ -31,12 +31,20 @@ from toree_profile import * from config import * class ToreeManager: + """ + A Helper class that enables connecting to a remote machine + via SSH and properly start/stop Toree instances + """ configManager = None def __init__(self): self.configManager = ConfigManager() - def getSSHClient(self): + def _getSSHClient(self): + """ + Configure and initialize a SSH client + :return: a configured SSH client + """ client = SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) @@ -46,11 +54,14 @@ class ToreeManager: username=self.configManager.get('toree.username'), \ password=self.configManager.get('toree.password')) - #print('Client connected successfuly') - return client - def getSSHChannel(self, client): + def _getSSHChannel(self, client): + """ + Configure and initialize a new SSH session on the client + :param client: The client to initialize the session + :return: the new SSH session + """ channel = client.invoke_shell() channel.settimeout(20) channel.set_combine_stderr(True) @@ -58,9 +69,16 @@ class ToreeManager: return channel def start_toree(self, profile): + """ + Connect to a remote system via SSH and + start an instance of Toree + :param profile: The Toree slot to read profile.json + configuration file + :return: None + """ try: - client = self.getSSHClient() - channel = self.getSSHChannel(client) + client = self._getSSHClient() + channel = self._getSSHChannel(client) channel = client.invoke_shell() channel.settimeout(30) @@ -84,9 +102,6 @@ class ToreeManager: config['iopub_port'], \ config['hb_port']) - - #print(command) - stdin.write(command) pid = None @@ -114,9 +129,17 @@ class ToreeManager: print('all closed') def stop_toree(self, profile): + """ + Connect to a remote system via SSH and + stop the associated Toree instance based on the + process id information stored in toree.pid + :param profile: The Toree slot to read toree.pid + configuration file + :return: None + """ try: - client = self.getSSHClient() - channel = self.getSSHChannel(client) + client = self._getSSHClient() + channel = self._getSSHChannel(client) stdin = channel.makefile('w') stdout = channel.makefile('r') diff --git a/python/toree_profile.py b/python/toree_profile.py index eaadc9d..b306b76 100644 --- a/python/toree_profile.py +++ b/python/toree_profile.py @@ -21,6 +21,10 @@ import json import time class Profile: + """ + Abstract the handling of a toree slot providing access + to configuration, process id, and any manipulations + """ PROCESS_FILE_NAME = "toree.pid" CONFIGURATION_FILE_NAME = "profile.json" @@ -30,28 +34,57 @@ class Profile: self.profilePath = profilePath def pidLocation(self): + """ + The location for the pid file + :return: absolute path to pid file + """ return self.profilePath + '/' + self.PROCESS_FILE_NAME def configurationLocation(self): + """ + The location for the profile.json configuration file + :return: absolute path to the profile.json + """ return self.profilePath + '/' + self.CONFIGURATION_FILE_NAME def isAvailable(self): + """ + Weather or not the Toree slot is available + :return: true in case the slot is available (no pid file) + """ taken = os.path.exists(self.pidLocation()) return not taken def reserve(self): + """ + Reserve the slot profile by adding a pid file into it + :return: + """ open(self.pidLocation(), 'a').close() def release(self): + """ + Release the slot profile by removing the pid file from it + :return: + """ if os.path.exists(self.pidLocation()): os.remove(self.pidLocation()) def pid(self): + """ + The Toree process id + :return: the pid number or None + """ with open(self.pidLocation(), 'r') as pid_file: data = pid_file.read() return data def updatePid(self, pid): + """ + Update the contents of the pid file + :param pid: The pid value + :return: + """ try: file = open(self.pidLocation(), 'w') file.write(pid) @@ -59,6 +92,10 @@ class Profile: file.close def config(self): + """ + The parsed content of the profile.json + :return: + """ with open(self.configurationLocation(), 'r') as data_file: return json.load(data_file) #, object_hook=util._byteify -- cgit v1.2.3