mirror of
https://github.com/outbackdingo/sysadm.git
synced 2026-01-27 10:20:26 +00:00
Add a new API call/system: sysadm/pkg.
This system reads the pkg database directly and returns any relevant information about the pkgs requested.
Note: The "repo" input is optional (defaults to "local"), and the "pkg_origins" will become optional here soon as well (going to make it default to listing all pkgs if the pkg_origins variable is missing/empty).
REST Request:
-------------------------------
PUT /sysadm/pkg
{
"pkg_origins" : [
"x11/lumina"
],
"repo" : "local",
"action" : "pkg_info"
}
WebSocket Request:
-------------------------------
{
"name" : "pkg",
"namespace" : "sysadm",
"args" : {
"repo" : "local",
"action" : "pkg_info",
"pkg_origins" : [
"x11/lumina"
]
},
"id" : "fooid"
}
Response:
-------------------------------
{
"args": {
"pkg_info": {
"x11/lumina": {
"arch": "FreeBSD:11:amd64",
"automatic": "0",
"comment": "Lumina Desktop Environment",
"dep_formula": "",
"dependencies": [
"x11-toolkits/qt5-gui",
"x11/qt5-x11extras",
"x11-wm/fluxbox",
"x11/libXdamage",
"devel/qt5-linguist",
"x11/numlockx",
"devel/qt5-buildtools",
"multimedia/qt5-multimedia",
"graphics/qt5-svg",
"x11/xbrightness",
"x11/xorg",
"devel/desktop-file-utils",
"devel/qt5-concurrent",
"x11/libX11",
"net/qt5-network",
"x11-themes/fluxbox-tenr-styles-pack",
"x11-themes/kde4-icons-oxygen",
"devel/qt5-core",
"x11/xscreensaver",
"multimedia/gstreamer1-plugins-core",
"graphics/qt5-imageformats"
],
"desc": "Lumina-DE is a lightweight, BSD licensed desktop environment,\ndesigned specifically for use on FreeBSD\n\nWWW: http://lumina-desktop.org",
"files": [
"/usr/local/share/licenses/lumina-0.8.8_2,1/catalog.mk",
"/usr/local/share/licenses/lumina-0.8.8_2,1/LICENSE",
"/usr/local/share/licenses/lumina-0.8.8_2,1/BSD3CLAUSE",
"/usr/local/bin/Lumina-DE",
"/usr/local/bin/lumina-config",
"/usr/local/bin/lumina-fileinfo",
"/usr/local/bin/lumina-fm",
"/usr/local/bin/lumina-info",
"/usr/local/bin/lumina-open",
"/usr/local/bin/lumina-screenshot",
"/usr/local/bin/lumina-search",
"/usr/local/bin/lumina-xconfig",
"/usr/local/etc/luminaDesktop.conf.dist",
"/usr/local/include/LuminaOS.h",
"/usr/local/include/LuminaSingleApplication.h",
"/usr/local/include/LuminaThemes.h",
"/usr/local/include/LuminaUtils.h",
"/usr/local/include/LuminaX11.h",
"/usr/local/include/LuminaXDG.h",
"/usr/local/lib/libLuminaUtils.so",
"/usr/local/lib/libLuminaUtils.so.1",
"/usr/local/lib/libLuminaUtils.so.1.0",
"/usr/local/lib/libLuminaUtils.so.1.0.0",
"/usr/local/share/Lumina-DE/Login.ogg",
"/usr/local/share/Lumina-DE/Logout.ogg",
"/usr/local/share/Lumina-DE/colors/Black.qss.colors",
"/usr/local/share/Lumina-DE/colors/Blue-Light.qss.colors",
"/usr/local/share/Lumina-DE/colors/Grey-Dark.qss.colors",
"/usr/local/share/Lumina-DE/colors/Lumina-Glass.qss.colors",
"/usr/local/share/Lumina-DE/colors/Lumina-Gold.qss.colors",
"/usr/local/share/Lumina-DE/colors/Lumina-Green.qss.colors",
"/usr/local/share/Lumina-DE/colors/Lumina-Purple.qss.colors",
"/usr/local/share/Lumina-DE/colors/Lumina-Red.qss.colors",
"/usr/local/share/Lumina-DE/colors/PCBSD10-Default.qss.colors",
"/usr/local/share/Lumina-DE/colors/Solarized-Dark.qss.colors",
"/usr/local/share/Lumina-DE/colors/Solarized-Light.qss.colors",
"/usr/local/share/Lumina-DE/desktop-background.jpg",
"/usr/local/share/Lumina-DE/fluxbox-init-rc",
"/usr/local/share/Lumina-DE/fluxbox-keys",
"/usr/local/share/Lumina-DE/luminaDesktop.conf",
"/usr/local/share/Lumina-DE/quickplugins/quick-sample.qml",
"/usr/local/share/Lumina-DE/themes/Lumina-default.qss.template",
"/usr/local/share/Lumina-DE/themes/None.qss.template",
"/usr/local/share/applications/lumina-fm.desktop",
"/usr/local/share/applications/lumina-info.desktop",
"/usr/local/share/applications/lumina-screenshot.desktop",
"/usr/local/share/applications/lumina-search.desktop",
"/usr/local/share/applications/lumina-support.desktop",
"/usr/local/share/pixmaps/Insight-FileManager.png",
"/usr/local/share/pixmaps/Lumina-DE.png",
"/usr/local/share/wallpapers/Lumina-DE/Lumina_Wispy_gold.jpg",
"/usr/local/share/wallpapers/Lumina-DE/Lumina_Wispy_green.jpg",
"/usr/local/share/wallpapers/Lumina-DE/Lumina_Wispy_purple.jpg",
"/usr/local/share/wallpapers/Lumina-DE/Lumina_Wispy_red.jpg",
"/usr/local/share/xsessions/Lumina-DE.desktop"
],
"flatsize": "12324767",
"icon": "\\\"http://www.pcbsd.org/appcafe/icons/x11_lumina.png\\\"",
"id": "2541",
"licenselogic": "1",
"licenses": [
"BSD3CLAUSE"
],
"locked": "0",
"maintainer": "kmoore@FreeBSD.org",
"manifestdigest": "2$0$4ypg5zrco9upyuioczmo3uwbtdd5yart7xuit6fx3gjrn1k979qb",
"message": "[{\"message\":\"The Lumina Desktop Environment has been installed!\\n\\nAn entry for for launching Lumina from a graphical login manager has already been added to the system, but if you with to start Lumina manually, you will need to do one of the following:\\n1) Put the line \\\"exec Lumina-DE\\\" at the end of your user's \\\"~/.xinitrc\\\" file before running startx\\n2) Wrap the Lumina binary call with an X initialization call: \\nExample: \\\"xinit ${PREFIX}/bin/Lumina-DE -- :0\\\"\\n\\nAlso note that the system-wide default settings for Lumina are contained in ${PREFIX}/etc/luminaDesktop.conf[.dist]. While it is possible to customize the desktop to the user's liking after logging in, you may want to adjust the default settings as necessary if there are multiple user accounts on this system.\"}]",
"mtree_id": "",
"name": "lumina",
"options": {
"MULTIMEDIA": "on",
"PCBSD": "on"
},
"origin": "x11/lumina",
"pkg_format_version": "",
"prefix": "/usr/local",
"repo_type": "binary",
"repository": "pcbsd-major",
"screen1": "\\\"http://www.pcbsd.org/appcafe/screenshots/x11/lumina/screen1.png\\\"",
"shlibs_provided": [
"libLuminaUtils.so.1"
],
"shlibs_required": [
"libxcb.so.1",
"libxcb-composite.so.0",
"libxcb-damage.so.0",
"libXdamage.so.1",
"libxcb-util.so.1",
"libGL.so.1",
"libQt5Core.so.5",
"libxcb-image.so.0",
"libxcb-icccm.so.4",
"libxcb-ewmh.so.2",
"libQt5Gui.so.5",
"libQt5Network.so.5",
"libQt5Widgets.so.5",
"libQt5Concurrent.so.5",
"libQt5Multimedia.so.5",
"libQt5MultimediaWidgets.so.5",
"libQt5Svg.so.5",
"libQt5X11Extras.so.5"
],
"time": "1458334158",
"version": "0.8.8_2,1",
"www": "http://lumina-desktop.org"
}
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "library/sysadm-systemmanager.h"
|
||||
#include "library/sysadm-update.h"
|
||||
#include "library/sysadm-zfs.h"
|
||||
#include "library/sysadm-pkg.h"
|
||||
|
||||
#include "syscache-client.h"
|
||||
|
||||
@@ -67,10 +68,16 @@ RestOutputStruct::ExitCode WebSocket::AvailableSubsystems(bool allaccess, QJsonO
|
||||
out->insert("sysadm/iohyve", "read/write");
|
||||
}
|
||||
|
||||
// - zfs
|
||||
if(QFile::exists("/sbin/zfs") && QFile::exists("/sbin/zpool")){
|
||||
out->insert("sysadm/zfs", allaccess ? "read/write" : "read");
|
||||
}
|
||||
|
||||
// - pkg
|
||||
if(QFile::exists("/usr/local/sbin/pkg")){
|
||||
out->insert("sysadm/pkg", "read/write");
|
||||
}
|
||||
|
||||
// - Generic system information
|
||||
out->insert("sysadm/systemmanager","read/write");
|
||||
|
||||
@@ -123,6 +130,8 @@ RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(const RestInputStru
|
||||
return EvaluateSysadmUpdateRequest(IN.args, out);
|
||||
}else if(namesp=="sysadm" && name=="zfs"){
|
||||
return EvaluateSysadmZfsRequest(IN.args, out);
|
||||
}else if(namesp=="sysadm" && name=="pkg"){
|
||||
return EvaluateSysadmPkgRequest(IN.args, out);
|
||||
}else{
|
||||
return RestOutputStruct::BADREQUEST;
|
||||
}
|
||||
@@ -681,3 +690,29 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmZfsRequest(const QJsonValue
|
||||
|
||||
return RestOutputStruct::OK;
|
||||
}
|
||||
|
||||
// ==== SYSADM PKG API ====
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateSysadmPkgRequest(const QJsonValue in_args, QJsonObject *out){
|
||||
if(!in_args.isObject() || !in_args.toObject().contains("action") ){ return RestOutputStruct::BADREQUEST; }
|
||||
//REQUIRED: "action"
|
||||
QString act = in_args.toObject().value("action").toString();
|
||||
//OPTIONAL: "repo" (uses local repo database by default)
|
||||
QString repo = "local";
|
||||
if(in_args.toObject().contains("repo")){ repo = in_args.toObject().value("repo").toString(); }
|
||||
//OPTIONAL: "pkg_origins" (defaults to everything for listing functions)
|
||||
QStringList pkgs;
|
||||
if(in_args.toObject().contains("pkg_origins")){
|
||||
if(in_args.toObject().value("pkg_origins").isString()){ pkgs << in_args.toObject().value("pkg_origins").toString(); }
|
||||
else if(in_args.toObject().value("pkg_origins").isArray()){ pkgs = JsonArrayToStringList(in_args.toObject().value("pkg_origins").toArray()); }
|
||||
}
|
||||
//Parse
|
||||
if(act=="pkg_info"){
|
||||
QJsonObject info = sysadm::PKG::pkg_info(pkgs, repo);
|
||||
if(!pkgs.isEmpty()){ out->insert("pkg_info",info); }
|
||||
}else{
|
||||
//unknown action
|
||||
return RestOutputStruct::BADREQUEST;
|
||||
}
|
||||
|
||||
return RestOutputStruct::OK;
|
||||
}
|
||||
@@ -70,6 +70,8 @@ private:
|
||||
RestOutputStruct::ExitCode EvaluateSysadmUpdateRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
// -- sysadm ZFS API
|
||||
RestOutputStruct::ExitCode EvaluateSysadmZfsRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
// -- sysadm PKG API
|
||||
RestOutputStruct::ExitCode EvaluateSysadmPkgRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
|
||||
private slots:
|
||||
void sendReply(QString msg);
|
||||
|
||||
@@ -13,7 +13,8 @@ HEADERS += $${PWD}/sysadm-global.h \
|
||||
$${PWD}/sysadm-systemmanager.h\
|
||||
$${PWD}/sysadm-update.h \
|
||||
$${PWD}/sysadm-usermanager.h \
|
||||
$${PWD}/sysadm-zfs.h
|
||||
$${PWD}/sysadm-zfs.h \
|
||||
$${PWD}/sysadm-pkg.h
|
||||
|
||||
SOURCES += $${PWD}/NetDevice.cpp \
|
||||
$${PWD}/sysadm-general.cpp \
|
||||
@@ -27,5 +28,6 @@ SOURCES += $${PWD}/NetDevice.cpp \
|
||||
$${PWD}/sysadm-systemmanager.cpp \
|
||||
$${PWD}/sysadm-update.cpp \
|
||||
$${PWD}/sysadm-usermanager.cpp \
|
||||
$${PWD}/sysadm-zfs.cpp
|
||||
$${PWD}/sysadm-zfs.cpp \
|
||||
$${PWD}/sysadm-pkg.cpp
|
||||
|
||||
|
||||
139
src/server/library/sysadm-pkg.cpp
Normal file
139
src/server/library/sysadm-pkg.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
//===========================================
|
||||
// PC-BSD source code
|
||||
// Copyright (c) 2015, PC-BSD Software/iXsystems
|
||||
// Available under the 3-clause BSD license
|
||||
// See the LICENSE file for full details
|
||||
//===========================================
|
||||
#include "sysadm-general.h"
|
||||
#include "sysadm-pkg.h"
|
||||
#include "sysadm-global.h"
|
||||
#include "globals.h"
|
||||
|
||||
using namespace sysadm;
|
||||
|
||||
// ==================
|
||||
// INLINE FUNCTIONS
|
||||
// ==================
|
||||
//Get Option Name
|
||||
inline QString option_from_id(QString id){
|
||||
QSqlQuery q("SELECT option FROM option WHERE option_id = '"+id+"'");
|
||||
while(q.next()){
|
||||
return q.value("option").toString();
|
||||
}
|
||||
return ""; //nothing found
|
||||
}
|
||||
//Get Annotation (name/value - both use ID's)
|
||||
inline QString anno_from_id(QString id){
|
||||
QSqlQuery q("SELECT annotation FROM annotation WHERE annotation_id = '"+id+"'");
|
||||
while(q.next()){
|
||||
return q.value("annotation").toString();
|
||||
}
|
||||
return ""; //nothing found
|
||||
}
|
||||
//Get origin from package_id (for reverse lookups)
|
||||
inline QStringList origins_from_package_ids(QStringList ids){
|
||||
QSqlQuery q("SELECT origin FROM packages WHERE id = '"+ids.join("' OR id = '")+"'");
|
||||
QStringList out;
|
||||
while(q.next()){ out << q.value("origin").toString(); }
|
||||
return out;
|
||||
}
|
||||
//Generic ID's -> Names function (known databases: users, groups, licenses, shlibs, categories )
|
||||
inline QStringList names_from_ids(QStringList ids, QString db){
|
||||
QSqlQuery q("SELECT name FROM "+db+" WHERE id = '"+ids.join("' OR id = '")+"'");
|
||||
QStringList out;
|
||||
while(q.next()){ out << q.value("name").toString(); }
|
||||
return out;
|
||||
}
|
||||
|
||||
// =================
|
||||
// MAIN FUNCTIONS
|
||||
// =================
|
||||
QJsonObject PKG::pkg_info(QStringList origins, QString repo){
|
||||
QJsonObject retObj;
|
||||
//Open the local database
|
||||
QSqlDatabase DB = QSqlDatabase::addDatabase("QSQLITE");
|
||||
DB.setHostName("localhost");
|
||||
if(repo=="local"){ DB.setDatabaseName( "/var/db/pkg/local.sqlite"); }
|
||||
else{ DB.setDatabaseName( "/var/db/pkg/repo-"+repo+".sqlite"); }
|
||||
DB.setConnectOptions("QSQLITE_OPEN_READONLY=1");
|
||||
if( !DB.open() ){ return retObj; } //cannot open database
|
||||
//Now do all the pkg info, one pkg origin at a time
|
||||
QSqlQuery query("SELECT * FROM packages" +(origins.isEmpty() ? "" : " WHERE origin = '"+origins.join("' OR origin = '")+"'") );
|
||||
//int id = query.record().indexOf("origin");
|
||||
while(query.next()){
|
||||
QJsonObject info;
|
||||
QString id = query.value("id").toString(); //need this pkg id for later
|
||||
QString origin = query.value("origin").toString(); //need the origin for later
|
||||
//General info
|
||||
for(int i=0; i<query.record().count(); i++){
|
||||
info.insert(query.record().fieldName(i), query.value(i).toString() );
|
||||
}
|
||||
//ANNOTATIONS
|
||||
QSqlQuery q2("SELECT tag_id, value_id FROM pkg_annotation WHERE package_id = '"+id+"'");
|
||||
while(q2.next()){
|
||||
//include the annotations as base-level fields as well
|
||||
info.insert( anno_from_id(q2.value("tag_id").toString()), anno_from_id(q2.value("value_id").toString()) );
|
||||
}
|
||||
//OPTIONS
|
||||
QSqlQuery q3("SELECT option_id, value FROM pkg_option WHERE package_id = '"+id+"'");
|
||||
QJsonObject options;
|
||||
while(q3.next()){ options.insert(option_from_id(q3.value("option_id").toString()), q3.value("value").toString() ); }
|
||||
if(!options.isEmpty()){ info.insert("options",options); }
|
||||
//DEPENDENCIES
|
||||
QSqlQuery q4("SELECT origin FROM deps WHERE package_id = '"+id+"'");
|
||||
QStringList tmpList;
|
||||
while(q4.next()){
|
||||
tmpList << q4.value("origin").toString();
|
||||
} //end deps query
|
||||
if(!tmpList.isEmpty()){ info.insert("dependencies", QJsonArray::fromStringList(tmpList) ); }
|
||||
//FILES
|
||||
QSqlQuery q5("SELECT path FROM files WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q5.next()){ tmpList << q5.value("path").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("files", QJsonArray::fromStringList(tmpList) ); }
|
||||
//REVERSE DEPENDENCIES
|
||||
QSqlQuery q6("SELECT package_id FROM deps WHERE origin = '"+origin+"'");
|
||||
tmpList.clear();
|
||||
while(q6.next()){ tmpList << q6.value("package_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("reverse_dependencies", QJsonArray::fromStringList(origins_from_package_ids(tmpList)) ); }
|
||||
//USERS
|
||||
QSqlQuery q7("SELECT user_id FROM pkg_users WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q7.next()){ tmpList << q7.value("user_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("users", QJsonArray::fromStringList(names_from_ids(tmpList, "users")) ); }
|
||||
//GROUPS
|
||||
QSqlQuery q8("SELECT group_id FROM pkg_groups WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q8.next()){ tmpList << q8.value("group_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("groups", QJsonArray::fromStringList(names_from_ids(tmpList, "users")) ); }
|
||||
//LICENSES
|
||||
QSqlQuery q9("SELECT license_id FROM pkg_licenses WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q9.next()){ tmpList << q9.value("license_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("licenses", QJsonArray::fromStringList(names_from_ids(tmpList, "licenses")) ); }
|
||||
//SHARED LIBS (REQUIRED)
|
||||
QSqlQuery q10("SELECT shlib_id FROM pkg_shlibs_required WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q10.next()){ tmpList << q10.value("shlib_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("shlibs_required", QJsonArray::fromStringList(names_from_ids(tmpList, "shlibs")) ); }
|
||||
//SHARED LIBS (PROVIDED)
|
||||
QSqlQuery q11("SELECT shlib_id FROM pkg_shlibs_provided WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q11.next()){ tmpList << q11.value("shlib_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("shlibs_provided", QJsonArray::fromStringList(names_from_ids(tmpList, "shlibs")) ); }
|
||||
//CONFLICTS
|
||||
QSqlQuery q12("SELECT conflict_id FROM pkg_conflicts WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q12.next()){ tmpList << q12.value("conflict_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("conflicts", QJsonArray::fromStringList(origins_from_package_ids(tmpList)) ); }
|
||||
//CONFIG FILES
|
||||
QSqlQuery q13("SELECT path FROM config_files WHERE package_id = '"+id+"'");
|
||||
tmpList.clear();
|
||||
while(q13.next()){ tmpList << q13.value("path").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("config_files", QJsonArray::fromStringList(tmpList) ); }
|
||||
//Now insert this information into the main object
|
||||
retObj.insert(origin,info);
|
||||
} //end loop over pkg matches
|
||||
DB.close();
|
||||
return retObj;
|
||||
}
|
||||
26
src/server/library/sysadm-pkg.h
Normal file
26
src/server/library/sysadm-pkg.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//===========================================
|
||||
// PC-BSD source code
|
||||
// Copyright (c) 2015, PC-BSD Software/iXsystems
|
||||
// Available under the 3-clause BSD license
|
||||
// See the LICENSE file for full details
|
||||
//===========================================
|
||||
#ifndef __PCBSD_LIB_UTILS_PKG_H
|
||||
#define __PCBSD_LIB_UTILS_PKG_H
|
||||
|
||||
#include <QJsonObject>
|
||||
#include "sysadm-global.h"
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlError>
|
||||
#include <QSqlIndex>
|
||||
#include <QSqlRecord>
|
||||
#include <QSqlQuery>
|
||||
namespace sysadm{
|
||||
|
||||
class PKG{
|
||||
public:
|
||||
static QJsonObject pkg_info(QStringList origins, QString repo);
|
||||
};
|
||||
|
||||
} //end of sysadm namespace
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@ TEMPLATE = app
|
||||
LANGUAGE = C++
|
||||
|
||||
CONFIG += qt warn_off release
|
||||
QT = core network websockets concurrent
|
||||
QT = core network websockets concurrent sql
|
||||
|
||||
HEADERS += globals.h globals-qt.h \
|
||||
WebServer.h \
|
||||
|
||||
Reference in New Issue
Block a user