@@ -32,21 +32,19 @@
del ConfigNode.ui_complete_bookmarks

# Custom modules
import string_ops
import ui_methods as ui
from . import cfg
from . import string_ops as c
from . import ui_methods as ui
try:
import ravello_sdk
from . import ravello_sdk
ravello_sdk.is_rsaw_sdk()
except:
print("Missing proper version of required python module (rsaw's ravello_sdk)\n"
"Get it from https://github.com/ryran/python-sdk/blob/ravshello-stable/lib/ravello_sdk.py\n")
raise

# Globals
user = c = rOpt = rClient = rCache = appnamePrefix = None
defaultAppExpireTime = 120
defaultAppExtendTime = 60
maxLearnerExtendTime = 120
# Set aside globals that will be used for code-clarity
rOpt = user = appnamePrefix = rClient = rCache = None


def is_admin():
@@ -85,14 +83,13 @@ def get_num_learner_active_vms(learner):
return activeVms


def main(opt, client):
# Set some important globals
global rOpt, rClient, user, appnamePrefix, c, rCache
rOpt = opt
rClient = client
user = rOpt.user
def main():
# Set aside globals that will be used for code-clarity
global rOpt, user, appnamePrefix, rClient, rCache
rOpt = cfg.opts
user = cfg.user
appnamePrefix = 'k:{}__'.format(user)
c = rOpt.c
rClient = cfg.rClient
rCache = ui.RavelloCache(rClient)
# Clear preferences if asked via cmdline arg
if rOpt.clearPreferences:
@@ -104,7 +101,7 @@ def main(opt, client):
shell.prefs['prompt_length'] = 0
shell.prefs['tree_show_root'] = True
shell.prefs['tree_status_mode'] = True
if not rOpt.enableColor:
if not c.enableColor:
shell.prefs['color_mode'] = False
if not rOpt.showAllApps:
# Turn off max depth restriction for admins in restricted-view mode
@@ -137,15 +134,15 @@ def main(opt, client):
else:
# What to do when not admin
if rOpt.cmdlineArgs or rOpt.scriptFile:
print(c.red("Sorry! Only admins are allowed to use ravshello non-interactively\n"))
print(c.red("Sorry! Only admins are allowed to use {} non-interactively\n".format(cfg.prog)))
return
try:
# Plan was to flush sys.stdin with this, per
# http://abelbeck.wordpress.com/2013/08/29/clear-sys-stdin-buffer/
# It always throws exception though, so I decided to just use it to quit
termios.tcflush(stdin, termios.TCIOFLUSH)
except:
print(c.red("Sorry! Only admins are allowed to use ravshello non-interactively\n"))
print(c.red("Sorry! Only admins are allowed to use {} non-interactively\n".format(cfg.prog)))
return
# Initial usage hints
print(c.BOLD("Instructions:"))
@@ -496,8 +493,8 @@ def ui_command_search_notifications(self, appId=None, maxResults=500,
Ravello always does times in a non-standard way, where the thousandths
of a second are always present, but there's no delimiting decimal place,
as is customary. ...
This ravshello function compensates for you by appending 3 zeroes to the
end of any number you pass (so basically, don't worry about it).
This function compensates for you by appending 3 zeroes to the end of any
number you pass (so basically, don't worry about it).
"""
print()
maxResults = self.ui_eval_param(maxResults, 'number', 500)
@@ -1413,7 +1410,7 @@ def __init__(self, bpName, parent, bp):
self.bpId = bp['id']
self.bpOwner = bp['owner']
self.creationTime = datetime.fromtimestamp(int(str(bp['creationTime'])[:-3]))
if bp.has_key('description') and any(tag in bp['description'] for tag in rOpt.learnerBlueprintTag):
if bp.has_key('description') and any(tag in bp['description'] for tag in cfg.learnerBlueprintTag):
self.isLearnerBp = True
parent.numberOfLearnerBps += 1
else:
@@ -1658,7 +1655,7 @@ def ui_command_DELETE_ALL(self, noconfirm='false'):
try:
self.get_child(appName).delete_app()
except:
print(c.yellow("\nThere is a new application available to you since you started ravshello!"))
print(c.yellow("\nThere is a new application available to you since you started {}!".format(cfg.prog)))
print("To avoid deleting an app you cannot see, we've refreshed the apps for you ..." +
"You'll now need to re-run this command\n")
return
@@ -1708,7 +1705,7 @@ def ui_command_new(self, blueprint='@prompt', name='@prompt',
description = bp['description']
except:
description = ''
if is_admin() or any(tag in description for tag in rOpt.learnerBlueprintTag) or '#k:{}'.format(user) in description:
if is_admin() or any(tag in description for tag in cfg.learnerBlueprintTag) or '#k:{}'.format(user) in description:
allowedBlueprints.append(bp['name'])
if not allowedBlueprints:
print(c.red("\nThere are no blueprints available for you to base an application on!\n"))
@@ -1749,10 +1746,10 @@ def ui_command_new(self, blueprint='@prompt', name='@prompt',
aFixed = c.replace_bad_chars_with_underscores(a)
if a != aFixed:
print(c.red(
"\nNote that configshell (which ravshello uses) won't accept certain chars in paths\n"
"\nNote that configshell (which {} uses) won't accept certain chars in paths\n"
"Namely, only the following are allowed: A-Za-z0-9:_.-\n"
"In order handle apps with characters BESIDES those, one would have to use the\n"
"*interactive* cd command with arrow keys"))
"*interactive* cd command with arrow keys".format(cfg.prog)))
response = raw_input(c.CYAN("\nReplace bad characters with underscores? [y/N] "))
if response == 'y':
a = aFixed
@@ -1778,7 +1775,7 @@ def ui_command_new(self, blueprint='@prompt', name='@prompt',
else:
appDesc = desc

appDesc += "[Created w/ravshello {} by {}]".format(rOpt.ravshelloVersion.split()[1], user)
appDesc += "[Created w/{} {} by {}]".format(cfg.prog, cfg.__version__, user)

# Build request dictionary
req = {'name' : appName, 'description' : appDesc, 'baseBlueprintId': baseBlueprintId}
@@ -1813,7 +1810,7 @@ def ui_complete_new(self, parameters, text, current_param):
description = bp['description']
except:
description = ''
if is_admin() or any(tag in description for tag in rOpt.learnerBlueprintTag) or '#k:{}'.format(user) in description:
if is_admin() or any(tag in description for tag in cfg.learnerBlueprintTag) or '#k:{}'.format(user) in description:
allowedBlueprints.append(bp['name'])
completions = [a for a in allowedBlueprints
if a.startswith(text)]
@@ -1838,7 +1835,7 @@ def ui_complete_new(self, parameters, text, current_param):
description = bp['description']
except:
description = ''
if is_admin() or any(tag in description for tag in rOpt.learnerBlueprintTag) or '#k:{}'.format(user) in description:
if is_admin() or any(tag in description for tag in cfg.learnerBlueprintTag) or '#k:{}'.format(user) in description:
allowedBlueprints[bp['name']] = bp['id']
try:
bpid = allowedBlueprints[blueprint]
@@ -2001,10 +1998,10 @@ def ui_command_loop_query_status(self, desiredState=None,
if intervalSec < 5:
print(c.red("\nUsing minimum learner interval of 5 sec"))
intervalSec = 5
if totalMin > maxLearnerExtendTime:
if totalMin > cfg.maxLearnerExtendTime:
print(c.red("\nUsing maximum learner watch-time of {} min"
.format(maxLearnerExtendTime)))
totalMin = maxLearnerExtendTime
.format(cfg.maxLearnerExtendTime)))
totalMin = cfg.maxLearnerExtendTime
elif totalMin < 1:
print(c.red("\nUsing minimum learner watch-time of 1 min"))
totalMin = 1
@@ -2185,20 +2182,20 @@ def extend_autostop(self, minutes=60):
.format(minutes)))
rCache.purge_app_cache(self.appId)

def ui_command_extend_autostop(self, minutes=defaultAppExtendTime):
def ui_command_extend_autostop(self, minutes=cfg.defaultAppExtendTime):
"""
Set the application auto-stop time via *minutes*.
Defaults to 60 min (defaultAppExtendTime). Learners can set the
auto-stop timer from 0 to 120 min (maxLearnerExtendTime).
Admins can set any value, including '-1' which disables auto-stop timer.
"""
minutes = self.ui_eval_param(minutes, 'number', defaultAppExtendTime)
minutes = self.ui_eval_param(minutes, 'number', cfg.defaultAppExtendTime)
if not is_admin():
if minutes > maxLearnerExtendTime:
if minutes > cfg.maxLearnerExtendTime:
print(c.red("\nUsing maximum learner auto-stop time of {} minutes"
.format(maxLearnerExtendTime)))
minutes = maxLearnerExtendTime
.format(cfg.maxLearnerExtendTime)))
minutes = cfg.maxLearnerExtendTime
elif minutes < 0:
print(c.RED("\nInvalid learner auto-stop time\n"))
return
@@ -2322,15 +2319,15 @@ def ui_command_publish(self, region='@prompt', startAllVms='true'):
if not is_admin():
# Check that we don't have more published apps than we should
totalActiveVms = get_num_learner_active_vms(user)
if self.parent.numberOfPublishedApps >= rOpt.maxLearnerPublishedApps:
if self.parent.numberOfPublishedApps >= cfg.maxLearnerPublishedApps:
print(c.red("\nYou have reached or exceeded the maximum number ({}) of published apps!"
.format(rOpt.maxLearnerPublishedApps)))
.format(cfg.maxLearnerPublishedApps)))
print("Delete an app and try running command:")
print(c.BOLD(" /apps/{}/ publish\n".format(self.appName)))
return
elif totalActiveVms >= rOpt.maxLearnerActiveVms:
elif totalActiveVms >= cfg.maxLearnerActiveVms:
print(c.red("\nYou have reached or exceeded the maximum number ({}) of active VMs!"
.format(rOpt.maxLearnerActiveVms)))
.format(cfg.maxLearnerActiveVms)))
print("Stop a VM (or a whole application) and then try running command:")
print(c.BOLD(" /apps/{}/ start\n".format(self.appName)))
return
@@ -2376,7 +2373,7 @@ def ui_command_publish(self, region='@prompt', startAllVms='true'):
print(c.yellow("\nRavello now publishing your application (Could take a while)"))
# Configure auto-stop
if startAllVms:
self.extend_autostop(minutes=defaultAppExpireTime)
self.extend_autostop(minutes=cfg.defaultAppExpireTime)
self.loop_query_status(desiredState='STARTED')
else:
rCache.purge_app_cache(self.appId)
@@ -2411,13 +2408,13 @@ def ui_command_start(self):
if not is_admin():
# Check that we don't have more started VMs than we should
totalActiveVms = get_num_learner_active_vms(user)
if totalActiveVms >= rOpt.maxLearnerActiveVms:
if totalActiveVms >= cfg.maxLearnerActiveVms:
print(c.red("\nYou have reached or exceeded the maximum number ({}) of active VMs!\n"
.format(rOpt.maxLearnerActiveVms)))
.format(cfg.maxLearnerActiveVms)))
print("Stop a VM (or a whole application) and then try this again")
return
# Start out by setting autostop
self.extend_autostop(minutes=defaultAppExpireTime)
self.extend_autostop(minutes=cfg.defaultAppExpireTime)
try:
rClient.start_application(self.appId)
except:
@@ -2450,7 +2447,7 @@ def ui_command_restart(self):
"""
if not self.confirm_app_is_published():
return
self.extend_autostop(minutes=defaultAppExpireTime)
self.extend_autostop(minutes=cfg.defaultAppExpireTime)
try:
rClient.restart_application(self.appId)
except:
@@ -2622,7 +2619,7 @@ def ui_command_start(self):
return
if not self.confirm_vm_is_state('STOPPED'):
return
self.parent.parent.extend_autostop(minutes=defaultAppExtendTime)
self.parent.parent.extend_autostop(minutes=cfg.defaultAppExtendTime)
try:
rClient.start_vm(self.appId, self.vmId)
except:
@@ -1,6 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2015 Ravshello Authors
# Copyright 2015, 2017 Ravshello Authors
# License: Apache License 2.0 (see LICENSE or http://apache.org/licenses/LICENSE-2.0.html)

# Modules from standard library
@@ -16,18 +16,18 @@
import os

# Custom modules
import string_ops
from ui_methods import get_timestamp_proximity, sanitize_timestamp
from modules import string_ops as c
from modules.ui_methods import get_timestamp_proximity, sanitize_timestamp
try:
import ravello_sdk
from modules import ravello_sdk
ravello_sdk.is_rsaw_sdk()
except:
print("Missing proper version of required python module (rsaw's ravello_sdk)\n"
"Get it from https://github.com/ryran/python-sdk/blob/ravshello-stable/lib/ravello_sdk.py\n")
raise

# Globals
rClient = rOpt = c = appnamePrefix = None
rClient = rOpt = appnamePrefix = None


# Helper functions
@@ -167,9 +167,9 @@ def act_on_imminent_app_expiration(runningApps=[], thresholdSecs=5*60,

def main(argparseOptions):

global c, rOpt, appnamePrefix, rClient
global rOpt, appnamePrefix, rClient
rOpt = argparseOptions
c = string_ops.Printer(rOpt.enableColor)
c.enableColor = rOpt.enableColor
runningApps = []
timestamps = []

@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2015, 2017 Ravshello Authors
# License: Apache License 2.0 (see LICENSE or http://apache.org/licenses/LICENSE-2.0.html)

# Modules from standard library
from __future__ import print_function
@@ -25,10 +27,10 @@


# Custom modules
import string_ops
import ui_methods
from modules import string_ops as c
from modules import ui_methods, cfg
try:
import ravello_sdk
from modules import ravello_sdk
ravello_sdk.is_rsaw_sdk()
except:
print("Missing proper version of required python module (rsaw's ravello_sdk)\n"
@@ -60,22 +62,22 @@ def get_passphrase(prompt="Enter passphrase: ", defaultPass=None):
return passwd


c = string_ops.Printer()
print(c.magenta("Note, you should import with: from rav_debugsh import *"))
print(c.cyan("Assuming that, get started by running:"))
print(c.CYAN(" r,R,c = start()"))
print(c.CYAN(" r,R,c = go()"))

def start():
def go():
r = ravello_sdk.RavelloClient()
R = ui_methods.RavelloCache(r)
defaultCfgFile = os.path.join(cfg.defaultUserCfgDir, cfg.defaultUserCfgFile)
try:
with open(os.path.expanduser('~/.ravshello/config.yaml')) as f:
cfg = yaml.safe_load(f)
with open(os.path.expanduser(defaultCfgFile)) as f:
config = yaml.safe_load(f)
except:
user = passwd = None
else:
user = cfg.get('ravelloUser', None)
passwd = cfg.get('ravelloPass', None)
user = config.get('ravelloUser', None)
passwd = config.get('ravelloPass', None)

if not user:
user = get_username(c.CYAN("Enter Ravello username: "))
@@ -24,24 +24,21 @@
import sys

# Custom modules
import _version, string_ops, auth_local, auth_ravello, user_interface
from modules import string_ops as c
from modules import auth_local, auth_ravello, user_interface, cfg


def main():
"""Parse cmdline args, configure prefs, login, and start captive UI."""

ravshelloVersion = "ravshello v{} last mod {}".format(
_version.__version__, _version.__date__)

# Setup parser
prog = 'ravshello'
description = ("Interface with Ravello Systems to create & manage apps "
"hosted around the world")
epilog = ("Version info: {}\n"
"To report bugs/RFEs: github.com/ryran/ravshello/issues "
"or rsaw@redhat.com").format(ravshelloVersion)
"or rsaw@redhat.com").format(cfg.version)
p = argparse.ArgumentParser(
prog=prog, description=description, add_help=False, epilog=epilog,
prog=cfg.prog, description=description, add_help=False, epilog=epilog,
formatter_class=argparse.RawDescriptionHelpFormatter)

# Setup groups for help page:
@@ -70,24 +67,25 @@ def main():
'-n', '--nocolor', dest='enableColor', action='store_false',
help="Disable all color terminal enhancements")
grpU.add_argument('--cfgdir', dest='userCfgDir', metavar='CFGDIR',
default='~/.ravshello',
default=cfg.defaultUserCfgDir,
help=("Explicitly specify path to user config directory "
"(default: '~/.ravshello/')"))
"(default: '{}')".format(cfg.defaultUserCfgDir)))
grpU.add_argument('--cfgfile', dest='cfgFileName', metavar='CFGFILE',
default='config.yaml',
default=cfg.defaultUserCfgFile,
help=("Explicitly specify basename of optional yaml config file "
"containing login credentials, etc (default: 'config.yaml')"))
"containing login credentials, etc (default: '{}')"
.format(cfg.defaultUserCfgFile)))
grpU.add_argument(
'--clearprefs', dest='clearPreferences', action='store_true',
help="Delete prefs.bin in user config directory before starting")
grpU.add_argument(
'-q', '--quiet', dest='enableVerboseMessages', action='store_false',
'-q', '--quiet', dest='enableVerbose', action='store_false',
help="Hide verbose messages during startup")
grpU.add_argument(
'-d', '--debug', dest='enableDebugging', action='store_true',
help="Turn on debugging features to help troubleshoot a problem")
grpU.add_argument(
'-V', '--version', action='version', version=ravshelloVersion)
'-V', '--version', action='version', version=cfg.version)

