Commit 2bf098fa authored by Aard's avatar Aard

Add prototype of a kickstart generator

parent 72c2ff65
......@@ -16,6 +16,8 @@
#define SSU_BOARD_MAPPING_CONFIGURATION "/usr/share/ssu/board-mappings.ini"
/// Path to config.d for board mappings
#define SSU_BOARD_MAPPING_CONFIGURATION_DIR "/usr/share/ssu/board-mappings.d"
/// Directory where all the non-user modifiable data sits
#define SSU_DATA_DIR "/usr/share/ssu/"
/// The SSU protocol version used by the ssu client libraries
#define SSU_PROTOCOL_VERSION "1"
/// Maximum recursion level for resolving variables
......
* Mon Apr 01 2013 Bernd Wachter <bernd.wachter@jollamobile.com> - 0.29
- Add prototype kickstart generator
* Sun Mar 31 2013 Bernd Wachter <bernd.wachter@jollamobile.com> - 0.28.1
- Enable repo listing for ssu CLI
......
Name: ssu
Version: 0.28.1
Version: 0.29
Release: 1
Summary: SSU enabler for RND
Group: System/Base
......@@ -45,6 +45,18 @@ Group: System/Base
%{_datadir}/ssu/*.ini
%package ks
Summary: Kickstart generator using %{name} data
Group: System/Base
%description ks
%{summary}. With ponies!
%files ks
%defattr(-,root,root,-)
%{_bindir}/ssuks
%package rnd-ui
Summary: Shiny user interface for %{name}
Group: System/Base
......
......@@ -4,7 +4,7 @@ contains(QT_VERSION, ^4\\.[0-7]\\..*) {
TEMPLATE = subdirs
SUBDIRS = libssu
SUBDIRS += rndssucli rndregisterui ssuurlresolver
SUBDIRS += rndssucli rndregisterui ssuurlresolver ssuks
ssuconfhack {
SUBDIRS += ssuconfperm
......@@ -16,6 +16,7 @@ rndssucli.depends = libssu
rndregisterui.depends = libssu
ssuurlresolver.depends = libssu
tests.depends = libssu
ssuks.depends = libssu
config.files = ssu.ini
config.path = /etc/ssu
......
/**
* @file ssukickstarter.cpp
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bwachter@lart.info>
* @date 2013
*/
#include <QStringList>
#include <QRegExp>
#include <QDirIterator>
#include "ssukickstarter.h"
#include "../constants.h"
/* TODO:
* - rnd/release handling.
* repo --name=adaptation0-@RNDRELEASE@
* --baseurl=https://releases.jollamobile.com/nemo/@RELEASE@-devel/adaptation-n9xx-common/@ARCH@/
* @RELEASE@ should be @RNDRELEASE@ in this case as well
* - commands from the command section should be verified
* - go through the variable lookup process for non-url variables as well
* - allow overriding brand key
* - use (and expand) filename key if no filename is given on command line
*/
SsuKickstarter::SsuKickstarter() {
SsuDeviceInfo deviceInfo;
deviceModel = deviceInfo.deviceModel();
if ((ssu.deviceMode() & Ssu::RndMode) == Ssu::RndMode)
rndMode = true;
else
rndMode = false;
}
QStringList SsuKickstarter::commands(){
SsuDeviceInfo deviceInfo(deviceModel);
QStringList result;
QHash<QString, QString> h = deviceInfo.variableSection("kickstart-commands");
// read commands from variable, ...
QHash<QString, QString>::const_iterator it = h.constBegin();
while (it != h.constEnd()){
result.append(it.key() + " " + it.value());
it++;
}
return result;
}
QStringList SsuKickstarter::repos(){
QStringList result;
SsuDeviceInfo deviceInfo(deviceModel);
QStringList repos = deviceInfo.repos(rndMode, SsuDeviceInfo::BoardFilter);
foreach (const QString &repo, repos){
QString repoUrl = ssu.repoUrl(repo, rndMode, QHash<QString, QString>(), repoOverride);
result.append(QString("repo --name=%1-%2 --baseurl=%3")
.arg(repo)
.arg((rndMode ? repoOverride.value("rndRelease")
: repoOverride.value("release")))
.arg(repoUrl)
);
}
return result;
}
QStringList SsuKickstarter::packages(){
QStringList result;
// insert @vendor configuration device
QString configuration = QString("@%1 Configuration %2")
.arg("Jolla")
.arg(deviceModel);
result.append(configuration);
// check if there's a kernel, and if so, append it as well
result.sort();
result.removeDuplicates();
result.prepend("%packages");
result.append("%end");
return result;
}
QStringList SsuKickstarter::partitions(){
QStringList result;
SsuDeviceInfo deviceInfo(deviceModel);
QString partitionFile;
QFile part;
QDir dir(QString("%1/kickstart/part/").arg(SSU_DATA_DIR));
if (dir.exists(deviceInfo.deviceVariant(true)))
partitionFile = deviceInfo.deviceVariant(true);
else if (dir.exists(deviceModel))
partitionFile = deviceModel;
else if (dir.exists("default"))
partitionFile = "default";
else {
result.append("## No partition configuration found.");
return result;
}
QFile file(dir.path() + "/" + partitionFile);
result.append("### partition setup from " + partitionFile);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
QTextStream in(&file);
while (!in.atEnd())
result.append(in.readLine());
}
return result;
}
// we intentionally don't support device-specific post scriptlets
QStringList SsuKickstarter::scriptletSection(QString name, bool chroot){
QStringList result;
QString path;
QDir dir;
if (chroot)
path = QString("%1/kickstart/%2/")
.arg(SSU_DATA_DIR)
.arg(name);
else
path = QString("%1/kickstart/%2_nochroot/")
.arg(SSU_DATA_DIR)
.arg(name);
dir.setPath(path);
QStringList scriptlets = dir.entryList(QDir::AllEntries|QDir::NoDot|QDir::NoDotDot,
QDir::Name);
foreach (const QString &scriptlet, scriptlets){
QFile file(path + scriptlet);
result.append("### begin " + scriptlet);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
QTextStream in(&file);
while (!in.atEnd())
result.append(in.readLine());
}
result.append("### end " + scriptlet);
}
if (!result.isEmpty()){
if (chroot)
result.prepend("%" + name);
else
result.prepend("%" + name + " --nochroot");
result.append("%end");
}
return result;
}
void SsuKickstarter::setRepoParameters(QHash<QString, QString> parameters){
repoOverride = parameters;
if (repoOverride.contains("model"))
deviceModel = repoOverride.value("model");
/*
else
repoOverride.insert("model", deviceInfo.deviceModel());
*/
}
void SsuKickstarter::write(QString kickstart){
QFile ks;
QTextStream kout;
SsuDeviceInfo deviceInfo;
if (kickstart.isEmpty())
ks.open(stdout, QIODevice::WriteOnly);
else {
ks.setFileName(kickstart);
ks.open(QIODevice::WriteOnly);
}
kout.setDevice(&ks);
QHash<QString, QString> defaults = deviceInfo.variableSection("kickstart-defaults");
QHash<QString, QString>::const_iterator it = defaults.constBegin();
while (it != defaults.constEnd()){
if (!repoOverride.contains(it.key()))
repoOverride.insert(it.key(), it.value());
it++;
}
kout << commands().join("\n") << endl << endl;
kout << partitions().join("\n") << endl << endl;
kout << repos().join("\n") << endl << endl;
kout << packages().join("\n") << endl << endl;
kout << scriptletSection("pre", false).join("\n") << endl << endl;
kout << scriptletSection("post").join("\n") << endl << endl;
kout << scriptletSection("post").join("\n") << endl << endl;
// add flags as bitmask?
// POST, die-on-error
}
/**
* @file ssukickstarter.h
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bwachter@lart.info>
* @date 2013
*/
#ifndef _SSUKICKSTARTER_H
#define _SSUKICKSTARTER_H
#include <QObject>
#include <QSettings>
#include <QHash>
#include <ssudeviceinfo.h>
#include <ssu.h>
/*
class Q_CORE_EXPORT SsuKickstarter: public QObject {
Q_OBJECT
*/
class SsuKickstarter {
public:
SsuKickstarter();
void setRepoParameters(QHash<QString, QString> parameters);
void write(QString kickstart="");
private:
QHash<QString, QString> repoOverride;
Ssu ssu;
bool rndMode;
QString deviceModel;
QStringList commands();
QStringList packages();
QStringList partitions();
QStringList repos();
QStringList scriptletSection(QString name, bool chroot=true);
};
#endif
/**
* @file ssuks.cpp
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bernd.wachter@jollamobile.com>
* @date 2013
*/
#include <QCoreApplication>
#include <QTranslator>
#include <QLocale>
#include <QLibraryInfo>
#include <QTimer>
#include <QStringList>
#include "ssukickstarter.h"
#include "ssuks.h"
void SsuKs::run(){
QStringList arguments = QCoreApplication::arguments();
// get rid of the binary name
arguments.removeFirst();
QTextStream qout(stdout);
QHash<QString, QString> repoParameters;
SsuKickstarter kickstarter;
QString fileName;
if (arguments.count() >= 1 && !arguments.at(0).contains("=")){
fileName = arguments.at(0);
arguments.removeFirst();
}
if (arguments.count() >= 1){
for (int i=0; i<arguments.count(); i++){
if (arguments.at(i).count("=") != 1){
qout << "Invalid flag: " << arguments.at(i) << endl;
return;
}
QStringList split = arguments.at(i).split("=");
repoParameters.insert(split.at(0), split.at(1));
}
kickstarter.setRepoParameters(repoParameters);
kickstarter.write(fileName);
} else
usage();
QCoreApplication::exit(0);
}
void SsuKs::usage(){
QTextStream qout(stdout);
qout << "\nUsage: ssuks <filename> <flags>" << endl
<< endl
<< "Flags are in the form key=value. 'model' and 'rnd' keys have special meanings." << endl
<< "To do a kickstart for N9 do 'ssuks model=N9'" << endl
<< endl;
qout.flush();
QCoreApplication::exit(1);
}
int main(int argc, char** argv){
QCoreApplication app(argc, argv);
QCoreApplication::setOrganizationName("Jolla");
QCoreApplication::setOrganizationDomain("http://www.jollamobile.com");
QCoreApplication::setApplicationName("ssuks");
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);
SsuKs mw;
QTimer::singleShot(0, &mw, SLOT(run()));
return app.exec();
}
/**
* @file ssuks.h
* @copyright 2013 Jolla Ltd.
* @author Bernd Wachter <bwachter@lart.info>
* @date 2013
*/
#ifndef _SSUKS_H
#define _SSUKS_H
#include <QObject>
#include <QDebug>
class SsuKs: public QObject {
Q_OBJECT
//class SsuKs {
public:
SsuKs(){};
public slots:
void run();
private:
void usage();
};
#endif
HEADERS = ssuks.h \
ssukickstarter.h
SOURCES = ssuks.cpp \
ssukickstarter.cpp
TEMPLATE = app
TARGET = ssuks
LIBS += -lssu
CONFIG -= app_bundle
CONFIG += console
QT -= gui
QT += network
unix:target.path = $${PREFIX}/usr/bin
INSTALLS += target
!include( ../buildpath.pri ) { error("Unable to find build path specification") }
Markdown is supported
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