Merge branch 'strictly-typed-timeout'

This commit is contained in:
Adriaan de Groot 2019-08-01 23:00:28 +02:00
commit e3ecb083a0
17 changed files with 103 additions and 85 deletions

View File

@ -31,7 +31,7 @@ namespace Calamares {
ProcessJob::ProcessJob( const QString& command, ProcessJob::ProcessJob( const QString& command,
const QString& workingPath, const QString& workingPath,
bool runInChroot, bool runInChroot,
int secondsTimeout, std::chrono::seconds secondsTimeout,
QObject* parent ) QObject* parent )
: Job( parent ) : Job( parent )
, m_command( command ) , m_command( command )

View File

@ -22,6 +22,8 @@
#include "Job.h" #include "Job.h"
#include <chrono>
namespace Calamares { namespace Calamares {
class ProcessJob : public Job class ProcessJob : public Job
@ -31,7 +33,7 @@ public:
explicit ProcessJob( const QString& command, explicit ProcessJob( const QString& command,
const QString& workingPath, const QString& workingPath,
bool runInChroot = false, bool runInChroot = false,
int secondsTimeout = 30, std::chrono::seconds secondsTimeout = std::chrono::seconds(30),
QObject* parent = nullptr ); QObject* parent = nullptr );
virtual ~ProcessJob() override; virtual ~ProcessJob() override;
@ -43,7 +45,7 @@ private:
QString m_command; QString m_command;
QString m_workingPath; QString m_workingPath;
bool m_runInChroot; bool m_runInChroot;
int m_timeoutSec; std::chrono::seconds m_timeoutSec;
}; };
} // namespace Calamares } // namespace Calamares

View File

@ -89,11 +89,13 @@ _target_env_command(
const std::string& stdin, const std::string& stdin,
int timeout ) int timeout )
{ {
// Since Python doesn't give us the type system for distinguishing
// seconds from other integral types, massage to seconds here.
return CalamaresUtils::System::instance()-> return CalamaresUtils::System::instance()->
targetEnvCommand( args, targetEnvCommand( args,
QString(), QString(),
QString::fromStdString( stdin ), QString::fromStdString( stdin ),
timeout ); std::chrono::seconds( timeout ) );
} }
int int

View File

@ -154,7 +154,7 @@ System::runCommand(
const QStringList& args, const QStringList& args,
const QString& workingPath, const QString& workingPath,
const QString& stdInput, const QString& stdInput,
int timeoutSec ) std::chrono::seconds timeoutSec )
{ {
QString output; QString output;
@ -219,7 +219,7 @@ System::runCommand(
} }
process.closeWriteChannel(); process.closeWriteChannel();
if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) ) if ( !process.waitForFinished( timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) )
{ {
cWarning().noquote().nospace() << "Timed out. Output so far:\n" << cWarning().noquote().nospace() << "Timed out. Output so far:\n" <<
process.readAllStandardOutput(); process.readAllStandardOutput();
@ -249,7 +249,7 @@ QString
System::targetPath( const QString& path ) const System::targetPath( const QString& path ) const
{ {
QString completePath; QString completePath;
if ( doChroot() ) if ( doChroot() )
{ {
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
@ -259,14 +259,14 @@ System::targetPath( const QString& path ) const
cWarning() << "No rootMountPoint in global storage, cannot create target file" << path; cWarning() << "No rootMountPoint in global storage, cannot create target file" << path;
return QString(); return QString();
} }
completePath = gs->value( "rootMountPoint" ).toString() + '/' + path; completePath = gs->value( "rootMountPoint" ).toString() + '/' + path;
} }
else else
{ {
completePath = QStringLiteral( "/" ) + path; completePath = QStringLiteral( "/" ) + path;
} }
return completePath; return completePath;
} }
@ -278,32 +278,32 @@ System::createTargetFile( const QString& path, const QByteArray& contents ) cons
{ {
return QString(); return QString();
} }
QFile f( completePath ); QFile f( completePath );
if ( f.exists() ) if ( f.exists() )
{ {
return QString(); return QString();
} }
QIODevice::OpenMode m = QIODevice::OpenMode m =
#if QT_VERSION >= QT_VERSION_CHECK( 5, 11, 0 ) #if QT_VERSION >= QT_VERSION_CHECK( 5, 11, 0 )
// New flag from Qt 5.11, implies WriteOnly // New flag from Qt 5.11, implies WriteOnly
QIODevice::NewOnly | QIODevice::NewOnly |
#endif #endif
QIODevice::WriteOnly | QIODevice::Truncate; QIODevice::WriteOnly | QIODevice::Truncate;
if ( !f.open( m ) ) if ( !f.open( m ) )
{ {
return QString(); return QString();
} }
if ( f.write( contents ) != contents.size() ) if ( f.write( contents ) != contents.size() )
{ {
f.close(); f.close();
f.remove(); f.remove();
return QString(); return QString();
} }
f.close(); f.close();
return QFileInfo( f ).canonicalFilePath(); return QFileInfo( f ).canonicalFilePath();
} }
@ -371,7 +371,7 @@ System::doChroot() const
} }
Calamares::JobResult Calamares::JobResult
ProcessResult::explainProcess( int ec, const QString& command, const QString& output, int timeout ) ProcessResult::explainProcess( int ec, const QString& command, const QString& output, std::chrono::seconds timeout )
{ {
using Calamares::JobResult; using Calamares::JobResult;
@ -401,7 +401,7 @@ ProcessResult::explainProcess( int ec, const QString& command, const QString& ou
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ), return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ),
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to finish in %2 seconds." ) QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to finish in %2 seconds." )
.arg( command ) .arg( command )
.arg( timeout ) .arg( timeout.count() )
+ outputMessage ); + outputMessage );
//Any other exit code //Any other exit code

