123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #include "deploy.hpp"
- #include "environment.hpp"
- #include "jptree.hpp"
- #include "jexcept.hpp"
- #include "jencrypt.hpp"
- #include "xslprocessor.hpp"
- #include "DeploymentEngine.hpp"
- #include "ThorDeploymentEngine.hpp"
- #include "EspDeploymentEngine.hpp"
- #include "dalideploymentengine.hpp"
- #include "RoxieDeploymentEngine.hpp"
- #include "configgenengine.hpp"
- #include "espconfiggenengine.hpp"
- #include "thorconfiggenengine.hpp"
- //---------------------------------------------------------------------------
- // CEnvironmentDeploymentEngine
- //---------------------------------------------------------------------------
- class CEnvironmentDeploymentEngine : public CInterface, implements IEnvDeploymentEngine
- {
- public:
- IMPLEMENT_IINTERFACE;
- //---------------------------------------------------------------------------
- // CEnvironmentDeploymentEngine
- //---------------------------------------------------------------------------
- CEnvironmentDeploymentEngine(IConstEnvironment &environment, IDeploymentCallback& callback,
- IPropertyTree* pSelectedComponents)
- : m_environment(environment),
- m_transform(NULL),
- m_abort(false),
- m_espModuleCount(0),
- m_tempFileCount(0),
- m_bLinuxDeployment(false),
- m_bInteractiveMode(true)
- {
- m_pCallback.set(&callback);
- m_validateAllXsl.clear().append("validateAll.xsl");
- if (pSelectedComponents)
- {
- initXML(pSelectedComponents);
-
- Owned<IPropertyTreeIterator> it = pSelectedComponents->getElements("*");
- ForEach(*it)
- {
- IPropertyTree* pComponent = &it->query();
- IDeploymentEngine* pEngine = addProcess(pComponent->queryName(), pComponent->queryProp("@name"));
-
- Owned<IPropertyTreeIterator> iter = pComponent->getElements("*");
- if (iter->first())
- {
- pEngine->resetInstances();
- ForEach(*iter)
- {
- IPropertyTree* pChild = &iter->query();
- const char* tagName = pChild->queryName();
- const char* instName = pChild->queryProp("@name");
- pEngine->addInstance(tagName, instName);
-
- //determine if this is linux deployment
- if (!m_bLinuxDeployment)
- {
- const char* computer = pChild->queryProp("@computer");
- IConstMachineInfo* pMachine = environment.getMachine(computer);
- if (pMachine->getOS() == MachineOsLinux)
- m_bLinuxDeployment = true;
- }
- }
- }
- else if (!m_bLinuxDeployment)//another previously added engine already does not have linux instance
- {
- //some components like thor and hole clusters don't show their instances in the
- //deployment wizard so detect if they have any linux instance.
- const IArrayOf<IPropertyTree>& instances = pEngine->getInstances();
- if (instances.ordinality() > 0)
- {
- Owned<IConstMachineInfo> machine = m_environment.getMachine(instances.item(0).queryProp("@computer"));
- if (machine && machine->getOS() == MachineOsLinux)
- m_bLinuxDeployment = true;
- }
- }
- }
- }
- #ifdef _WINDOWS
- EnumerateNetworkConnections();
- #endif
- }
-
- //---------------------------------------------------------------------------
- // ~CEnvironmentDeploymentEngine
- //---------------------------------------------------------------------------
- virtual ~CEnvironmentDeploymentEngine()
- {
- //delete all temporary files generated during deployemnt
- int count = m_tempFiles.length();
- int i;
- for (i = 0; i < count; i++)
- if (!DeleteFile(m_tempFiles.item(i)))
- WARNLOG("Couldn't delete file %s", m_tempFiles.item(i));
-
- count = m_tempDirs.length();
- for (i = 0; i < count; i++)
- deleteRecursive(m_tempDirs.item(i));
-
- m_processes.kill(); // must do this before destroying deplyCallback and deployLog
- m_pDeployLog.clear(); // this causes the log file to be written
- m_pCallback.clear();
-
- termXML();
- }
-
- void deleteRecursive(const char* path)
- {
- Owned<IFile> pDir = createIFile(path);
- if (pDir->exists())
- {
- if (pDir->isDirectory())
- {
- Owned<IDirectoryIterator> it = pDir->directoryFiles(NULL, false, true);
- ForEach(*it)
- {
- StringBuffer name;
- it->getName(name);
-
- StringBuffer childPath(path);
- childPath.append(PATHSEPCHAR);
- childPath.append(name);
-
- deleteRecursive(childPath.str());
- }
- }
- pDir->remove();
- }
- }
-
- //---------------------------------------------------------------------------
- // addProcess
- //---------------------------------------------------------------------------
- IDeploymentEngine* addProcess(const char* processType, const char* processName)
- {
- assertex(processType);
- assertex(processName);
- StringBuffer xpath;
- xpath.appendf("Software/%s[@name='%s']", processType, processName);
-
- Owned<IPropertyTree> tree = &m_environment.getPTree();
- IPropertyTree* pComponent = tree->queryPropTree(xpath.str());
- if (!pComponent)
- throw MakeStringException(0, "%s with name %s was not found!", processType, processName);
-
- IDeploymentEngine* deployEngine;
-
- if (strcmp(processType, "DaliServerProcess")==0)
- deployEngine = new CDaliDeploymentEngine(*this, *m_pCallback, *pComponent);
- else if (strcmp(processType, "ThorCluster")==0)
- deployEngine = new CThorDeploymentEngine(*this, *m_pCallback, *pComponent);
- else if (strcmp(processType, "RoxieCluster")==0)
- deployEngine = new CRoxieDeploymentEngine(*this, *m_pCallback, *pComponent);
- else if (strcmp(processType, "EspProcess")==0)
- deployEngine = new CEspDeploymentEngine(*this, *m_pCallback, *pComponent);
- else
- deployEngine = new CDeploymentEngine(*this, *m_pCallback, *pComponent, "Instance", true);
-
- assertex(deployEngine);
- deployEngine->setXsl(m_processor, m_transform);
- m_processes.append(*deployEngine); // array releases members when destroyed
- return deployEngine;
- }
-
- //---------------------------------------------------------------------------
- // setSshAccount
- //---------------------------------------------------------------------------
- void setSshAccount(const char* userid, const char* password)
- {
- m_sSshUserid = userid;
- m_sSshPassword = password;
- }
-
- //---------------------------------------------------------------------------
- // isLinuxDeployment
- //---------------------------------------------------------------------------
- bool isLinuxDeployment() const
- {
- return m_bLinuxDeployment;
- }
-
- //---------------------------------------------------------------------------
- // start
- //---------------------------------------------------------------------------
- void start()
- {
- ForEachItemIn(idx, m_processes)
- {
- m_processes.item(idx).start();
- }
- }
-
- //---------------------------------------------------------------------------
- // stop
- //---------------------------------------------------------------------------
- void stop()
- {
- ForEachItemInRev(idx, m_processes)
- {
- m_processes.item(idx).stop();
- }
- }
-
- //---------------------------------------------------------------------------
- // stripXsltMessage
- //---------------------------------------------------------------------------
- void stripXsltMessage(StringBuffer& msg)
- {
- //for better readability of msg, remove redundant prefix of "[XSLT warning: ", if present
- const char* pattern = "[ElemMessageTerminateException: ";
- const int len =sizeof("[ElemMessageTerminateException: ")-1;
- if (!strncmp(msg, pattern, len))
- msg.remove(0, len);
-
- //remove the excessive info about XSLT context when this was thrown
- const char* begin = msg.str();
- const char* end = strstr(begin, "(file:");
-
- if (end)
- msg.setLength(end-begin);
- }
-
- //---------------------------------------------------------------------------
- // check
- //---------------------------------------------------------------------------
- void check()
- {
- if (m_pCallback->getAbortStatus())
- throw MakeStringException(0, "User abort");
-
- bool valid = false;
- m_nValidationErrors = 0;
-
- StringBuffer outputXml;
-
- Owned<IXslFunction> externalFunction;
- externalFunction.setown(m_transform->createExternalFunction("validationMessage", validationMessageFromXSLT));
- m_transform->setExternalFunction(SEISINT_NAMESPACE, externalFunction.get(), true);
- m_transform->loadXslFromFile(m_validateAllXsl.str());
- m_transform->setUserData(this);
-
- try
- {
- m_transform->transform( outputXml );
- m_transform->closeResultTarget();
-
- m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, m_transform->getMessages());
- if (!m_nValidationErrors)//this may get filled in by the external function
- valid = true;
- }
- catch (IException* e)
- {
- StringBuffer msg;
- e->errorMessage(msg);
- e->Release();
- stripXsltMessage(msg);
- m_sValidationErrors.append(msg);
- }
- catch (...)
- {
- m_sValidationErrors.appendf("Validation failed: Unspecified XSL error!");
- }
- m_transform->setExternalFunction(SEISINT_NAMESPACE, externalFunction.get(), false);
- m_transform->setUserData(NULL);
- if (!valid)
- {
- const char* errors = m_sValidationErrors.str();
- if (!errors || !*errors)
- errors = "Continue?";
- m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Preliminary validation failed!");
- while ( !m_pCallback->processException(NULL, NULL, NULL, NULL, errors, "Preliminary validation failed!", NULL) )
- ;
- valid = true; //ignore validation errors
- }
- if (valid)
- {
- ForEachItemIn(idx, m_processes)
- m_processes.item(idx).check();
-
- m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL);
- }
- }
-
-
- //---------------------------------------------------------------------------
- // compare
- //---------------------------------------------------------------------------
- void compare(unsigned mode)
- {
- ForEachItemIn(idx, m_processes)
- {
- m_processes.item(idx).compare(mode);
- }
- }
-
- //---------------------------------------------------------------------------
- // deploy
- //---------------------------------------------------------------------------
- void deploy(unsigned flags, bool useTempDir)
- {
- m_tempFileCount = m_espModuleCount = 0;
- if (flags != DEFLAGS_NONE)
- {
- ForEachItemIn(idx, m_processes)
- {
- m_processes.item(idx).deploy(flags, useTempDir);
- }
- }
- }
-
- //---------------------------------------------------------------------------
- // deploy
- //---------------------------------------------------------------------------
- void deploy(unsigned flags, BackupMode backupMode, bool bStop, bool bStart)
- {
- switch (backupMode)
- {
- case DEBACKUP_NONE:
- if (bStop)
- stop();
- deploy(flags, false);
- if (bStart)
- start();
- break;
-
- case DEBACKUP_COPY:
- backupDirs();
- if (bStop)
- stop();
- deploy(flags, false);
- if (bStart)
- start();
- break;
-
- case DEBACKUP_RENAME:
- deploy(flags, true);
- if (bStop)
- stop();
- renameDirs();
- if (bStart)
- start();
- break;
-
- default:
- assertex(false);
- }
- }
-
- //---------------------------------------------------------------------------
- // renameDirs
- //---------------------------------------------------------------------------
- void renameDirs()
- {
- ForEachItemIn(idx, m_processes)
- {
- m_processes.item(idx).renameDirs();
- }
- }
-
- //---------------------------------------------------------------------------
- // backupDirs
- //---------------------------------------------------------------------------
- void backupDirs()
- {
- ForEachItemIn(idx, m_processes)
- {
- m_processes.item(idx).backupDirs();
- }
- }
-
- //---------------------------------------------------------------------------
- // abort
- //---------------------------------------------------------------------------
- void abort()
- {
- m_abort = true;
- ForEachItemIn(idx, m_processes)
- {
- m_processes.item(idx).abort();
- }
- }
-
- //---------------------------------------------------------------------------
- // archive
- //---------------------------------------------------------------------------
- void archive(const char* filename)
- {
- if (!filename || !*filename) return;
- if (m_abort)
- {
- m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Aborted!");
- throw MakeStringException(0, "User abort");
- }
-
- m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Archiving environment data to %s...", filename);
- Owned<IPropertyTree> tree = &m_environment.getPTree();
- StringBuffer xml;
- toXML(tree, xml);
- Owned<IDeployTask> task = createDeployTask(*m_pCallback, "Archive File", NULL, NULL, NULL, NULL,
- filename, "", "", "", false);
- task->createFile(xml.str());
- m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL);
- if (task->getAbort())
- throw MakeStringException(0, "User abort");
-
- Owned<IFile> pFile = createIFile(filename);
- pFile->setReadOnly(true);
- }
-
- //---------------------------------------------------------------------------
- // setLog
- //---------------------------------------------------------------------------
- void setLog(const char* filename, const char* envname)
- {
- if (!filename || !*filename) return;
- m_pDeployLog.setown(createDeployLog(*m_pCallback, filename, envname));
- }
-
- //---------------------------------------------------------------------------
- // initXML
- //---------------------------------------------------------------------------
- void initXML(IPropertyTree* pSelectedComponents)
- {
- if (m_abort)
- throw MakeStringException(0, "User abort");
-
- m_pCallback->printStatus(STATUS_NORMAL, NULL, NULL, NULL, "Loading environment...");
- m_processor.setown(getXslProcessor());
- m_transform.setown(m_processor->createXslTransform());
-
- //decrypt external function is no longer used by any xslt
- //
- //m_externalFunction.setown(m_transform->createExternalFunction("decrypt", decrypt));
- //m_transform->setExternalFunction(SEISINT_NAMESPACE, m_externalFunction.get(), true);
-
- Owned<IPropertyTree> tree = &m_environment.getPTree();
-
- IPropertyTree* pDeploy = tree->queryPropTree("DeployComponents");
- if (pDeploy)
- tree->removeTree(pDeploy);
- pDeploy = tree->addPropTree("DeployComponents", createPTreeFromIPT(pSelectedComponents));
-
- StringBuffer xml;
- toXML(tree, xml);
-
- tree->removeTree(pDeploy);
-
- if (m_transform->setXmlSource(xml.str(), xml.length()) != 0)
- throw MakeStringException(0, "Invalid environment XML string");
- }
- //---------------------------------------------------------------------------
- // termXML
- //---------------------------------------------------------------------------
- void termXML()
- {
- //decrypt external function is no longer used by any xslt
- //
- //m_transform->setExternalFunction(SEISINT_NAMESPACE, m_externalFunction.get(), false);
- m_externalFunction.clear();
- m_transform.clear();
- m_processor.clear();
- }
-
- //---------------------------------------------------------------------------
- // incrementTempFileCount
- //---------------------------------------------------------------------------
- virtual int incrementTempFileCount()
- {
- return ++m_tempFileCount;
- }
-
- //---------------------------------------------------------------------------
- // incrementEspModuleCount
- //---------------------------------------------------------------------------
- virtual int incrementEspModuleCount()
- {
- return ++m_espModuleCount;
- }
-
- //---------------------------------------------------------------------------
- // validationMessageFromXSLT
- //---------------------------------------------------------------------------
- static void validationMessageFromXSLT(StringBuffer &ret, const char *in, IXslTransform* pTransform)
- {
- CEnvironmentDeploymentEngine* pEnvDepEngine = (CEnvironmentDeploymentEngine*) pTransform->getUserData();
- IDeploymentCallback* pCallback = pEnvDepEngine->m_pCallback;
- //input 'in' has format of the form [type]:[compType]:[compName]:[message]
- //type is either 'error' or 'warning' and any of the other parts may be empty strings
- //
- StringArray sArray;
- sArray.appendList(in, ":");
- if (sArray.ordinality() != 4)
- {
- pCallback->printStatus(STATUS_ERROR, NULL, NULL, NULL, "%s", in);
- return;
- }
-
- const char* msgType = sArray.item(0);
- const char* compType = sArray.item(1);
- const char* compName = sArray.item(2);
- const char* msg = sArray.item(3);
- if (compType && !*compType)
- compType = NULL;
-
- if (compName && !*compName)
- compName = NULL;
- StatusType statusType;
- if (!stricmp(msgType, "error"))
- {
- statusType = STATUS_ERROR;
- pEnvDepEngine->m_nValidationErrors++;
- if (!compType || !compName)//if this error is not being reported under a particular component in tree
- pEnvDepEngine->m_sValidationErrors.append(msg).append("\n");
- }
- else if (!strnicmp(msgType, "warn", 4))
- statusType = STATUS_WARN;
- else if (!stricmp(msgType, "OK"))
- statusType = STATUS_OK;
- else if (!strnicmp(msgType, "inc", 3))
- statusType = STATUS_INCOMPLETE;
- else statusType = !stricmp(msgType, "normal") ? STATUS_NORMAL : STATUS_ERROR;
- try
- {
- if (pCallback)
- pCallback->printStatus( statusType,
- compType,
- compName,
- NULL,
- "%s", msg);
- }
- catch (IException* e)
- {
- StringBuffer buf;
- e->errorMessage(buf);
- e->Release();
- pCallback->printStatus(STATUS_ERROR, NULL, NULL, NULL, "%s", buf.str());
- }
- catch(...)
- {
- pCallback->printStatus(STATUS_ERROR, NULL, NULL, NULL, "Unknown exception!");
- }
- }
-
- //---------------------------------------------------------------------------
- // getCallback
- //---------------------------------------------------------------------------
- virtual IDeploymentCallback& getCallback() const
- {
- return *m_pCallback;
- }
-
- //---------------------------------------------------------------------------
- // setInteractiveMode
- //---------------------------------------------------------------------------
- virtual void setInteractiveMode(bool bSet)
- {
- m_bInteractiveMode = bSet;
- }
-
- //---------------------------------------------------------------------------
- // getEnvironment
- //---------------------------------------------------------------------------
- IConstEnvironment& getEnvironment() const
- {
- return m_environment;
- }
- //---------------------------------------------------------------------------
- // getInteractiveMode
- //---------------------------------------------------------------------------
- virtual bool getInteractiveMode() const
- {
- return m_bInteractiveMode;
- }
- //---------------------------------------------------------------------------
- // getDeployLog
- //---------------------------------------------------------------------------
- virtual IDeployLog* getDeployLog()
- {
- return m_pDeployLog ? m_pDeployLog.getLink() : NULL;
- }
- //---------------------------------------------------------------------------
- // addTempFile
- //---------------------------------------------------------------------------
- virtual void addTempFile(const char* filePath)
- {
- if (filePath)
- m_tempFiles.append(filePath);
- }
- //---------------------------------------------------------------------------
- // addTempDirectory
- //---------------------------------------------------------------------------
- virtual void addTempDirectory(const char* dirPath)
- {
- if (dirPath)
- m_tempDirs.append(dirPath);
- }
- //---------------------------------------------------------------------------
- // setDeployToFolder
- //---------------------------------------------------------------------------
- virtual void setDeployToFolder(const char* path)
- {
- StringBuffer machineName;
- StringBuffer localPath;
- StringBuffer tail;
- StringBuffer ext;
- if (splitUNCFilename(path, &machineName, &localPath, &tail, &ext))
- {
- const char* hostName = machineName.str() + 2;
- Owned<IConstMachineInfo> machine = m_environment.getMachine(hostName);
- if (!machine)
- throw MakeStringException(-1, "The computer '%s' used for deployment folder is undefined!", hostName);
- StringAttr netAddress;
- StringAttrAdaptor adaptor(netAddress);
- machine->getNetAddress(adaptor);
- if (!netAddress.get() || !*netAddress.get())
- throw MakeStringException(-1,
- "The computer '%s' used for deployment folder does not have any network address defined!", hostName);
- StringBuffer uncPath(PATHSEPSTR PATHSEPSTR);
- uncPath.append( netAddress.get() );
- if (*localPath.str() != PATHSEPCHAR)
- uncPath.append( PATHSEPCHAR );
- uncPath.append( localPath );//note that the path ends with PATHSEPCHAR
- uncPath.append( tail );
- uncPath.append( ext );
-
- m_sDeployToFolder.set( uncPath.str() );
- getAccountInfo(hostName, m_sDeployToUser, m_sDeployToPswd);
- }
- else
- m_sDeployToFolder.set( path );
- /*
- Owned<IDeployTask> task = createDeployTask(*m_pCallback, "Create Directory", NULL, NULL, NULL, NULL, m_sDeployToFolder.get());
- m_pCallback->printStatus(task);
- task->createDirectory();
- m_pCallback->printStatus(task);
- */
- }
- //---------------------------------------------------------------------------
- // getDeployToFolder
- //---------------------------------------------------------------------------
- virtual const char* getDeployToFolder() const
- {
- return m_sDeployToFolder.get();
- }
- //---------------------------------------------------------------------------
- // getDeployToAccountInfo
- //---------------------------------------------------------------------------
- virtual void getDeployToAccountInfo(const char*& user, const char*& pswd) const
- {
- user = m_sDeployToUser.get();
- pswd = m_sDeployToPswd.get();
- }
- //---------------------------------------------------------------------------
- // lookupNetAddress
- //---------------------------------------------------------------------------
- StringAttr& lookupNetAddress(StringAttr& str, const char* computer) const
- {
- Owned<IConstMachineInfo> machine = m_environment.getMachine(computer);
- if (machine)
- {
- StringAttrAdaptor adaptor(str);
- machine->getNetAddress(adaptor);
- }
- return str;
- }
- //---------------------------------------------------------------------------
- // lookupMachineOS
- //---------------------------------------------------------------------------
- EnvMachineOS lookupMachineOS(IPropertyTree& node) const
- {
- Owned<IConstMachineInfo> machine = m_environment.getMachine(node.queryProp("@computer"));
- return machine ? machine->getOS() : MachineOsUnknown;
- }
- //---------------------------------------------------------------------------
- // getAccountInfo
- //---------------------------------------------------------------------------
- void getAccountInfo(const char* computer, StringAttr& user, StringAttr& pwd) const
- {
- Owned<IConstMachineInfo> machine = m_environment.getMachine(computer);
- if (machine)
- {
- Owned<IConstDomainInfo> domain = machine->getDomain();
- if (!domain)
- throw MakeStringException(-1, "The computer '%s' does not have any domain information!", computer);
- StringBuffer x;
- if (machine->getOS() == MachineOsW2K)
- {
- domain->getName(StringBufferAdaptor(x));
- if (x.length())
- x.append(PATHSEPCHAR);
- }
- domain->getAccountInfo(StringBufferAdaptor(x), StringAttrAdaptor(pwd));
- user.set(x.str());
- }
- else
- throw MakeStringException(-1, "The computer '%s' is undefined!", computer);
- }
- //---------------------------------------------------------------------------
- // getSSHAccountInfo
- //---------------------------------------------------------------------------
- void getSSHAccountInfo(const char* computer, StringAttr& user, StringAttr& sshKeyFile, StringAttr& sshKeyPassphrase) const
- {
- Owned<IConstMachineInfo> machine = m_environment.getMachine(computer);
- if (machine)
- {
- Owned<IConstDomainInfo> domain = machine->getDomain();
- if (!domain)
- throw MakeStringException(-1, "The computer '%s' does not have any domain information!", computer);
- StringBuffer x;
- if (machine->getOS() == MachineOsW2K)
- {
- domain->getName(StringBufferAdaptor(x));
- if (x.length())
- x.append(PATHSEPCHAR);
- }
- domain->getSSHAccountInfo(StringBufferAdaptor(x), StringAttrAdaptor(sshKeyFile), StringAttrAdaptor(sshKeyPassphrase));
- user.set(x.str());
- }
- else
- throw MakeStringException(-1, "The computer '%s' is undefined!", computer);
- }
- virtual void setSourceDaliAddress( const char* addr )
- {
- m_sSrcDaliAddress.set( addr );
- }
- virtual const char* getSourceDaliAddress()
- {
- return m_sSrcDaliAddress.get();
- }
- virtual IArrayOf<IDeploymentEngine>& queryProcesses() { return m_processes; }
- #ifdef _WINDOWS
- void NetErrorHandler(DWORD dwResult)
- {
- StringBuffer out;
- formatSystemError(out, dwResult);
- out.insert(0, "Failed to enumerate existing network connections:\n");
- while ( !m_pCallback->processException(NULL, NULL, NULL, NULL, out, "Network Error", NULL) )
- ;
- }
- bool EnumerateNetworkConnections()
- {
- DWORD dwResult;
- HANDLE hEnum;
- DWORD cbBuffer = 16384; // 16K is a good size
- DWORD cEntries = -1; // enumerate all possible entries
- LPNETRESOURCE lpnr; // pointer to enumerated structures
- //
- // Call the WNetOpenEnum function to begin the enumeration.
- //
- dwResult = WNetOpenEnum(RESOURCE_CONNECTED, // connected network resources
- RESOURCETYPE_ANY,// all resources
- 0, // enumerate all resources
- NULL, // NULL first time the function is called
- &hEnum); // handle to the resource
- if (dwResult != NO_ERROR)
- {
- NetErrorHandler(dwResult);
- return false;
- }
- //
- // Call the GlobalAlloc function to allocate resources.
- //
- lpnr = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
- do
- {
- ZeroMemory(lpnr, cbBuffer);
- // Call the WNetEnumResource function to continue
- // the enumeration.
- //
- dwResult = WNetEnumResource( hEnum, // resource handle
- &cEntries, // defined locally as -1
- lpnr, // LPNETRESOURCE
- &cbBuffer); // buffer size
- // If the call succeeds, loop through the structures.
- //
- if (dwResult == NO_ERROR)
- {
- StringBuffer networkPath;
- for (DWORD i = 0; i < cEntries; i++)
- if (lpnr[i].lpRemoteName)
- {
- // make a valid UNC path to connect to and see if we are not already connected
- if (CDeploymentEngine::stripTrailingDirsFromUNCPath(lpnr[i].lpRemoteName, networkPath.clear()) &&
- m_persistentConnections.find( networkPath.str() ) == m_persistentConnections.end())
- {
- //::MessageBox(NULL, networkPath.str(), lpnr[i].lpRemoteName, MB_OK);
- m_persistentConnections.insert( networkPath.str() );
- }
- }
- }
- else if (dwResult != ERROR_NO_MORE_ITEMS)
- {
- NetErrorHandler(dwResult);
- break;
- }
- }
- while (dwResult != ERROR_NO_MORE_ITEMS);
- GlobalFree((HGLOBAL)lpnr); // free the memory
- dwResult = WNetCloseEnum(hEnum); // end the enumeration
- if (dwResult != NO_ERROR)
- {
- NetErrorHandler(dwResult);
- return false;
- }
- return true;
- }
- #endif//WINDOWS
- virtual bool IsPersistentConnection(const char* networkPath) const
- {
- return m_persistentConnections.find( networkPath ) != m_persistentConnections.end();
- }
- protected:
- IArrayOf<IDeploymentEngine> m_processes;
- IConstEnvironment& m_environment;
- Owned<IDeploymentCallback> m_pCallback;
- Owned<IXslProcessor> m_processor;
- Owned<IXslTransform> m_transform;
- Owned<IXslFunction> m_externalFunction;
- Owned<IDeployLog> m_pDeployLog;
- set<string> m_persistentConnections;
- int m_espModuleCount;
- int m_tempFileCount;
- bool m_abort;
- bool m_bLinuxDeployment;
- bool m_bInteractiveMode;
- StringBuffer m_sSshUserid;
- StringBuffer m_sSshPassword;
- StringBuffer m_validateAllXsl;
- unsigned int m_nValidationErrors;
- StringBuffer m_sValidationErrors;
- StringArray m_tempFiles;
- StringArray m_tempDirs;
- StringAttr m_sDeployToFolder;
- StringAttr m_sDeployToUser;
- StringAttr m_sDeployToPswd;
- StringAttr m_sSrcDaliAddress;
- };
- class CConfigGenMgr : public CEnvironmentDeploymentEngine
- {
- public:
- IMPLEMENT_IINTERFACE;
- //---------------------------------------------------------------------------
- // CConfigGenMgr
- //---------------------------------------------------------------------------
- CConfigGenMgr(IConstEnvironment& environment, IDeploymentCallback& callback,
- IPropertyTree* pSelectedComponents, const char* inputDir, const char* outputDir, const char* compName, const char* compType, const char* ipAddr)
- : CEnvironmentDeploymentEngine(environment, callback, NULL),
- m_inDir(inputDir),
- m_outDir(outputDir),
- m_compName(compName),
- m_compType(compType),
- m_hostIpAddr(ipAddr)
- {
- m_validateAllXsl.clear().append(inputDir);
- if (m_validateAllXsl.length() > 0 &&
- m_validateAllXsl.charAt(m_validateAllXsl.length() - 1) != PATHSEPCHAR)
- m_validateAllXsl.append(PATHSEPCHAR);
- m_validateAllXsl.append("validateAll.xsl");
- Owned<IPropertyTree> pSelComps;
- if (!pSelectedComponents)
- {
- Owned<IPropertyTree> pEnvTree = &m_environment.getPTree();
- pSelComps.setown(getInstances(pEnvTree, compName, compType, ipAddr));
- pSelectedComponents = pSelComps;
- }
- initXML(pSelectedComponents);
- {
- Owned<IPropertyTreeIterator> it = pSelectedComponents->getElements("*");
- ForEach(*it)
- {
- IPropertyTree* pComponent = &it->query();
- IDeploymentEngine* pEngine = addProcess(pComponent->queryName(), pComponent->queryProp("@name"));
- Owned<IPropertyTreeIterator> iter = pComponent->getElements("*");
- if (iter->first())
- {
- pEngine->resetInstances();
- ForEach(*iter)
- {
- IPropertyTree* pChild = &iter->query();
- const char* tagName = pChild->queryName();
- const char* instName = pChild->queryProp("@name");
- pEngine->addInstance(tagName, instName);
- //determine if this is linux deployment
- if (!m_bLinuxDeployment)
- {
- const char* computer = pChild->queryProp("@computer");
- Owned<IConstMachineInfo> pMachine = environment.getMachine(computer);
- if (!pMachine)
- throw MakeStringException(0, "Invalid Environment file. Instance '%s' of '%s' references a computer '%s' that has not been defined!", pChild->queryProp("@name"), pComponent->queryProp("@name"), computer);
- else if (pMachine->getOS() == MachineOsLinux)
- m_bLinuxDeployment = true;
- }
- }
- }
- else if (!m_bLinuxDeployment)//another previously added engine already does not have linux instance
- {
- //some components like thor and hole clusters don't show their instances in the
- //deployment wizard so detect if they have any linux instance.
- const IArrayOf<IPropertyTree>& instances = pEngine->getInstances();
- if (instances.ordinality() > 0)
- {
- Owned<IConstMachineInfo> machine;// = m_environment.getMachine(instances.item(0).queryProp("@computer"));
- if (machine && machine->getOS() == MachineOsLinux)
- m_bLinuxDeployment = true;
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- // addProcess
- //---------------------------------------------------------------------------
- IDeploymentEngine* addProcess(const char* processType, const char* processName)
- {
- assertex(processType);
- assertex(processName);
- StringBuffer xpath;
- xpath.appendf("Software/%s[@name='%s']", processType, processName);
- Owned<IPropertyTree> tree = &m_environment.getPTree();
- IPropertyTree* pComponent = tree->queryPropTree(xpath.str());
- if (!pComponent)
- throw MakeStringException(0, "%s with name %s was not found!", processType, processName);
- IDeploymentEngine* deployEngine;
- if (strcmp(processType, "RoxieCluster")==0)
- deployEngine = new CConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir, "*");
- else if (strcmp(processType, "ThorCluster")==0)
- deployEngine = new CThorConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir);
- else if (strcmp(processType, "EspProcess")==0)
- deployEngine = new CEspConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir);
- else
- deployEngine = new CConfigGenEngine(*this, *m_pCallback, *pComponent, m_inDir, m_outDir, "Instance", true);
- assertex(deployEngine);
- deployEngine->setXsl(m_processor, m_transform);
- m_processes.append(*deployEngine); // array releases members when destroyed
- return deployEngine;
- }
- void deploy(unsigned flags, BackupMode backupMode, bool bStop, bool bStart)
- {
- switch (backupMode)
- {
- case DEBACKUP_NONE:
- check();
- CEnvironmentDeploymentEngine::deploy(flags, false);
- break;
- case DEBACKUP_COPY:
- throw MakeStringException(-1, "Invalid option Backup copy while generating configurations");
- case DEBACKUP_RENAME:
- throw MakeStringException(-1, "Invalid option Backup rename while generating configurations");
- default:
- throw MakeStringException(-1, "Invalid option while generating configurations");
- }
- }
- private:
- StringBuffer m_inDir;
- StringBuffer m_outDir;
- StringBuffer m_compName;
- StringBuffer m_compType;
- StringBuffer m_hostIpAddr;
- };
- //---------------------------------------------------------------------------
- // Factory functions
- //---------------------------------------------------------------------------
- IEnvDeploymentEngine* createEnvDeploymentEngine(IConstEnvironment& environment,
- IDeploymentCallback& callback,
- IPropertyTree* pSelectedComponents)
- {
- try
- {
- return new CEnvironmentDeploymentEngine(environment, callback, pSelectedComponents);
- }
- catch (IException* e)
- {
- throw e;
- }
- catch(...)
- {
- throw MakeStringException(-1, "Unknown exception!");
- }
- }
- IEnvDeploymentEngine* createConfigGenMgr(IConstEnvironment& env,
- IDeploymentCallback& callback,
- IPropertyTree* pSelectedComponents,
- const char* inputDir,
- const char* outputDir,
- const char* compName,
- const char* compType,
- const char* ipAddr)
- {
- try
- {
- StringBuffer inDir(inputDir);
- if (inDir.length() && inDir.charAt(inDir.length() - 1) != PATHSEPCHAR)
- inDir.append(PATHSEPCHAR);
- StringBuffer outDir(outputDir);
- if (outDir.length() && outDir.charAt(outDir.length() - 1) != PATHSEPCHAR)
- outDir.append(PATHSEPCHAR);
- return new CConfigGenMgr(env, callback, pSelectedComponents, inDir.str(), outDir.str(), compName, compType, ipAddr);
- }
- catch (IException* e)
- {
- throw e;
- }
- catch(...)
- {
- throw MakeStringException(-1, "Unknown exception!");
- }
- }
- bool matchDeployAddress(const char *searchIP, const char *envIP)
- {
- if (searchIP && envIP && *searchIP && *envIP)
- {
- IpAddress ip(envIP);
- if (strcmp(searchIP, ".")==0)
- return ip.isLocal();
- else
- {
- IpAddress ip2(searchIP);
- return ip.ipequals(ip2);
- }
- }
- return false;
- }
- IPropertyTree* getInstances(const IPropertyTree* pEnvRoot, const char* compName,
- const char* compType, const char* ipAddr, bool listall)
- {
- Owned<IPropertyTree> pSelComps(createPTree("SelectedComponents"));
- Owned<IPropertyTreeIterator> iter = pEnvRoot->getElements("Software/*");
- const char* instanceNodeNames[] = { "Instance", "RoxieServerProcess" };
- const char* logDirNames[] = { "@logDir", "@LogDir", "@dfuLogDir", "@eclLogDir" };
- ForEach(*iter)
- {
- IPropertyTree* pComponent = &iter->query();
- const char* type = pComponent->queryName();
- if (stricmp(type, "Topology")!=0 && stricmp(type, "Directories")!=0 &&
- ((!compName && !compType) || (compName && !strcmp(pComponent->queryProp("@name"), compName)) ||
- (!compName && compType && !strcmp(pComponent->queryProp("@buildSet"), compType))))
- {
- const char* name = pComponent->queryProp("@name");
- const char* build = pComponent->queryProp("@build");
- const char* buildSet= pComponent->queryProp("@buildSet");
- const char* logDir = NULL;
- if (listall)
- for (int i = 0; i < sizeof(logDirNames)/sizeof(char*); i++)
- {
- logDir = pComponent->queryProp(logDirNames[i]);
- if (logDir)
- break;
- }
- StringBuffer sXPath;
- sXPath.appendf("Programs/Build[@name='%s']/BuildSet[@name='%s']/@deployable", build, buildSet);
- const char* deployable = pEnvRoot->queryProp(sXPath.str());
- //either the @deployable does not exist or it is not one of 'no', 'false' or '0'
- if (!deployable ||
- (strcmp(deployable, "no") != 0 && strcmp(deployable, "false") != 0 && strcmp(deployable, "0") != 0))
- {
- IPropertyTree* pSelComp = NULL;
- Owned<IPropertyTreeIterator> iterInst = pComponent->getElements("*", iptiter_sort);
- bool bAdded = false;
- ForEach(*iterInst)
- {
- IPropertyTree* pInst = &iterInst->query();
- const char* computer = pInst->queryProp("@computer");
- const char* netAddr = pInst->queryProp("@netAddress");
- if (!computer || !*computer || !strcmp("Notes", pInst->queryName()))
- continue;
- if (!strcmp(buildSet, "thor"))
- {
- sXPath.clear().appendf("Hardware/Computer[@name=\"%s\"]", computer);
- IPropertyTree* pComputer = pEnvRoot->queryPropTree(sXPath.str());
- if (pComputer == NULL)
- throw MakeStringException(-1,"XPATH: %s is invalid.\n(Did you configure the Hardware?)", sXPath.str());
- netAddr = pComputer->queryProp("@netAddress");
- if (matchDeployAddress(ipAddr, netAddr) ||
- (!ipAddr && netAddr && *netAddr))
- {
- if (!bAdded)
- {
- pSelComp = pSelComps->addPropTree(pComponent->queryName(), createPTree());
- pSelComp->addProp("@name", name);
- pSelComp->addProp("@buildSet", buildSet);
- pSelComp->addProp("@logDir", logDir);
- bAdded = true;
- }
- if (listall)
- {
- IPropertyTree* pInstance = pSelComp->addPropTree(pInst->queryName(), createPTree());
- pInstance->addProp("@name", pInst->queryProp("@name"));
- pInstance->addProp("@computer", computer);
- pInstance->addProp("@netAddress", netAddr);
- }
- }
- }
- else if (matchDeployAddress(ipAddr, netAddr) ||
- (!ipAddr && netAddr && *netAddr))
- {
- if (!bAdded)
- {
- pSelComp = pSelComps->addPropTree(pComponent->queryName(), createPTree());
- pSelComp->addProp("@name", name);
- pSelComp->addProp("@buildSet", buildSet);
- pSelComp->addProp("@logDir", logDir);
- bAdded = true;
- }
- StringBuffer sb(pInst->queryName());
- for (UINT i=0; i<sizeof(instanceNodeNames) / sizeof(instanceNodeNames[0]); i++)
- if (!strcmp(sb.str(), instanceNodeNames[i]))
- {
- //allow multiple instances but do not allow roxie servers more than once per computer
- if (listall || sb.str()[0] != 'R' || !pSelComp->queryPropTree(StringBuffer().appendf("*[@computer=\"%s\"]", computer)))
- {
- IPropertyTree* pInstance = pSelComp->addPropTree(sb.str(), createPTree());
- pInstance->addProp("@name", pInst->queryProp("@name"));
- pInstance->addProp("@computer", pInst->queryProp("@computer"));
- pInstance->addProp("@port", pInst->queryProp("@port"));
- pInstance->addProp("@netAddress", pInst->queryProp("@netAddress"));
- const char* directory = pInst->queryProp(sb.str()[0]=='R' ? "@dataDirectory" : "@directory");
- if (directory && *directory)
- pInstance->addProp("@directory", directory);
- }
- break;
- }
- }
- }
- }
- }
- }
- return pSelComps.getLink();
- }
- //---------------------------------------------------------------------------
- // Module Globals
- //---------------------------------------------------------------------------
- const char* findFileExtension(const char* pszPath)
- {
- const char* lastSlash = pathTail(pszPath);
- return strrchr(lastSlash ? lastSlash : pszPath, '.');
- }
- void removeTrailingPathSepChar(char* pszPath)
- {
- if (pszPath)
- {
- char* lastChar = pszPath + strlen(pszPath) - 1;
- if (isPathSepChar(*lastChar))
- *lastChar = '\0';
- }
- }
- void stripNetAddr(const char* dir, StringBuffer& destpath, StringBuffer& destip, bool makeLinux)
- {
- destpath.clear().append(dir);
- if (dir[0] == '\\' && dir[1] == '\\' && strlen(dir) > 2)
- {
- destip.clear().append(strchr(dir + 2, '\\') - (dir + 2), dir + 2);
- destpath.clear().append(strchr(dir + 2, '\\'));
- }
-
- if (makeLinux)
- destpath.replace('\\', '/');
- }
- //returns temp path that ends with path sep
- //
- #ifdef _WIN32
- extern DWORD getLastError() { return ::GetLastError(); }
- void getTempPath(char* tempPath, unsigned int bufsize, const char* subdir/*=NULL*/)
- {
- ::GetTempPath(bufsize, tempPath);
- ::GetLongPathName(tempPath, tempPath, bufsize);
- if (subdir && *subdir)
- {
- const int len = strlen(tempPath);
- char* p = tempPath + len;
- strcpy(p, subdir);
- p += strlen(subdir);
- *p++ = '\\';
- *p = '\0';
- }
- }
- #else//Linux specifics follow
- extern DWORD getLastError() { return errno; }
- void getTempPath(char* tempPath, unsigned int bufsize, const char* subdir/*=NULL*/)
- {
- assert(bufsize > 5);
- strcpy(tempPath, "/tmp/");
- if (subdir && *subdir)
- {
- strcat(tempPath, subdir);
- strcat(tempPath, "/");
- }
- }
- #endif
|