host/config/configwrapper.cpp (1,189 lines of code) (raw):
//
// Copyright (c) 2008 InMage
// This file contains proprietary and confidential information and
// remains the unpublished property of InMage. Use, disclosure,
// or reproduction is prohibited except as permitted by express
// written license aggreement with InMage.
//
// File : configwrappers.h
//
// Description:
// exception free wrapper implementation over configurator calls
//
#include "configwrapper.h"
#include "configurator2.h"
#include "configurevxagent.h"
#include "inmageex.h"
#include "portablehelpersmajor.h"
#include "localconfigurator.h"
#include "rpcconfigurator.h"
#include "marshal.h"
#include <ace/Guard_T.h>
#include <ace/Mutex.h>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
boost::mutex g_AlertMutex;
static bool ignoreCxErrors = false;
static SV_LOG_LEVEL logLevel = SV_LOG_ERROR;
static ACE_Mutex g_lock;
static Configurator* g_ConfiguratorInstance = NULL;
bool Configurator::instanceFlag = false;
Configurator::Configurator()
{
instanceFlag = true;
}
Configurator::~Configurator()
{
instanceFlag = false;
g_ConfiguratorInstance = NULL;
}
/*
* FUNCTION NAME : InitializeConfigurator
*
* DESCRIPTION :
* Create Configurator Instance
*
* INPUT PARAMETERS :
* configSource = Source for configuration
*
* OUTPUT PARAMETERS :
* pointer to configurator instance
*
* NOTES :
*
*
* return value : true on success, otherwise false
*
*/
bool InitializeConfigurator(Configurator ** ppconfigurator,
ConfigSource configSource,
const SerializeType_t serializetype,
const std::string& cachepath)
{
bool rv = false;
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
ACE_Guard<ACE_Mutex> guard( g_lock );
do
{
LocalConfigurator localConfigurator;
try
{
if(!ppconfigurator)
{
rv = false;
break;
}
if(Configurator::instanceFlag)
{
// configurator was previously created
// return the existing configurator
// Configurator initialization (creation) shall
// be done only once
*ppconfigurator = g_ConfiguratorInstance;
rv = true;
break;
}
g_ConfiguratorInstance = new RpcConfigurator(serializetype, configSource, cachepath);
*ppconfigurator = g_ConfiguratorInstance;
rv = true;
DebugPrintf(SV_LOG_ALWAYS,
"Configurator cx ip:%s port:%d.\n",
GetCxIpAddress().c_str(),
localConfigurator.getHttp().port);
}
catch ( ContextualException& ce )
{
rv = false;
g_ConfiguratorInstance = NULL;
DebugPrintf(logLevel,
"Configurator instantiation failed cx ip:%s port:%d exception:%s.\n",
GetCxIpAddress().c_str(),
localConfigurator.getHttp().port,
ce.what());
}
catch ( ... )
{
rv = false;
g_ConfiguratorInstance = NULL;
DebugPrintf(logLevel,
"Configurator instantiation failed cx ip:%s port:%d exception:unknown.\n",
GetCxIpAddress().c_str(),
localConfigurator.getHttp().port);
}
if(!rv)
break;
try
{
g_ConfiguratorInstance ->GetCurrentSettings();
}
catch ( ContextualException& ce )
{
rv = false;
g_ConfiguratorInstance->Stop();
delete g_ConfiguratorInstance;
g_ConfiguratorInstance = NULL;
*ppconfigurator = NULL;
DebugPrintf(logLevel,
"Configurator GetInitialSettings failed cx ip:%s port:%d exception:%s.\n",
GetCxIpAddress().c_str(),
localConfigurator.getHttp().port,
ce.what());
}
catch ( ... )
{
rv = false;
g_ConfiguratorInstance->Stop();
delete g_ConfiguratorInstance;
g_ConfiguratorInstance = NULL;
*ppconfigurator = NULL;
DebugPrintf(logLevel,
"Configurator GetInitialSettings failed cx ip:%s port:%d exception:unknown.\n",
GetCxIpAddress().c_str(),
localConfigurator.getHttp().port);
}
} while(0);
if(rv)
{
DebugPrintf(SV_LOG_DEBUG, "Configurator instantiated.\n");
}
DebugPrintf(SV_LOG_DEBUG,"EXITED %s\n",FUNCTION_NAME);
return rv;
}
/*
* FUNCTION NAME : InitializeConfigurator
*
* DESCRIPTION : create a singleton instance of the Configurator.
*
* INPUT PARAMETERS :
*
* ip - cx ip
* port - cx port
* hostId - agent id
*
* OUTPUT PARAMETERS :
* configurator instance
*
* NOTES :
*
*
* return value : true on success, false otherwise
*
*/
bool InitializeConfigurator(Configurator** ppconfigurator,
std::string const& ip,
int port,
std::string const& hostId,
const SerializeType_t serializetype)
{
bool rv = false;
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
ACE_Guard<ACE_Mutex> guard( g_lock );
do
{
try
{
if(!ppconfigurator)
{
rv = false;
break;
}
if(Configurator::instanceFlag)
{
// configurator was previously created
// return the existing configurator
// Configurator initialization (creation) shall
// be done only once
*ppconfigurator = g_ConfiguratorInstance;
rv = true;
break;
}
g_ConfiguratorInstance = new RpcConfigurator( serializetype, ip, port, hostId);
*ppconfigurator = g_ConfiguratorInstance;
rv = true;
}
catch ( ContextualException& ce )
{
rv = false;
g_ConfiguratorInstance = NULL;
DebugPrintf(logLevel,
"Configurator instantiation failed cx ip:%s port:%d exception:%s.\n",
ip.c_str(), port, ce.what());
}
catch ( ... )
{
rv = false;
g_ConfiguratorInstance = NULL;
DebugPrintf(logLevel,
"Configurator instantiation failed cx ip:%s port:%d exception:unknown.\n",
ip.c_str(), port);
}
if(!rv)
break;
try
{
g_ConfiguratorInstance ->GetCurrentSettings();
}
catch ( ContextualException& ce )
{
rv = false;
g_ConfiguratorInstance->Stop();
delete g_ConfiguratorInstance;
g_ConfiguratorInstance = NULL;
*ppconfigurator = NULL;
DebugPrintf(logLevel,
"Configurator instantiation failed cx ip:%s port:%d exception:%s.\n",
ip.c_str(), port, ce.what());
}
catch ( ... )
{
rv = false;
g_ConfiguratorInstance->Stop();
delete g_ConfiguratorInstance;
g_ConfiguratorInstance = NULL;
*ppconfigurator = NULL;
DebugPrintf(logLevel,
"Configurator GetInitialSettings failed cx ip:%s port:%d exception:unknown.\n",
ip.c_str(), port);
}
} while (0);
DebugPrintf(SV_LOG_DEBUG,"EXITED %s\n",FUNCTION_NAME);
return rv;
}
/*
* FUNCTION NAME : GetConfigurator
*
* DESCRIPTION : return previously created instance of the Configurator.
*
* INPUT PARAMETERS : none
*
*
* OUTPUT PARAMETERS :
* configurator instance
*
* NOTES :
*
*
* return value : true on success, false otherwise
*
*/
bool GetConfigurator(Configurator** ppconfigurator)
{
bool rv = false;
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
ACE_Guard<ACE_Mutex> guard( g_lock );
do
{
if(!ppconfigurator)
{
rv = false;
break;
}
if(Configurator::instanceFlag)
{
// configurator was previously created
// return the existing configurator
// Configurator initialization (creation) shall
// be done only once
*ppconfigurator = g_ConfiguratorInstance;
rv = true;
break;
} else
{
rv = false;
break;
}
} while (0);
DebugPrintf(SV_LOG_DEBUG,"EXITED %s\n",FUNCTION_NAME);
return rv;
}
/*
* FUNCTION NAME : makeSnapshotActive
*
* DESCRIPTION : wrapper over configurator call to make a snapshot instance ready
* on arrival of a event.
*
* INPUT PARAMETERS : snapshotid - snapshot instance identifier
*
* OUTPUT PARAMETERS :
*
* NOTES :
*
* return value : true on success, false otherwise
*
*/
bool makeSnapshotActive(Configurator & configurator, const std::string & snapshotId)
{
bool rv = true;
do
{
try
{
SV_UINT rc = configurator.getVxAgent().makeSnapshotActive(snapshotId);
//
// if activation request fails due to conflict
//
if(rc == 2)
{
rv = false;
DebugPrintf(logLevel,
"\nmakeSnapshotActive call to cx failed with return code 2 for snapshot id %s.\n",
snapshotId.c_str());
break;
}
//
// activation fails due to some other reason
//
if(rc == 0)
{
rv = false;
DebugPrintf(logLevel,
"\nmakeSnapshotActive call to cx failed with return code 0 for snapshot id %s.\n",
snapshotId.c_str());
break;
}
rv = true;
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nmakeSnapshotActive call to cx for snapshot id %s failed with exception %s.\n",
snapshotId.c_str(), ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nmakeSnapshotActive call to cx for snapshot id %s failed with unknown exception.\n",
snapshotId.c_str());
}
} while(0);
return rv;
}
/*
* FUNCTION NAME : notifyCxOnSnapshotStatus
*
* DESCRIPTION : wrapper over configurator call to send snapshot status information
*
* INPUT PARAMETERS : snapId - snapshot instance identifier
* rest - todo: explanation pending?
*
* OUTPUT PARAMETERS :
*
* NOTES :
*
* return value : success/failure status from Cx
*
*/
bool notifyCxOnSnapshotStatus(Configurator & configurator, const std::string & snapId, int timeval,const SV_ULONGLONG &VsnapId, const std::string &errMessage, int status)
{
bool rv = true;
try
{
status = configurator.getVxAgent().notifyCxOnSnapshotStatus(snapId,timeval,VsnapId,errMessage,status);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotStatus call to cx for snapshot id %s failed with exception %s.\n",
snapId.c_str(), ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotStatus call to cx for snapshot id %s failed with unknown exception.\n",
snapId.c_str());
}
return rv;
}
/*
* FUNCTION NAME : notifyCxOnSnapshotProgress
*
* DESCRIPTION : wrapper over configurator call to send snapshot progress information
*
* INPUT PARAMETERS : snapId - snapshot instance identifier
* percentage - progress indicator
* rpoint - actual recovery point (currently unused)
*
* OUTPUT PARAMETERS :
*
* NOTES :
*
* return value : success/failure status from Cx
*
*/
bool notifyCxOnSnapshotProgress(Configurator & configurator, const std::string &snapId, int percentage, int rpoint)
{
bool rv = true;
try
{
rv = configurator.getVxAgent().notifyCxOnSnapshotProgress(snapId,percentage,rpoint);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotProgress call to cx for snapshot id %s failed with exception %s.\n",
snapId.c_str(), ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotProgress call to cx for snapshot id %s failed with unknown exception.\n",
snapId.c_str());
}
return rv;
}
/*
* FUNCTION NAME : notifyCxOnSnapshotCreation
*
* DESCRIPTION : wrapper over configurator call to send snapshot status information
*
* INPUT PARAMETERS : vsnapInfo - Vsnap Information to be added to database
*
*
* OUTPUT PARAMETERS : results - list of true/false values representing the sucess/failure of vsnap updation at CX
*
* NOTES :
*
* return value : success/failure status from Cx
*
*/
bool notifyCxOnSnapshotCreation(Configurator & configurator,std::vector<VsnapPersistInfo> vsnapInfo, std::vector<bool>& results)
{
bool rv = true;
std::vector<VsnapPersistInfo>::iterator it = vsnapInfo.begin();
for(; it != vsnapInfo.end(); ++it)
{
convertToCxFormattedPersistInfo((*it));
}
try
{
results = configurator.getVxAgent().notifyCxOnSnapshotCreation(vsnapInfo);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotCreation call to cx for failed with exception %s.\n",
ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotCreation call to cx for failed with unknown exception.\n"
);
}
return rv;
}
bool notifyCxOnSnapshotDeletion(Configurator & configurator,std::vector<VsnapDeleteInfo> vsnapInfo, std::vector<bool>& results)
{
bool rv = true;
std::vector<VsnapDeleteInfo>::iterator it = vsnapInfo.begin();
for(; it != vsnapInfo.end(); ++it)
{
convertToCxFormattedVsnapDeleteInfo((*it));
}
try
{
results = configurator.getVxAgent().notifyCxOnSnapshotDeletion(vsnapInfo);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotDeletion call to cx for failed with exception %s.\n",
ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxOnSnapshotDeletion call to cx for failed with unknown exception.\n"
);
}
return rv;
}
bool notifyCxDiffsDrained(Configurator & configurator, const std::string &devname, const SV_ULONGLONG& bytesAppliedPerSecond)
{
bool rv = true;
try
{
SV_INT rc = configurator.getVxAgent().notifyCxDiffsDrained(devname, bytesAppliedPerSecond);
if( 0 != rc)
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxDiffsDrained call to cx for device %s failed with return code %d .\n",
devname.c_str(), rc);
}
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxDiffsDrained call to cx for device %s failed with exception %s.\n",
devname.c_str(), ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nnotifyCxDiffsDrained call to cx for device %s failed with unknown exception.\n",
devname.c_str());
}
return rv;
}
/*
* FUNCTION NAME : deleteVirtualSnapshot
*
* DESCRIPTION : wrapper over configurator call to informa vsnap deletion
*
* INPUT PARAMETERS : targetVolume - target volume name
* rest - todo: explanation pending?
*
* OUTPUT PARAMETERS :
*
* NOTES :
*
* return value : success/failure status from Cx
*
*/
bool deleteVirtualSnapshot(Configurator & configurator, const std::string & targetVolume,unsigned long long vsnapid , int status, const std::string & message)
{
bool rv = true;
try
{
std::string cxVolName = targetVolume;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
rv = configurator.getVxAgent().deleteVirtualSnapshot( cxVolName,vsnapid,status, message);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\ndeleteVirtualSnapshot call to cx for snapshot id " ULLSPEC " failed with exception %s.\n",
vsnapid, ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\ndeleteVirtualSnapshot call to cx for snapshot id " ULLSPEC " failed with unknown exception.\n",
vsnapid);
}
return rv;
}
// Bug #6298
/*
* FUNCTION NAME : updateReplicationStateStatus
*
* DESCRIPTION : wrapper over configurator call to update the replication pair status(to go ahead deleting the rep. pair as the
* vsnaps associated with the target are deleted)
*
* INPUT PARAMETERS : deviceName - the target volume of rep. pair for which the status is being reported
* state - the state being reported( CLEANUP_DONE on success/ CLEANUP_FAILED on failure)
*
*
* OUTPUT PARAMETERS : None
*
* NOTES : None
*
* return value : success/failure status - failure in case of exception in reporting to cx
*
*/
bool updateReplicationStateStatus(Configurator & configurator, const std::string& deviceName, VOLUME_SETTINGS::PAIR_STATE state)
{
bool rv = true;
std::string cxVolName;
try
{
cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
rv = configurator.getVxAgent().updateReplicationStateStatus( cxVolName, state );
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nupdateReplicationStateStatus call to cx for device %s failed with exception %s.\n",
cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nupdateReplicationStateStatus call to cx for device %s failed with unknown exception.\n",
cxVolName.c_str());
}
return rv;
}
bool updateVolumeAttribute(Configurator & configurator, NOTIFY_TYPE notifyType,const std::string & deviceName,VOLUME_STATE volumeState,const std::string & mountPoint, bool & status)
{
bool rv = true;
try
{
std::string cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
status = configurator.getVxAgent().updateVolumeAttribute(notifyType,cxVolName,volumeState,mountPoint);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nupdateVolumeAttribute call to cx for device %s failed with exception %s.\n",
deviceName.c_str(), ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nupdateVolumeAttribute call to cx for device %s failed with unknown exception.\n",
deviceName.c_str());
}
return rv;
}
int getCurrentVolumeAttribute(Configurator & configurator, const std::string & deviceName)
{
CHANGEFSTAGOP failedStatus = OPERATION_FAILED;
int visibilityStatus = failedStatus;
try
{
std::string cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
visibilityStatus = configurator.getVxAgent().getCurrentVolumeAttribute(cxVolName);
}
catch ( ContextualException& ce )
{
visibilityStatus = failedStatus;
DebugPrintf(logLevel,
"\ngetCurrentVolumeAttribute call to cx for device %s failed with exception %s.\n",
deviceName.c_str(), ce.what());
}
catch ( ... )
{
visibilityStatus = failedStatus;
DebugPrintf(logLevel,
"\ngetCurrentVolumeAttribute call to cx for device %s failed with unknown exception.\n",
deviceName.c_str());
}
return visibilityStatus;
}
bool setTargetResyncRequired(Configurator & configurator, const std::string & deviceName, bool & status, const std::string& errStr,
const ResyncReasonStamp &resyncReasonStamp, long errorcode)
{
bool rv = true;
try
{
std::string cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
status = configurator.getVxAgent().setTargetResyncRequired(cxVolName, errStr, resyncReasonStamp, errorcode);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nsetTargetResyncRequired call to cx for device %s failed with exception %s.\n",
deviceName.c_str(), ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nsetTargetResyncRequired call to cx for device %s failed with unknown exception.\n",
deviceName.c_str());
}
return rv;
}
bool getSourceRawSize(Configurator & configurator, const std::string & deviceName, SV_ULONGLONG & capacity)
{
bool rv = true;
std::string cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
capacity = configurator.getVxAgent().getSourceRawSize(cxVolName);
if(!capacity)
rv = false;
return rv;
}
bool getSourceCapacity(Configurator & configurator, const std::string & deviceName, SV_ULONGLONG & capacity)
{
bool rv = true;
std::string cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
capacity = configurator.getVxAgent().getSourceCapacity(cxVolName);
if(!capacity)
rv = false;
return rv;
}
/*
* FUNCTION NAME : setIgnoreCxErrors
*
* DESCRIPTION : set the flag to ignore cx errors
*
* INPUT PARAMETERS : status - true or false
*
* OUTPUT PARAMETERS : None
*
* NOTES :
*
* return value : None
*
*/
void setIgnoreCxErrors(bool status)
{
ignoreCxErrors = status;
if(ignoreCxErrors)
{
logLevel = SV_LOG_DEBUG;
}
}
/*
* FUNCTION NAME : updatePendingDataInfo
*
* DESCRIPTION : sends the pending data size of target volumes contained in pendingDataInfo
*
* INPUT PARAMETERS : pendingDataInfo
*
* OUTPUT PARAMETERS : None
*
* NOTES :
*
* return value : true if successeds false otherwise
*
*/
bool updatePendingDataInfo(Configurator & configurator, const std::map<std::string,SV_ULONGLONG>& pendingDataInfo)
{
bool rv = true;
try
{
rv = configurator.getVxAgent().updatePendingDataInfo(pendingDataInfo);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\nupdatePendingDataInfo call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\nupdatePendingDataInfo call to cx failed with unknown exception.\n");
}
return rv;
}
/*
* FUNCTION NAME : updateCleanUpActionStatus
*
* DESCRIPTION : wrapper over configurator call to update the clean up status(to go ahead deleting the rep. pair as the
* clean up associated with the target are done)
*
* INPUT PARAMETERS : deviceName - the target volume of rep. pair for which the status is being reported
* cleanupstr - the state, error message for 5 clean up status(Pending directory,vsnap, retaintion log, unlock volume) being reported
*
*
* OUTPUT PARAMETERS : None
*
* NOTES : None
*
* return value : success/failure status - failure in case of exception in reporting to cx
*
*/
bool updateCleanUpActionStatus(Configurator & configurator, const std::string& deviceName, const std::string & cleanupstr)
{
bool rv = true;
std::string cxVolName;
try
{
cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
DebugPrintf(SV_LOG_DEBUG, "@LINE %d in FILE %s, cxVolName = %s\n", LINE_NO, FILE_NAME, cxVolName.c_str());
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
rv = configurator.getVxAgent().updateCleanUpActionStatus( cxVolName, cleanupstr );
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,"\nupdateCleanUpActionStatus call to cx for device %s failed with exception %s.\n",cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,"\nupdateCleanUpActionStatus call to cx for device %s failed with unknown exception.\n",cxVolName.c_str());
}
return rv;
}
/*
* FUNCTION NAME : updateRestartResyncCleanupStatus
*
* DESCRIPTION : wrapper over configurator call to update the clean up status on restart resync
*
* INPUT PARAMETERS : deviceName - the target volume of rep. pair for which the status is being reported
* success - whether the cleanup operation succeded or failed on target
*
*
* OUTPUT PARAMETERS : None
*
* NOTES : None
*
* return value : success/failure status - failure in case of exception in reporting to cx
*
*/
bool updateRestartResyncCleanupStatus(Configurator & configurator, const std::string& deviceName, bool& success, const std::string& err_message)
{
bool rv = true;
std::string cxVolName;
try
{
cxVolName = deviceName;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
DebugPrintf(SV_LOG_DEBUG, "@LINE %d in FILE %s, cxVolName = %s\n", LINE_NO, FILE_NAME, cxVolName.c_str());
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
rv = configurator.getVxAgent().updateRestartResyncCleanupStatus( cxVolName, success, err_message );
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,"\nupdateRestartResyncCleanupStatus call to cx for device %s failed with exception %s.\n",cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,"\nupdateRestartResyncCleanupStatus call to cx for device %s failed with unknown exception.\n",cxVolName.c_str());
}
return rv;
}
bool sendCacheCleanupStatus(Configurator & configurator, const std::string & devicename, bool status, const std::string & info)
{
bool rv = true;
std::string cxVolName;
try
{
cxVolName = devicename;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
std::stringstream cache_cleanup_status;
VOLUME_SETTINGS::PAIR_STATE state = (status)? VOLUME_SETTINGS::CACHE_CLEANUP_COMPLETE:VOLUME_SETTINGS::CACHE_CLEANUP_FAILED;
cache_cleanup_status << "cache_dir_del=yes;"
<< "cache_dir_del_status="
<< state << ";"
<< "cache_dir_del_message="
<< info << ";";
rv = configurator.getVxAgent().updateCleanUpActionStatus( cxVolName, cache_cleanup_status.str());
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nupdateCleanUpActionStatus call to cx for device %s failed with exception %s.\n",
cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nupdateCleanUpActionStatus call to cx for device %s failed with unknown exception.\n",
cxVolName.c_str());
}
return rv;
}
bool registerClusterInfo(Configurator & configurator, const std::string & action, const ClusterInfo & clusterInfo )
{
bool rv = true;
try
{
configurator.getVxAgent().registerClusterInfo(action, clusterInfo);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\nregisterClusterInfo call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\nregisterClusterInfo call to cx failed with unknown exception.\n");
}
return rv;
}
bool getResyncStartTimeStamp(Configurator & configurator, const std::string & volname, const std::string & jobId, ResyncTimeSettings& rtsettings, const std::string &hostType)
{
bool rv = true;
try
{
rtsettings = configurator.getVxAgent().getResyncStartTimeStamp(volname, jobId, hostType);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\ngetResyncStartTimeStamp call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\ngetResyncStartTimeStamp call to cx failed with unknown exception.\n");
}
return rv;
}
bool getTargetReplicationJobId(Configurator & configurator, std::string deviceName, std::string& jid )
{
bool rv = true;
try
{
jid = configurator.getVxAgent().getTargetReplicationJobId(deviceName);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\ngetTargetReplicationJobId call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\ngetTargetReplicationJobId call to cx failed with unknown exception.\n");
}
return rv;
}
bool getResyncEndTimeStamp(Configurator & configurator, const std::string & volname, const std::string & jobId, ResyncTimeSettings& rtsettings, const std::string &hostType)
{
bool rv = true;
try
{
rtsettings = configurator.getVxAgent().getResyncEndTimeStamp(volname, jobId, hostType);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\ngetResyncEndTimeStamp call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\ngetResyncEndTimeStamp call to cx failed with unknown exception.\n");
}
return rv;
}
bool getVolumeCheckpoint(Configurator & configurator, std::string const & drivename, JOB_ID_OFFSET& jidoffset )
{
bool rv = true;
try
{
jidoffset = configurator.getVxAgent().getVolumeCheckpoint(drivename);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\ngetVolumeCheckpoint call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\ngetVolumeCheckpoint call to cx failed with unknown exception.\n");
}
return rv;
}
bool getVsnapRemountVolumes(Configurator & configurator, VsnapRemountVolumes& remountvols)
{
bool rv = true;
try
{
remountvols = configurator.getVxAgent().getVsnapRemountVolumes();
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\ngetVsnapRemountVolumes call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\ngetVsnapRemountVolumes call to cx failed with unknown exception.\n");
}
return rv;
}
bool sendEndQuasiStateRequest(Configurator & configurator, const std::string & volname, int& status)
{
bool rv = true;
try
{
status = configurator.getVxAgent().sendEndQuasiStateRequest(volname);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel, "\nsendEndQuasiStateRequest call to cx failed with exception %s.\n", ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel, "\nsendEndQuasiStateRequest call to cx failed with unknown exception.\n");
}
return rv;
}
/*
* FUNCTION NAME : NotifyMaintenanceActionStatus
*
* DESCRIPTION : wrapper over configurator call to update the pause replication status(to go ahead pause maintenace or
* pause pending activity is done for the rep. pair as the
* pause maintenance task associated with the target are done)
*
* INPUT PARAMETERS : deviceName - the target volume of rep. pair for which the status is being reported
* cleanupstr - the state, error message for 5 clean up status(Pending directory,vsnap, retaintion log, unlock volume) being reported
*
*
* OUTPUT PARAMETERS : None
*
* NOTES : None
*
* return value : success/failure status - failure in case of exception in reporting to cx
*
*/
bool NotifyMaintenanceActionStatus(Configurator & configurator, const std::string & devicename, int hosttype, const std::string & respstr)
{
bool rv = true;
std::string cxVolName;
try
{
cxVolName = devicename;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
DebugPrintf(SV_LOG_DEBUG, "@LINE %d in FILE %s, cxVolName = %s\n", LINE_NO, FILE_NAME, cxVolName.c_str());
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
rv = configurator.getVxAgent().setPauseReplicationStatus( cxVolName,hosttype,respstr);
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,"\nNotifyMaintenanceActionStatus call to cx for device %s failed with exception %s.\n",cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,"\nNotifyMaintenanceActionStatus call to cx for device %s failed with unknown exception.\n",cxVolName.c_str());
}
return rv;
}
void convertToCxFormattedPersistInfo(VsnapPersistInfo & vsnap)
{
if(!vsnap.mountpoint.empty())
FormatVolumeNameForCxReporting(vsnap.mountpoint);
if(!vsnap.devicename.empty())
FormatVolumeNameForCxReporting(vsnap.devicename);
if(!vsnap.target.empty())
FormatVolumeNameForCxReporting(vsnap.target);
}
void convertToCxFormattedVsnapDeleteInfo(VsnapDeleteInfo & vsnap)
{
FormatVolumeNameForCxReporting(vsnap.target_device);
FormatVolumeNameForCxReporting(vsnap.vsnap_device);
}
bool IsVsnapDriverAvailable()
{
Configurator * configurator;
bool rv = true;
if(GetConfigurator(&configurator))
{
rv = configurator->getVxAgent().IsVsnapDriverAvailable();
}
else
{
// assign the default expected values
rv = true;
}
return rv;
}
bool IsVolpackDriverAvailable()
{
Configurator * configurator;
bool rv = true;
if(GetConfigurator(&configurator))
{
rv = configurator->getVxAgent().IsVolpackDriverAvailable();
}
else
{
// assign the default expected values
rv = false;
}
return rv;
}
void printVolVgs(VolToVgs_t &voltovgs)
{
for (VolToVgsIter_t cit = voltovgs.begin(); cit != voltovgs.end(); cit++)
{
DebugPrintf(SV_LOG_DEBUG, "====\n");
DebugPrintf(SV_LOG_DEBUG, "volume: %s\n", cit->first);
printVgsPtrVec(cit->second);
DebugPrintf(SV_LOG_DEBUG, "====\n");
}
}
void printVgsPtrVec(VgsPtrs_t &vgs)
{
for (VgsPtrsIter_t vit = vgs.begin(); vit != vgs.end(); vit++)
{
VOLUME_GROUP_SETTINGS *pvgs = *vit;
VOLUME_GROUP_SETTINGS &vgs = *pvgs;
DebugPrintf(SV_LOG_DEBUG, "volumegroup id: %d\n", vgs.id);
for (VOLUME_GROUP_SETTINGS::volumes_iterator volit = vgs.volumes.begin(); volit != vgs.volumes.end(); volit++)
{
VOLUME_SETTINGS &vs = volit->second;
DebugPrintf(SV_LOG_DEBUG, "device name: %s\n", volit->first.c_str());
DebugPrintf(SV_LOG_DEBUG, "host id: %s\n", vs.hostId.c_str());
}
}
}
void Object::Print(const SV_LOG_LEVEL LogLevel)
{
PrintAttributes(m_Attributes, LogLevel);
}
void Object::Reset(void)
{
m_Attributes.clear();
}
void PrintAttributes(const Attributes_t &attributes, const SV_LOG_LEVEL LogLevel)
{
DebugPrintf(LogLevel, "Attributes (name --> value):\n");
for (ConstAttributesIter_t it = attributes.begin(); it != attributes.end(); it++)
{
DebugPrintf(LogLevel, "%s --> %s\n", it->first.c_str(), it->second.c_str());
}
}
std::ostream& operator<< (std::ostream& out, const Objects_t &objs)
{
for (ConstObjectsIter_t oit = objs.begin(); oit != objs.end(); oit++)
{
out << *oit;
}
return out;
}
std::ostream& operator<< (std::ostream& out, const Object &o)
{
out << "object:\n";
out << o.m_Attributes;
return out;
}
std::ostream& operator<< (std::ostream& out, const Attributes_t &attrs)
{
out << "Attributes (name --> value):\n";
for (ConstAttributesIter_t it = attrs.begin(); it != attrs.end(); it++)
{
out << it->first << " --> " << it->second << '\n';
}
return out;
}
HOST_VOLUME_GROUP_SETTINGS::volumeGroups_t GetEndPointVolumeSettings(HOST_VOLUME_GROUP_SETTINGS& hostVolumeGroupSettings,std::list<VOLUME_SETTINGS> endPointVolSettings)
{
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
bool bFound = false;
HOST_VOLUME_GROUP_SETTINGS::volumeGroups_t endPointVolumeGroupSettings;
VOLUME_GROUP_SETTINGS::volumes_iterator volumeIter;
VOLUME_GROUP_SETTINGS::volumes_iterator volumeEnd;
HOST_VOLUME_GROUP_SETTINGS::volumeGroups_iterator volumeGroupIter = hostVolumeGroupSettings.volumeGroups.begin();
HOST_VOLUME_GROUP_SETTINGS::volumeGroups_iterator volumeGroupEnd = hostVolumeGroupSettings.volumeGroups.end();
for (; volumeGroupIter != volumeGroupEnd; ++volumeGroupIter)
{
volumeIter = (*volumeGroupIter).volumes.begin();
volumeEnd = (*volumeGroupIter).volumes.end();
bFound = false;
if( (TARGET == (*volumeGroupIter).direction))
{
for (; volumeIter != volumeEnd && (!bFound); ++volumeIter)
{
std::string deviceName = (*volumeIter).second.deviceName;
std::string hostId = (*volumeIter).second.hostId;;
VOLUME_SETTINGS::endpoints_iterator endPointsIter = endPointVolSettings.begin();
VOLUME_SETTINGS::endpoints_iterator endPointsIterEnd = endPointVolSettings.end();
while(endPointsIter != endPointsIterEnd)
{
if((deviceName == endPointsIter->deviceName) &&
(hostId.compare(endPointsIter->hostId) == 0))
{
DebugPrintf(SV_LOG_DEBUG,"Device Name %s EndPoint Device Name %s\n",deviceName.c_str(),endPointsIter->deviceName.c_str());
endPointVolumeGroupSettings.push_back((*volumeGroupIter));
bFound = true;
break;
}
endPointsIter++;
}
}
}
}
DebugPrintf(SV_LOG_DEBUG,"EXITED %s\n",FUNCTION_NAME);
return endPointVolumeGroupSettings;
}
bool sendFlushAndHoldWritesPendingStatusToCx(Configurator & configurator,std::string volumename,bool status, int error_num, std::string errmsg)
{
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
bool rv = true;
std::string cxVolName;
try
{
cxVolName = volumename;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
DebugPrintf(SV_LOG_DEBUG, "%s, cxVolName = %s, status = %d, error_msg = %s, error_num = %d\n", FUNCTION_NAME, cxVolName.c_str(), rv, errmsg.c_str(), error_num);
if(configurator.getVxAgent().updateFlushAndHoldWritesPendingStatus(cxVolName,status,errmsg,error_num) == 1)
{
rv = false;
}
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,"sendFlushAndHoldWritesPendingStatusToCx call to cx for device %s failed with exception %s.\n",cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,"sendFlushAndHoldWritesPendingStatusToCx call to cx for device %s failed with unknown exception.\n",cxVolName.c_str());
}
DebugPrintf(SV_LOG_DEBUG,"LEAVING %s\n",FUNCTION_NAME);
return rv;
}
bool sendFlushAndHoldResumePendingStatusToCx(Configurator & configurator,std::string volumename,bool status, int error_num, std::string errmsg)
{
bool rv = true;
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
std::string cxVolName;
try
{
cxVolName = volumename;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
DebugPrintf(SV_LOG_DEBUG, "%s, cxVolName = %s, status = %d, error_msg = %s, error_num = %d\n", FUNCTION_NAME, cxVolName.c_str(),rv,errmsg.c_str(),error_num);
if(configurator.getVxAgent().updateFlushAndHoldResumePendingStatus(cxVolName,status,errmsg,error_num) == 1)
{
rv = false;
}
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,"sendFlushAndHoldResumePendingStatusToCx call to cx for device %s failed with exception %s.\n",cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,"sendFlushAndHoldResumePendingStatusToCx call to cx for device %s failed with unknown exception.\n",cxVolName.c_str());
}
DebugPrintf(SV_LOG_DEBUG,"LEAVING %s\n",FUNCTION_NAME);
return rv;
}
bool getFlushAndHoldRequestSettings(Configurator & configurator,std::string volumename,FLUSH_AND_HOLD_REQUEST & flushAndHoldRequestSettings)
{
bool rv = true;
std::string cxVolName;
try
{
cxVolName = volumename;
FormatVolumeNameForCxReporting(cxVolName);
FirstCharToUpperForWindows(cxVolName);
if (IsReportingRealNameToCx())
{
/* Then get the device name and send to CX */
GetDeviceNameFromSymLink(cxVolName);
}
DebugPrintf(SV_LOG_DEBUG, "%s, cxVolName = %s\n", FUNCTION_NAME, cxVolName.c_str());
flushAndHoldRequestSettings = configurator.getVxAgent().getFlushAndHoldRequestSettings(cxVolName);
}
catch( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,"getFlushAndHoldRequestSettings call to cx for device %s failed with exception %s.\n",cxVolName.c_str(), ce.what());
}
catch( ... )
{
rv = false;
DebugPrintf(logLevel,"getFlushAndHoldRequestSettings call to cx for device %s failed with unknown exception.\n",cxVolName.c_str());
}
return rv;
}
bool cdpStopReplication(Configurator & configurator, const std::string &volname, const std::string &cleanupaction)
{
bool rv = true;
try
{
rv = configurator.getVxAgent().cdpStopReplication(volname,cleanupaction);
}
catch ( ContextualException& ce )
{
rv = false;
DebugPrintf(logLevel,
"\nNote: Replication pair deletion request for %s failed with exception %s\n. It will be deleted when communication with Central Management Server is restored.\n", volname.c_str(), ce.what());
}
catch ( ... )
{
rv = false;
DebugPrintf(logLevel,
"\nNote: Replication pair deletion request for %s did not complete and will be tried again when communication with Central Management Server is restored\n\n",volname.c_str() );
}
return rv;
}
bool SendAlertToRcm(SV_ALERT_TYPE AlertType, SV_ALERT_MODULE AlertingModule, const InmAlert &Alert)
{
return true;
}
bool SendAlertToCx(SV_ALERT_TYPE AlertType, SV_ALERT_MODULE AlertingModule, const InmAlert &Alert)
{
LocalConfigurator localConfigurator;
if (localConfigurator.isMobilityAgent() &&
(localConfigurator.IsAzureToAzureReplication() ||
boost::iequals(localConfigurator.getCSType(), CSTYPE_CSPRIME)))
{
DebugPrintf(SV_LOG_DEBUG, "SendAlertToCx: Control plane is RCM.\n");
return SendAlertToRcm(AlertType, AlertingModule, Alert);
}
boost::mutex::scoped_lock guard(g_AlertMutex);
bool rv = false;
static LastAlertDetails s_La;
Configurator* TheConfigurator = NULL;
if(!GetConfigurator(&TheConfigurator))
{
DebugPrintf(SV_LOG_DEBUG, "Error obtaining configurator %s\t%d\n", FUNCTION_NAME, LINE_NO);
DebugPrintf(SV_LOG_ERROR,"FAILED:sendAlertToCx call failed.\n");
return rv;
}
time_t ltime;
struct tm *today;
std::string Agent_type; /* To hold the agent type */
time( <ime );
time_t ltimecopy = ltime;
std::stringstream alertwithtypeandmodule;
const char SEP = '@';
alertwithtypeandmodule << Alert.GetID() << SEP << cxArg(Alert.GetParameters()) << SEP << AlertType << SEP << AlertingModule;
if (alertwithtypeandmodule.str() == s_La.GetAlert()) {
if ((ltimecopy-s_La.GetTime()) <= TheConfigurator->getVxAgent().getRepeatingAlertIntervalInSeconds()) {
DebugPrintf(SV_LOG_DEBUG, "Alert %s is already recorded (with same parameters) with in repeating alert interval. Hence not recording again.\n", alertwithtypeandmodule.str().c_str());
rv = true;
return rv;
}
}
DebugPrintf(SV_LOG_DEBUG, "Recording alert %s\n", alertwithtypeandmodule.str().c_str());
today = gmtime( <ime );
char szGmtTimeBuff[100]; /* To hold the time in buffer form */
// initialize 100 bytes of the character string to 0
memset(szGmtTimeBuff,0,100);
inm_sprintf_s(szGmtTimeBuff, ARRAYSIZE(szGmtTimeBuff), "(20%02d-%02d-%02d %02d:%02d:%02d):",
today->tm_year - 100,
today->tm_mon + 1,
today->tm_mday,
today->tm_hour,
today->tm_min,
today->tm_sec
);
if(GetLoggerAgentType() == FxAgentLogger)
Agent_type="FX";
else
Agent_type="VX";
try
{
if(TheConfigurator->getVxAgent().sendAlertToCx(szGmtTimeBuff, "ALERT", Agent_type,
AlertType, AlertingModule, Alert))
{
s_La.SetDetails(alertwithtypeandmodule.str(), ltimecopy);
rv = true;
}
}catch(...) {
DebugPrintf(SV_LOG_ERROR,"FAILED:sendAlertToCx call failed for alert id, parameters and module: %s\n", alertwithtypeandmodule.str().c_str());
}
return (rv);
}