initial commit

This commit is contained in:
Blue 2018-08-05 00:46:25 +03:00 committed by Юрий Губич
commit 4b60ece582
327 changed files with 28286 additions and 0 deletions

View file

@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 2.8.12)
project(robouteModels)
find_package(Qt5Core REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(HEADERS
applistmodel.h
appmodel.h
service.h
apppropertiesmodel.h
appcommandsmodel.h
)
set(SOURCES
applistmodel.cpp
appmodel.cpp
service.cpp
apppropertiesmodel.cpp
appcommandsmodel.cpp
)
add_library(robouteModels STATIC ${HEADERS} ${SOURCES})
target_link_libraries(robouteModels Qt5::Core)
target_link_libraries(robouteModels wType)
target_link_libraries(robouteModels wSocket)
target_link_libraries(robouteModels wSsh)
target_link_libraries(robouteModels wController)

View file

@ -0,0 +1,110 @@
#include "appcommandsmodel.h"
AppCommandsModel::AppCommandsModel(QObject* parent):
QAbstractListModel(parent),
index(),
map(),
toInsert()
{
}
AppCommandsModel::~AppCommandsModel()
{
clear();
}
void AppCommandsModel::inserCommand(const QString& name, const ArgsMap& args)
{
toInsert.push_back(Pair(name, new ArgsMap(args)));
insertRows(rowCount(), 1);
}
void AppCommandsModel::removeCommand(const QString& name)
{
for (int i = 0; i < index.size(); ++i) {
if (index[i].key() == name) {
removeRows(i, 1);
break;
}
}
}
int AppCommandsModel::rowCount(const QModelIndex& parent) const
{
return index.size();
}
QVariant AppCommandsModel::data(const QModelIndex& i, int role) const
{
Map::iterator itr = index[i.row()];
switch(role) {
case Qt::DisplayRole:
return itr.key();
case Qt::TextAlignmentRole:
return Qt::AlignCenter + Qt::AlignVCenter;
}
return QVariant();
}
bool AppCommandsModel::insertRows(int row, int count, const QModelIndex& parent)
{
if (toInsert.size() != count) {
return false;
}
beginInsertRows(parent, row, row + count - 1);
Index::const_iterator target = index.begin() + row;
for (int i = 0; i < count; ++i) {
List::iterator itr = toInsert.begin();
Map::iterator mItr = map.insert(itr->first, itr->second);
index.insert(target, mItr);
toInsert.erase(itr);
}
endInsertRows();
return true;
}
bool AppCommandsModel::removeRows(int row, int count, const QModelIndex& parent)
{
if (row + count > index.size()) {
return false;
}
beginRemoveRows(parent, row, row + count - 1);
Index::iterator itr;
Index::iterator beg = index.begin() + row;
Index::iterator end = beg + count;
for (itr = beg; itr != end; ++itr) {
Map::iterator mItr = *itr;
ArgsMap* app = *mItr;
delete app;
map.erase(mItr);
}
index.erase(beg, end);
endRemoveRows();
return true;
}
AppCommandsModel::ArgsMap AppCommandsModel::getCommandArgs(const QString& name)
{
return *(map[name]);
}
void AppCommandsModel::clear()
{
beginResetModel();
Map::iterator itr = map.begin();
Map::iterator end = map.end();
for (; itr != end; ++itr) {
delete itr.value();
}
map.clear();
index.clear();
endResetModel();
}

View file

@ -0,0 +1,40 @@
#ifndef APPCOMMANDSMODEL_H
#define APPCOMMANDSMODEL_H
#include <QtCore/QAbstractListModel>
#include <QtCore/QMap>
#include <deque>
#include <list>
class AppCommandsModel : public QAbstractListModel
{
Q_OBJECT
typedef QMap<QString, uint64_t> ArgsMap;
public:
AppCommandsModel(QObject* parent = 0);
~AppCommandsModel();
void inserCommand(const QString& name, const ArgsMap& args);
void removeCommand(const QString& name);
ArgsMap getCommandArgs(const QString& name);
void clear();
QVariant data(const QModelIndex &i, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
private:
typedef QMap<QString, ArgsMap*> Map;
typedef std::deque<Map::iterator> Index;
typedef std::pair<QString, ArgsMap*> Pair;
typedef std::list<Pair> List;
Index index;
Map map;
List toInsert;
};
#endif // APPCOMMANDSMODEL_H

View file

@ -0,0 +1,187 @@
#include "applistmodel.h"
#include <iostream>
AppListModel::AppListModel(QObject* parent):
QAbstractListModel(parent),
index(),
helper(),
map(),
toInsert()
{
}
AppListModel::~AppListModel()
{
clear();
}
void AppListModel::push_back(uint64_t id, const QString& name)
{
AppModel* item = new AppModel(id, name);
toInsert.push_back(Pair(id, item));
insertRows(rowCount(), 1);
}
void AppListModel::removeElement(uint64_t id)
{
int index = *(helper.find(id));
removeRows(index, 1);
}
int AppListModel::rowCount(const QModelIndex& parent) const
{
//std::cout << index.size() << std::endl;
return index.size();
}
QVariant AppListModel::data(const QModelIndex& i, int role) const
{
Map::iterator itr = index[i.row()];
switch(role) {
case Qt::DisplayRole:
return itr.value()->getName();
case Qt::TextAlignmentRole:
return Qt::AlignCenter + Qt::AlignVCenter;
case Qt::UserRole:
quint64 id = itr.key();
return id;
}
return QVariant();
}
bool AppListModel::insertRows(int row, int count, const QModelIndex& parent)
{
if (toInsert.size() != count) {
return false;
}
beginInsertRows(parent, row, row + count - 1);
Index::const_iterator target = index.begin() + row;
for (int i = 0; i < count; ++i) {
List::iterator itr = toInsert.begin();
Map::iterator mItr = map.insert(itr->first, itr->second);
index.insert(target, mItr);
helper.insert(itr->first, row + i);
toInsert.erase(itr);
}
endInsertRows();
return true;
}
bool AppListModel::removeRows(int row, int count, const QModelIndex& parent)
{
if (row + count > index.size()) {
return false;
}
beginRemoveRows(parent, row, row + count - 1);
Index::iterator itr;
Index::iterator beg = index.begin() + row;
Index::iterator end = beg + count;
for (itr = beg; itr != end; ++itr) {
Map::iterator mItr = *itr;
AppModel* app = *mItr;
IndexHelper::iterator hItr = helper.find(app->id);
delete app;
map.erase(mItr);
helper.erase(hItr);
}
index.erase(beg, end);
endRemoveRows();
return true;
}
void AppListModel::logMessage(uint64_t id, const QString& msg)
{
map[id]->logMessage(msg);
}
AppModel* AppListModel::getApp(uint64_t id)
{
return map[id];
}
void AppListModel::clear()
{
beginResetModel();
Map::iterator itr = map.begin();
Map::iterator end = map.end();
for (; itr != end; ++itr) {
delete itr.value();
}
map.clear();
index.clear();
helper.clear();
endResetModel();
}
void AppListModel::setConnectable(uint64_t id, bool value)
{
map[id]->setConnectable(value);
}
void AppListModel::setConnected(uint64_t id, bool value)
{
map[id]->setConnected(value);
}
void AppListModel::setLaunchable(uint64_t id, bool value)
{
map[id]->setLaunchable(value);
}
void AppListModel::setLaunched(uint64_t id, bool value)
{
map[id]->setLaunched(value);
}
void AppListModel::setEditable(uint64_t id, bool value)
{
map[id]->setEditable(value);
}
void AppListModel::setAttribute(uint64_t id, const QString& key, const QString& value)
{
map[id]->props.setProp(key, value);
}
void AppListModel::addCommand(uint64_t id, const QString& key, const QMap<QString, uint64_t>& arguments)
{
map[id]->commands.inserCommand(key, arguments);
}
void AppListModel::removeCommand(uint64_t id, const QString& key)
{
map[id]->commands.removeCommand(key);
}
void AppListModel::clearCommands(uint64_t id)
{
map[id]->commands.clear();
}
void AppListModel::clearLog(uint64_t id)
{
map[id]->clearLog();
}
void AppListModel::setName(uint64_t id, const QString& name)
{
map[id]->setName(name);
int row = *(helper.find(id));
emit dataChanged(QAbstractListModel::index(row), QAbstractListModel::index(row), {Qt::DisplayRole});
}

View file

@ -0,0 +1,58 @@
#ifndef APPLISTMODEL_H
#define APPLISTMODEL_H
#include <QtCore/QAbstractListModel>
#include <QtCore/QMap>
#include <QtCore/QVariant>
#include <deque>
#include <list>
#include "appmodel.h"
class AppListModel : public QAbstractListModel
{
Q_OBJECT
public:
AppListModel(QObject* parent = 0);
~AppListModel();
void push_back(uint64_t id, const QString& name);
void removeElement(uint64_t id);
AppModel* getApp(uint64_t id);
void clear();
QVariant data(const QModelIndex &i, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
void setConnectable(uint64_t id, bool value);
void setConnected(uint64_t id, bool value);
void setLaunchable(uint64_t id, bool value);
void setLaunched(uint64_t id, bool value);
void setEditable(uint64_t id, bool value);
void setName(uint64_t id, const QString& name);
void setAttribute(uint64_t id, const QString& key, const QString& value);
void addCommand(uint64_t id, const QString& key, const QMap<QString, uint64_t>& arguments);
void removeCommand(uint64_t id, const QString& key);
void clearCommands(uint64_t id);
void clearLog(uint64_t id);
private:
typedef QMap<uint64_t, AppModel*> Map;
typedef QMap<uint64_t, uint64_t> IndexHelper;
typedef std::deque<Map::iterator> Index;
typedef std::pair<uint64_t, AppModel*> Pair;
typedef std::list<Pair> List;
Index index;
IndexHelper helper;
Map map;
List toInsert;
public slots:
void logMessage(uint64_t id, const QString& msg);
};
#endif // APPLISTMODEL_H

119
roboute/models/appmodel.cpp Normal file
View file

@ -0,0 +1,119 @@
#include "appmodel.h"
AppModel::AppModel(uint64_t p_id, const QString& p_name):
QObject(),
id(p_id),
props(),
commands(),
name(p_name),
log(),
connectable(false),
connected(false),
launchable(false),
launched(false),
editable(false)
{
}
const QString & AppModel::getName() const
{
return name;
}
void AppModel::logMessage(const QString& msg)
{
log.push_back(msg);
emit newLogMessage(msg);
}
QString* AppModel::getHistory() const
{
List::const_iterator itr = log.begin();
List::const_iterator end = log.end();
QString* history = new QString();
for (; itr != end; ++itr) {
history->append(*itr);
}
return history;
}
bool AppModel::getConnectable() const
{
return connectable;
}
bool AppModel::getConnected() const
{
return connected;
}
bool AppModel::getLaunchable() const
{
return launchable && connected;
}
bool AppModel::getLaunched() const
{
return launched;
}
bool AppModel::getEditable() const
{
return editable && !connected;
}
void AppModel::setConnectable(bool value)
{
if (value != connectable) {
connectable = value;
emit changedConnectable(connectable);
}
}
void AppModel::setConnected(bool value)
{
if (value != connected) {
connected = value;
emit changedConnected(connected);
emit changedLaunchable(launchable && connected);
}
}
void AppModel::setLaunchable(bool value)
{
if (value != launchable) {
launchable = value;
emit changedLaunchable(launchable && connected);
}
}
void AppModel::setLaunched(bool value)
{
if (value != launched) {
launched = value;
emit changedLaunched(launched);
}
}
void AppModel::setEditable(bool value)
{
if (value != editable) {
editable = value;
emit changedEditable(editable && !connected);
}
}
void AppModel::clearLog()
{
log.clear();
emit clearedLog();
}
void AppModel::setName(const QString& p_name)
{
name = p_name;
}

61
roboute/models/appmodel.h Normal file
View file

@ -0,0 +1,61 @@
#ifndef APPMODEL_H
#define APPMODEL_H
#include "apppropertiesmodel.h"
#include "appcommandsmodel.h"
#include <QtCore/QObject>
#include <list>
class AppModel : public QObject
{
Q_OBJECT
public:
AppModel(uint64_t p_id, const QString& p_name);
const QString& getName() const;
void setName(const QString& p_name);
void logMessage(const QString& msg);
QString* getHistory() const;
bool getConnectable() const;
bool getConnected() const;
bool getLaunchable() const;
bool getLaunched() const;
bool getEditable() const;
void clearLog();
public:
const uint64_t id;
AppPropertiesModel props;
AppCommandsModel commands;
signals:
void newLogMessage(const QString& msg);
void changedConnectable(bool value);
void changedConnected(bool value);
void changedLaunchable(bool value);
void changedLaunched(bool value);
void changedEditable(bool value);
void clearedLog();
public slots:
void setConnectable(bool value);
void setConnected(bool value);
void setLaunchable(bool value);
void setLaunched(bool value);
void setEditable(bool value);
private:
typedef std::list<QString> List;
QString name;
List log;
bool connectable;
bool connected;
bool launchable;
bool launched;
bool editable;
};
#endif // APPMODEL_H

View file

@ -0,0 +1,143 @@
#include "apppropertiesmodel.h"
AppPropertiesModel::AppPropertiesModel(QObject* parent):
QAbstractTableModel(parent),
index(),
helper(),
map(),
toInsert()
{
}
AppPropertiesModel::~AppPropertiesModel()
{
clear();
}
void AppPropertiesModel::clear()
{
beginResetModel();
Map::iterator itr = map.begin();
Map::iterator end = map.end();
for (; itr != end; ++itr) {
delete itr.value();
}
map.clear();
index.clear();
helper.clear();
endResetModel();
}
int AppPropertiesModel::columnCount(const QModelIndex& parent) const
{
return 2;
}
bool AppPropertiesModel::insertRows(int row, int count, const QModelIndex& parent)
{
if (toInsert.size() != count) {
return false;
}
beginInsertRows(parent, row, row + count - 1);
Index::const_iterator target = index.begin() + row;
for (int i = 0; i < count; ++i) {
List::iterator itr = toInsert.begin();
Map::iterator mItr = map.insert(itr->first, itr->second);
index.insert(target, mItr);
helper.insert(itr->first, row + i);
toInsert.erase(itr);
}
endInsertRows();
return true;
}
bool AppPropertiesModel::removeRows(int row, int count, const QModelIndex& parent)
{
if (row + count > index.size()) {
return false;
}
beginRemoveRows(parent, row, row + count - 1);
Index::iterator itr;
Index::iterator beg = index.begin() + row;
Index::iterator end = beg + count;
for (itr = beg; itr != end; ++itr) {
Map::iterator mItr = *itr;
AppProp* prop = *mItr;
IndexHelper::iterator hItr = helper.find(prop->key);
delete prop;
map.erase(mItr);
helper.erase(hItr);
}
index.erase(beg, end);
endRemoveRows();
return true;
}
int AppPropertiesModel::rowCount(const QModelIndex& parent) const
{
return index.size();
}
void AppPropertiesModel::setProp(const QString& key, const QString& value)
{
Map::iterator itr = map.find(key);
if (itr != map.end()) {
itr.value()->value = value;
const QModelIndex ind = QAbstractTableModel::index(*(helper.find(key)), 1);
emit dataChanged(ind, ind);
} else {
AppProp* item = new AppProp{key, value};
toInsert.push_back(Pair(key, item));
insertRows(rowCount(), 1);
}
}
void AppPropertiesModel::removeProp(const QString& key)
{
IndexHelper::iterator itr = helper.find(key);
if (itr != helper.end()) {
removeRows(*itr, 1);
}
}
QVariant AppPropertiesModel::data(const QModelIndex& i, int role) const
{
Map::iterator itr = index[i.row()];
int col = i.column();
switch(role) {
case Qt::DisplayRole:
if (col == 0) {
return itr.key();
} else if (col == 1) {
return itr.value()->value;
}
}
return QVariant();
}
QVariant AppPropertiesModel::headerData(int section, Qt::Orientation orientation, int role) const
{
switch (orientation) {
case Qt::Horizontal:
switch(role) {
case Qt::DisplayRole:
if (section == 0) {
return "Key";
} else if (section == 1) {
return "Value";
}
}
}
return QVariant();
}

View file

@ -0,0 +1,51 @@
#ifndef APPPROPERTIESMODEL_H
#define APPPROPERTIESMODEL_H
#include <QtCore/QAbstractTableModel>
#include <QtCore/QMap>
#include <QtCore/QVariant>
#include <deque>
#include <list>
class AppPropertiesModel : public QAbstractTableModel
{
Q_OBJECT
struct AppProp
{
QString key;
QString value;
};
public:
AppPropertiesModel(QObject* parent = 0);
~AppPropertiesModel();
void setProp(const QString& key, const QString& value);
void removeProp(const QString& key);
void clear();
QVariant data(const QModelIndex &i, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
private:
typedef QMap<QString, AppProp*> Map;
typedef QMap<QString, uint64_t> IndexHelper;
typedef std::deque<Map::iterator> Index;
typedef std::pair<QString, AppProp*> Pair;
typedef std::list<Pair> List;
Index index;
IndexHelper helper;
Map map;
List toInsert;
};
#endif // APPPROPERTIESMODEL_H

View file

@ -0,0 +1,10 @@
#include "commands.h"
Commands::Commands(const W::Address& address, QObject* parent):
C::Vocabulary(address, parent)
{
}
Commands::~Commands()
{
}

13
roboute/models/commands.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef ROBOUTE_COMMANDS_H
#define ROBOUTE_COMMANDS_H
#include <wController/vocabulary.h>
class Commands : public C::Vocabulary
{
public:
Commands(const W::Address& address, QObject* parent = 0);
~Commands();
};
#endif // ROBOUTE_COMMANDS_H

489
roboute/models/service.cpp Normal file
View file

@ -0,0 +1,489 @@
#include "service.h"
uint64_t Service::lastId = 0;
Service::Service(
uint64_t p_id,
const QString& p_name,
const QString& p_address,
const QString& p_port,
const QString& p_login,
const QString& p_password,
const QString& p_logFile,
const QString& p_command
):
QObject(),
socket(new W::Socket(W::String(u"Roboute"))),
dataSsh(new W::SshSocket(p_login, p_password)),
commandSsh(new W::SshSocket(p_login, p_password)),
attributes(new C::Attributes(W::Address{u"attributes"})),
commands(new C::Vocabulary(W::Address{u"management"})),
login(p_login),
password(p_password),
logFile(p_logFile),
command(p_command),
psResults(),
pid(),
state(Disconnected),
appState(Unknown),
name(p_name),
address(p_address),
port(p_port),
id(p_id)
{
QObject::connect(dataSsh, SIGNAL(opened()), this, SLOT(onDataSshOpened()));
QObject::connect(dataSsh, SIGNAL(closed()), this, SLOT(onSshClosed()));
QObject::connect(dataSsh, SIGNAL(data(const QString&)), this, SLOT(onDataSshData(const QString&)));
QObject::connect(dataSsh, SIGNAL(error(W::SshSocket::Error, const QString&)), this, SLOT(onSshError(W::SshSocket::Error, const QString&)));
QObject::connect(dataSsh, SIGNAL(finished()), this, SLOT(onDataSshFinished()));
QObject::connect(commandSsh, SIGNAL(opened()), this, SLOT(onCommandSshOpened()));
QObject::connect(commandSsh, SIGNAL(closed()), this, SLOT(onSshClosed()));
QObject::connect(commandSsh, SIGNAL(data(const QString&)), this, SLOT(onCommandSshData( const QString&)));
QObject::connect(commandSsh, SIGNAL(error(W::SshSocket::Error, const QString&)), this, SLOT(onSshError(W::SshSocket::Error, const QString&)));
QObject::connect(commandSsh, SIGNAL(finished()), this, SLOT(onCommandSshFinished()));
QObject::connect(socket, SIGNAL(connected()), this, SLOT(onSocketConnected()));
QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
QObject::connect(socket, SIGNAL(error(W::Socket::SocketError, const QString&)), this, SLOT(onSocketError(W::Socket::SocketError, const QString&)));
QObject::connect(attributes, SIGNAL(attributeChange(const W::String&, const W::Object&)),
this, SLOT(onAttrChange(const W::String&, const W::Object&)));
QObject::connect(attributes, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&)));
QObject::connect(commands, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&)));
QObject::connect(commands, SIGNAL(newElement(const W::String&, const W::Object&)), SLOT(onAddCommand(const W::String&, const W::Object&)));
QObject::connect(commands, SIGNAL(removeElement(const W::String&)), SLOT(onRemoveCommand(const W::String&)));
QObject::connect(commands, SIGNAL(clear()), SLOT(onClearCommands()));
}
Service::~Service()
{
delete commands;
delete attributes;
delete commandSsh;
delete dataSsh;
delete socket;
}
Service* Service::create(const QMap<QString, QString>& params)
{
QString name = params["name"];
QString address = params["address"];
QString port = params["port"];
QString login = params["login"];
QString password = params["password"];
QString logFile = params["logFile"];
QString command = params["command"];
Service* srv = new Service(++lastId, name, address, port, login, password, logFile, command);
return srv;
}
Service* Service::fromSerialized(const QMap<QString, QVariant>& params)
{
QString name = params["name"].toString();
QString address = params["address"].toString();
QString port = params["port"].toString();
QString login = params["login"].toString();
QString password = params["password"].toString();
QString logFile = params["logFile"].toString();
QString command = params["command"].toString();
uint64_t id = params["id"].toUInt();
if (id > lastId) {
lastId = id;
}
Service* srv = new Service(id, name, address, port, login, password, logFile, command);
return srv;
}
void Service::onDataSshOpened()
{
if (state == Connecting) {
state = Echo;
dataSsh->execute("echo === Roboute connected === >> " + logFile);
emit serviceMessage("checking log file");
} else {
//TODO;
}
}
void Service::onCommandSshOpened()
{
if (appState == Unknown) {
appState = Checking;
requestPid();
emit serviceMessage("checking if the process launched");
}
}
void Service::onSshClosed()
{
if (state == Disconnected) {
emit serviceMessage("connection clozed");
emit stopped();
emit disconnected();
}
if (state == Disconnecting) {
state = Disconnected;
}
}
void Service::onSshError(W::SshSocket::Error errCode, const QString& msg)
{
emit serviceMessage(msg);
switch (state) {
case Disconnected:
break;
case Connecting:
state = Disconnected;
emit disconnected();
break;
case Echo:
case Listening:
case Connected:
disconnect();
break;
default:
break;
}
}
void Service::onDataSshData(const QString& data)
{
switch (state) {
case Listening:
state = Connected;
emit connected();
emit serviceMessage("first data from log file, connected!");
case Connected:
if (appState == Launching) {
if (data.contains("ready")) {
connectWebsocket();
requestPid();
}
}
emit log(data);
break;
default:
break;
}
}
void Service::onCommandSshData(const QString& data)
{
QStringList list = data.split("\n");
psResults.insert(psResults.end(), list.begin(), list.end());
}
void Service::onCommandSshFinished()
{
switch (appState) {
case Checking:
case WaitingWebSocket:
case Active: //that's very bad!
{
bool found = false;
std::list<QString>::const_iterator itr = psResults.begin();
std::list<QString>::const_iterator end = psResults.end();
QString option;
for (; itr != end; ++itr) {
option = *itr;
if (!option.contains(" grep ") && option.contains(command)) {
found = true;
break;
}
}
if (found) {
QStringList mems = option.split(QRegExp("\\s"));
QStringList::const_iterator mItr = mems.begin();
QStringList::const_iterator mEnd = mems.end();
found = false;
for (; mItr != mEnd; ++mItr) {
QString candidate = *mItr;
if (candidate.contains(QRegExp("\\d{2,}"))) {
pid = candidate;
found = true;
break;
}
}
if (found) {
emit serviceMessage("got the process id: " + pid + ", correct?");
} else {
emit serviceMessage("Couldn't find process id");
}
emit serviceMessage("process seems to be launched");
if (appState == Checking) {
connectWebsocket();
}
} else {
appState = Dead;
emit stopped();
emit serviceMessage("process seems to be not launched");
}
break;
}
case Launching:
emit serviceMessage(QString("process launch command sent,") +
" requesting pid, waiting for specific 'ready' key in log"); //need to do smthing about this
break;
default:
break;
}
}
void Service::connect()
{
if (state == Disconnected) {
dataSsh->open(address);
commandSsh->open(address);
state = Connecting;
emit serviceMessage("connecting to " + address);
emit connecting();
} else {
//TODO;
}
}
void Service::disconnect()
{
if (state != Disconnected) {
state = Disconnecting;
if (appState == Active) {
commands->unsubscribe();
attributes->unsubscribe();
socket->close();
}
pid = "";
psResults.clear();
appState = Unknown;
emit serviceMessage("disconnecting");
emit disconnecting();
emit stopped();
dataSsh->interrupt();
dataSsh->close();
commandSsh->close();
}
}
void Service::onDataSshFinished()
{
switch (state) {
case Echo:
emit serviceMessage("log file checked");
dataSsh->execute("tail -f " + logFile);
state = Listening;
emit serviceMessage("listening to the log file");
break;
default:
break;
}
}
QVariant Service::saveState() const
{
QMap<QString, QVariant> state;
quint64 qid = id;
state.insert("id", qid);
state.insert("login", login);
state.insert("password", password);
state.insert("logFile", logFile);
state.insert("name", name);
state.insert("address", address);
state.insert("port", port);
state.insert("command", command);
return state;
}
void Service::launch()
{
if (state == Connected && appState == Dead) {
appState = Launching;
commandSsh->execute("nohup " + command + " >> " + logFile + " 2>&1 &");
emit launching();
}
}
void Service::stop()
{
if (state == Connected && appState == Active) {
QString file = command.section("/", -1);
commandSsh->execute("kill -s SIGINT " + pid);
appState = Stopping;
emit stopping();
}
}
void Service::onSocketConnected()
{
appState = Active; //this is a fail It's not right!
attributes->subscribe();
commands->subscribe();
emit launched();
}
void Service::onSocketDisconnected()
{
appState = Dead; //this is not correct!
emit stopped();
}
void Service::onSocketError(W::Socket::SocketError err, const QString& msg)
{
emit serviceMessage(msg); //this is not correct!
appState = Dead;
emit stopped();
}
void Service::registerContollers(W::Dispatcher* dp)
{
QObject::connect(socket, SIGNAL(message(const W::Event&)), dp, SLOT(pass(const W::Event&)));
attributes->registerController(dp, socket);
commands->registerController(dp, socket);
}
void Service::unregisterControllers(W::Dispatcher* dp)
{
QObject::disconnect(socket, SIGNAL(message(const W::Event&)), dp, SLOT(pass(const W::Event&)));
commands->unregisterController();
attributes->unregisterController();
}
void Service::requestPid()
{
pid = "";
psResults.clear();
commandSsh->execute("ps -ax | grep '" + command + "'");
}
void Service::connectWebsocket()
{
appState = WaitingWebSocket;
socket->open(W::String(address.toStdString()), W::Uint64(port.toInt()));
emit serviceMessage("trying to reach service by websocket");
}
void Service::onAttrChange(const W::String& key, const W::Object& value)
{
emit attributeChanged(QString::fromStdString(key.toString()), QString::fromStdString(value.toString()));
}
void Service::onAddCommand(const W::String& key, const W::Object& value)
{
QMap<QString, uint64_t> arguments;
const W::Vocabulary& vc = static_cast<const W::Vocabulary&>(value);
const W::Vocabulary& args = static_cast<const W::Vocabulary&>(vc.at(u"arguments"));
W::Vector keys = args.keys();
uint64_t size = keys.length();
for (int i = 0; i < size; ++i) {
const W::String& name = static_cast<const W::String&>(keys.at(i));
const W::Uint64& type = static_cast<const W::Uint64&>(args.at(name));
arguments.insert(QString::fromStdString(name.toString()), type);
}
emit addCommand(QString::fromStdString(key.toString()), arguments);
}
void Service::onRemoveCommand(const W::String& key)
{
emit removeCommand(QString::fromStdString(key.toString()));
}
void Service::onClearCommands()
{
emit clearCommands();
}
void Service::launchCommand(const QString& name, const QMap<QString, QVariant>& args)
{
const W::Vocabulary& val = static_cast<const W::Vocabulary&>(commands->at(W::String(name.toStdString())));
const W::Vocabulary& aT = static_cast<const W::Vocabulary&>(val.at(u"arguments"));
QMap<QString, QVariant>::const_iterator itr = args.begin();
QMap<QString, QVariant>::const_iterator end = args.end();
W::Vocabulary* vc = new W::Vocabulary();
for (; itr != end; ++itr) {
W::String wKey(itr.key().toStdString());
const W::Uint64& wType = static_cast<const W::Uint64&>(aT.at(wKey));
int type = wType;
W::Object* value;
switch (type) {
case 0:
value = new W::String(itr.value().toString().toStdString());
break;
case 2:
value = new W::Uint64(itr.value().toInt());
break;
default:
throw 1;
}
vc->insert(wKey, value);
}
W::Event ev(static_cast<const W::Address&>(val.at(u"address")), vc);
ev.setSenderId(socket->getId());
socket->send(ev);
}
QMap<QString, QString> Service::getData() const
{
QMap<QString, QString> data;
data["name"] = name;
data["address"] = address;
data["port"] = port;
data["login"] = login;
data["password"] = password;
data["logFile"] = logFile;
data["command"] = command;
return data;
}
void Service::passNewData(const QMap<QString, QString> data)
{
if (data.contains("name") && data.value("name") != name) {
name = data.value("name");
emit changeName(name);
}
if (data.contains("address") && data.value("address") != address) {
address = data.value("address");
}
if (data.contains("port") && data.value("port") != port) {
port = data.value("port");
}
if (data.contains("login") && data.value("login") != login) {
login = data.value("login");
dataSsh->setLogin(login);
commandSsh->setLogin(login);
}
if (data.contains("password") && data.value("password") != password) {
password = data.value("password");
dataSsh->setPassword(password);
commandSsh->setPassword(password);
}
if (data.contains("logFile") && data.value("logFile") != logFile) {
logFile = data.value("logFile");
}
if (data.contains("command") && data.value("command") != command) {
command = data.value("command");
}
}