View File

@ -27,6 +27,8 @@
#include <QPair> #include <QPair>
#include <QString> #include <QString>
#include <chrono>
namespace CalamaresUtils namespace CalamaresUtils
{ {
class ProcessResult : public QPair< int, QString > class ProcessResult : public QPair< int, QString >
@ -60,16 +62,16 @@ public:
* @param timeout Timeout passed to the process runner, for explaining * @param timeout Timeout passed to the process runner, for explaining
* error code -4 (timeout). * error code -4 (timeout).
*/ */
static Calamares::JobResult explainProcess( int errorCode, const QString& command, const QString& output, int timeout ); static Calamares::JobResult explainProcess( int errorCode, const QString& command, const QString& output, std::chrono::seconds timeout );
/// @brief Convenience wrapper for explainProcess() /// @brief Convenience wrapper for explainProcess()
inline Calamares::JobResult explainProcess( const QString& command, int timeout ) const inline Calamares::JobResult explainProcess( const QString& command, std::chrono::seconds timeout ) const
{ {
return explainProcess( getExitCode(), command, getOutput(), timeout ); return explainProcess( getExitCode(), command, getOutput(), timeout );
} }
/// @brief Convenience wrapper for explainProcess() /// @brief Convenience wrapper for explainProcess()
inline Calamares::JobResult explainProcess( const QStringList& command, int timeout ) const inline Calamares::JobResult explainProcess( const QStringList& command, std::chrono::seconds timeout ) const
{ {
return explainProcess( getExitCode(), command.join( ' ' ), getOutput(), timeout ); return explainProcess( getExitCode(), command.join( ' ' ), getOutput(), timeout );
} }
@ -138,7 +140,7 @@ public:
const QStringList &args, const QStringList &args,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
int timeoutSec = 0 ); std::chrono::seconds timeoutSec = std::chrono::seconds(0) );
/** @brief Convenience wrapper for runCommand(). /** @brief Convenience wrapper for runCommand().
* Runs the command in the location specified through the boolean * Runs the command in the location specified through the boolean
@ -149,7 +151,7 @@ public:
const QStringList &args, const QStringList &args,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
int timeoutSec = 0 ) std::chrono::seconds timeoutSec = std::chrono::seconds(0) )
{ {
return runCommand( return runCommand(
m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost,
@ -163,7 +165,7 @@ public:
inline int targetEnvCall( const QStringList& args, inline int targetEnvCall( const QStringList& args,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
int timeoutSec = 0 ) std::chrono::seconds timeoutSec = std::chrono::seconds(0) )
{ {
return targetEnvCommand( args, workingPath, stdInput, timeoutSec ).first; return targetEnvCommand( args, workingPath, stdInput, timeoutSec ).first;
} }
@ -172,7 +174,7 @@ public:
inline int targetEnvCall( const QString& command, inline int targetEnvCall( const QString& command,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
int timeoutSec = 0 ) std::chrono::seconds timeoutSec = std::chrono::seconds(0) )
{ {
return targetEnvCall( QStringList{ command }, workingPath, stdInput, timeoutSec ); return targetEnvCall( QStringList{ command }, workingPath, stdInput, timeoutSec );
} }
@ -185,7 +187,7 @@ public:
QString& output, QString& output,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
int timeoutSec = 0 ) std::chrono::seconds timeoutSec = std::chrono::seconds(0) )
{ {
auto r = targetEnvCommand( args, workingPath, stdInput, timeoutSec ); auto r = targetEnvCommand( args, workingPath, stdInput, timeoutSec );
output = r.second; output = r.second;
@ -200,45 +202,45 @@ public:
QString& output, QString& output,
const QString& workingPath = QString(), const QString& workingPath = QString(),
const QString& stdInput = QString(), const QString& stdInput = QString(),
int timeoutSec = 0 ) std::chrono::seconds timeoutSec = std::chrono::seconds(0) )
{ {
return targetEnvOutput( QStringList{ command }, output, workingPath, stdInput, timeoutSec ); return targetEnvOutput( QStringList{ command }, output, workingPath, stdInput, timeoutSec );
} }
/** @brief Gets a path to a file in the target system, from the host. /** @brief Gets a path to a file in the target system, from the host.
* *
* @param path Path to the file; this is interpreted * @param path Path to the file; this is interpreted
* from the root of the target system (whatever that may be, * from the root of the target system (whatever that may be,
* but / in the chroot, or / in OEM modes). * but / in the chroot, or / in OEM modes).
* *
* @return The complete path to the target file, from * @return The complete path to the target file, from
* the root of the host system, or empty on failure. * the root of the host system, or empty on failure.
* *
* For instance, during installation where the target root is * For instance, during installation where the target root is
* mounted on /tmp/calamares-something, asking for targetPath("/etc/passwd") * mounted on /tmp/calamares-something, asking for targetPath("/etc/passwd")
* will give you /tmp/calamares-something/etc/passwd. * will give you /tmp/calamares-something/etc/passwd.
* *
* No attempt is made to canonicalize anything, since paths might not exist. * No attempt is made to canonicalize anything, since paths might not exist.
*/ */
DLLEXPORT QString targetPath( const QString& path ) const; DLLEXPORT QString targetPath( const QString& path ) const;
/** @brief Create a (small-ish) file in the target system. /** @brief Create a (small-ish) file in the target system.
* *
* @param path Path to the file; this is interpreted * @param path Path to the file; this is interpreted
* from the root of the target system (whatever that may be, * from the root of the target system (whatever that may be,
* but / in the chroot, or / in OEM modes). * but / in the chroot, or / in OEM modes).
* @param contents Actual content of the file. * @param contents Actual content of the file.
* *
* Will not overwrite files. Returns an empty string if the * Will not overwrite files. Returns an empty string if the
* target file already exists. * target file already exists.
* *
* @return The complete canonical path to the target file from the * @return The complete canonical path to the target file from the
* root of the host system, or empty on failure. (Here, it is * root of the host system, or empty on failure. (Here, it is
* possible to be canonical because the file exists). * possible to be canonical because the file exists).
*/ */
DLLEXPORT QString createTargetFile( const QString& path, const QByteArray& contents ) const; DLLEXPORT QString createTargetFile( const QString& path, const QByteArray& contents ) const;
/** /**
* @brief getTotalMemoryB returns the total main memory, in bytes. * @brief getTotalMemoryB returns the total main memory, in bytes.
* *

View File

@ -35,10 +35,10 @@ namespace CalamaresUtils
static CommandLine get_variant_object( const QVariantMap& m ) static CommandLine get_variant_object( const QVariantMap& m )
{ {
QString command = CalamaresUtils::getString( m, "command" ); QString command = CalamaresUtils::getString( m, "command" );
int timeout = CalamaresUtils::getInteger( m, "timeout", CommandLine::TimeoutNotSet ); int timeout = CalamaresUtils::getInteger( m, "timeout", -1 );
if ( !command.isEmpty() ) if ( !command.isEmpty() )
return CommandLine( command, timeout ); return CommandLine( command, timeout >= 0 ? std::chrono::seconds( timeout ) : CommandLine::TimeoutNotSet() );
cWarning() << "Bad CommandLine element" << m; cWarning() << "Bad CommandLine element" << m;
return CommandLine(); return CommandLine();
} }
@ -50,7 +50,7 @@ static CommandList_t get_variant_stringlist( const QVariantList& l )
for ( const auto& v : l ) for ( const auto& v : l )
{ {
if ( v.type() == QVariant::String ) if ( v.type() == QVariant::String )
retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet ) ); retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet() ) );
else if ( v.type() == QVariant::Map ) else if ( v.type() == QVariant::Map )
{ {
auto command( get_variant_object( v.toMap() ) ); auto command( get_variant_object( v.toMap() ) );
@ -65,13 +65,13 @@ static CommandList_t get_variant_stringlist( const QVariantList& l )
return retl; return retl;
} }
CommandList::CommandList( bool doChroot, int timeout ) CommandList::CommandList( bool doChroot, std::chrono::seconds timeout )
: m_doChroot( doChroot ) : m_doChroot( doChroot )
, m_timeout( timeout ) , m_timeout( timeout )
{ {
} }
CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, int timeout ) CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, std::chrono::seconds timeout )
: CommandList( doChroot, timeout ) : CommandList( doChroot, timeout )
{ {
if ( v.type() == QVariant::List ) if ( v.type() == QVariant::List )
@ -155,7 +155,7 @@ Calamares::JobResult CommandList::run()
QStringList shell_cmd { "/bin/sh", "-c" }; QStringList shell_cmd { "/bin/sh", "-c" };
shell_cmd << processed_cmd; shell_cmd << processed_cmd;
int timeout = i->timeout() >= 0 ? i->timeout() : m_timeout; std::chrono::seconds timeout = i->timeout() >= std::chrono::seconds::zero() ? i->timeout() : m_timeout;
ProcessResult r = System::runCommand( ProcessResult r = System::runCommand(
location, shell_cmd, QString(), QString(), timeout ); location, shell_cmd, QString(), QString(), timeout );

View File

@ -24,6 +24,8 @@
#include <QStringList> #include <QStringList>
#include <QVariant> #include <QVariant>
#include <chrono>
namespace CalamaresUtils namespace CalamaresUtils
{ {
@ -31,23 +33,23 @@ namespace CalamaresUtils
* Each command can have an associated timeout in seconds. The timeout * Each command can have an associated timeout in seconds. The timeout
* defaults to 10 seconds. Provide some convenience naming and construction. * defaults to 10 seconds. Provide some convenience naming and construction.
*/ */
struct CommandLine : public QPair< QString, int > struct CommandLine : public QPair< QString, std::chrono::seconds >
{ {
enum { TimeoutNotSet = -1 }; static inline constexpr std::chrono::seconds TimeoutNotSet() { return std::chrono::seconds(-1); }
/// An invalid command line /// An invalid command line
CommandLine() CommandLine()
: QPair< QString, int >( QString(), TimeoutNotSet ) : QPair( QString(), TimeoutNotSet() )
{ {
} }
CommandLine( const QString& s ) CommandLine( const QString& s )
: QPair< QString, int >( s, TimeoutNotSet ) : QPair( s, TimeoutNotSet() )
{ {
} }
CommandLine( const QString& s, int t ) CommandLine( const QString& s, std::chrono::seconds t )
: QPair< QString, int >( s, t) : QPair( s, t)
{ {
} }
@ -56,7 +58,7 @@ struct CommandLine : public QPair< QString, int >
return first; return first;
} }
int timeout() const std::chrono::seconds timeout() const
{ {
return second; return second;
} }
@ -82,8 +84,8 @@ class CommandList : protected CommandList_t
{ {
public: public:
/** @brief empty command-list with timeout to apply to entries. */ /** @brief empty command-list with timeout to apply to entries. */
CommandList( bool doChroot = true, int timeout = 10 ); CommandList( bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) );
CommandList( const QVariant& v, bool doChroot = true, int timeout = 10 ); CommandList( const QVariant& v, bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) );
~CommandList(); ~CommandList();
bool doChroot() const bool doChroot() const
@ -106,7 +108,7 @@ protected:
private: private:
bool m_doChroot; bool m_doChroot;
int m_timeout; std::chrono::seconds m_timeout;
} ; } ;
} // namespace } // namespace

