Skip to content
Permalink
Browse files
Add prototype of a kickstart generator
  • Loading branch information
bwachter committed Apr 1, 2013
1 parent 72c2ff6 commit 2bf098fadef663b4dc6e76993dc5a756861eca98
Showing with 388 additions and 2 deletions.
  1. +2 −0 constants.h
  2. +3 −0 rpm/ssu.changes
  3. +13 −1 rpm/ssu.spec
  4. +2 −1 ssu.pro
  5. +205 −0 ssuks/ssukickstarter.cpp
  6. +40 −0 ssuks/ssukickstarter.h
  7. +79 −0 ssuks/ssuks.cpp
  8. +28 −0 ssuks/ssuks.h
  9. +16 −0 ssuks/ssuks.pro
@@ -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
@@ -1,3 +1,6 @@
* 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

@@ -1,5 +1,5 @@
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
@@ -0,0 +1,205 @@
/**
* @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
}
@@ -0,0 +1,40 @@
/**
* @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
@@ -0,0 +1,79 @@
/**
* @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();
}

0 comments on commit 2bf098f

Please sign in to comment.