131
roboute/models/service.h Normal file
View file

@ -0,0 +1,131 @@
#ifndef SERVICE_H
#define SERVICE_H
#include <list>
#include <wSocket/socket.h>
#include <wSsh/sshsocket.h>
#include <wType/string.h>
#include <wType/uint64.h>
#include <wController/attributes.h>
#include <wController/vocabulary.h>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QMap>
#include <QtCore/QVariant>
class Service : public QObject
{
Q_OBJECT
private:
Service(uint64_t p_id,
const QString& p_name,
const QString& p_address,
const QString& p_port,
const QString& p_login,
const QString& p_password,
const QString& p_logFile,
const QString& p_command
);
public:
~Service();
static Service* create(const QMap<QString, QString>& params);
static Service* fromSerialized(const QMap<QString, QVariant>& params);
QVariant saveState() const;
void registerContollers(W::Dispatcher* dp);
void unregisterControllers(W::Dispatcher* dp);
QMap<QString, QString> getData() const;
void passNewData(const QMap<QString, QString> data);
private:
enum State {
Disconnected,
Connecting,
Echo,
Listening,
Connected,
Disconnecting
};
enum AppState {
Unknown,
Checking,
Dead,
Launching,
WaitingWebSocket,
Active,
Stopping
};
W::Socket* socket;
W::SshSocket* dataSsh;
W::SshSocket* commandSsh;
C::Attributes* attributes;
C::Vocabulary* commands;
static uint64_t lastId;
QString login;
QString password;
QString logFile;
QString command;
std::list<QString> psResults;
QString pid;
State state;
AppState appState;
void requestPid();
void connectWebsocket();
public:
QString name;
QString address;
QString port;
const uint64_t id;
signals:
void serviceMessage(const QString& msg);
void connecting();
void connected();
void disconnecting();
void disconnected();
void launching();
void launched();
void stopping();
void stopped();
void log(const QString& data);
void attributeChanged(const QString& name, const QString& value);
void addCommand(const QString& name, const QMap<QString, uint64_t>& arguments);
void removeCommand(const QString& name);
void clearCommands();
void changeName(const QString& name);
public slots:
void connect();
void disconnect();
void launch();
void stop();
void launchCommand(const QString& name, const QMap<QString, QVariant>& args);
private slots:
void onDataSshOpened();
void onCommandSshOpened();
void onSshClosed();
void onDataSshData(const QString& data);
void onCommandSshData(const QString& data);
void onSshError(W::SshSocket::Error errCode, const QString& msg);
void onDataSshFinished();
void onCommandSshFinished();
void onSocketConnected();
void onSocketDisconnected();
void onSocketError(W::Socket::SocketError err, const QString& msg);
void onAttrChange(const W::String& key, const W::Object& value);
void onAddCommand(const W::String& key, const W::Object& value);
void onRemoveCommand(const W::String& key);
void onClearCommands();
};
#endif // SERVICE_H