View File

@ -72,10 +72,13 @@ ProcessJobModule::initFrom( const QVariantMap& moduleDescriptor )
m_command = moduleDescriptor.value( "command" ).toString(); m_command = moduleDescriptor.value( "command" ).toString();
} }
m_secondsTimeout = 30; m_secondsTimeout = std::chrono::seconds( 30 );
if ( moduleDescriptor.contains( "timeout" ) && !moduleDescriptor.value( "timeout" ).isNull() ) if ( moduleDescriptor.contains( "timeout" ) && !moduleDescriptor.value( "timeout" ).isNull() )
{ {
m_secondsTimeout = moduleDescriptor.value( "timeout" ).toInt(); int sec = moduleDescriptor.value( "timeout" ).toInt();
if ( sec < 0 )
sec = 0;
m_secondsTimeout = std::chrono::seconds( sec );
} }
m_runInChroot = false; m_runInChroot = false;
@ -88,7 +91,7 @@ ProcessJobModule::initFrom( const QVariantMap& moduleDescriptor )
ProcessJobModule::ProcessJobModule() ProcessJobModule::ProcessJobModule()
: Module() : Module()
, m_secondsTimeout( 30 ) , m_secondsTimeout( std::chrono::seconds( 30 ) )
, m_runInChroot( false ) , m_runInChroot( false )
{ {
} }