# Admin-only opts:
grpA.add_argument(
@@ -108,27 +106,29 @@ def main():
"command to execute instead of entering the interactive shell"))

# Build out options namespace
cfg.opts = rOpt = p.parse_args()

rOpt = p.parse_args()
# Halp-quit
if rOpt.showHelp:
p.print_help()
sys.exit()

# Join together all cmdline args
rOpt.cmdlineArgs = " ".join(rOpt.cmdlineArgs)

rOpt.c = c = string_ops.Printer(rOpt.enableColor,
rOpt.enableVerboseMessages)
# Setup color/verbosity
c.enableColor = rOpt.enableColor
c.enableVerbose = rOpt.enableVerbose

# Trigger -a if -A was called
if rOpt.showAllApps:
rOpt.enableAdminFuncs = True

rOpt.ravshelloVersion = ravshelloVersion

# Expand userCfgDir in case of tildes; set to default if missing specified dir
if os.path.isdir(os.path.expanduser(rOpt.userCfgDir)):
rOpt.userCfgDir = os.path.expanduser(rOpt.userCfgDir)
else:
rOpt.userCfgDir = os.path.expanduser('~/.ravshello')
rOpt.userCfgDir = os.path.expanduser(cfg.defaultUserCfgDir)

try:
# Read yaml config to dictionary
@@ -148,20 +148,9 @@ def main():
else:
rOpt.cfgFile['sshKeyFile'] = None

# Learner mode can only create apps from blueprints which have
# one of these strings in their description
rOpt.learnerBlueprintTag = [
"#is_learner_blueprint",
"#learner_bp",
]

# More learner mode rules
rOpt.maxLearnerPublishedApps = 3
rOpt.maxLearnerActiveVms = 8

print(c.BOLD(
"Welcome to ravshello, "
"a shell to provision & manage machines with Ravello!"))
"Welcome to {}, "
"a shell to provision & manage machines with Ravello!".format(cfg.prog)))

# Liftoff
# 1.) Establish a local user name to use in ravshello
@@ -170,15 +159,14 @@ def main():
# - To construct names for new apps
# - To restrict which apps can be seen
# - To determine if admin functionality is unlockable (assuming -a or -A)
rOpt.user = auth_local.authorize_user(rOpt)
cfg.user = auth_local.authorize_user()

# 2.) Use ravello_sdk.RavelloClient() object to log in to Ravello
rClient = auth_ravello.login(rOpt)
cfg.rClient = auth_ravello.login()

# 3.) Launch the main configShell user interface
# Pass it the rOpt namespace full of all our options
# Also of course pass it the RavelloClient() object
user_interface.main(rOpt, rClient)
# It will read options and objects from the cfg module
user_interface.main()


if __name__ == '__main__':

This file was deleted.