__author__ = "Andre Merzky, Ole Weidner"
__copyright__ = "Copyright 2012-2013, The SAGA Project"
__license__ = "MIT"
import radical.utils as ru
import radical.utils.signatures as rus
from ..constants import SYNC, ASYNC, TASK
from ..adaptors import base as sab
from .. import sasync
from .. import task as st
from .. import base as sb
from .. import session as ss
from .. import exceptions as se
from .. import constants as sc
from . import description as descr
from . import resource as resrc
from . import constants as c
# ------------------------------------------------------------------------------
#
[docs]class Manager (sb.Base, sasync.Async) :
"""
In the context of RADICAL-SAGA, a *ResourceManager* is a service which
asserts control over a set of resources. That manager can, on request,
render control over subsets of those resources (resource slices) to an
application.
This :class:`Manager` class represents the contact point to such
ResourceManager instances -- the application can thus acquire compute, data
or network resources, according to some resource specification, for a bound
or unbound amount of time.
"""
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
rus.optional (str, ru.Url),
rus.optional (ss.Session),
rus.optional (sab.Base),
rus.optional (dict),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns (rus.nothing)
def __init__ (self, url=None, session=None,
_adaptor=None, _adaptor_state={}, _ttype=None) :
"""
__init__(url)
Create a new Manager instance. Connect to a remote resource management endpoint.
:type url: :class:`saga.Url`
:param url: resource management endpoint
"""
# param checks
_url = ru.Url(url)
scheme = _url.scheme.lower()
if not session :
session = ss.Session (default=True)
self._base = super (Manager, self)
self._base.__init__ (scheme, _adaptor, _adaptor_state,
_url, session, ttype=_ttype)
# --------------------------------------------------------------------------
#
@classmethod
@rus.takes ('Manager',
rus.optional ((ru.Url, str)),
rus.optional (ss.Session),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns (st.Task)
def create (cls, url_in=None, session=None, ttype=sc.SYNC) :
"""
This is the asynchronous class constructor, returning
a :class:`saga:Task` instance. For details on the accepted parameters,
please see the description of :func:`__init__`.
"""
return cls (url_in, session, _ttype=ttype)._init_task
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
rus.optional (rus.one_of (c.COMPUTE, c.STORAGE, c.NETWORK)),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((rus.list_of (str), st.Task))
def list (self, rtype=None, ttype=None) :
"""
list(rtype=None)
List known resource instances (which can be acquired).
Returns a list of IDs.
:type rtype: None or enum (COMPUTE | STORAGE | NETWORK)
:param rtype: filter for one or more resource types
"""
return self._adaptor.list (rtype, ttype=ttype)
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
rus.optional (str),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((descr.Description, st.Task))
def get_description (self, rid, ttype=None) :
"""
get_description(rid)
Get the resource :class:`Description` for the specified resource.
:type rid: str
:param rid: identifies the resource to be described.
"""
# TODO / NOTE: if rid is None, should we return a description of
# the managed resources?
return self._adaptor.get_description (id, ttype=ttype)
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
rus.optional (rus.one_of (c.COMPUTE, c.STORAGE, c.NETWORK)),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((rus.list_of (str), st.Task))
def list_templates (self, rtype=None, ttype=None) :
"""
list_templates(rtype=None)
List template names available for the specified resource type(s).
Returns a list of strings.
:type rtype: None or enum (COMPUTE | STORAGE | NETWORK)
:param rtype: filter for one or more resource types
"""
return self._adaptor.list_templates (rtype, ttype=ttype)
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
rus.optional (str),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((descr.Description, st.Task))
def get_template (self, name, ttype=None) :
"""
get_template(name)
Get a :class:`Description` for the specified template.
:type name: str
:param name: specifies the name of the template
The returned resource description instance may not have all attributes
filled, and may in fact not sufficiently complete to allow for
successful resource acquisition. The only guaranteed attribute in the
returned description is `TEMPLATE`, containing the very template id
specified in the call parameters.
"""
return self._adaptor.get_template (name, ttype=ttype)
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
rus.optional (rus.one_of (c.COMPUTE, c.STORAGE, c.NETWORK)),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((rus.list_of (str), st.Task))
def list_images (self, rtype=None, ttype=None) :
"""
list_images(rtype=None)
List image names available for the specified resource type(s).
Returns a list of strings.
:type rtype: None or enum (COMPUTE | STORAGE | NETWORK)
:param rtype: filter for one or more resource types
"""
return self._adaptor.list_images (rtype, ttype=ttype)
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
str,
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((dict, st.Task))
def get_image (self, name, ttype=None) :
"""
get_image(name)
Get a description string for the specified image.
:type name: str
:param name: specifies the image name
"""
return self._adaptor.get_image (name, ttype=ttype)
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
(str, ru.Url, descr.Description),
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((resrc.Resource, st.Task))
def acquire (self, spec, ttype=None) :
"""
acquire(desc)
Create a new :class:`saga.resource.Resource` handle for a
resource specified by the description.
:type spec: :class:`Description` or Url
:param spec: specifies the resource
Depending on the `RTYPE` attribute in the description, the
returned resource may be a :class:`saga.resource.Compute`,
:class:`saga.resource.Storage` or :class:`saga.resource.Network`
instance.
If the `spec` parameter is
"""
if isinstance (spec, ru.Url) or \
isinstance (spec, str) :
return self._adaptor.acquire_by_id(spec, ttype=ttype)
else :
# make sure at least 'executable' is defined
if spec.rtype is None:
raise se.BadParameter ("resource type undefined in description")
# spec_copy = descr.Description ()
# spec._attributes_deep_copy (spec_copy)
return self._adaptor.acquire (spec, ttype=ttype)
# --------------------------------------------------------------------------
#
[docs] @rus.takes ('Manager',
str,
rus.optional (rus.one_of (SYNC, ASYNC, TASK)))
@rus.returns ((rus.nothing, st.Task))
def destroy (self, rid, ttype=None) :
"""
destroy(rid)
Destroy / release a resource.
:type rid : string
:param rid : identifies the resource to be released
"""
return self._adaptor.destroy (rid, ttype=ttype)
# FIXME: add
# templates = property(list_templates, get_template) # dict{string: Description}
# images = property(list_images, get_image) # dict{string: dict}
# resources = property(list, get_description) # dict{string: Description}
# ------------------------------------------------------------------------------