Commit 6501cf07 authored by David Johnson's avatar David Johnson

Pythonize the whole library so that PYTHONPATH and module paths are sane.

There are a couple bugfixes in here -- there was a bad call to
super().__init__ that passed self as the first arg.  I also removed the
config file manager_class and helper_class defaults.

Also updates the slurm module and adds important notes about subclassing
both an existing helper and manager inside of a single class... method
resolution order is important!  See the slurm module, or the new docs
for SimpleElasticSliceManager for that.
parent d538b17a
*~
*.pyc
build/
elasticslice.egg-info/
This diff is collapsed.
import logging
from manager import SimpleElasticSliceManager, SimpleElasticSliceHelper
from util import ShellCommand
from elasticslice.managers.core import SimpleElasticSliceHelper, \
SimpleElasticSliceManager
from elasticslice.util.util import ShellCommand
SECOND = 1
MINUTE = SECOND * 60
......@@ -11,7 +12,15 @@ YEAR = DAY * 365
LOG = logging.getLogger(__name__)
class SlurmDynamicManager(SimpleElasticSliceManager, SimpleElasticSliceHelper):
#
# NB: it is very important that, as documented, SimpleElasticSliceHelper
# is the first class here, so that its methods override those of
# SimpleElasticSliceManager. Why? Because SimpleElasticSliceManager is
# also a helper -- it is a PluginElasticSliceHelper, which means it
# accepts a plugin helper, and doesn't have any functionality of its own
# (other than to call the the plugin helper object's methods).
#
class SlurmDynamicManager(SimpleElasticSliceHelper,SimpleElasticSliceManager):
DEF_ORDER = [ 'ensure_slice','ensure_sliver','update_sliver_status',
'renew','update_available','update_all','get_system_state',
......@@ -22,10 +31,10 @@ class SlurmDynamicManager(SimpleElasticSliceManager, SimpleElasticSliceHelper):
add_nodes=5 * MINUTE,delete_nodes=5 * MINUTE)
def __init__(self,server,config=None):
SimpleElasticSliceHelper.__init__(self,server,config=config)
SimpleElasticSliceManager.__init__(self,server,config=config,
manage_order=SlurmDynamicManager.DEF_ORDER,
manage_intervals=SlurmDynamicManager.DEF_INTERVALS)
SimpleElasticSliceHelper.__init__(self,server,config=config)
self.slurm = SlurmScheduler()
# Manager functions redefined:
......
......@@ -4,7 +4,7 @@ import os
import traceback
import time
import threading
from protogeniclientlib import ProtoGeniClientDefs, ProtoGeniServer, \
from elasticslice.rpc.protogeni import ProtoGeniClientDefs, ProtoGeniServer, \
ProtoGeniResponse, ProtoGeniManifestWrapper, \
ProtoGeniClientServerEndpoint, ProtoGeniClientServer, SENDMAIL
import geni.rspec.pgad as RSpecAd
......@@ -157,7 +157,7 @@ class SimpleElasticSliceHelper(ElasticSliceHelper):
num_pcs=1,image_urn=None,num_lans=0,multiplex_lans=False,
tarballs=[],startup_command=None,nodetype=None,
node_prefix="node",lan_prefix="lan"):
super(SimpleElasticSliceHelper,self).__init__(self,server)
super(SimpleElasticSliceHelper,self).__init__(server)
self.config = config
self.rspec = RSpec.Request()
......@@ -789,13 +789,36 @@ class SimpleElasticSliceManager(ElasticSliceManager,
ElasticSliceManager locks using a per-instance threading.RLock.
Thus, once one thread has the lock, they're good.
If you subclass SimpleElasticSliceManager, and want to replace its
helper functions, it is very important that you first subclass
whatever helper class you're extending, then
SimpleElasticSliceManager. For instance,
class FooManager(SimpleElasticSliceHelper,SimpleElasticSliceManager):
Why? Because that makes the method resolution order inside of FooManager
be FooManager, SimpleElasticSliceHelper, SimpleElasticSliceManager ... .
If you instead tried to do the reverse:
class FooManager(SimpleElasticSliceManager,SimpleElasticSliceHelper):
the method resolution order would be FooManager, SimpleElasticSliceManager,
SimpleElasticSliceHelper. Because SimpleElasticSliceManager provides an
implementation of each method in the ElasticSliceHelper interface, those
methods will be called, and those from SimpleElasticSliceHelper will never
be called (which defeats the point, that you hoped to re-use the helper
methods from SimpleElasticSliceHelper). So consider method resolution
order! Helpers are not mixins, because an ElasticSliceManager is also
an ElasticSliceHelper! This is an OO multiple inheritance style, not a
mixin style.
"""
def __init__(self,server,config=None,
minthreshold=DEF_MIN_THRESHOLD,maxthreshold=DEF_MAX_THRESHOLD,
percent_available_minimum=0.50,
manage_order=DEF_ORDER,manage_intervals=DEF_INTERVALS,
retry_interval=MINUTE/2,
nodetype=None,cmlist=None,enable_delete=False,email=True):
minthreshold=DEF_MIN_THRESHOLD,maxthreshold=DEF_MAX_THRESHOLD,
percent_available_minimum=0.50,
manage_order=DEF_ORDER,manage_intervals=DEF_INTERVALS,
retry_interval=MINUTE/2,
nodetype=None,cmlist=None,enable_delete=False,email=True):
ElasticSliceManager.__init__(self,server=server)
PluginElasticSliceHelper.__init__(self,server=server)
......@@ -818,6 +841,8 @@ class SimpleElasticSliceManager(ElasticSliceManager,
self.server = server
self.config = config
LOG.debug("server = %s, config = %s" % (server,config))
self.minthreshold = (config and 'minthreshold' in config.all
and config.all['minthreshold']) or minthreshold
self.maxthreshold = (config and 'maxthreshold' in config.all
......
......@@ -127,9 +127,11 @@ def parse_options():
parser.add_option("--image_urn", dest="image_urn",
help="Set the default image URN, e.g. urn:publicid:IDN+emulab.net+image+emulab-ops:UBUNTU14-64-STD")
parser.add_option("--manager_class",dest="manager_class",
help="The class to instantiate and use as the Manager [default: %default]")
help="The class to instantiate and use as the Manager [default: elasticslice.managers.core.SimpleElasticSliceManager]")
# default="manager.SimpleElasticSliceManager")
parser.add_option("--helper_class",dest="helper_class",
help="The class to instantiate and use as the Helper [default: %default]")
help="The class to instantiate and use as the Helper [default: elasticslice.managers.core.SimpleElasticSliceHelper, if you also use the default manager_class]")
# default="manager.SimpleElasticSliceHelper")
parser.add_option("--clientserver_endpoint_class",
dest="clientserver_endpoint_class [default %default]",
help="The class to instantiate and use as the Client Server endpoint [default: %default]")
......
[metadata]
name = elasticslice
version = 0.1
summary = A library and tools to manage ProtoGeni experiments that dynamically change size
description-file =
README.rst
author = David M Johnson, Dmitry Duplyakin
author-email = johnsond@flux.utah.edu, dmitry.duplyakin@gmail.com
home-page = https://gitlab.flux.utah.edu/elasticslice/elasticslice
classifier =
Intended Audience :: Information Technology
Intended Audience :: System Administrators
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
[files]
packages =
elasticslice
#data_files =
# etc/main.conf =
# etc/elasticslice.conf
[global]
setup-hooks =
pbr.hooks.setup_hook
[pbr]
warnerrors = true
#!/usr/bin/env python
import setuptools
setuptools.setup(
setup_requires=['pbr'],
pbr=True)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment