diff --git a/net/alien/inc/LinkDef.h b/net/alien/inc/LinkDef.h index a069accc5ff39f13abe88a1b6e9631b52e9523dd..8949432c5e7bea66d20b8d00ceed7b12b2dfaede 100644 --- a/net/alien/inc/LinkDef.h +++ b/net/alien/inc/LinkDef.h @@ -17,4 +17,5 @@ #pragma link C++ class TAlienDirectoryEntry; #pragma link C++ class TAlienSystem; #pragma link C++ class TAlienJobStatusList; +#pragma link C++ class TAlienPackage; #endif diff --git a/net/alien/inc/TAlienPackage.h b/net/alien/inc/TAlienPackage.h new file mode 100644 index 0000000000000000000000000000000000000000..132d33ff64c0286111707943e9d200c98ca70cc2 --- /dev/null +++ b/net/alien/inc/TAlienPackage.h @@ -0,0 +1,107 @@ +// @(#)root/alien:$Id$ +// Author: Lucia Jancurova/Andreas-Joachim Peters 1/10/2007 + +/************************************************************************* + * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TAlienPackage +#define ROOT_TAlienPackage + +#ifndef ROOT_Rtypes +#include "Rtypes.h" +#endif +#ifndef ROOT_TList +#include "TList.h" +#endif +#ifndef ROOT_TGrid +#include "TGrid.h" +#endif + +////////////////////////////////////////////////////////////////////////// +// // +// TAlienPackage // +// // +// Class providing package management functionality like the AliEn // +// Package Management System. // +// Allows to setup software packages on a local desktop like in the // +// GRID environment. // +// // +////////////////////////////////////////////////////////////////////////// + +class TAlienPackage { + +private: + TString fName; // package principal name + TString fVersion; // package version + TString fPlatform; // package platform + TString fInstallationDirectory; // installation directory + TString fAliEnMainPackageDir; // path to alien packages in the AliEn FC + TString fPostInstallCommand; // command to execute for postinstall + TString fEnableCommand; // command to enable the package + TList *fInstallList; // package list with names of dependency packages + TList *fPackages; // package list TPackage with this and dependency packages + Int_t fDebugLevel; // internal debug level + Bool_t fEnabled; // true if package is enabled for execution + + Bool_t PostInstall (TString name, TString version); // runs the postinstall procedure for this package + Bool_t InstallSinglePackage (TString name, TString version, Bool_t isDep = kFALSE); // installs the defined package without dependencies + Bool_t InstallAllPackages (); // installs the defined package + all dependency packages + + public: + TAlienPackage (); + + TAlienPackage(const char *name, + const char *version, + const char *platform, + const char *installationdirectory = "/var/tmp/alien/packages"); + + virtual ~ TAlienPackage (); + + Bool_t Enable(); // install/enable the defined package + const char *GetEnable(); // return shell command to enable package + Bool_t Exec(const char *cmdline); // execute <cmd> with this package + Bool_t UnInstall(); // uninstall the defined package + Bool_t ReInstall(); // reinstall the defined package + Bool_t CheckDependencies(); // get all the dependencies of a package + + Bool_t IsDirectory(const char *dir1, const char *str); // check for <str> in GRID directory <dir1> + Bool_t CheckDirectories(TString name, TString version); // check that the defined package is existing as an alien package directory + + void SetName(const TString & theValue) { fName = theValue; } + // set the name of the package + TString GetName() const { return fName; } + // get the name of the package + void SetVersion(const TString & theValue) { fVersion = theValue; } + // set the version of the package + TString GetVersion() const { return fVersion; } + // get the version of the package + void SetPlatform(const TString & theValue) { fPlatform = theValue; } + // set the platform for the package + TString GetPlatform() const { return fPlatform; } + // get the platform for the package + void SetInstallationDirectory(const TString & theValue) { fInstallationDirectory = theValue; } + // set the installation directory + TString GetInstallationDirectory() const { return fInstallationDirectory; } + // get the installation directory + void SetAliEnMainPackageDir(const TString & theValue) { fAliEnMainPackageDir = theValue; } + // set the alien path to look for the named package + TString GetAliEnMainPackageDir() const { return fAliEnMainPackageDir; } + // get the alien path to look for the named package + void SetInstallList(TList * theValue) { fInstallList = theValue; } + // set the install(dependency) package list + TList *GetInstallList() const { return fInstallList; } + // get the install(dependency) package list; + void SetDebugLevel(Int_t & theValue) { fDebugLevel = theValue; } + // set the internal debug level + Int_t GetDebugLevel() { return fDebugLevel; } + // get the internal debug level + + ClassDef (TAlienPackage, 0); // Alien package interface +}; + +#endif diff --git a/net/alien/src/TAlienPackage.cxx b/net/alien/src/TAlienPackage.cxx new file mode 100644 index 0000000000000000000000000000000000000000..306e15ba12f84e7af0d12523245e84c29569422f --- /dev/null +++ b/net/alien/src/TAlienPackage.cxx @@ -0,0 +1,523 @@ +// @(#)root/alien:$Id$ +// Author: Lucia Jancurova/Andreas-Joachim Peters 1/10/2007 + +/************************************************************************* + * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#include "Riostream.h" +#include "TSystem.h" +#include "TGridResult.h" +#include "TFile.h" +#include "TObjString.h" +#include "TObjArray.h" +#include "TError.h" +#include "TAlienPackage.h" + +////////////////////////////////////////////////////////////////////////// +// // +// TAlienPackage // +// // +// Class providing package management functionality like the AliEn // +// Package Management System. // +// Allows to setup software packages on a local desktop like in the // +// GRID environment and to execute the contained programs. // +// Registered Dependencies are automatically resolved and missing // +// packages are automatically installed. // +// Currently there is no support for 'source' packages. // +// The desired platform has to be specified in the constructor. // +// The default constructor takes packages from the global package // +// section in AliEn. If you want to install a user package, you have to // +// set the AliEn package directory to your local package directory using// +// 'package->SetAliEnMainPackageDir("/alice/cern.ch/user/..../packages")// +// // +// ---------------------------------------------------------------------///////////////////////// +// Examples of use: // +// root [0] TAlienPackage* package = new TAlienPackage("AliRoot","v4-07-Rev-01","Linux-i686"); // +// root [1] package->Exec("aliroot -b -q ") // +// // +// root [0] TAlienPackage* package = new TAlienPackage("ROOT","v5-16-00","Linux-i686"); // +// root [1] package->Exec("root -b -q ") // +///////////////////////////////////////////////////////////////////////////////////////////////// + + + +ClassImp (TAlienPackage) + +//______________________________________________________________________________ +TAlienPackage::TAlienPackage() : fInstallList (0), fPackages (0), fDebugLevel (0) +{ + // Default constructor of a AliEn package constructing a ROOT:v5-16-00 for Linux-i686. + + fName = "ROOT"; + fVersion = "v5-16-00"; + fPlatform = "Linux-i686"; + fAliEnMainPackageDir = "/alice/packages"; + fInstallationDirectory = "/var/tmp/alien/packages"; + fPostInstallCommand = "post_install"; + fEnableCommand = ""; + + if (gDebug > 0) + Info ("TAlienPackage", + "\tPackage=%s Version=%s Platform=%s Installdir=%s AlienInstalldir=%s PostInstall=%s", + fName.Data (), fVersion.Data (), fPlatform.Data (), + fInstallationDirectory.Data (), fAliEnMainPackageDir.Data (), + fPostInstallCommand.Data ()); + if (!gGrid) + gGrid = TGrid::Connect ("alien://"); + + if (!fInstallList) + fInstallList = new TList (); + if (!fPackages) + fPackages = new TList (); + + fEnabled = kFALSE; + fPackages->SetOwner (kFALSE); +} + +//______________________________________________________________________________ +TAlienPackage::TAlienPackage(const char *name, const char *version, + const char *platform, + const char *installationdirectory) : + fInstallList (0), fPackages (0), fDebugLevel (0) +{ + // Constructor of a AliEn package. + + fName = name; + + fVersion = version; + + fAliEnMainPackageDir = "/alice/packages"; + fInstallationDirectory = installationdirectory; + fPostInstallCommand = "post_install"; + fEnableCommand = ""; + fPlatform = platform; + fEnabled = kFALSE; + + if (gDebug > 0) + Info ("TAlienPackage", + "\tPackage=%s Version=%s Platform=%s Installdir=%s AlienInstalldir=%s PostInstall=%s", + name, version, platform, installationdirectory, + fAliEnMainPackageDir.Data (), fPostInstallCommand.Data ()); + + if (!gGrid) + gGrid = TGrid::Connect ("alien://"); + + if (!fInstallList) + fInstallList = new TList (); + + if (!fPackages) + fPackages = new TList (); + fPackages->SetOwner (kFALSE); +} + +//______________________________________________________________________________ +TAlienPackage::~TAlienPackage() +{ + // Destructor. + + if (GetDebugLevel () > 2) + Info ("~TAlienPackage", "\tDestr: Package=%s Version=%s Platform=%s", + fName.Data (), fVersion.Data (), fPlatform.Data ()); + SafeDelete (fInstallList); +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::Enable() +{ + // Install/enable an AliEn package on the local computer. + + fInstallList->Clear (); + if (GetDebugLevel () > 1) + Info ("Install", "\t\tInstalling Package=%s Version=%s Platform=%s", + fName.Data (), fVersion.Data (), fPlatform.Data ()); + + if (CheckDirectories (fName, fVersion) == kFALSE) + return kFALSE; + + if (CheckDependencies () == kFALSE) + return kFALSE; + + if (InstallAllPackages () == kFALSE) + return kFALSE; + + gSystem->Exec(Form("mkdir -p %s/%s/%s/%s ; touch %s/%s/%s/%s/.safeguard", + fInstallationDirectory.Data (), fName.Data (), fVersion.Data (), + fVersion.Data (), fInstallationDirectory.Data (), fName.Data (), + fVersion.Data (), fVersion.Data ())); + + fEnabled = kTRUE; + return kTRUE; +} + +//______________________________________________________________________________ +const char *TAlienPackage::GetEnable () +{ + // Return shell command to enable package. + + fEnableCommand = + Form ("%s/%s/%s/.alienEnvironment %s/%s/%s ", + fInstallationDirectory.Data (), fName.Data (), fVersion.Data (), + fInstallationDirectory.Data (), fName.Data (), fVersion.Data ()); + return fEnableCommand.Data (); +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::UnInstall () +{ + // Uninstall a package e.g. remove it from the local disk. + + gSystem->Exec(Form + ("test -e %s/%s/%s/%s/.safeguard && rm -rf %s/%s/%s", + fInstallationDirectory.Data (), fName.Data (), fVersion.Data (), + fVersion.Data (), fInstallationDirectory.Data (), fName.Data (), + fVersion.Data ())); + fEnabled = kFALSE; + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::IsDirectory (const char *dir1, const char *str) +{ + // Check that <str> is listed in GRID directory <dir1>. + + TGridResult *result = gGrid->Ls (dir1); + Int_t i = 0; + while (result->GetFileName (i)) { + if (TString (result->GetFileName (i)) == str) { + return kTRUE; + } + i++; + } + + return kFALSE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::CheckDirectories (TString name, TString version) +{ + // Check the name and version directory of package/version given. + + TString s(GetAliEnMainPackageDir()); + + if ((IsDirectory (s.Data (), name.Data ())) == kTRUE) { + if (GetDebugLevel () > 1) + Info ("CheckDirectories", "\t%s/%s exists.", s.Data (), name.Data ()); + + s += "/" + name; + if ((IsDirectory (s, version.Data ())) == kTRUE) { + if (GetDebugLevel () > 1) + Info ("CheckDirectories", "\t%s/%s exist.", s.Data (), version.Data ()); + + s += "/" + version; + if ((IsDirectory (s, GetPlatform ().Data ())) == kTRUE) { + if (GetDebugLevel () > 1) + Info ("CheckDirectories", "\t%s/%s exist.", s.Data (), GetPlatform ().Data ()); + return kTRUE; + } else { + Error ("CheckDirectories", "\t%s/%s does not exist.", s.Data (), GetPlatform ().Data ()); + } + } else { + Error ("CheckDirectories", "\t%s/%s does not exist.", s.Data (), version.Data ()); + } + } else { + Info ("CheckDirectories", "\t%s/%s exists.", s.Data (), name.Data ()); + } + + return kFALSE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::ReInstall () +{ + // Reinstalls a package e.g. uninstall + install. + + if (UnInstall () == kFALSE) + return kFALSE; + + if (Enable () == kFALSE) + return kFALSE; + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::PostInstall (TString name, TString version) +{ + // Execute post_install procedure for a package. + + TGridResult *result = + gGrid->Command (Form + ("showTagValue -z %s/%s/%s PackageDef", + fAliEnMainPackageDir.Data (), name.Data (), version.Data ())); + TString post_install (result->GetKey (0, "post_install")); + + if (post_install.IsNull () == kTRUE) { + if (GetDebugLevel () > 0) + Info ("PostInstall", + "\tNo post install procedure defined in AliEn."); + return kTRUE; + } + + if (GetDebugLevel () > 0) + Info ("PostInstall", + "\tDownloading PostInstall for Package=%s Version=%s", + name.Data (), version.Data ()); + + if (!TFile::Cp(Form("alien://%s", post_install.Data ()), + Form("%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (), + version.Data (), fPostInstallCommand.Data ()))) { + Error ("PostInstall", "\tCannot download the PostInstall script %s!", post_install.Data ()); + return kFALSE; + } + + gSystem->ChangeDirectory (Form + ("%s/%s/%s", fInstallationDirectory.Data (), + name.Data (), version.Data ())); + gSystem->Exec (Form ("chmod +x %s", fPostInstallCommand.Data ())); + gSystem->Exec (Form ("./%s %s/%s/%s", fPostInstallCommand.Data (), + fInstallationDirectory.Data (), name.Data (), version.Data ())); + + if (GetDebugLevel () > 1) + Info ("PostInstall", + "\tExecuted PostInstall for Package=%s Version=%s ", name.Data (), + version.Data ()); + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::Exec (const char *cmdline) +{ + // Execute package command. + + TString fullline = ""; + + if (!fEnabled) { + if (!Enable ()) + return kFALSE; + } + + for (Int_t j = 0; j < fPackages->GetEntries (); j++) { + TAlienPackage *package = (TAlienPackage *) fPackages->At (j); + fullline += package->GetEnable (); + fullline += " "; + } + + fullline += cmdline; + + Info("Exec", "\t\tExecuting Package=%s Version=%s \"%s\"", fName.Data (), + fVersion.Data (), fullline.Data ()); + + gSystem->Exec(fullline.Data()); + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::CheckDependencies () +{ + // Check the dependency packages of this package. + + TString path (Form("%s/%s/%s", fAliEnMainPackageDir.Data (), fName.Data (), + fVersion.Data ())); + + TGridResult *result = + gGrid->Command (Form ("showTagValue -z %s PackageDef", path.Data ())); + + TString strDep (result->GetKey (0, "dependencies")); + + if (strDep.IsNull () == kTRUE) { + if (GetDebugLevel () > 0) + Info ("CheckDepencencies", "\tFound no dependencies ... "); + TObjString *strObj = + new TObjString (Form ("%s::%s", fName.Data (), fVersion.Data ())); + fInstallList->Add (strObj); + return kTRUE; + } + + TObjArray *strDeps = strDep.Tokenize (","); + + if (GetDebugLevel () > 0) + Info ("CheckDepencencies", "\tFound %d dependencies ... ", + strDeps->GetEntries ()); + + for (Int_t i = 0; i < strDeps->GetEntries (); i++) { + TObjString *strObj = (TObjString *) strDeps->At (i); + TObjArray *strDepsPackgAndVer = strObj->GetString ().Tokenize ("@"); + TObjString *strObj2 = (TObjString *) strDepsPackgAndVer->At (1); + + if (GetDebugLevel () > 2) + Info ("CheckDependencies", "\t[%d] Dep. Package=%s", i, + strObj2->GetString ().Data ()); + fInstallList->Add (strObj2); + } + + TObjString *strObj = new TObjString (Form ("%s::%s", fName.Data (), fVersion.Data ())); + fInstallList->Add (strObj); + + for (Int_t j = 0; j < fInstallList->GetEntries (); j++) { + TObjString *strObj = (TObjString *) fInstallList->At (j); + TObjArray *strDepsPackgOrVer = strObj->GetString ().Tokenize ("::"); + TObjString *strObjPackage = (TObjString *) strDepsPackgOrVer->At (0); + TObjString *strObjVersion = (TObjString *) strDepsPackgOrVer->At (1); + + if (GetDebugLevel () > 2) + Info ("CheckDepencencies", "\t[%d] Name=%s Version=%s", j, + strObjPackage->GetString ().Data (), + strObjVersion->GetString ().Data ()); + + if (CheckDirectories(strObjPackage->GetString (), strObjVersion->GetString ()) == kFALSE) + return kFALSE; + } + + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::InstallSinglePackage(TString name, TString version, Bool_t isDep) +{ + // Install a single package. + + Info ("InstallSinglePackage", "\t%s %s", name.Data (), version.Data ()); + // install a package without dependencies + TString s1 (Form ("%s/%s/%s/%s", fAliEnMainPackageDir.Data (), name.Data (), + version.Data (), fPlatform.Data ())); + TString s2 (Form ("%s(%s)", name.Data (), version.Data ())); + TString s3 (Form ("%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (), + version.Data (), version.Data ())); + TString s4 (Form ("%s/%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (), + version.Data (), version.Data (), fPlatform.Data ())); + TString s5 (Form ("%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (), + version.Data (), fPlatform.Data ())); + TString s6 (Form ("%s/%s", fAliEnMainPackageDir.Data (), name.Data ())); + TString s7 (Form ("%s/%s/%s", fInstallationDirectory.Data (), name.Data (), + version.Data ())); + TString s8 (Form ("%s/%s/%s/%s/.safeguard", fInstallationDirectory.Data (), + name.Data (), version.Data (), version.Data ())); + + if (gSystem->AccessPathName (s8.Data ()) == 0) { + if (isDep == kFALSE) { + if (GetDebugLevel () > 0) { + Warning ("InstallSinglePackage", + "\tPackage=%s exists in /%s directory.", + s2.Data (), s3.Data ()); + Warning ("InstallSinglePackage", + "\tYou might use function UnInstall() before Enable(), or do ReInstall() !!!!"); + } + return kTRUE; + } else { + return kTRUE; + } + } + + if (GetDebugLevel () > 1) + Info ("InstallSinglePackage", "\tCopying from alien://%s to %s ", + s1.Data (), s5.Data ()); + + gSystem->Exec (Form ("mkdir -p %s", s3.Data ())); + + if (gSystem->AccessPathName (s3.Data ())) { + Error ("InstallSinglePackage", "\tCouldn't create directory %s !", + s3.Data ()); + return kFALSE; + } + + if (!TFile::Cp (Form ("alien://%s", s1.Data ()), Form ("%s", s5.Data ()))) { + Error ("InstallSinglePackage", "\tCouldn't copy alien://%s -> %s", + s1.Data (), s5.Data ()); + return kFALSE; + } + + if (GetDebugLevel () > 2) + Info ("InstallSinglePackage", "\tEntering directory %s ", s7.Data ()); + + if (!gSystem->ChangeDirectory (Form ("%s", s7.Data ()))) { + Error ("InstallSinglePackage", "\tCannot change into directory %s", + s7.Data ()); + return kFALSE; + } + + if (GetDebugLevel () > 2) + Info ("InstallSinglePackage", "\tUnpacking the package %s ...", + s2.Data ()); + + gSystem->Exec (Form ("tar -xzf %s", fPlatform.Data ())); + + if (GetDebugLevel () > 2) + Info ("InstallSinglePackage", "\tUnpacking the package %s DONE ...", + s2.Data ()); + + gSystem->Exec (Form ("rm -f %s", fPlatform.Data ())); + + if (GetDebugLevel () > 2) + Info ("InstallSinglePackage", + "\tCopying PostInstall alien://%s/%s -> %s", s6.Data (), + fPostInstallCommand.Data (), s7.Data ()); + + if (!PostInstall (name, version)) { + Error ("InstallSinglePackage", + "\tPostInstall procedure failed for package %s failed!", + s2.Data ()); + return kFALSE; + } + + return kTRUE; +} + +//______________________________________________________________________________ +Bool_t TAlienPackage::InstallAllPackages () +{ + // Installs a package and all its direct dependencies. + + Bool_t isDep = kFALSE; + + Info ("InstallAllPackages", "\tPackage=%s Version=%s", fName.Data (), + fVersion.Data ()); + + for (Int_t j = 0; j < fPackages->GetEntries (); j++) { + TAlienPackage *package = (TAlienPackage *) fPackages->At (j); + if (package && (package != this)) + delete package; + } + + fPackages->Clear (); + + for (Int_t j = 0; j < fInstallList->GetEntries (); j++) { + TObjString *strObj = (TObjString *) fInstallList->At (j); + + TObjArray *strDepsPackgOrVer = strObj->GetString ().Tokenize ("::"); + TObjString *strObjPackage = (TObjString *) strDepsPackgOrVer->At (0); + TObjString *strObjVersion = (TObjString *) strDepsPackgOrVer->At (1); + if (GetDebugLevel () > 1) + Info ("InstallAllPackages", "\tPackage=%s Version=%s", + strObjPackage->GetString ().Data (), + strObjVersion->GetString ().Data ()); + + if (j < (fInstallList->GetEntries () - 1)) + isDep = kTRUE; + else + isDep = kFALSE; + + if (j == (fInstallList->GetEntries () - 1)) { + if (InstallSinglePackage(strObjPackage->GetString (), strObjVersion->GetString (), isDep) == kFALSE) + return kFALSE; + fPackages->Add ((TObject *) this); + } else { + TAlienPackage *newpackage = new TAlienPackage(strObjPackage->GetName(), + strObjVersion->GetName(), + fPlatform.Data()); + if (newpackage) { + if (!newpackage->Enable ()) + return kFALSE; + } else { + return kFALSE; + } + + fPackages->Add ((TObject *) newpackage); + } + } + + return kTRUE; +}