Commit ea1ee4bc authored by Maria Arsuaga Rios's avatar Maria Arsuaga Rios
Browse files

FTS-793: Provide an Optimizer API

parent 5bffdbec
Pipeline #166426 passed with stage
in 19 seconds
......@@ -310,3 +310,22 @@ Unbanning:
`curl --capath /etc/grid-security/certificates -E ~/proxy.pem --cacert ~/proxy.pem "https://fts3-pilot.cern.ch:8446/ban/dn?user_dn=/DC=.../CN=..." -X DELETE`
Mind that unbanning returns nothing.
Get Current Optimizer values
------------------------
Return the current optimizer values for a given pair (source, destination).
`curl -E "${X509_USER_PROXY}" --cacert "${X509_USER_PROXY}" --capath "/etc/grid-security/certificates" "https://fts3-pilot.cern.ch:8446/optimizer/current?source_se="source-test"&dest_se="dest-test"" -H "Content-Type: application/json"`
Set Current Optimizer values
------------------------
Set the current optimizer values for given pair (source, destination).
` curl -E "${X509_USER_PROXY}" --cacert "${X509_USER_PROXY}" --capath "/etc/grid-security/certificates" https://fts3-pilot.cern.ch:8446/optimizer/current -H "Content-Type: application/json" -X POST -d '{"source_se": "source-test", "dest_se": "dest-test", "active": 4, "nostreams": 1, "ema": 3.4}'`
Get Current Optimizer Evolution
------------------------
Returns the evolution information for a given pair (source, destination).
`curl -E "${X509_USER_PROXY}" --cacert "${X509_USER_PROXY}" --capath "/etc/grid-security/certificates" "https://fts3-pilot.cern.ch:8446/optimizer/evolution?source_se="source-test"&dest_se="dest-test"" -H "Content-Type: application/json"`
......@@ -44,7 +44,10 @@ class Optimizer(Base):
source_se = Column(String(150), nullable=True, primary_key=True)
dest_se = Column(String(150), nullable=True, primary_key=True)
ema = Column(Float)
active = Column(Integer)
datetime = Column(DateTime)
nostreams = Column(Integer)
def __str__(self):
return "%s => %s" % (self.source_se, self.dest_se)
......@@ -188,6 +188,11 @@ def do_connect(config, map):
map.connect('/optimizer/evolution', controller='optimizer',
action='evolution',
conditions=dict(method=['GET']))
map.connect('/optimizer/current', controller='optimizer',
action='get_optimizer_values',
conditions=dict(method=['GET']))
map.connect('/optimizer/current', controller='optimizer', action='set_optimizer_values',
conditions=dict(method=['POST']))
# GFAL2 bindings
map.connect('/dm/list', controller='datamanagement', action='list',
......
......@@ -52,7 +52,6 @@ class SeConfigurationController(BaseController):
Set the configuration parameters for a given SE
"""
input_dict = get_input_as_dict(request)
try:
for storage, cfg in input_dict.iteritems():
se_info_new = cfg.get('se_info', None)
......@@ -63,7 +62,7 @@ class SeConfigurationController(BaseController):
for key, value in se_info_new.iteritems():
#value = validate_type(Se, key, value)
setattr(se_info, key, value)
audit_configuration('set-se-config', 'Set config %s: %s' % (storage, json.dumps(cfg)))
Session.merge(se_info)
......@@ -91,7 +90,7 @@ class SeConfigurationController(BaseController):
except:
Session.rollback()
raise
return None
return (se_info, operations)
@doc.query_arg('se', 'Storage element', required=False)
@doc.response(403, 'The user is not allowed to query the configuration')
......
......@@ -15,11 +15,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
try:
import simplejson as json
except:
import json
import logging
from pylons import config,request
from fts3rest.lib.api import doc
from fts3rest.lib.base import BaseController, Session
from fts3rest.lib.helpers import jsonify
from fts3rest.lib.helpers import jsonify, accept, get_input_as_dict
from fts3.model import OptimizerEvolution, Optimizer
from pylons import config, request
from datetime import datetime
from fts3rest.lib.http_exceptions import *
class OptimizerController(BaseController):
......@@ -53,7 +62,7 @@ class OptimizerController(BaseController):
@doc.return_type(array_of=Optimizer)
@jsonify
def get_current_value(self):
def get_optimizer_values(self):
"""
Returns the current number of actives and streams
"""
......@@ -65,5 +74,63 @@ class OptimizerController(BaseController):
optimizer = optimizer.order_by(Optimizer.datetime.desc())
return optimizer[:0]
return optimizer
@doc.response(400, 'Invalid values passed in the request')
@jsonify
def set_optimizer_values(self):
"""
Set the number of actives and streams
"""
input_dict = get_input_as_dict(request)
source_se = input_dict.get('source_se', None)
dest_se = input_dict.get('dest_se', None)
current_time = datetime.utcnow()
if not source_se or not dest_se:
raise HTTPBadRequest('Missing source and/or destination')
try:
active = int(input_dict.get('active', 2))
except Exception, e:
raise HTTPBadRequest('Active must be an integer (%s)' % str(e))
if active < 0:
raise HTTPBadRequest('Active must be positive (%s)' % str(active))
try:
nostreams = int(input_dict.get('nostreams', 1))
except Exception, e:
raise HTTPBadRequest('Nostreams must be an integer (%s)' % str(e))
if nostreams < 0:
raise HTTPBadRequest('Nostreams must be positive (%s)' % str(nostreams))
try:
ema = float(input_dict.get('ema', 0))
except Exception, e:
raise HTTPBadRequest('Ema must be a float (%s)' % str(e))
if ema < 0:
raise HTTPBadRequest('Ema must be positive (%s)' % str(ema))
optimizer = Optimizer(
source_se=source_se,
dest_se=dest_se,
datetime = current_time,
ema = ema,
active=active,
nostreams=nostreams
)
for key, value in input_dict.iteritems():
setattr(optimizer, key, value)
Session.merge(optimizer)
try:
Session.commit()
except:
Session.rollback()
raise
return optimizer
......@@ -107,6 +107,9 @@ class TestOptions(TestController):
response = self.app.options('/optimizer/evolution', status=200)
self.assertItemsEqual(['GET', 'OPTIONS'], response.allow)
response = self.app.options('/optimizer/current', status=200)
self.assertItemsEqual(['GET','POST', 'OPTIONS'], response.allow)
def test_options_404(self):
"""
......
Supports Markdown
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