Newer
Older
// TMSSBridge.cc: Implementation of the TMSS Bridge, interface between MAC Scheduler and TMSS
//
// Copyright (C) 2020
// ASTRON (Netherlands Foundation for Research in Astronomy)
// P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, softwaresupport@astron.nl
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// $Id$
#include "TMSSBridge.h"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/algorithm/string.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <curl/curl.h>
#include <jsoncpp/json/json.h>
using namespace std;
namespace LOFAR {
namespace MainCU {
//
// TMSSBridge Constructor
//

Jorrit Schaap
committed
TMSSBridge::TMSSBridge(const std::string &hostname, int port, const std::string &username, const std::string &password):
itsUser(username),
itsPassword(password),
itsHost(hostname),
itsPort(port)
{
}
//
// TMSSBridge Destructor
//
TMSSBridge::~TMSSBridge()
{
}
//
// get all subTaskIDS that should run within three minutes (ordered in time if multiple are found)
// for given cluster
//
Json::Value TMSSBridge::getSubTasksStartingInThreeMinutes()
time_t now = time(0);
ptime lower_limit = from_time_t(now);
ptime upper_limit = from_time_t(now+3*60);
string queryStr = "/api/subtask/?start_time__gt=" + to_iso_extended_string(lower_limit) + "&start_time__lt=" + to_iso_extended_string(upper_limit) + "&ordering=start_time";
Json::Value result = httpGETAsJson(queryStr);
return result["results"];
std::string TMSSBridge::getParsetAsText(int subtask_id)
{
string queryStr = "/api/subtask/" + to_string(subtask_id) + "/parset";
return httpGET(queryStr);
}
std::size_t callback(const char* in,
std::size_t size,
std::size_t num,
std::string* out)
{
const std::size_t totalBytes(size * num);
out->append(in, totalBytes);
return totalBytes;
}
//
// Performs an HTTP GET and return the response body
// Need to check respons status code of http (200)
// Inspired by https://gist.github.com/connormanning/41efa6075515019e499c
// Example:

Jorrit Schaap
committed
// httpGET("/api/subtask/?start_time__lt=2020-03-04T12:03:00"
// results in a json string output
//
string TMSSBridge::httpGET(const string& target)
{
const std::string url(std::string("http://") + itsHost + std::string(":") + std::to_string(itsPort) + target);
CURL* curl = curl_easy_init();

Jorrit Schaap
committed
// setup authentication
curl_easy_setopt(curl, CURLOPT_USERNAME, itsUser.c_str());
curl_easy_setopt(curl, CURLOPT_PASSWORD, itsPassword.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Set remote URL.
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
// Don't bother trying IPv6, which would increase DNS resolution time.
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
// Don't wait forever, time out after 10 seconds.
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
// Follow HTTP redirects if necessary.
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// Response information.
long httpCode(0);
std::unique_ptr<std::string> httpData(new std::string());
// Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
// Hook up data container (will be passed as the last parameter to the
// callback handling function). Can be any pointer type, since it will
// internally be passed as a void pointer.
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
// Run our HTTP GET command, capture the HTTP response code, and clean up.
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
curl_easy_cleanup(curl);
if (httpCode == 200)
{
std::cout << "\nGot successful response from " << url << std::endl;
return string(*httpData.get());
THROW(TMSSBridgeException, "Couldn't GET from " + url + " exiting with http code " + to_string(httpCode));
}
Json::Value TMSSBridge::httpGETAsJson(const string& target)
{
std::string httpResponse = this->httpGET(target);
Json::Value jsonData("");
Json::Reader jsonReader;
if (jsonReader.parse(httpResponse, jsonData))
// TODO:
// How we deal with logging in Lofar C++ ?
// for now just do a stdout...
std::cout << "Successfully parsed JSON data" << std::endl;
std::cout << "\nJSON data received:" << std::endl;
std::cout << jsonData.toStyledString() << std::endl;
return jsonData;
THROW(TMSSBridgeException, "Could not parse HTTP data as JSON. HTTP data was:\n" + httpResponse);
}
};//MainCU
};//LOFAR