View File

@ -24,6 +24,8 @@
#include "UiDllMacro.h" #include "UiDllMacro.h"
#include <chrono>
namespace Calamares namespace Calamares
{ {
@ -46,7 +48,7 @@ private:
QString m_command; QString m_command;
QString m_workingPath; QString m_workingPath;
int m_secondsTimeout; std::chrono::seconds m_secondsTimeout;
bool m_runInChroot; bool m_runInChroot;
job_ptr m_job; job_ptr m_job;
}; };

View File

@ -170,7 +170,7 @@ ContextualProcessJob::setConfigurationMap( const QVariantMap& configurationMap )
continue; continue;
} }
CalamaresUtils::CommandList* commands = new CalamaresUtils::CommandList( valueiter.value(), !dontChroot, timeout ); CalamaresUtils::CommandList* commands = new CalamaresUtils::CommandList( valueiter.value(), !dontChroot, std::chrono::seconds( timeout ) );
binding->append( valueString, commands ); binding->append( valueString, commands );
} }

View File

@ -74,8 +74,8 @@ InitcpioJob::exec()
cDebug() << "Updating initramfs with kernel" << m_kernel; cDebug() << "Updating initramfs with kernel" << m_kernel;
auto r = CalamaresUtils::System::instance()->targetEnvCommand( auto r = CalamaresUtils::System::instance()->targetEnvCommand(
{ "mkinitcpio", "-p", m_kernel }, QString(), QString(), 0 ); { "mkinitcpio", "-p", m_kernel }, QString(), QString() /* no timeout , 0 */ );
return r.explainProcess( "mkinitcpio", 10 ); return r.explainProcess( "mkinitcpio", std::chrono::seconds( 10 ) /* fake timeout */ );
} }
void void
@ -89,7 +89,7 @@ InitcpioJob::setConfigurationMap( const QVariantMap& configurationMap )
else if ( m_kernel == "$uname" ) else if ( m_kernel == "$uname" )
{ {
auto r = CalamaresUtils::System::runCommand( auto r = CalamaresUtils::System::runCommand(
CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), 3 ); CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), std::chrono::seconds( 3 ) );
if ( r.getExitCode() == 0 ) if ( r.getExitCode() == 0 )
{ {
m_kernel = r.getOutput(); m_kernel = r.getOutput();

View File

@ -63,8 +63,8 @@ InitramfsJob::exec()
// And then do the ACTUAL work. // And then do the ACTUAL work.
auto r = CalamaresUtils::System::instance()->targetEnvCommand( auto r = CalamaresUtils::System::instance()->targetEnvCommand(
{ "update-initramfs", "-k", m_kernel, "-c", "-t" }, QString(), QString(), 0 ); { "update-initramfs", "-k", m_kernel, "-c", "-t" }, QString(), QString() /* no timeout, 0 */ );
return r.explainProcess( "update-initramfs", 10 ); return r.explainProcess( "update-initramfs", std::chrono::seconds( 10 ) /* fake timeout */ );
} }
@ -79,7 +79,7 @@ InitramfsJob::setConfigurationMap( const QVariantMap& configurationMap )
else if ( m_kernel == "$uname" ) else if ( m_kernel == "$uname" )
{ {
auto r = CalamaresUtils::System::runCommand( auto r = CalamaresUtils::System::runCommand(
CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), 3 ); CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), std::chrono::seconds( 3 ) );
if ( r.getExitCode() == 0 ) if ( r.getExitCode() == 0 )
{ {
m_kernel = r.getOutput(); m_kernel = r.getOutput();

View File

@ -71,7 +71,7 @@ struct LuksDevice
* Given a list of partitions (as set up by the partitioning module, * Given a list of partitions (as set up by the partitioning module,
* so there's maps with keys inside), returns just the list of * so there's maps with keys inside), returns just the list of
* luks passphrases for each device. * luks passphrases for each device.
*/ */
static QList< LuksDevice > static QList< LuksDevice >
getLuksDevices( const QVariantList& list ) getLuksDevices( const QVariantList& list )
{ {
@ -130,7 +130,7 @@ static bool
setupLuks( const LuksDevice& d ) setupLuks( const LuksDevice& d )
{ {
auto r = CalamaresUtils::System::instance()->targetEnvCommand( auto r = CalamaresUtils::System::instance()->targetEnvCommand(
{ "cryptsetup", "luksAddKey", d.device, keyfile }, QString(), d.passphrase, 15 ); { "cryptsetup", "luksAddKey", d.device, keyfile }, QString(), d.passphrase, std::chrono::seconds( 15 ) );
if ( r.getExitCode() != 0 ) if ( r.getExitCode() != 0 )
{ {
cWarning() << "Could not configure LUKS keyfile on" << d.device << ':' << r.getOutput() << "(exit code" cWarning() << "Could not configure LUKS keyfile on" << d.device << ':' << r.getOutput() << "(exit code"

View File

@ -75,7 +75,7 @@ ShellProcessJob::setConfigurationMap( const QVariantMap& configurationMap )
if ( configurationMap.contains( "script" ) ) if ( configurationMap.contains( "script" ) )
{ {
m_commands = new CalamaresUtils::CommandList( configurationMap.value( "script" ), !dontChroot, timeout ); m_commands = new CalamaresUtils::CommandList( configurationMap.value( "script" ), !dontChroot, std::chrono::seconds( timeout ) );
if ( m_commands->isEmpty() ) if ( m_commands->isEmpty() )
cDebug() << "ShellProcessJob: \"script\" contains no commands for" << moduleInstanceKey(); cDebug() << "ShellProcessJob: \"script\" contains no commands for" << moduleInstanceKey();
} }

View File

@ -34,6 +34,8 @@
QTEST_GUILESS_MAIN( ShellProcessTests ) QTEST_GUILESS_MAIN( ShellProcessTests )
using CommandList = CalamaresUtils::CommandList; using CommandList = CalamaresUtils::CommandList;
using std::operator""s;
ShellProcessTests::ShellProcessTests() ShellProcessTests::ShellProcessTests()
{ {
@ -68,8 +70,9 @@ ShellProcessTests::testProcessListSampleConfig()
CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) );
QVERIFY( !cl.isEmpty() ); QVERIFY( !cl.isEmpty() );
QCOMPARE( cl.count(), 3 ); QCOMPARE( cl.count(), 3 );
QCOMPARE( cl.at(0).timeout(), -1 );
QCOMPARE( cl.at(2).timeout(), 3600 ); // slowloris QCOMPARE( cl.at(0).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() );
QCOMPARE( cl.at(2).timeout(), 3600s ); // slowloris
} }
void ShellProcessTests::testProcessListFromList() void ShellProcessTests::testProcessListFromList()
@ -105,9 +108,10 @@ script: "ls /tmp"
)" ); )" );
CommandList cl( CommandList cl(
CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) );
QVERIFY( !cl.isEmpty() ); QVERIFY( !cl.isEmpty() );
QCOMPARE( cl.count(), 1 ); QCOMPARE( cl.count(), 1 );
QCOMPARE( cl.at(0).timeout(), 10 ); QCOMPARE( cl.at(0).timeout(), 10s );
QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) );
// Not a string // Not a string
@ -118,7 +122,6 @@ script: false
CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) );
QVERIFY( cl1.isEmpty() ); QVERIFY( cl1.isEmpty() );
QCOMPARE( cl1.count(), 0 ); QCOMPARE( cl1.count(), 0 );
} }
void ShellProcessTests::testProcessFromObject() void ShellProcessTests::testProcessFromObject()
@ -130,9 +133,10 @@ script:
)" ); )" );
CommandList cl( CommandList cl(
CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) );
QVERIFY( !cl.isEmpty() ); QVERIFY( !cl.isEmpty() );
QCOMPARE( cl.count(), 1 ); QCOMPARE( cl.count(), 1 );
QCOMPARE( cl.at(0).timeout(), 20 ); QCOMPARE( cl.at(0).timeout(), 20s );
QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) );
} }
@ -148,9 +152,9 @@ script:
CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) );
QVERIFY( !cl.isEmpty() ); QVERIFY( !cl.isEmpty() );
QCOMPARE( cl.count(), 2 ); QCOMPARE( cl.count(), 2 );
QCOMPARE( cl.at(0).timeout(), 12 ); QCOMPARE( cl.at(0).timeout(), 12s );
QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) );
QCOMPARE( cl.at(1).timeout(), -1 ); // not set QCOMPARE( cl.at(1).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() ); // not set
} }
void ShellProcessTests::testRootSubstitution() void ShellProcessTests::testRootSubstitution()
@ -182,30 +186,31 @@ script:
QVERIFY( gs != nullptr ); QVERIFY( gs != nullptr );
qDebug() << "Expect WARNING, ERROR, WARNING"; qDebug() << "Expect WARNING, ERROR, WARNING";
// Doesn't use @@ROOT@@, so no failures // Doesn't use @@ROOT@@, so no failures
QVERIFY( bool(CommandList(plainScript, false, 10 ).run()) ); QVERIFY( bool(CommandList(plainScript, false, 10s ).run()) );
// Doesn't use @@ROOT@@, but does chroot, so fails // Doesn't use @@ROOT@@, but does chroot, so fails
QVERIFY( !bool(CommandList(plainScript, true, 10 ).run()) ); QVERIFY( !bool(CommandList(plainScript, true, 10s ).run()) );
// Does use @@ROOT@@, which is not set, so fails // Does use @@ROOT@@, which is not set, so fails
QVERIFY( !bool(CommandList(rootScript, false, 10 ).run()) ); QVERIFY( !bool(CommandList(rootScript, false, 10s ).run()) );
// .. fails for two reasons // .. fails for two reasons
QVERIFY( !bool(CommandList(rootScript, true, 10 ).run()) ); QVERIFY( !bool(CommandList(rootScript, true, 10s ).run()) );
gs->insert( "rootMountPoint", "/tmp" ); gs->insert( "rootMountPoint", "/tmp" );
// Now that the root is set, two variants work .. still can't // Now that the root is set, two variants work .. still can't
// chroot, unless the rootMountPoint contains a full system, // chroot, unless the rootMountPoint contains a full system,
// *and* we're allowed to chroot (ie. running tests as root). // *and* we're allowed to chroot (ie. running tests as root).
qDebug() << "Expect no output."; qDebug() << "Expect no output.";
QVERIFY( bool(CommandList(plainScript, false, 10 ).run()) ); QVERIFY( bool(CommandList(plainScript, false, 10s ).run()) );
QVERIFY( bool(CommandList(rootScript, false, 10 ).run()) ); QVERIFY( bool(CommandList(rootScript, false, 10s ).run()) );
qDebug() << "Expect ERROR"; qDebug() << "Expect ERROR";
// But no user set yet // But no user set yet
QVERIFY( !bool(CommandList(userScript, false, 10 ).run()) ); QVERIFY( !bool(CommandList(userScript, false, 10s ).run()) );
// Now play dangerous games with shell expansion // Now play dangerous games with shell expansion
gs->insert( "username", "`id -u`" ); gs->insert( "username", "`id -u`" );
QVERIFY( bool(CommandList(userScript, false, 10 ).run()) ); QVERIFY( bool(CommandList(userScript, false, 10s ).run()) );
} }

View File

@ -125,7 +125,7 @@ sed -i "s,URI =.*,URI = http://releases.neon.kde.org/meta-release/${MACHINE_ID},
sed -i "s,URI_LTS =.*,URI_LTS = http://releases.neon.kde.org/meta-release-lts/${MACHINE_ID}," /etc/update-manager/meta-release sed -i "s,URI_LTS =.*,URI_LTS = http://releases.neon.kde.org/meta-release-lts/${MACHINE_ID}," /etc/update-manager/meta-release
true true
)x"), )x"),
1); std::chrono::seconds( 1 ) );
if ( r == 0 ) if ( r == 0 )
return Calamares::JobResult::ok(); return Calamares::JobResult::ok();

View File

@ -158,7 +158,7 @@ CreateUserJob::exec()
if ( commandResult.getExitCode() ) if ( commandResult.getExitCode() )
{ {
cError() << "useradd failed" << commandResult.getExitCode(); cError() << "useradd failed" << commandResult.getExitCode();
return commandResult.explainProcess( useradd, 10 /* bogus timeout */ ); return commandResult.explainProcess( useradd, std::chrono::seconds( 10 ) /* bogus timeout */ );
} }
commandResult = CalamaresUtils::System::instance()->targetEnvCommand( commandResult = CalamaresUtils::System::instance()->targetEnvCommand(
@ -166,7 +166,7 @@ CreateUserJob::exec()
if ( commandResult.getExitCode() ) if ( commandResult.getExitCode() )
{ {
cError() << "usermod failed" << commandResult.getExitCode(); cError() << "usermod failed" << commandResult.getExitCode();
return commandResult.explainProcess( "usermod", 10 ); return commandResult.explainProcess( "usermod", std::chrono::seconds( 10 ) /* bogus timeout */ );
} }
QString userGroup = QString( "%1:%2" ).arg( m_userName ).arg( m_userName ); QString userGroup = QString( "%1:%2" ).arg( m_userName ).arg( m_userName );
@ -176,7 +176,7 @@ CreateUserJob::exec()
if ( commandResult.getExitCode() ) if ( commandResult.getExitCode() )
{ {
cError() << "chown failed" << commandResult.getExitCode(); cError() << "chown failed" << commandResult.getExitCode();
return commandResult.explainProcess( "chown", 10 ); return commandResult.explainProcess( "chown", std::chrono::seconds( 10 ) /* bogus timeout */ );
} }
return Calamares::JobResult::ok(); return Calamares::JobResult::ok();