host/common/portablehelpers.cpp (3,507 lines of code) (raw):
#include "portablehelpers.h"
#include "portablehelperscommonheaders.h"
#include "portablehelpersmajor.h"
#include "inmquitfunction.h"
#include "svutils.h"
#include "version.h"
#include "inmageex.h"
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include "file.h"
#include "npwwnif.h"
#include "printfunctions.h"
#include "inmdefines.h"
#include "inm_md5.h"
#include "transport_settings.h"
#include "genericstream.h"
#include "transportstream.h"
#include "serializevolumegroupsettings.h"
#include "configutils.h"
#include "diskslayoutupdater.h"
#include "diskslayoutupdaterimp.h"
#include "inmsafecapis.h"
#include "inmsafeint.h"
#include "inmageex.h"
#include "curlwrapper.h"
#include "configwrapper.h"
#include "inmalertdefs.h"
#include "fingerprintmgr.h"
#include "csgetfingerprint.h"
#include "errorexception.h"
#include <sstream>
#include <fstream>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <cstdarg>
#include <cerrno>
#include <boost/algorithm/string/replace.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/asio.hpp>
#include <ace/Time_Value.h>
#include <curl/curl.h>
#include <boost/chrono.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::chrono;
using std::max;
const std::string AZURE_ASSET_TAG("7783-7084-3265-9085-8269-3286-77");
const long IMDS_RETRY_INTERVAL_IN_SECS = 5;
typedef struct tagMemoryStruct
{
char *memory;
size_t insize;
size_t size;
} MemoryStruct;
SVERROR MakeReadOnly(const char *drive, void *VolumeGuid, etBitOperation Op);
SVERROR MakeVirtualVolumeReadOnly(const char *mountpoint, void * volumeGuid, etBitOperation ReadOnlyBitFlag);
void GetHypervisorInfo(HypervisorInfo_t &hypervisorinfo);
void PrintHypervisorInfo(const HypervisorInfo_t &hypervisorinfo);
void GetNicInfos(NicInfos_t &nicinfos);
bool HasNicInfoPhysicaIPs(const NicInfos_t &nicinfos);
void PrintNicInfos(NicInfos_t &nicinfos, const SV_LOG_LEVEL logLevel = SV_LOG_DEBUG);
void mountBootableVolumesIfRequried();
extern bool SystemDiskUEFICheck(std::string &errormsg);
extern bool IsSystemAndBootDiskSame(const VolumeSummaries_t &volumeSummaries, std::string &errormsg);
extern bool IsUEFIBoot(void);
boost::mutex g_RegisterHostMutex; //Provide mutual exclusive access to RegisterHost() calls
const size_t SECTOR_SIZE = 512;
//bool IsNewSparseFileFormat(const std::string vol_name)
//{
// std::string sparsefile;
// ACE_stat s;
// if(!IsVolPackDevice(vol_name.c_str() ,sparsefile) )
// return false;
//
// std::string partfile = sparsefile + SPARSE_PARTFILE_EXT;
// partfile += "0";
//
// if( sv_stat( getLongPathName(partfile.c_str()).c_str(), &s ) == 0 )
// {
// return true;
// }
// return false;
//}
/*
Function: IsVolPackDevice
Description: 1. Find the given device file is a volpack volume or not
2. Detect whether its a multi sparse or single sparse file
Note: Here there is a extra check if devicefile supplied a sparse file of a volpack
then it will return true and also tell whether is multi sparse or not
Input: deviceFile
output: sparsefile,multisparse
return value: true if volpack device or sparse file for a volpack device otherwise false
*/
bool IsVolPackDevice(char const * deviceFile,std::string & sparsefile,bool & multisparse)
{
LocalConfigurator TheLocalConfigurator;
multisparse = false;
int counter = TheLocalConfigurator.getVirtualVolumesId();
while(counter != 0) {
char regData[26];
inm_sprintf_s(regData, ARRAYSIZE(regData), "VirVolume%d", counter);
std::string data = TheLocalConfigurator.getVirtualVolumesPath(regData);
std::string sparsefilename;
std::string volume;
if (!ParseSparseFileNameAndVolPackName(data, sparsefilename, volume))
{
counter--;
continue;
}
std::string deviceName = deviceFile;
FormatVolumeName(deviceName);
if(0 == stricmp(volume.c_str(),deviceName.c_str())) {
sparsefile = sparsefilename;
std::string partfile = sparsefile;
partfile += ".filepart0";
ACE_stat s;
if( sv_stat( getLongPathName(partfile.c_str()).c_str(), &s ) == 0 )
{
multisparse = true;
}
return true;
} else if(0 == stricmp(sparsefilename.c_str(),deviceFile))
{
sparsefile = sparsefilename;
std::string partfile = sparsefile;
partfile += ".filepart0";
ACE_stat s;
if( sv_stat( getLongPathName(partfile.c_str()).c_str(), &s ) == 0 )
{
multisparse = true;
}
return true;
}else {
counter--;
continue;
}
}
return false;
}
bool containsVolpackFiles(const std::string & volumename)
{
LocalConfigurator TheLocalConfigurator;
int counter = TheLocalConfigurator.getVirtualVolumesId();
std::string inputvolume = volumename;
while(counter!=0)
{
char regData[26]; // TODO: why 26?
inm_sprintf_s(regData, ARRAYSIZE(regData), "VirVolume%d", counter);
std::string data = TheLocalConfigurator.getVirtualVolumesPath(regData);
std::string sparsefile;
std::string virtualvolume;
if(!ParseSparseFileNameAndVolPackName(data, sparsefile, virtualvolume))
{
counter--;
continue;
}
FormatVolumeName(inputvolume);
std::string sparsefile_volume_mnpt;
GetVolumeRootPath(sparsefile,sparsefile_volume_mnpt);
std::string sparsefilevolumename;
GetDeviceNameForMountPt(sparsefile_volume_mnpt,sparsefilevolumename);
FormatVolumeName(sparsefilevolumename);
if(sameVolumeCheck(sparsefilevolumename,inputvolume))
{
return true;
}
counter--;
}
return false;
}
/** COMMONTOALL : START */
SVERROR OpenVolume( /* out */ ACE_HANDLE *pHandleVolume,
/* in */ const char *pch_VolumeName
)
{
return OpenVolumeExtended (pHandleVolume, pch_VolumeName, O_RDWR);
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
///
/// Frees the resources associated with an opened volume. See also CloseVolumeExclusive.
///
SVERROR CloseVolume( ACE_HANDLE handleVolume )
{
SVERROR sve = SVS_OK;
ACE_OS::last_error(0);
do
{
DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( "ENTERED CloseVolume()...\n" );
if( ( ACE_INVALID_HANDLE != handleVolume ) &&
ACE_OS::close( handleVolume ))
{
sve = ACE_OS::last_error();
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( SV_LOG_ERROR, "FAILED CloseVolume()... err = %s\n", sve.toString() );
break;
}
}
while( FALSE );
return( sve );
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
// TODO: we need to do more investigation on the volume size for now
// GetFileSystemVolumeSize
// GetDriverVolumeSize
// CanReadDriverSize
// GetVolumeSize
// all are used to determine the volume size
// the current approach
// get the file system reported size
// get the driver reported size
// if files system size is < driver size
// then see if the volume can be read up to the driver volume size
// if so use it, else use the file system size
bool GetFileSystemVolumeSize(char *vol, SV_ULONGLONG* size, unsigned int* sectorSize)
{
std::string volName;
if (vol == NULL)
return false;
volName = vol;
SVERROR sve = GetFsVolSize(volName.c_str(), size);
if (sve.failed())
{
DebugPrintf(SV_LOG_WARNING, "WARN: GetFsVolSize() failed. volume = %s (OK if volume is a hidden target or cluster volume offline)\n", volName.c_str());
return false;
}
(void)GetFsSectorSize(volName.c_str(), sectorSize);
return true;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
bool GetVolumeSize(char *vol, SV_ULONGLONG* size)
{
unsigned int sectorSize;
SV_ULONGLONG fsSize = 0;
SV_ULONGLONG driverSize = 0;
bool fsOk = GetFileSystemVolumeSize(vol, &fsSize, §orSize);
bool driverOk = GetDriverVolumeSize(vol, &driverSize);
if (!(fsOk || driverOk)) {
// both failed
return false;
}
if (fsOk && driverOk) {
// both succeeded
if (fsSize < driverSize) {
// OK let's see if we can read the driver reported size
if (CanReadDriverSize(vol, driverSize, sectorSize)) {
(*size) = driverSize;
return true;
}
}
(*size) = fsSize;
} else if (fsOk) {
// only file system succeeded
(*size) = fsSize;
} else {
// only driver succeeded
// TODO: for now return 0 so that the CX does not update this info
// if we return the driverSize it causes several issues in that the
// size can be incorrect and the file system type may not be reported
// this case will happen for cluster nodes that are offline or volumes
// that are hidden
(*size) = 0; // driverSize;
}
return true;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
bool Tokenize(const std::string& input, std::vector<std::string>& outtoks,const std::string& separators)
{
std::string::size_type pp, cp;
outtoks.clear();
pp = input.find_first_not_of(separators, 0);
cp = input.find_first_of(separators, pp);
while ((std::string::npos != cp) || (std::string::npos != pp)) {
outtoks.push_back(input.substr(pp, cp-pp));
pp = input.find_first_not_of(separators, cp);
cp = input.find_first_of(separators, pp);
}
return true;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
SVERROR HideDrive(const char * drive, char const* mountPoint )
{
std::string output, error;
SVERROR sve = HideDrive(drive, mountPoint, output, error);
if(sve.failed())
{
DebugPrintf(SV_LOG_ERROR, "%s\n", error.c_str());
}
return sve;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
SVERROR SetReadOnly(const char * drive, void * VolumeGUID, bool isVirtualVolume )
{
if( ! isVirtualVolume)
return MakeReadOnly(drive, VolumeGUID, ecBitOpSet);
return MakeVirtualVolumeReadOnly(drive, VolumeGUID, ecBitOpSet);
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
SVERROR ResetReadOnly(const char * drive, void * VolumeGUID, bool isVirtualVolume)
{
LocalConfigurator localConfigurator;
if( ! isVirtualVolume && localConfigurator.IsFilterDriverAvailable())
return MakeReadOnly(drive, VolumeGUID, ecBitOpReset);
else if (isVirtualVolume && localConfigurator.IsFilterDriverAvailable() && localConfigurator.IsVolpackDriverAvailable())
return MakeVirtualVolumeReadOnly(drive, VolumeGUID, ecBitOpReset);
else
{
DebugPrintf(SV_LOG_DEBUG, "Filter driver is not present. So cannot reset read only flag.\n");
return SVS_OK;
}
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
// --------------------------------------------------------------------------
// deletes the local file
// --------------------------------------------------------------------------
bool DeleteLocalFile(std::string const & name)
{
// PR#10815: Long Path support
return ( -1 != ACE_OS::unlink(getLongPathName(name.c_str()).c_str()));
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
SVERROR BaseName( const char *pszFullName, char *pszBaseName, const int pszBaseNameLen)
{
SVERROR hr = SVS_OK;
char *curr = (char *) pszFullName;
char *last = (char *) pszFullName;
char *first = (char *) pszFullName;
// Verify input
if ( (NULL == pszFullName) || (NULL == pszBaseName) )
{
hr = SVE_INVALIDARG;
return hr;
}
// Prep the return string
pszBaseName[0] = '\0';
// Find the last path delimiter
while (*curr)
{
if ( ( *curr == '/' ) || ( *curr == '\\' ) ) {
last = curr;
}
++curr;
}
// Skip the last path delimiter
if (last != first)
{
last++;
}
// Copy the basename to return string
inm_strcpy_s(pszBaseName, pszBaseNameLen, last);
//printf("Basename is %s\n", pszBaseName);
return hr;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
SVERROR DirName( const char *pszFullName, char *pszDirName, const int pszDirNameLen)
{
SVERROR hr = SVS_OK;
char *curr = (char *) pszFullName;
char *last = (char *) pszFullName;
char *first = (char *) pszFullName;
// Verify input
if ( (NULL == pszFullName) || (NULL == pszDirName) )
{
hr = SVE_INVALIDARG;
return hr;
}
// Prep the return string
pszDirName[0] = '\0';
// Find the last path delimiter
while (*curr)
{
if ( ( *curr == '/') || ( *curr == '\\' ) ) {
last = curr;
//printf("Match at %s, \n", last);
}
++curr;
}
// Copy over the dirname and null terminate it
inm_strncpy_s(pszDirName, pszDirNameLen, first, (last - first));
pszDirName[last-first] = '\0';
//printf("Dirname is %s\n", pszDirName);
return hr;
}
/** COMMONTOALL : END */
std::string basename_r(const std::string &name, const char &separator_char)
{
std::string::size_type scp = name.rfind(separator_char);
return (std::string::npos == scp) ? name : name.substr(scp+1);
}
std::string dirname_r(const std::string &name, const char &separator_char)
{
std::string::size_type scp = name.rfind('\\');
if (std::string::npos == scp)
scp = name.rfind('/');
return (std::string::npos == scp) ? std::string(".") : name.substr(0, scp);
}
std::string PlatformBasedDirname(const std::string &name, const char &separator_char)
{
std::string::size_type scp = name.rfind(separator_char);
return (std::string::npos == scp) ? std::string(".") : name.substr(0, scp);
}
/** COMMONTOALL : START */
///
/// Replaces (Translates) all instances of inputChar in the string pszInString with outputChar. This is
/// an inplace replacement; no new memory is allocated. Equivalent to perl's tr// operator.
///
SVERROR ReplaceChar(char *pszInString, char inputChar, char outputChar) {
int i;
if (NULL == pszInString) {
return EINVAL;
}
for (i=0; '\0' != pszInString[i]; i++)
{
if (pszInString[i] == inputChar) {
pszInString[i] = outputChar;
}
}
return SVS_OK;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
///
/// Appends the input character and a null terminator
/// to the input string
///
SVERROR AppendChar(char *pszInString, char inputChar) {
unsigned int i;
if (!pszInString)
{
return SVE_FAIL;
}
if (NULL == pszInString) {
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( SV_LOG_ERROR, "FAILED in AppendChar(), pszInString == NULL\n");
return EINVAL;
}
for (i=0; '\0' != pszInString[i]; i++)
{
}
// Warning
if (i > 10000)
{
DebugPrintf( SV_LOG_WARNING, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( SV_LOG_WARNING, "WARNING Possibly a bad input string?, i = %d\n", i);
}
pszInString[i] = inputChar;
pszInString[i+1] = '\0';
return SVS_OK;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
bool IsColon( std::string::value_type ch ) { return ':' == ch; }
bool IsQuestion( std::string::value_type ch ) { return '?' == ch; }
/** COMMONTOALL : END */
/** COMMONTOALL : START */
bool RegExpMatch(const char *srchptrn, const char *input)
{
char *p;
char t;
const char *ps;
char c;
for (ps = input;;)
{
switch (c = *srchptrn++)
{
case '\0':
return (*input == '\0');
case '?':
if (*input == '\0')
{
return false;
}
if ((*input == '.') && (input == ps))
{
return false;
}
++input;
break;
case '*':
c = *srchptrn;
while (c == '*')
{
c = *++srchptrn;
}
if ((*input == '.') && (input == ps))
{
return false;
}
if (c == '\0')
{
return true;
}
while ((t = *input) != '\0')
{
if (RegExpMatch(srchptrn, input))
{
return true;
}
++input;
}
return false;
case '[':
if (*input == '\0')
{
return false;
}
if ((*input == '.') && (input == ps))
{
return false;
}
switch (DoesRegExpRangeMatch(srchptrn, *input,&p))
{
case -1:
goto regular;
case 1:
srchptrn = p;
break;
case 0:
return false;
}
++input;
break;
case '\\':
if ((c = *srchptrn++) == '\0')
{
c = '\\';
--srchptrn;
}
default:
regular:
/* The regular string */
if (c != *input )
{
return false;
}
++input;
break;
}
}
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
svector_t split(const std::string &arg,
const std::string &delim,
const int numFields)
{
svector_t splitList;
int delimetersFound = 0;
std::string::size_type delimLength = delim.length();
std::string::size_type argEndIndex = arg.length();
std::string::size_type front = 0;
//
// Find the location of the first delimeter.
//
std::string::size_type back = arg.find(delim, front);
while( back != std::string::npos ) {
++delimetersFound;
if( (numFields) && (delimetersFound >= numFields) ) {
break;
}
//
// Put the first (left most) field of the string into
// the vector of strings.
//
// Example:
//
// field1:field2:field3
// ^ ^
// front back
//
// The substr() call will take characters starting
// at front extending to the length of (back - front).
//
// This puts 'field1' into the splitList.
//
splitList.push_back(arg.substr(front, (back - front)));
//
// Get the front of the second field in arg. This is done
// by adding the length of the delimeter to the back (ending
// index) of the previous find() call.
//
// This makes front point to the first character after
// the delimeter.
//
// Example:
//
// 'field1:field2:field3'
// ^^
// back front
//
// delimLength = 1
//
front = back + delimLength;
//
// Find the location of the next delimeter.
//
back = arg.find(delim, front);
}
//
// After we get through the entire string, there may be data at the
// end of the arg that has not been stored. The data will be
// the trailing remnant (or the entire string if no delimeter was found).
// So put the "remainder" into the splitList (this would add 'field3'
// to the list.)
//
// Example:
//
// 'field1:field2:field3'
// ^ ^
// front argEndIndex
//
// (argEndIndex - front) yeilds the number of elements to grab.
//
if( front < argEndIndex ) {
splitList.push_back(arg.substr(front, (argEndIndex - front)));
}
return splitList;
}
/** COMMONTOALL : START */
int DoesRegExpRangeMatch(const char *srchptrn, char verify, char **ptrcurr)
{
char eachchar;
char tmpchar;
int fine;
int reverse;
if ((reverse = (*srchptrn == '!' || *srchptrn == '^')))
{
++srchptrn;
}
fine = 0;
eachchar = *srchptrn++;
do {
if (eachchar == '\\')
{
eachchar = *srchptrn++;
}
if (eachchar == '\0')
{
return -1;
}
if ((*srchptrn == '-') && ((tmpchar = *(srchptrn+1)) != '\0') && (tmpchar != ']'))
{
srchptrn += 2;
if (tmpchar == '\\' )
{
tmpchar = *srchptrn++;
}
if (tmpchar == '\0')
{
return -1;
}
if (eachchar <= verify && verify <= tmpchar)
{
fine = 1;
}
}
else if (eachchar == verify)
{
fine = 1;
}
} while ((eachchar = *srchptrn++) != ']');
*ptrcurr = (char *)(srchptrn);
return ((fine == reverse)?0:1);
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
SVERROR CleanupDirectory( const char *pszDirectory, const char *pszFilePattern )
{
SVERROR sve = SVS_OK;
do
{
if( ( NULL == pszDirectory ) || ( NULL == pszFilePattern ) )
{
sve = EINVAL;
break;
}
//Open directory
// PR#10815: Long Path support
ACE_DIR *dirp = sv_opendir(pszDirectory);
if (dirp == NULL)
{
int lasterror = ACE_OS::last_error();
if (ENOENT == lasterror || ESRCH == lasterror || EXDEV == lasterror)
{
sve = SVS_OK;
} else
{
sve = lasterror;
DebugPrintf(SV_LOG_ERROR, "opendir failed, path = %s, errno = 0x%x\n", pszDirectory, ACE_OS::last_error());
}
break;
}
struct ACE_DIRENT *dp = NULL;
do
{
ACE_OS::last_error(0);
//Get directory entry
if ((dp = ACE_OS::readdir(dirp)) != NULL)
{
//Find a matching entry
if (RegExpMatch(pszFilePattern, ACE_TEXT_ALWAYS_CHAR(dp->d_name)))
{
std::string filePath;
filePath = pszDirectory;
filePath += ACE_DIRECTORY_SEPARATOR_CHAR_A;
filePath += ACE_TEXT_ALWAYS_CHAR(dp->d_name);
//Delete file
// PR#10815: Long Path support
if (ACE_OS::unlink(getLongPathName(filePath.c_str()).c_str()) != 0)
{
DebugPrintf(SV_LOG_ERROR, "unlink failed, path = %s, errno = 0x%x\n", filePath.c_str(), ACE_OS::last_error());
sve = ACE_OS::last_error();
}
}
}
} while(dp);
//Close directory
ACE_OS::closedir(dirp);
} while(false);
return( sve );
}
bool sv_get_filecount_spaceusage(const char * directory, const char * file_pattern,
SV_ULONGLONG & filecount, SV_ULONGLONG & size_on_disk ,SV_ULONGLONG& logicalsize)
{
bool rv = true;
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s \n", FUNCTION_NAME);
do
{
size_on_disk = 0;
filecount = 0;
logicalsize = 0;
if( ( NULL == directory ) || ( NULL == file_pattern ) )
{
DebugPrintf(SV_LOG_ERROR, "FUNCTION:%s invalid (null) input.\n",
FUNCTION_NAME);
rv = false;
break;
}
// open directory
// PR#10815: Long Path support
ACE_DIR *dirp = sv_opendir(directory);
if (dirp == NULL)
{
int lasterror = ACE_OS::last_error();
if (ENOENT == lasterror || ESRCH == lasterror || EXDEV == lasterror)
{
size_on_disk = 0;
filecount = 0;
rv = true;
} else
{
rv = false;
DebugPrintf(SV_LOG_ERROR,
"FUNCTION:%s opendir failed, path = %s, errno = %d\n",
FUNCTION_NAME, directory, ACE_OS::last_error());
}
break;
}
struct ACE_DIRENT *dp = NULL;
do
{
ACE_OS::last_error(0);
// Get directory entry
if ((dp = ACE_OS::readdir(dirp)) != NULL)
{
//Find a matching entry
if (RegExpMatch(file_pattern, ACE_TEXT_ALWAYS_CHAR(dp->d_name)))
{
std::string filePath;
filePath = directory;
filePath += ACE_DIRECTORY_SEPARATOR_CHAR_A;
filePath += ACE_TEXT_ALWAYS_CHAR(dp->d_name);
size_on_disk += File::GetSizeOnDisk(filePath);
ACE_stat statbuf = {0};
if(sv_stat(getLongPathName(filePath.c_str()).c_str(), &statbuf) != 0)
{
DebugPrintf(SV_LOG_ERROR, "FUNCTION:%s Failed to get file :%s statistics. errno = %d.\n",
FUNCTION_NAME,filePath.c_str(), ACE_OS::last_error());
continue;
//rv = false;
//break;
}
else
{
logicalsize += statbuf.st_size;
}
filecount += 1;
}
}
} while(dp);
//Close directory
ACE_OS::closedir(dirp);
DebugPrintf(SV_LOG_DEBUG, "FUNCTION:%s directory:%s pattern:%s, size_on_disk =" ULLSPEC " \n",
FUNCTION_NAME, directory,file_pattern, size_on_disk);
} while(false);
DebugPrintf(SV_LOG_DEBUG, "EXITED %s \n", FUNCTION_NAME);
return rv;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
///
/// Returns true if the string ends with the ending string argument
///
bool endsWith( const char* str, const char* ending, bool caseSensitive )
{
bool rc = false;
int const stringLength = strlen( str );
int const endingLength = strlen( ending );
if( stringLength >= endingLength )
{
char const* stringEnd = str + stringLength - endingLength;
rc = 0 == (caseSensitive ? strcmp( stringEnd, ending ) : strcmpi( stringEnd, ending ) );
}
return( rc );
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
static int mkdirRecursiveHelper( char* pathname, mode_t mode )
{
// PR#10815: Long Path support
if( ACE_OS::mkdir( getLongPathName(pathname).c_str(), mode ) == 0 )
{
return 0;
}
switch( errno )
{
default:
break;
case EEXIST:
{
ACE_stat stat;
// PR#10815: Long Path support
if (sv_stat(getLongPathName(pathname).c_str(), &stat) == 0)
{
errno = ((stat.st_mode & S_IFDIR) == S_IFDIR) ? EEXIST : ENOTDIR;
//errno = S_ISDIR(stat.st_mode) ? EEXIST : ENOTDIR;
}
break;
}
case ENOENT:
case ENOTDIR:
char* last_sep( ACE_OS::strrchr(
pathname, ACE_DIRECTORY_SEPARATOR_CHAR_A ) );
if( 0 != last_sep && pathname != last_sep )
{
*last_sep = '\0';
int result = mkdirRecursive( pathname, mode );
*last_sep = ACE_DIRECTORY_SEPARATOR_CHAR_A;
if( 0 == result || EEXIST == errno )
{
// Now that the parent is made, try to remake this one
// PR#10815: Long Path support
return ACE_OS::mkdir( getLongPathName(pathname).c_str(), mode );
}
}
break;
}
return -1;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
///
/// Creates a directory even if the parent directories do not exist
/// E.g. creates /tmp/parent/mydir even if /tmp/parent is missing.
/// NOTE: On Windows, doesn't respect / as a separator
///
int mkdirRecursive( char const* pathname, mode_t mode )
{
char buffer[ MAXPATHLEN + 1 ];
if( strlen( pathname ) > sizeof( buffer ) - 1 )
{
errno = ENAMETOOLONG;
return -1;
}
else
{
inm_strcpy_s( buffer, ARRAYSIZE(buffer), pathname );
}
return mkdirRecursiveHelper( buffer, mode );
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
// Function moved from CDPCli
void GetConsoleYesOrNoInput(char & ch)
{
ch = getchar();
while((ch != 'y') && (ch != 'n') && (ch != 'Y') && (ch != 'N'))
{
fflush(stdin);
printf("Press y/Y/N/n....\n");
ch = getchar();
}
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
std::string getLocalTime()
{
char szLocalTime[90];
tm *today;
time_t ltime;
time( <ime );
today = localtime(<ime);
inm_sprintf_s(szLocalTime, ARRAYSIZE(szLocalTime), "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
);
DebugPrintf(SV_LOG_DEBUG,"[Portablehelpers::RegisterHost():getLocalTime()] AgentLocalTime = %s\n", szLocalTime);
return std::string(szLocalTime);
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
std::string getTimeZone()
{
static std::string zone;
if(!zone.empty())
return zone;
int zonediff;
char zonesign;
char zonebuf[10];
time_t t, lt, gt;
t = time(NULL);
lt = mktime (localtime(&t));
gt = mktime (gmtime(&t));
zonediff = (int)difftime(lt, gt);
zonesign = (zonediff >= 0)? '+' : '-';
inm_sprintf_s(zonebuf, ARRAYSIZE(zonebuf), "%c%.2d%.2d", zonesign, abs(zonediff) / 3600, abs(zonediff) % 3600 / 60);
zone = std::string(zonebuf);
DebugPrintf(SV_LOG_DEBUG,"[Portablehelpers::RegisterHost():getTimeZone()] AgentZone = %s\n", zonebuf);
return zone;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
// Prepare patch_history with fields seperated by ',' & records seperated by '|'
std::string getPatchHistory(std::string pszInstallPath)
{
char line[2001];
std::fstream fp;
std::string patchfile, patch_history;
patchfile = pszInstallPath + PATCH_FILE;
fp.open (patchfile.c_str(), std::fstream::in);
if(!fp.fail())
{
while(true)
{
fp.getline(line, sizeof(line));
if (0 == fp.gcount())
break;
if(line[0] == '#' )
continue;
if(patch_history.empty())
patch_history = std::string(line) ;
else
patch_history += '|' + std::string(line) ;
}
fp.close();
DebugPrintf(SV_LOG_DEBUG,"[Portablehelpers::RegisterHost()]PatchHistory= %s\n", patch_history.c_str());
}
else
DebugPrintf(SV_LOG_DEBUG,"[Portablehelpers::RegisterHost()] %s File cannot be opened \n", patchfile.c_str());
return patch_history;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
std::string ToUpper(const std::string& toConvert)
{
std::string sUpper = toConvert;
const int length = sUpper.length();
for(int i=0; i!=length ; ++i)
{
sUpper[i] = std::toupper(sUpper[i]);
}
return sUpper;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
std::string ToLower(const std::string& toConvert)
{
std::string sLower = toConvert;
const int length = sLower.length();
for(int i=0; i!=length ; ++i)
{
sLower[i] = std::tolower(sLower[i]);
}
return sLower;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
/** Added by BSR - Issue#5288 **/
bool resolvePathAndVerify( std::string& pathName )
{
bool bReturn = false ;
// PR#10815: Long Path support
#if defined (SV_WINDOWS) && defined (SV_USES_LONGPATHS)
ACE_TCHAR *resolvedPath = NULL;
// ACE_OS::realpath calls _wfullpath on windows. This function will malloc the buffer of sefficient size
if( (resolvedPath = ACE_OS::realpath( ACE_TEXT_CHAR_TO_TCHAR(pathName.c_str()), NULL )) != NULL )
{
ACE_stat stat ;
if( sv_stat( getLongPathName(ACE_TEXT_ALWAYS_CHAR(resolvedPath)).c_str(), &stat ) == 0 )
{
bReturn = true ;
pathName = ACE_TEXT_ALWAYS_CHAR(resolvedPath) ;
}
}
free(resolvedPath);
resolvedPath = NULL;
#else
ACE_TCHAR resolvedPath[SV_MAX_PATH];
// ACE::realpath calls realpath() on linux/solaris. realpath() on solaris fails if any
// of the pointer passed as arg is NULL. So we provide the buffer.
if( ACE_OS::realpath( ACE_TEXT_CHAR_TO_TCHAR(pathName.c_str()), resolvedPath ) != NULL )
{
ACE_stat stat ;
if( sv_stat( getLongPathName(ACE_TEXT_ALWAYS_CHAR(resolvedPath)).c_str(), &stat ) == 0 )
{
bReturn = true ;
pathName = ACE_TEXT_ALWAYS_CHAR(resolvedPath) ;
}
}
#endif
return bReturn ;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
// Bug# 5527 Added SVUnlink to be used by DeleteVsnapLogs
/*
* FUNCTION NAME : SVUnlink
*
* DESCRIPTION : Deletes the file specified by filename and prints the errno
* and error string if failed to delete
*
* INPUT PARAMETERS : filename - the file to delete
*
* OUTPUT PARAMETERS : None
*
* NOTES : If the specified file doesn't exist then it considers
* it as deleted and returns true.
*
* return value : true if the file was deleted, otherwise false is returned
*
*/
bool SVUnlink( const std::string& filename )
{
// PR#10815: Long Path support
if(0!=ACE_OS::unlink(getLongPathName(filename.c_str()).c_str()))
{
int err = ACE_OS::last_error();
if(err != ENOENT)
{
std::stringstream msg;
msg << "Error deleting file " << filename << ", errno = " << err << std::endl
<< "FAILED @ LINE " << __LINE__ << " in FUNCTION " << __FUNCTION__ << " in FILE "
<< __FILE__ << std::endl;
DebugPrintf(SV_LOG_ERROR,"%s", msg.str().c_str());
ACE_OS::last_error(0);
return false;
}
}
return true;
}
/** COMMONTOALL : END */
/** COMMONTOALL : START */
void TruncateTrailingSlash(char *str)
{
size_t Length = strlen(str);
Length--;
while (((str[Length]=='\\') && Length) || ((str[Length]=='/') && Length))
{
str[Length] = '\0';
Length--;
}
return ;
}
/** COMMONTOALL : END */
int RegisterHost(const std::string & onDemandRegistrationRequestId,
const std::string & disksLayoutOption,
QuitFunction_t qf)
{
boost::mutex::scoped_lock guard(g_RegisterHostMutex);
DebugPrintf( SV_LOG_DEBUG,"ENTERED: RegisterHost with on demand request id: %s, disks layout option: %s, qf = %s\n",
onDemandRegistrationRequestId.c_str(), disksLayoutOption.c_str(), (qf?"set":"not set"));
int ret = 0 ;
try{
Configurator* TheConfigurator = NULL;
if(!GetConfigurator(&TheConfigurator))
{
DebugPrintf(SV_LOG_DEBUG, "Unable to obtain configurator %s %d", FUNCTION_NAME, LINE_NO);
DebugPrintf(SV_LOG_DEBUG,"EXITED: RegisterHost\n" );
ret = -1;
return ret;
}
// version info
std::string agentVersion(InmageProduct::GetInstance().GetProductVersionStr());
std::string driverVersion;
if (TheConfigurator->getVxAgent().isMobilityAgent())
{
driverVersion = InmageProduct::GetInstance().GetDriverVersion();
if (driverVersion.empty())
{
DebugPrintf(SV_LOG_ERROR, "%s: failed to get driver version.\n", FUNCTION_NAME);
ret = -1;
return ret;
}
}
// hostname
std::string hostName;
if( TheConfigurator->getVxAgent().getUseConfiguredHostname() ) {
hostName = TheConfigurator->getVxAgent().getConfiguredHostname();
}
else {
hostName = Host::GetInstance().GetHostName();
}
// ip address
std::string ipAddress;
if( TheConfigurator->getVxAgent().getUseConfiguredIpAddress() ) {
ipAddress = TheConfigurator->getVxAgent().getConfiguredIpAddress();
}
else {
ipAddress = Host::GetInstance().GetIPAddress();
if (ipAddress.empty())
{
DebugPrintf(SV_LOG_ERROR, "RegisterHost failed: ipAddress blank.\n");
ret = -1;
return ret;
}
}
static HypervisorInfo_t hypervinfo;
if (HypervisorInfo_t::HypervisorStateUnknown == hypervinfo.state)
{
GetHypervisorInfo(hypervinfo);
}
PrintHypervisorInfo(hypervinfo);
NicInfos_t nicinfos;
GetNicInfos(nicinfos);
if (!HasNicInfoPhysicaIPs(nicinfos))
{
std::stringstream sserrormsg;
sserrormsg << "No valid physical IP found in available nicinfos.";
sserrormsg << " Possible cause is one of Tcpip interface in registry path";
sserrormsg << " \"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\\"";
sserrormsg << " does not have valid DhcpIPAddress but EnableDHCP is set.";
DebugPrintf(SV_LOG_ERROR, "%s: %s\n", FUNCTION_NAME, sserrormsg.str().c_str());
DebugPrintf(SV_LOG_ALWAYS, "%s: Printing discovered nicinfos,\n", FUNCTION_NAME);
PrintNicInfos(nicinfos, SV_LOG_ALWAYS);
throw ERROR_EXCEPTION << sserrormsg.str() << '\n';
}
PrintNicInfos(nicinfos);
DebugPrintf("sending hostname = %s, IP address = %s to CS\n",
hostName.c_str(), ipAddress.c_str());
// Mount bootable volumes so that their vol info is also collected
mountBootableVolumesIfRequried();
// volume information
VolumeSummaries_t volumeSummaries;
VolumeDynamicInfos_t volumeDynamicInfos;
VolumeInfoCollector volumeCollector((DeviceNameTypes_t)GetDeviceNameTypeToReport(hypervinfo.name));
volumeCollector.GetVolumeInfos(volumeSummaries, volumeDynamicInfos, true); // TODO: should have a configurator option to deterime
std::string errormsg;
if (TheConfigurator->getVxAgent().isMobilityAgent() && !IsSystemAndBootDiskSame(volumeSummaries, errormsg))
{
throw ERROR_EXCEPTION << errormsg << '\n';
}
Options_t miscInfo;
if (!onDemandRegistrationRequestId.empty())
{
miscInfo.insert(std::make_pair( NameSpaceInitialSettings::ON_DEMAND_REGISTRATION_REQUEST_ID_KEY, onDemandRegistrationRequestId ));
}
boost::shared_ptr<DisksLayoutUpdater> dlu(new DisksLayoutUpdaterImp(TheConfigurator));
dlu->Update(disksLayoutOption, miscInfo);
TheConfigurator->getVxAgent().insertRole(miscInfo);
miscInfo.insert(std::make_pair(NameSpaceInitialSettings::RESOURCE_ID_KEY, TheConfigurator->getVxAgent().getResourceId()));
miscInfo.insert(std::make_pair(KEY_MT_SUPPORTED_DATAPLANES, TheConfigurator->getVxAgent().getMTSupportedDataPlanes()));
std::string externalIpAddress = TheConfigurator->getVxAgent().getExternalIpAddress();
if (!externalIpAddress.empty())
{
miscInfo.insert(std::make_pair(external_ip_address, externalIpAddress));
}
#ifdef WIN32
if (TheConfigurator->getVxAgent().isMasterTarget())
{
std::list<InstalledProduct> marsProduct;
if (GetMarsProductDetails(marsProduct))
{
DebugPrintf(SV_LOG_DEBUG, "Number of products received : %d\n", marsProduct.size());
marsProduct.sort(CompareProudctVersion);
marsProduct.unique();
if (1 == marsProduct.size())
{
DebugPrintf(SV_LOG_DEBUG, "Mars Agent Version: %s\n", marsProduct.begin()->version.c_str());
miscInfo.insert(make_pair("MarsAgentVersion", marsProduct.begin()->version));
}
else
{
if (marsProduct.size())
{
DebugPrintf(SV_LOG_ERROR, "More than one MARS agent has been discovered on MT, not sending the MARS agent verison details.\n");
DumpProductDetails(marsProduct);
}
else
{
DebugPrintf(SV_LOG_ERROR, "No MARS agent has been discovered on MT, not sending the MARS agent verison details.\n");
}
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "Failed to discover MARS agent details on MT, not sending the MARS agent details.\n");
}
}
#endif
miscInfo.insert(std::make_pair("FirmwareType", (IsUEFIBoot()) ? "UEFI" : "BIOS"));
miscInfo.insert(std::make_pair("SystemUUID", GetSystemUUID()));
std::string fqdn;
#ifdef SV_WINDOWS
fqdn = Host::GetInstance().GetFQDN();
#else
fqdn = Host::GetInstance().GetHostName();
#endif
miscInfo.insert(std::make_pair("FQDN", fqdn.empty() ? hostName : fqdn));
DebugPrintf(SV_LOG_DEBUG, "MiscInfo map:\n");
PrintOptions(miscInfo);
std::string installPath = TheConfigurator->getVxAgent().getInstallPath();
// System Volume, Capacity, FreeSpace
std::string sysVol;
unsigned long long sysVolFreeSpace = 0;
unsigned long long sysVolCapacity = 0;
unsigned long long insVolFreeSpace = 0;
unsigned long long insVolCapacity = 0;
/**
* Defined function that will give system volume
* , capacity and freespace based on platform
*/
if (!GetSysVolCapacityAndFreeSpace(sysVol, sysVolFreeSpace, sysVolCapacity))
{
DebugPrintf(SV_LOG_ERROR, "FAILED: @LINE %d in FILE %s, GetSysVolCapacityAndFreeSpace failed.\n", LINE_NO,
FILE_NAME);
ret = -1 ;
return ret;
}
/**
* Defined function that will give installation volume
* , capacity and freespace based on platform
*/
if (!GetInstallVolCapacityAndFreeSpace(installPath, insVolFreeSpace, insVolCapacity))
{
DebugPrintf(SV_LOG_ERROR, "FAILED: @LINE %d in FILE %s, GetInstallVolCapacityAndFreeSpace failed.\n", LINE_NO,
FILE_NAME);
ret = -1 ;
return ret;
}
std::string prod_version = PROD_VERSION;
NwwnPwwns_t npwwns;
GetNwwnPwwns(npwwns);
PrintNPWwns(npwwns);
std::map<std::string, std::string> acnvpairs;
if (TheConfigurator->getVxAgent().getAccountInfo(acnvpairs))
{
DebugPrintf(SV_LOG_DEBUG, "account information:\n");
InmPrint(acnvpairs);
}
else
{
DebugPrintf(SV_LOG_DEBUG, "could not read account information\n");
}
// Passing all the information to cx
std::string agentMode = TheConfigurator->getVxAgent().getAgentMode();
DebugPrintf(SV_LOG_DEBUG, "Agent Mode: %s\n", agentMode.c_str());
DebugPrintf(SV_LOG_DEBUG, "Product Version: %s\n", prod_version.c_str() );
DebugPrintf(SV_LOG_DEBUG, "Agent Version: %s\n", agentVersion.c_str() );
DebugPrintf(SV_LOG_DEBUG, "Driver Version: %s\n", driverVersion.c_str());
const CpuInfos_t & cpuinfos = Host::GetInstance().GetCpuInfos();
const Object & osinfo = OperatingSystem::GetInstance().GetOsInfo();
const ENDIANNESS & e = OperatingSystem::GetInstance().GetEndianness();
const OS_VAL & osval = OperatingSystem::GetInstance().GetOsVal();
const unsigned long long memory = Host::GetInstance().GetAvailableMemory();
const int RETRY_INTERVAL_IN_SECONDS = 120;
bool shouldRetry = !TheConfigurator->getCxAgent().IsHostStaticInfoRegisteredAtleastOnce();
const uint32_t maxRetryTimeInSeconds = TheConfigurator->getVxAgent().getRegisterHostInterval();
steady_clock::time_point endTime = steady_clock::now();
endTime += seconds(maxRetryTimeInSeconds);
DebugPrintf(SV_LOG_DEBUG, "Retry immediately = %s.\n", STRBOOL(shouldRetry));
do {
ConfigureCxAgent::RegisterHostStatus_t rgss = TheConfigurator->getCxAgent().RegisterHostStaticInfo(
!onDemandRegistrationRequestId.empty(),
agentVersion,
driverVersion,
hostName,
ipAddress,
osinfo,
CurrentCompatibilityNum(),
TheConfigurator->getVxAgent().getInstallPath(),
osval,
getTimeZone(),
sysVol,
getPatchHistory(TheConfigurator->getVxAgent().getInstallPath()),
volumeSummaries,
agentMode,
prod_version,
nicinfos,
hypervinfo,
npwwns,
e,
cpuinfos,
acnvpairs,
memory,
miscInfo
);
std::string rgsstr = TheConfigurator->getCxAgent().GetRegisterHostStatusStr(rgss);
DebugPrintf(SV_LOG_DEBUG, "RegisterHostStaticInfo returned %s\n", rgsstr.c_str());
if (ConfigureCxAgent::HostRegistered != rgss)
{
DebugPrintf(SV_LOG_ERROR, "RegisterHostStaticInfo failed with %s. Immediate retry with interval %d seconds will occur in case host did not register atleast once.\n", rgsstr.c_str(), RETRY_INTERVAL_IN_SECONDS);
HTTP_CONNECTION_SETTINGS s = TheConfigurator->getVxTransport().getHttp();
VxPeriodicRegistrationFailedAlert a(GetCxIpAddress(), s.port, TheConfigurator->getVxTransport().IsHttps());
SendAlertToCx(SV_ALERT_CRITICAL, SV_ALERT_MODULE_HOST_REGISTRATION, a);
ret = -1;
shouldRetry = shouldRetry && (steady_clock::now() < endTime);
DebugPrintf(SV_LOG_DEBUG, "Retry register host = %s.\n", STRBOOL(shouldRetry));
}
else
{
DebugPrintf(SV_LOG_DEBUG, "RegisterHostStaticInfo succeeded\n");
dlu->Clear(miscInfo);
ret = 0;
break;
}
} while (shouldRetry && qf && !qf(RETRY_INTERVAL_IN_SECONDS));
if (0 == ret) { // do dynamic registration when static succeeds or static info checksum match
do {
ConfigureCxAgent::RegisterHostStatus_t rgsd = TheConfigurator->getCxAgent().RegisterHostDynamicInfo(
getLocalTime(),
sysVolCapacity,
sysVolFreeSpace,
insVolCapacity,
insVolFreeSpace,
volumeDynamicInfos
);
std::string rgsdstr = TheConfigurator->getCxAgent().GetRegisterHostStatusStr(rgsd);
DebugPrintf(SV_LOG_DEBUG, "RegisterHostDynamicInfo returned %s. \n", rgsdstr.c_str());
if (ConfigureCxAgent::HostRegistered != rgsd)
{
DebugPrintf(SV_LOG_ERROR, "RegisterHostDynamicInfo failed with %s. Immediate retry with interval %d seconds will occur in case host did not register atleast once.\n", rgsdstr.c_str(), RETRY_INTERVAL_IN_SECONDS);
ret = -1;
shouldRetry = shouldRetry && (steady_clock::now() < endTime);
}
else
{
DebugPrintf(SV_LOG_DEBUG, "RegisterHostDynamicInfo succeeded\n");
ret = 0;
break;
}
} while (shouldRetry && qf && !qf(RETRY_INTERVAL_IN_SECONDS)); //Retry dynamic call also in case host static registration never happened earlier
}
}
catch( std::string const& e ) {
ret = -1;
DebugPrintf( SV_LOG_ERROR,"FAILED: RegisterHost: exception %s\n", e.c_str() );
}
catch( char const* e ) {
ret = -1;
DebugPrintf( SV_LOG_ERROR,"FAILED: RegisterHost: exception %s\n", e );
}
catch( std::exception const& e ) {
ret = -1;
DebugPrintf( SV_LOG_ERROR,"FAILED: RegisterHost: exception %s\n", e.what() );
}
catch(...) {
ret = -1;
DebugPrintf( SV_LOG_ERROR,"FAILED: RegisterHost: exception...\n" );
}
DebugPrintf( SV_LOG_DEBUG,"EXITED: RegisterHost %s with return value = %d\n", onDemandRegistrationRequestId.c_str(), ret);
return ret;
}
bool IsDirectoryExisting(const std::string& path)
{
std::string sDir = path;
if ( !sDir.empty())
{
ToStandardFileName(sDir);
ACE_stat fileStat;
// PR#10815: Long Path support
if ( sv_stat(getLongPathName(sDir.c_str()).c_str(),&fileStat) >= 0 )
{
if ( fileStat.st_mode & S_IFDIR )
return true;
else
return false;
}
else
return false;
}
return false;
}
/*
* FUNCTION NAME : volnamecmp::operator()
*
* DESCRIPTION :
*
* compare two volume names
*
* windows:
* based on volume guid
*
* unix:
* based on real path
*
* INPUT PARAMETERS : name of volumes to compare
*
* OUTPUT PARAMETERS : none
*
* NOTES :
*
* return value : true if both represent same volume, false otherwise
*
*/
bool volnamecmp::operator() (const std::string & vol1, const std::string & vol2) const
{
std::string s1 = vol1;
std::string s2 = vol2;
// Convert the volume name to a standard format
FormatVolumeName(s1);
FormatVolumeNameToGuid(s1);
ExtractGuidFromVolumeName(s1);
// convert to standard device name if symbolic link
// was passed as argument
/**
*
* TODO:
* Currently not calling GetDeviceNameFromSymLink in solaris
* since link name is what CX has and if we operate on actual
* device name, calls to CX are failing. This has to be handled
* in a more neet manner.
*
*/
if (IsReportingRealNameToCx())
{
GetDeviceNameFromSymLink(s1);
}
// Convert the volume name to a standard format
FormatVolumeName(s2);
FormatVolumeNameToGuid(s2);
ExtractGuidFromVolumeName(s2);
// convert to standard device name if symbolic link
// was passed as argument
if (IsReportingRealNameToCx())
{
GetDeviceNameFromSymLink(s2);
}
/**
* Wrapper function that will call strcmp on
* unix and stricmp on windows
*/
return comparevolnames(s1.c_str(), s2.c_str()) < 0;
}
/*
* FUNCTION NAME : volequalitycmp::operator()
*
* DESCRIPTION :
*
* compare two volume names
*
* windows:
* based on volume guid
*
* unix:
* based on real path
*
* INPUT PARAMETERS : name of volumes to compare
*
* OUTPUT PARAMETERS : none
*
* NOTES :
*
* return value : true if both represent same volume, false otherwise
*
*/
bool volequalitycmp::operator() (const std::string & vol1, const std::string & vol2) const
{
std::string s1 = vol1;
std::string s2 = vol2;
// Convert the volume name to a standard format
FormatVolumeName(s1);
FormatVolumeNameToGuid(s1);
ExtractGuidFromVolumeName(s1);
// convert to standard device name if symbolic link
// was passed as argument
if (IsReportingRealNameToCx())
{
GetDeviceNameFromSymLink(s1);
}
// Convert the volume name to a standard format
FormatVolumeName(s2);
FormatVolumeNameToGuid(s2);
ExtractGuidFromVolumeName(s2);
// convert to standard device name if symbolic link
// was passed as argument
if (IsReportingRealNameToCx())
{
GetDeviceNameFromSymLink(s2);
}
/**
* Wrapper function that will call strcmp on
* unix and stricmp on windows
*/
return (!comparevolnames(s1.c_str(), s2.c_str()));
}
/*
* FUNCTION NAME : sameVolumecheck
*
* DESCRIPTION : checks if the specified volumes are same
*
*
* INPUT PARAMETERS : none
*
* OUTPUT PARAMETERS : none
*
* NOTES :
*
*
* return value : true on success, otherwise false
*
*/
bool sameVolumeCheck(const std::string & vol1, const std::string & vol2)
{
std::string s1 = vol1;
std::string s2 = vol2;
// Convert the volume name to a standard format
FormatVolumeName(s1);
FormatVolumeNameToGuid(s1);
ExtractGuidFromVolumeName(s1);
// convert to standard device name if symbolic link
// was passed as argument
if (IsReportingRealNameToCx())
{
GetDeviceNameFromSymLink(s1);
}
// Convert the volume name to a standard format
FormatVolumeName(s2);
FormatVolumeNameToGuid(s2);
ExtractGuidFromVolumeName(s2);
// convert to standard device name if symbolic link
// was passed as argument
if (IsReportingRealNameToCx())
{
GetDeviceNameFromSymLink(s2);
}
return (s1 == s2);
}
/*
* FUNCTION NAME : IsCacheVolume
*
* DESCRIPTION : Determines if the volume is being used as a cache volume
*
* INPUT PARAMETERS : volume name
*
* OUTPUT PARAMETERS : cache - set to true if volume is cache volume. otherwise false
*
*
* return value : true if the function succeeds. else false
*
*/
bool IsCacheVolume(std::string const & volume)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s for %s\n", FUNCTION_NAME, volume.c_str());
bool rv = false;
do
{
LocalConfigurator localConfigurator;
std::string cacheDir = localConfigurator.getCacheDirectory();
std::string cacheRoot;
if(!GetVolumeRootPath(cacheDir, cacheRoot))
{
DebugPrintf(SV_LOG_DEBUG, "Unable to determine the root of %s\n", cacheDir.c_str());
rv = true;
break;
}
std::string cacheDevice;
if(!GetDeviceNameForMountPt(cacheRoot, cacheDevice))
{
DebugPrintf(SV_LOG_DEBUG, "Unable to get the devicename for %s\n", cacheRoot.c_str());
rv = true;
break;
}
rv = sameVolumeCheck(volume, cacheDevice);
} while (0);
DebugPrintf( SV_LOG_DEBUG, "EXITED %s for %s\n", FUNCTION_NAME, volume.c_str());
return rv;
}
/*
* FUNCTION NAME : IsInstallPathVolume
*
* DESCRIPTION : Determines if the volume is being used as a instalation path
*
* INPUT PARAMETERS : volume name
*
* OUTPUT PARAMETERS : cache - set to true if volume is cache volume. otherwise false
*
*
* return value : true if the function succeeds. else false
*
*/
bool IsInstallPathVolume(std::string const & volume)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s for %s\n", FUNCTION_NAME, volume.c_str());
bool rv = false;
do
{
LocalConfigurator localConfigurator;
std::string installDir = localConfigurator.getInstallPath();
std::string installRoot;
if(!GetVolumeRootPath(installDir, installRoot))
{
DebugPrintf(SV_LOG_DEBUG, "Unable to determine the root of %s\n", installDir.c_str());
rv = true;
break;
}
std::string installDevice;
if(!GetDeviceNameForMountPt(installRoot, installDevice))
{
DebugPrintf(SV_LOG_DEBUG, "Unable to get the devicename for %s\n", installRoot.c_str());
rv = true;
break;
}
rv = sameVolumeCheck(volume, installDevice);
} while (0);
DebugPrintf( SV_LOG_DEBUG, "EXITED %s for %s\n", FUNCTION_NAME, volume.c_str());
return rv;
}
bool IsPreAdded(const std::string &filename, const char &delim, std::string &prefile)
{
bool bpreadded = false;
prefile = filename;
size_t basenamepos = prefile.rfind(delim);
if (std::string::npos == basenamepos)
{
basenamepos = 0;
}
else
{
basenamepos++;
}
const char *p = prefile.c_str();
size_t prelen = strlen(PREUNDERSCORE);
if (*(p + basenamepos) != '\0')
{
if (strncmp(p + basenamepos, PREUNDERSCORE, prelen))
{
p = NULL;
prefile.insert(basenamepos, PREUNDERSCORE);
bpreadded = true;
}
}
return bpreadded;
}
// PR#10815: Long Path support
ACE_DIR *sv_opendir(const char *filename)
{
#if defined (SV_USES_LONGPATHS)
std::string fileName(filename);
fileName += ACE_DIRECTORY_SEPARATOR_CHAR_A;
return ACE_OS::opendir(getLongPathName(fileName.c_str()).c_str());
#else
return ACE_OS::opendir(filename);
#endif
}
bool IsVirtual(std::string &hypervisorname, std::string &hypervisorvers)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bisvirtual = false;
const std::string delim = ",";
do
{
LocalConfigurator lc;
std::string vmtext = lc.getVMPats();
std::vector<std::string> vmops;
Tokenize(vmtext, vmops, delim);
Pats pats(vmops);
/* step 1: use some deterministic ways specific to OS */
bisvirtual = IsVmDeterministic(pats, hypervisorname, hypervisorvers);
if (bisvirtual)
{
break;
}
/* step 2: use cmds that if succeed says vm */
vmops.clear();
vmtext = lc.getVMCmds();
Tokenize(vmtext, vmops, delim);
bisvirtual = IsAnyCmdSucceeded(vmops, hypervisorname);
if (bisvirtual)
{
break;
}
/* step 3: if command output has pattern, then a vm */
vmops.clear();
vmtext = lc.getVMCmdsForPats();
Tokenize(vmtext, vmops, delim);
bisvirtual = HasPatternInCmd(vmops, pats, hypervisorname);
if (bisvirtual)
{
break;
}
/* step 4: if wmi any column has pattern, then a vm */
/* TODO: For now this code just returns false;
* since for a generic wmi to give information,
* we not only need columns but also their types
vmops.clear();
vmtext = lc.getVMWMIsForPats();
Tokenize(vmtext, vmops, delim);
bisvirtual = HasPatternInWMIDB(vmops, pats);
*/
} while (false);
DebugPrintf(SV_LOG_DEBUG, "EXITED %s IsVirtual: %s\n", FUNCTION_NAME, bisvirtual? "True":"False");
return bisvirtual;
}
bool IsAnyCmdSucceeded(const std::vector<std::string> &cmds, std::string &cmd)
{
bool bsucceeded = false;
std::vector<std::string>::const_iterator iter = cmds.begin();
for ( /* empty */ ; iter != cmds.end(); iter++)
{
std::string output, err;
int ecode = 0;
bsucceeded = RunInmCommand(*iter, output, err, ecode);
if (bsucceeded)
{
cmd = *iter;
break;
}
}
return bsucceeded;
}
bool HasPatternInCmd(const std::vector<std::string> cmds,
Pats &pats, std::string &pat)
{
bool bhaspat = false;
std::vector<std::string>::const_iterator iter = cmds.begin();
for ( /* empty */ ; (iter != cmds.end()) && (false == bhaspat) ; iter++)
{
std::string output, err;
int ecode = 0;
bool bsucceeded = RunInmCommand(*iter, output, err, ecode);
if (bsucceeded)
{
bhaspat = pats.IsMatched(output, pat);
}
}
return bhaspat;
}
bool RunInmCommand(
const std::string& cmd,
std::string &outputmsg,
std::string& errormsg,
int & ecode
)
{
bool rv = true;
InmCommand mount(cmd);
InmCommand::statusType status = mount.Run();
if (status != InmCommand::completed)
{
if(!mount.StdErr().empty())
{
errormsg = mount.StdErr();
ecode = mount.ExitCode();
}
if(!mount.StdOut().empty())
{
outputmsg = mount.StdOut();
}
rv = false;
}
else if (mount.ExitCode())
{
errormsg = mount.StdErr();
ecode = mount.ExitCode();
if(!mount.StdOut().empty())
{
outputmsg = mount.StdOut();
}
rv = false;
}
else
{
outputmsg = mount.StdOut();
}
return rv;
}
bool IsVmDeterministic(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bisvm = false;
bisvm = IsVmFromDeterministics(pats, hypervisorname, hypervisorvers);
if (false == bisvm)
{
bisvm = IsNativeVm(pats, hypervisorname, hypervisorvers);
}
if (false == bisvm)
{
bisvm = IsOpenVzVM(pats, hypervisorname, hypervisorvers);
}
if (false == bisvm)
{
bisvm = IsVMFromCpuInfo(pats, hypervisorname, hypervisorvers);
}
if (false == bisvm)
{
bisvm = IsXenVm(pats, hypervisorname, hypervisorvers);
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s IsVM = %s\n", FUNCTION_NAME, bisvm? "TRUE":"FALSE");
return bisvm;
}
void PrintHypervisorInfo(const HypervisorInfo_t &hypervisorinfo)
{
DebugPrintf(SV_LOG_DEBUG, "======\n");
DebugPrintf(SV_LOG_DEBUG, "Hypervisor State: %s\n", StrHypervisorState[hypervisorinfo.state]);
DebugPrintf(SV_LOG_DEBUG, "Hypervisor Name: %s\n", hypervisorinfo.name.c_str());
DebugPrintf(SV_LOG_DEBUG, "Hypervisor Version: %s\n", hypervisorinfo.version.c_str());
DebugPrintf(SV_LOG_DEBUG, "======\n");
}
bool IsValidIP(const std::string &ip)
{
bool bisvalid = false;
const size_t READABLE_IP_SIZE = 15;
const size_t NTABS_INIP = 4;
const size_t MAX_BYTE = 255;
const char IP_TAB_SEP = '.';
size_t iplen = ip.length();
if (iplen && (iplen <= READABLE_IP_SIZE))
{
int a, b, c, d;
a = b = c = d = -1;
int rc = sscanf(ip.c_str(), "%3d.%3d.%3d.%3d", &a, &b, &c, &d);
std::stringstream formedbackip;
formedbackip << a << IP_TAB_SEP
<< b << IP_TAB_SEP
<< c << IP_TAB_SEP
<< d;
if ((NTABS_INIP == rc) && (formedbackip.str() == ip))
{
if (a || b || c || d)
{
if ((a >= 0) && (a <= MAX_BYTE) &&
(b >= 0) && (b <= MAX_BYTE) &&
(c >= 0) && (c <= MAX_BYTE) &&
(d >= 0) && (d <= MAX_BYTE))
{
bisvalid = true;
}
}
}
}
if (!bisvalid)
{
DebugPrintf(SV_LOG_WARNING, "ip %s is invalid\n", ip.c_str());
}
return bisvalid;
}
void GetFirstInpFromFile(const std::string &filename, NUMFORMAT nfmt, SV_LONGLONG *pcontents)
{
std::ifstream ifile(filename.c_str());
if (ifile.is_open())
{
if (ifile.good())
{
if (E_HEX == nfmt)
ifile >> std::hex >> (*pcontents);
else if (E_OCT == nfmt)
ifile >> std::oct >> (*pcontents);
else
ifile >> (*pcontents);
}
ifile.close();
}
}
void GetFirstStringFromFile(const std::string &filename, std::string &str)
{
std::ifstream ifile(filename.c_str());
if (ifile.is_open())
{
if (ifile.good())
{
ifile >> str;
}
ifile.close();
}
}
void GetFirstLineFromFile(const std::string &filename, std::string &str)
{
std::ifstream ifile(filename.c_str());
if (ifile.is_open())
{
if (ifile.good())
{
std::getline(ifile, str);
}
ifile.close();
}
}
void RemoveChar(std::string &s, const char &c)
{
std::string::iterator nend = std::remove(s.begin(), s.end(), c);
s.erase(nend, s.end());
}
void RemoveLastMatchingChar(std::string &s, const char &c)
{
size_t ns = s.length();
if ((ns > 0) && c == s[ns - 1])
{
s.erase(ns - 1);
}
}
void PrintString(const std::string &s)
{
DebugPrintf(SV_LOG_DEBUG, "%s\n", s.c_str());
}
void Trim(std::string& s, const std::string &trim_chars )
{
size_t begIdx = s.find_first_not_of(trim_chars);
if (begIdx == std::string::npos)
{
begIdx = 0;
}
size_t endIdx = s.find_last_not_of(trim_chars);
if (endIdx == std::string::npos)
{
endIdx = s.size() - 1;
}
s = s.substr(begIdx, endIdx-begIdx+1);
}
bool IsNotxString(const std::string &s)
{
return !IsxString(s);
}
bool IsxString(const std::string &s)
{
return (s.end() == find_if(s.begin(), s.end(), isnotxdigit));
}
bool isnotxdigit(const char &c)
{
return !isxdigit(c);
}
std::string GetUpperCase(const std::string &str)
{
std::string ustr;
for (size_t i = 0; i < str.length(); i++)
{
ustr.push_back(toupper(str[i]));
}
return ustr;
}
const char *GetStartOfLastNumber(const char *cs)
{
const char *num = NULL;
size_t len = strlen(cs);
const char *start = cs;
const char *p = start + (len - 1);
const char *numstart = NULL;
while ((p >= start) && (isdigit(*p)))
{
numstart = p;
p--;
}
if ((p >= start) && numstart)
{
num = numstart;
}
return num;
}
std::string RemoveSuffix(const std::string &s, const std::string &suffix)
{
std::string final;
size_t suffixidx = s.rfind(suffix);
if (std::string::npos != suffixidx)
{
final = s.substr(0, suffixidx);
}
else
{
final = s;
}
return final;
}
bool AreAllDigits(const char *p)
{
bool baredigits = strlen(p);
for (const char *q = p; *q ; q++)
{
if (!isdigit(*q))
{
baredigits = false;
break;
}
}
return baredigits;
}
SVERROR getFileContent( std::string filePath, std::string& content )
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
ACE_HANDLE handle = ACE_INVALID_HANDLE;
SVERROR status = SVS_FALSE;
handle = ACE_OS::open( filePath.c_str(), O_RDONLY );
if( handle == ACE_INVALID_HANDLE )
{
DebugPrintf(SV_LOG_WARNING, "%s: The %s is not readable.. Error %d\n", FUNCTION_NAME, filePath.c_str(), ACE_OS::last_error());
}
else
{
SV_ULONGLONG const fileSize = File::GetSizeOnDisk( filePath );
size_t infosize;
INM_SAFE_ARITHMETIC(infosize = InmSafeInt<SV_ULONGLONG>::Type(fileSize) + 1, INMAGE_EX(fileSize))
boost::shared_array<char> info (new (std::nothrow) char[infosize]);
if( (size_t) fileSize == ACE_OS::read(handle, info.get(), (size_t)fileSize) )
{
info[ (ptrdiff_t)fileSize ] = '\0';
content = info.get();
status = SVS_OK;
DebugPrintf(SV_LOG_DEBUG, "%s: read the entire file %s. Requested Read size %d %s\n", FUNCTION_NAME, filePath.c_str(), fileSize, content.c_str());
}
else
{
DebugPrintf(SV_LOG_ERROR, "%s: Failed to read the file %s. Requested Read size %d\n", FUNCTION_NAME, filePath.c_str(), fileSize);
}
ACE_OS::close( handle );
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return status;
}
bool isFileExited(const std::string& fileNamePath)
{
bool retVal = false;
ACE_stat stat ;
if(sv_stat(getLongPathName(fileNamePath.c_str()).c_str(), &stat) == 0)
{
retVal = true;
DebugPrintf(SV_LOG_DEBUG, "File %s is already available \n", fileNamePath.c_str());
}
else
{
DebugPrintf(SV_LOG_DEBUG, "File %s is not available \n", fileNamePath.c_str());
}
return retVal;
}
void pruneFiles(const std::string& dirName, const std::string& date, bool recursive, bool bFirst)
{
ACE_stat stat ;
ACE_DIR * ace_dir = NULL ;
ACE_DIRENT * dirent = NULL ;
static std::string lastFile;
if(bFirst)
{
lastFile = "";
}
std::string currentPath;
if(dirName.empty() == false && sv_stat(getLongPathName(dirName.c_str()).c_str(), &stat) == 0)
{
ace_dir = sv_opendir(dirName.c_str()) ;
if( ace_dir != NULL )
{
for(dirent = ACE_OS::readdir(ace_dir); dirent != NULL; dirent = ACE_OS::readdir(ace_dir))
{
std::string fileName = ACE_TEXT_ALWAYS_CHAR(dirent->d_name);
if( strcmp(fileName.c_str(), "." ) == 0 || strcmp(fileName.c_str(), ".." ) == 0 )
{
continue ;
}
currentPath = "";
currentPath = dirName+ACE_DIRECTORY_SEPARATOR_CHAR_A+ fileName;
if(sv_stat(getLongPathName(currentPath.c_str()).c_str(), &stat) == 0)
{
if(stat.st_mode & S_IFDIR)
{
if(recursive)
{
pruneFiles(currentPath, date, true, false);
}
}
else
{
std::string::size_type index = currentPath.find_last_of("_");
if(index != std::string::npos)
{
std::string leftString = currentPath.substr(0, index+1);
std::string rightString = currentPath.substr(index+1);
if(strcmp(rightString.c_str(), date.c_str()) <= 0)
{
if(lastFile.empty())
{
lastFile = rightString;
}
else
{
std::string removedFile = leftString + rightString;
if(strcmp(lastFile.c_str(), rightString.c_str()) < 0)
{
removedFile = leftString + lastFile;
lastFile = rightString;
}
remove(removedFile.c_str());
DebugPrintf(SV_LOG_DEBUG, "Successfully removed file: %s \n", removedFile.c_str());
}
}
}
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "getLongPathName() Failed. Path Name: %s \n.", currentPath.c_str());
}
}
ACE_OS::closedir( ace_dir ) ;
}
else
{
DebugPrintf(SV_LOG_ERROR, "sv_opendir() failed. Dir Name: %s \n", dirName.c_str());
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "getLogPathName() Failed. Dir Name: %s \n", dirName.c_str());
}
}
std::list<std::string> getFirstLevelDirPathNameList(const std::string& dirName)
{
std::list<std::string> dirNamePathList;
ACE_stat stat ;
ACE_DIR * ace_dir = NULL ;
ACE_DIRENT * dirent = NULL ;
std::string currentPath;
if(dirName.empty() == false && sv_stat(getLongPathName(dirName.c_str()).c_str(), &stat) == 0)
{
ace_dir = sv_opendir(dirName.c_str()) ;
if( ace_dir != NULL )
{
for(dirent = ACE_OS::readdir(ace_dir); dirent != NULL; dirent = ACE_OS::readdir(ace_dir))
{
std::string fileName = ACE_TEXT_ALWAYS_CHAR(dirent->d_name);
if( strcmp(fileName.c_str(), "." ) == 0 || strcmp(fileName.c_str(), ".." ) == 0 )
{
continue ;
}
currentPath = dirName+ACE_DIRECTORY_SEPARATOR_CHAR_A+ fileName;
if(sv_stat(getLongPathName(currentPath.c_str()).c_str(), &stat) == 0)
{
if(stat.st_mode & S_IFDIR)
{
dirNamePathList.push_back(currentPath);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "getLongPathName() Failed. Path Name: %s \n.", currentPath.c_str());
}
}
ACE_OS::closedir( ace_dir ) ;
}
else
{
DebugPrintf(SV_LOG_ERROR, "sv_opendir() failed. Dir Name: %s \n", dirName.c_str());
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "getLogPathName() Failed. Dir Name: %s \n", dirName.c_str());
}
return dirNamePathList;
}
void pruneDirs(const std::string& repoPath, const std::list<std::string>& sourceHostIdList)
{
std::list<std::string> dirNamePathList = getFirstLevelDirPathNameList(repoPath);
std::list<std::string>::iterator begIter = dirNamePathList.begin();
std::list<std::string>::iterator endIter = dirNamePathList.end();
while(begIter != endIter)
{
std::list<std::string>::const_iterator sourceHostIdListBegIter = sourceHostIdList.begin();
std::list<std::string>::const_iterator sourceHostIdListEndIter = sourceHostIdList.end();
while(sourceHostIdListBegIter != sourceHostIdListEndIter)
{
if(strstr(begIter->c_str(), sourceHostIdListBegIter->c_str()))
{
break;
}
sourceHostIdListBegIter++;
}
if(sourceHostIdListBegIter == sourceHostIdListEndIter)
{
remove(begIter->c_str());
}
begIter++;
}
}
void PrintStatuses(const Statuses_t &ss, SV_LOG_LEVEL lvl)
{
for (Statuses_t::size_type i = 0; i < ss.size(); i++)
{
std::stringstream msg;
msg << "For stage " << i
<< ", state is " << StrState[ss[i].m_State]
<< ", exception message is " << ss[i].m_ExcMsg;
DebugPrintf(lvl, "%s\n", msg.str().c_str());
}
}
void GetStatuses(const Statuses_t &ss, std::string &s)
{
for (Statuses_t::size_type i = 0; i < ss.size(); i++)
{
std::stringstream msg;
msg << "For subtask: " << i
<< ", state is " << StrState[ss[i].m_State]
<< ", exception message is " << ss[i].m_ExcMsg << ". ";
s += msg.str();
}
}
void DataAndLength::Print(void)
{
DebugPrintf(SV_LOG_DEBUG, "data = %p, length = %u\n", m_pData, m_length);
}
std::string getSourceConfigFilesTimeFormat(SV_ULONGLONG timeValue)
{
time_t t1 = timeValue;
char localTime[128];
strftime(localTime, 128, "%Y%m%d%H%M%S", localtime(&t1));
std::stringstream timeFormat;
timeFormat << localTime;
return timeFormat.str();
}
bool RestoreNtfsOrFatSignature(const std::string & volumename)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool rv = true;
bool shouldwriteheader = false;
// open the handle
// read the first 512 bytes
ACE_HANDLE handle = ACE_INVALID_HANDLE;
SVERROR status = SVS_FALSE;
size_t sectorsize = 512;
char pbuffer[SECTOR_SIZE];
ACE_LOFF_T seekOffset;
seekOffset = (ACE_LOFF_T)0LL;
handle = ACE_OS::open( volumename.c_str(), O_RDWR );
do
{
if( handle == ACE_INVALID_HANDLE )
{
DebugPrintf(SV_LOG_WARNING, "unable to open %s. error %d\n", volumename.c_str(), ACE_OS::last_error());
rv = false;
break;
}
if( (size_t) sectorsize != ACE_OS::read(handle, pbuffer, sectorsize) )
{
DebugPrintf(SV_LOG_ERROR, "Failed to read the volume %s. Requested Read size %d , error %d\n", volumename.c_str(), sectorsize ,ACE_OS::last_error());
rv = false;
break;
}
// Check if this is FAT and not NTFS (NTFS can look like FAT if we don't make additional checks)
Bpb* bpb = (Bpb*)(pbuffer);
if ((bpb->BS_jmpBoot[0] == BS_JMP_BOOT_VALUE_0xEC || bpb->BS_jmpBoot[0] == BS_JMP_BOOT_VALUE_0xEA) &&
(0 != memcmp(&pbuffer[SV_NTFS_MAGIC_OFFSET], SV_MAGIC_SVFS, SV_FSMAGIC_LEN)) &&
(0 != memcmp(&pbuffer[SV_NTFS_MAGIC_OFFSET], SV_MAGIC_NTFS, SV_FSMAGIC_LEN)) )
{
if (FST_SCTR_OFFSET_510_VALUE == pbuffer[FST_SCTR_OFFSET_510] && FST_SCTR_OFFSET_511_VALUE == pbuffer[FST_SCTR_OFFSET_511]) {
// Change the BPB to hide it
// I.E We make jmpboot instruction to be either 0xEB, or 0xE9
// Which makes it an invalid FAT volume
bpb->BS_jmpBoot[0] -= 1;
shouldwriteheader = true;
}
}
// check for svfs
if (0 == memcmp(&pbuffer[SV_NTFS_MAGIC_OFFSET], SV_MAGIC_SVFS, SV_FSMAGIC_LEN)) {
inm_memcpy_s(&pbuffer[SV_NTFS_MAGIC_OFFSET], sizeof(pbuffer) - SV_NTFS_MAGIC_OFFSET, SV_MAGIC_NTFS, SV_FSMAGIC_LEN);
shouldwriteheader = true;
}
if(shouldwriteheader )
{
#ifndef LLSEEK_NOT_SUPPORTED
seekOffset = (ACE_LOFF_T)0LL;
if (ACE_OS::llseek(handle, seekOffset, SEEK_SET) < 0) {
#else
seekOffset = (off_t)0LL;
if (ACE_OS::lseek(handleVolume, seekOffset, SEEK_SET) < 0) {
#endif
DebugPrintf( SV_LOG_ERROR, "FAILED ACE_OS::llseek, err = %d\n", ACE_OS::last_error());
rv = false;
break;
}
//done with altering the buffer ,now lets dump it
if(sectorsize != ACE_OS::write(handle,pbuffer,sectorsize))
{
DebugPrintf(SV_LOG_ERROR, "Failed to write volume %s. Requested write size %d .error %d\n", volumename.c_str(), sectorsize ,ACE_OS::last_error() );
rv = false;
break;
}
}
}while(0);
// close the handle
if( handle != ACE_INVALID_HANDLE)
ACE_OS::close(handle);
DebugPrintf( SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return rv;
}
size_t WriteMemoryCallbackFileReplication(void *ptr, size_t size, size_t nmemb, void *data)
{
DebugPrintf(SV_LOG_DEBUG, "Entering %s\n", __FUNCTION__);
size_t realsize;
INM_SAFE_ARITHMETIC(realsize = InmSafeInt<size_t>::Type(size) * nmemb, INMAGE_EX(size)(nmemb))
MemoryStruct *mem = (MemoryStruct *)data;
size_t memorylen;
INM_SAFE_ARITHMETIC(memorylen = InmSafeInt<size_t>::Type(mem->size) + realsize + 1, INMAGE_EX(mem->size)(realsize))
mem->memory = (char *)realloc(mem->memory, memorylen);
if (mem->memory) {
inm_memcpy_s(&(mem->memory[mem->size]), realsize + 1, ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
DebugPrintf(SV_LOG_DEBUG, "Exiting %s\n", __FUNCTION__);
return realsize;
}
SVERROR postToCx(const char* pszHost,
SV_INT Port,
const char* pszUrl,
const char* pszBuffer,
char** ppszBuffer,bool useSecure,
SV_ULONG size,
SV_ULONG retryCount
)
{
DebugPrintf(SV_LOG_DEBUG, "Entering %s\n", __FUNCTION__);
SVERROR rc = SVE_FAIL ;
int retries = 0;
MemoryStruct chunk = {0};
if ( Port > 65535 || Port < 1 )
{
DebugPrintf(SV_LOG_ERROR, "The Port is out of range.. Please choose port number between range 1-65535 on which the CX server is listening\n");
}
else
{
DebugPrintf(SV_LOG_DEBUG,"Server = %s\n",pszHost);
DebugPrintf(SV_LOG_DEBUG,"Port = %d\n",Port);
DebugPrintf(SV_LOG_DEBUG,"Secure = %d\n",useSecure);
DebugPrintf(SV_LOG_DEBUG,"PHP URL = %s\n",pszUrl);
std::string result;
CurlOptions options(pszHost,Port, pszUrl, useSecure);
options.writeCallback( static_cast<void *>( &chunk ),WriteMemoryCallbackFileReplication);
options.lowSpeedLimit(10);
options.lowSpeedTime(120);
options.transferTimeout(CX_TIMEOUT);
while ( retries < retryCount && rc == SVE_FAIL )
{
DebugPrintf(SV_LOG_DEBUG, "Attemt %d: PostToServer ...\n", retries );
chunk.memory = NULL;
chunk.size = 0; /* no data at this point */
try {
CurlWrapper cw;
cw.post(options,pszBuffer);
if( chunk.size > 0)
{
if(ppszBuffer != NULL)
{
*ppszBuffer = chunk.memory;
}
else
{
free( chunk.memory ) ;
}
}
rc = SVS_OK;
} catch(ErrorException& exception )
{
DebugPrintf(SV_LOG_ERROR, "FAILED : %s with error %s\n",FUNCTION_NAME, exception.what());
rc = SVE_FAIL;
}
retries++;
#ifdef SV_WINDOWS
Sleep(retries * 5000 );
#else
sleep(retries * 5 );
#endif
}
if( rc == SVE_FAIL )
{
DebugPrintf(SV_LOG_ERROR, "PostToServer server failed even after %d attempts, This may cause file replication jobs to fail...\n", retries);
}
}
DebugPrintf(SV_LOG_DEBUG, "Exiting %s\n", __FUNCTION__);
return( rc );
}
bool DoesFileExist(const std::string &file)
{
E_INM_TRISTATE st;
std::string errmsg;
st = DoesFileExist(file, errmsg);
if (E_INM_TRISTATE_FLOATING == st)
DebugPrintf(SV_LOG_ERROR, "%s\n", errmsg.c_str());
return (E_INM_TRISTATE_TRUE == st);
}
/*
1. It is working as expected on local files.
2. Sample run on cifs:
==================
--> Not logged into cifs :
C:\run>exists.exe \\10.0.0.5\public\read.exe
Failed to find file existence with error Failed to open file \\10.0.0.5\public\read.exe,
to check its existence, with error Invalid argument.
C:\run>exists.exe \\10.0.0.5\public\re
Failed to find file existence with error Failed to open file \\10.0.0.5\public\re,
to check its existence, with error Invalid argument.
--> Now login to cifs :
C:\run>exists.exe \\10.0.0.5\public\read.exe
File exists.
C:\run>exists.exe \\10.0.0.5\public\re
File does not exist.
*/
E_INM_TRISTATE DoesFileExist(const std::string &file, std::string &errmsg)
{
std::string openmode("r");
openmode += FOPEN_MODE_NOINHERIT;
FILE *fp = fopen(file.c_str(), openmode.c_str());
E_INM_TRISTATE st = E_INM_TRISTATE_FLOATING;
if (fp) {
st = E_INM_TRISTATE_TRUE;
fclose(fp);
} else if (ENOENT == errno)
st = E_INM_TRISTATE_FALSE;
else {
int saveerrno = errno;
errmsg = "Failed to open file ";
errmsg += file;
errmsg += ", to check its existence, with error ";
errmsg += strerror(saveerrno);
}
return st;
}
bool InmFtruncate(const std::string &file, std::string &errmsg)
{
std::string openmode("w");
openmode += FOPEN_MODE_NOINHERIT;
FILE *fp = fopen(file.c_str(), openmode.c_str());
if (fp)
{
fclose(fp);
}
else
{
int saveerrno = errno;
errmsg = "Failed to truncate(open in write mode) file ";
errmsg += file;
errmsg += " with error ";
errmsg += strerror(saveerrno);
}
return fp;
}
bool InmFopen(FILE **fpp, const std::string &name, const std::string &mode, std::string &errmsg)
{
if ((*fpp = fopen(name.c_str(), mode.c_str())) == 0)
{
int saveerrno = errno;
errmsg = "Opening of file " + name + " in mode " + mode + " failed with error: " + strerror(saveerrno);
}
return *fpp;
}
bool InmFclose(FILE **fpp, const std::string &name, std::string &errmsg)
{
bool bclosed = true;
if (*fpp)
{
bclosed = false;
if (0 != fclose(*fpp))
{
int saveerrno = errno;
errmsg = "Closing file ";
errmsg += name;
errmsg += ", failed with error: ";
errmsg += strerror(saveerrno);
}
else
{
*fpp = 0;
bclosed = true;
}
}
return bclosed;
}
bool InmFprintf(FILE *fp, const std::string &name, std::string &errmsg, const bool &brestorefilepointer, const long &writepos, const char *fmt, ...)
{
bool bproceed = true;
std::string filestr = "For file ";
filestr += name;
filestr += ", ";
long savepos = -1;
if (brestorefilepointer)
{
savepos = ftell(fp);
if (-1 == savepos)
{
int saveerrno = errno;
errmsg = filestr;
errmsg += "getting file pointer position failed with error: ";
errmsg += strerror(saveerrno);
bproceed = false;
}
}
if (bproceed && writepos)
{
if (0 != fseek(fp, writepos, SEEK_SET))
{
int saveerrno = errno;
std::stringstream sswp;
sswp << writepos;
errmsg = filestr;
errmsg += "seeking to write position ";
errmsg += sswp.str();
errmsg += " failed with error: ";
errmsg += strerror(saveerrno);
bproceed = false;
}
}
if (bproceed)
{
va_list ap;
va_start(ap, fmt);
if (vfprintf(fp, fmt, ap) < 0)
{
int saveerrno = errno;
errmsg = filestr;
errmsg += "writing formatted text";
errmsg += " failed with error: ";
errmsg += strerror(saveerrno);
bproceed = false;
}
else if (0 != fflush(fp))
{
int saveerrno = errno;
bproceed = false;
errmsg = filestr;
errmsg += "flushing file failed with error: ";
errmsg += strerror(saveerrno);
}
va_end(ap);
}
/* TODO: restore even if no write or flush failure ? */
if (brestorefilepointer)
{
if (0 != fseek(fp, savepos, SEEK_SET))
{
int saveerrno = errno;
errmsg = filestr;
errmsg += "seeking in file failed with error: ";
errmsg += strerror(saveerrno);
bproceed = false;
}
}
return bproceed;
}
bool SyncFile(const std::string &file, std::string &errmsg)
{
bool bsynced = false;
ACE_HANDLE h = ACE_OS::open(file.c_str(), O_RDWR);
if (ACE_INVALID_HANDLE != h)
{
if (-1 != ACE_OS::fsync(h))
{
bsynced = true;
}
else
{
std::stringstream sserr;
sserr << "failed to sync file " << file
<< " with error number: " << ACE_OS::last_error();
errmsg = sserr.str();
}
if (0 != ACE_OS::close(h))
{
bsynced = false;
std::stringstream sserr;
sserr << "failed to close file " << file
<< " with error number: " << ACE_OS::last_error();
errmsg = sserr.str();
}
}
else
{
std::stringstream sserr;
sserr << "failed to open file " << file
<< " with error number: " << ACE_OS::last_error();
errmsg = sserr.str();
}
return bsynced;
}
bool InmCopyTextFile(const std::string &src, const std::string &dest, const bool &busetemporary, std::string &errmsg)
{
FILE *srcfp, *destfp;
bool bcopied = false;
std::string rmode = "r";
rmode += FOPEN_MODE_NOINHERIT;
std::string wmode = "w";
wmode += FOPEN_MODE_NOINHERIT;
std::string ferrmsg;
srcfp = destfp = NULL;
std::string filetowrite = busetemporary ? (dest + ".tmp") : dest;
if (InmFopen(&srcfp, src, rmode, ferrmsg))
{
if (InmFopen(&destfp, filetowrite, wmode, ferrmsg))
{
int c;
while ((c = getc(srcfp)) != EOF)
{
putc(c, destfp);
}
/* for output functions, fclose gives the
* output was successfully written or not */
bcopied = InmFclose(&destfp, filetowrite, ferrmsg);
}
InmFclose(&srcfp, src, ferrmsg);
}
if (!bcopied)
{
errmsg = "Failed to copy file ";
errmsg += src;
errmsg += " to ";
errmsg += filetowrite;
errmsg += " with error message: ";
errmsg += ferrmsg;
}
else if (busetemporary)
{
bcopied = InmRename(filetowrite.c_str(), dest.c_str(), errmsg);
if (!bcopied)
{
/* remove temporary if we did not
* rename */
std::string err;
InmRemoveFile(filetowrite, err);
}
}
return bcopied;
}
bool InmRemoveFile(const std::string &file, std::string &errmsg)
{
bool bremoved = false;
std::string suberrmsg;
E_INM_TRISTATE st = DoesFileExist(file, suberrmsg);
if (E_INM_TRISTATE_FLOATING != st) {
bremoved = (E_INM_TRISTATE_TRUE == st) ? (0 == remove(file.c_str())) : true;
if (!bremoved)
suberrmsg = strerror(errno);
}
if (!bremoved) {
errmsg = "failed to remove file ";
errmsg += file;
errmsg += " with error: ";
errmsg += suberrmsg;
}
return bremoved;
}
void TrimChar(char *str, const char &c)
{
size_t len = strlen(str);
if (len && (str[len - 1] == c))
{
str[len - 1] = '\0';
}
}
bool InmRenameAndRemoveFile(const std::string &file, std::string &errmsg)
{
std::string renamefile = file;
renamefile += ".D.";
ACE_Time_Value aceTv = ACE_OS::gettimeofday();
std::stringstream ss;
ss << std::hex << std::setw(16) << std::setfill('0') <<
ACE_TIME_VALUE_AS_USEC(aceTv);
renamefile += ss.str();
return InmRename(file, renamefile, errmsg) && InmRemoveFile(renamefile, errmsg);
}
SVERROR WriteStringIntoFile(const std::string& fileName,const std::string& str)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME) ;
SVERROR retValue = SVS_OK;
std::ofstream out;
if( !fileName.empty() )
{
out.open(fileName.c_str(),std::ios::app);
if (!out.is_open())
{
DebugPrintf(SV_LOG_ERROR,"Failed to createFile %s\n",fileName.c_str());
}
else
{
out<<str;
}
out.close();
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME) ;
return retValue;
}
//
// FUNCTION NAME : getvolpackproperties
//
// DESCRIPTION : Fetches the properties of specified volpack device
//
// INPUT PARAMETERS : volpack device name
//
// OUTPUT PARAMETERS : volpackproperties structure
//
//Return Value : INM_NOT_A_VOLPACK (if device is not a volpack)
// 0 (on success)
// -1 ( on failure)
//
int getvolpackproperties(const std::string& volpack_device,volpackproperties& volpackinstance )
{
int retvalue = 0;
volpackinstance.m_logicalsize = 0;
volpackinstance.m_sizeondisk = 0;
do
{
std::string sparsefilename;
bool new_sparsefile_format = false;
ACE_stat statbuf = {0};
if(!IsVolPackDevice(volpack_device.c_str(),sparsefilename,new_sparsefile_format))
{
retvalue = INM_NOT_A_VOLPACK;
break;
}
volpackinstance.m_sparsefilename = sparsefilename;
if(!new_sparsefile_format)
{
if(sv_stat(getLongPathName(sparsefilename.c_str()).c_str(), &statbuf) != 0)
{
DebugPrintf(SV_LOG_ERROR, "FUNCTION:%s Failed to get file :%s statitics.\n",
FUNCTION_NAME,sparsefilename.c_str());
retvalue = -1;
break;
}
volpackinstance.m_logicalsize = statbuf.st_size;
volpackinstance.m_sizeondisk = File::GetSizeOnDisk(sparsefilename);
break;
}
int i = 0;
std::stringstream sparsepartfile;
while(true)
{
sparsepartfile.str("");
sparsepartfile << sparsefilename << SPARSE_PARTFILE_EXT << i;
if( sv_stat( getLongPathName(sparsepartfile.str().c_str()).c_str(), &statbuf ) < 0 )
{
break;
}
volpackinstance.m_logicalsize += statbuf.st_size;
volpackinstance.m_sizeondisk += File::GetSizeOnDisk(sparsepartfile.str());
i++;
}
} while(0);
return retvalue;
}
void removeStringSpaces( std::string& s)
{
Trim(s, " \n\b\t\a\r\xc");
}
void PrintNicInfos(NicInfos_t &nicinfos, const SV_LOG_LEVEL logLevel)
{
DebugPrintf(SV_LOG_DEBUG, "nicinfos:\n");
for (NicInfosIter_t it = nicinfos.begin(); it != nicinfos.end(); it++)
{
DebugPrintf(logLevel, "Hardware Address: %s\n", it->first.c_str());
DebugPrintf(logLevel, "Configurations:\n");
Objects_t &nicconfs = it->second;
for (ObjectsIter_t cit = nicconfs.begin(); cit != nicconfs.end(); cit++)
{
cit->Print(logLevel);
}
}
}
// ValidateAndGetIPAddress chacks input ipAddress(es) for an IPv4 private address space format.
// On Windows input is comma saparated IP addresses. For example,
// 10.150.2.120,fe80::6d35:68a9:f2f9:956a,2404:f801:4800:2:6d35:68a9:f2f9:956a
// On Linux input is single IP addresses. For example,
// 10.150.2.135
// It checks input IP address(es) and returns an ipAddress string in IPv4 private address space format.
// If check fails it returns a blank string.
std::string ValidateAndGetIPAddress(const std::string &ipAddress, std::string &errMsg)
{
std::string validIPAddress;
try{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer_t;
boost::char_separator<char> ipSep(",");
tokenizer_t ipTokens(ipAddress, ipSep);
tokenizer_t::iterator ipItr(ipTokens.begin());
for (ipItr; ipItr != ipTokens.end(); ++ipItr)
{
if (!boost::asio::ip::address::from_string(*ipItr).is_v4())
{
errMsg = *ipItr;
errMsg += " not in IPv4 format";
continue;
}
if (boost::asio::ip::address::from_string(*ipItr).is_loopback())
{
errMsg = *ipItr;
errMsg += " not in IPv4 private address space format";
continue;
}
// check APIPA format
const std::string strAPIPA_IPAddress = "169.254.";
if (0 == strAPIPA_IPAddress.compare((*ipItr).substr(0, strAPIPA_IPAddress.length())))
{
errMsg = *ipItr;
errMsg += " not in IPv4 private address space format";
continue;
}
validIPAddress = *ipItr;
break;
}
}catch (const std::exception &e){
errMsg += "caught exception: ";
errMsg += e.what();
}catch (...){
errMsg += FUNCTION_NAME;
errMsg += " ";
errMsg += "caught unknown exception";
}
return validIPAddress;
}
// GetIPAddressSetFromNicInfo collects all IP addresses in IPv4 private address space format in NIC in an out param ips.
// After successful processing ips set contains IP address(es) in following order,
// 10.0.0.0 - 10.255.255.255 (10 / 8 prefix)
// 172.16.0.0 - 172.31.255.255 (172.16 / 12 prefix)
// 192.168.0.0 - 192.168.255.255 (192.168 / 16 prefix)
//
// Returns true if any of NIC found with IP addresses in IPv4 private address space format.
// Returns false if none of NIC found with IP addresses in IPv4 private address space format.
// Returns false for any other error condition.
bool GetIPAddressSetFromNicInfo(strset_t &ips, std::string &errMsg)
{
NicInfos_t nicinfos;
GetNicInfos(nicinfos);
ConstNicInfosIter_t nicinfosItr = nicinfos.begin();
if (nicinfosItr == nicinfos.end())
{
errMsg = "nicinfo missing";
return false;
}
for (nicinfosItr; nicinfosItr != nicinfos.end(); nicinfosItr++)
{
const Objects_t &nicconfs = nicinfosItr->second;
for (ConstObjectsIter_t objectsItr = nicconfs.begin(); objectsItr != nicconfs.end(); objectsItr++)
{
Attributes_t::const_iterator attributeItr = objectsItr->m_Attributes.find(NSNicInfo::IP_ADDRESSES);
if (attributeItr != objectsItr->m_Attributes.end())
{
std::string err;
std::string ipAddr = ValidateAndGetIPAddress(attributeItr->second, err);
if (!ipAddr.empty())
{
ips.insert(ipAddr);
}
else
{
errMsg += err;
errMsg += ", ";
}
}
else
{
errMsg = NSNicInfo::IP_ADDRESSES;
errMsg += " missing in nicinfo ";
errMsg += nicinfosItr->first;
errMsg += ", ";
}
}
}
if (ips.empty())
{
errMsg += "No valid IP found in nicifo.";
return false;
}
return true;
}
void InsertNicInfo(NicInfos_t &nicInfos, const std::string &name, const std::string &hardwareaddress, const std::string &ipaddress,
const std::string &netmask, const E_INM_TRISTATE &isdhcpenabled)
{
NicInfosIter_t nicinfoiter = nicInfos.find(hardwareaddress);
Object *p;
if (nicinfoiter != nicInfos.end())
{
Objects_t &nicobjs = nicinfoiter->second;
ObjectsIter_t oit = nicobjs.insert(nicobjs.end(), Object());
Object &o = *oit;
p = &o;
}
else
{
std::pair<NicInfosIter_t, bool> pr = nicInfos.insert(std::make_pair(hardwareaddress, Objects_t()));
Objects_t &nicobjs = pr.first->second;
ObjectsIter_t oit = nicobjs.insert(nicobjs.end(), Object());
Object &o = *oit;
p = &o;
}
/* name is assumed to non empty */
p->m_Attributes.insert(std::make_pair(NSNicInfo::NAME, name));
if (!ipaddress.empty())
{
p->m_Attributes.insert(std::make_pair(NSNicInfo::IP_ADDRESSES, ipaddress));
}
if (!netmask.empty())
{
p->m_Attributes.insert(std::make_pair(NSNicInfo::IP_SUBNET_MASKS, netmask));
}
if (E_INM_TRISTATE_FLOATING != isdhcpenabled)
{
const char *v = (E_INM_TRISTATE_TRUE == isdhcpenabled) ? "true" : "false";
p->m_Attributes.insert(std::make_pair(NSNicInfo::IS_DHCP_ENABLED, v));
}
}
void UpdateNicInfoAttr(const std::string &attr, const std::string &value, NicInfos_t &nicinfos)
{
for (NicInfosIter_t it = nicinfos.begin(); it != nicinfos.end(); it++)
{
Objects_t &objs = it->second;
for (ObjectsIter_t oit = objs.begin(); oit != objs.end(); oit++)
{
Object &o = *oit;
o.m_Attributes.insert(std::make_pair(attr, value));
}
}
}
std::string Escapexml(const std::string& value)
{
std::string str = value ;
boost::replace_all ( str, "&", "&" );
boost::replace_all ( str, "\"", """ );
boost::replace_all ( str, "\'", "'" );
boost::replace_all ( str, ">", ">" );
boost::replace_all ( str, "<", "<" );
return str;
}
void InmHexStrToUll(const std::string &s, unsigned long long &ull)
{
std::stringstream ss(s);
ss >> std::hex >> ull;
}
bool EnQ(ACE_Message_Queue<ACE_MT_SYNCH> *Q, ACE_Message_Block *mb, const int &waitsecs, QuitFunction_t &qf)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s with mb = %p\n", FUNCTION_NAME, mb);
bool bretval = true;
do
{
ACE_Time_Value time = ACE_OS::gettimeofday() ;
time += waitsecs ;
if( -1 == Q->enqueue_prio( mb, &time ) )
{
if (errno == EWOULDBLOCK )
{
qf && qf( waitsecs ) ;
}
else
{
DebugPrintf(SV_LOG_ERROR, "failed to enqueue with errno %d\n", errno);
bretval = false;
break;
}
}
else
{
break;
}
} while (qf && !qf(0));
DebugPrintf(SV_LOG_DEBUG, "EXITED %s with return value = %s\n", FUNCTION_NAME, bretval?"true":"false");
return bretval;
}
ACE_Message_Block * DeQ( ACE_Message_Queue<ACE_MT_SYNCH> * Q, const int &waitsecs, const bool &getwaittime, ACE_Time_Value *pwaittime )
{
ACE_Message_Block *mb = NULL;
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME ) ;
DeQ_t ds[] = {&DirectDeQ, &DeQWithRecordedWaitTime};
DeQ_t p = ds[getwaittime];
ACE_Time_Value wait = ACE_OS::gettimeofday ();
wait.sec (wait.sec () + waitsecs);
int deqrv = (*p)(Q, &mb, wait, pwaittime);
if (-1 == deqrv)
{
if ((errno != EWOULDBLOCK) && (errno != ESHUTDOWN))
{
DebugPrintf(SV_LOG_ERROR, "failed to deque with errno %d\n", errno);
}
}
DebugPrintf( SV_LOG_DEBUG, "EXITED %s with mb = %p\n", FUNCTION_NAME, mb) ;
return mb ;
}
int DeQWithRecordedWaitTime( ACE_Message_Queue<ACE_MT_SYNCH> * Q, ACE_Message_Block **mb, ACE_Time_Value &absolutewaittime, ACE_Time_Value *pwaittime)
{
ACE_Time_Value TimeBeforeDeQ, TimeAfterDeQ;
TimeBeforeDeQ = ACE_OS::gettimeofday();
int rv = Q -> dequeue_head(*mb, &absolutewaittime);
TimeAfterDeQ = ACE_OS::gettimeofday();
*pwaittime += (TimeAfterDeQ-TimeBeforeDeQ);
return rv;
}
int DirectDeQ( ACE_Message_Queue<ACE_MT_SYNCH> * Q, ACE_Message_Block **mb, ACE_Time_Value &absolutewaittime, ACE_Time_Value *pwaittime)
{
return Q -> dequeue_head(*mb, &absolutewaittime);
}
int RemoveDirectories(const std::string &parentdirectory, const std::set<std::string> &exceptionlist)
{
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
struct ACE_DIRENT *dp = NULL;
// PR#10815: Long Path support
ACE_DIR *dir = sv_opendir(parentdirectory.c_str());
// Check if we could successfully open the directory dir1
if (dir == NULL)
{
// we could not open the directory dir1
if (ACE_OS::last_error() != ENOENT)
{
// Get the error and display the error
DebugPrintf(SV_LOG_WARNING, " LocalDirectSync::CleanUpChkptOffsetDir() opendir failed, path = %s, errno = 0x%x\n", parentdirectory.c_str(), ACE_OS::last_error());
}
return -1;
}
//Get directory entry for parentdirectory
while ((dp = ACE_OS::readdir(dir)) != NULL)
{
std::string filename = ACE_TEXT_ALWAYS_CHAR(dp->d_name);
// we ignore the "." and ".." files
if ( strcmp(".", filename.c_str()) == 0 || strcmp(".." , filename.c_str()) == 0 )
continue;
if ( exceptionlist.end() == exceptionlist.find(filename) )
{
std::string chkptDir = parentdirectory + filename.c_str();
DebugPrintf(SV_LOG_DEBUG, "Cleaning up directory : %s\n", chkptDir.c_str());
CleanupDirectory(chkptDir.c_str(), "*");
// PR#10815: Long Path support
ACE_OS::rmdir(getLongPathName(chkptDir.c_str()).c_str());
}
}
ACE_OS::closedir(dir);
DebugPrintf(SV_LOG_DEBUG,"EXITED %s\n",FUNCTION_NAME);
return 0;
}
bool IsFileORVolumeExisting(const std::string& sName)
{
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
bool bExist = false;
ACE_HANDLE hHandle = ACE_INVALID_HANDLE;
std::string sFile = sName;
FormatVolumeNameToGuid(sFile);
SV_ULONG access = O_RDONLY;
hHandle = ACE_OS::open(getLongPathName(sFile.c_str()).c_str(),access);
bExist = (ACE_INVALID_HANDLE == hHandle) ? false : true;
if (bExist)
{
ACE_OS::close(hHandle);
}
DebugPrintf(SV_LOG_DEBUG,"EXITED %s\n",FUNCTION_NAME);
return bExist;
}
void CreateTransportStream(boost::shared_ptr<TransportStream> &ts, const TRANSPORT_PROTOCOL &tp,
const TRANSPORT_CONNECTION_SETTINGS &tss, const VOLUME_SETTINGS::SECURE_MODE &securemode)
{
/* this calls delete first */
ts.reset(new (std::nothrow) TransportStream(tp, tss));
STREAM_MODE mode = GenericStream::Mode_Open | GenericStream::Mode_RW;
if ( VOLUME_SETTINGS::SECURE_MODE_SECURE == securemode )
mode |= GenericStream::Mode_Secure;
if ( SV_FAILURE == ts->Open(mode) )
{
ts.reset();
DebugPrintf(SV_LOG_ERROR, "FAILED: Unable to open transport stream\n");
return ;
}
}
int comparememory(const void *s1, const void *s2, size_t n)
{
return memcmp(s1, s2, n);
}
int alwaysreturnunequal(const void *s1, const void *s2, size_t n)
{
return 1;
}
bool GetMD5Hash(const std::string &fileNamePath, unsigned char *hash)
{
bool got = false;
std::ifstream is;
is.open(fileNamePath.c_str(), std::ios::in | std::ios::binary);
if(is.is_open())
{
INM_MD5_CTX ctx;
INM_MD5Init(&ctx);
/* 4k to be more efficient */
const size_t ALLOCLEN = 4096;
boost::shared_array<char> buffer(new char[ALLOCLEN]);
bool read = false;
std::streamsize count;
while (!read)
{
is.read(buffer.get(), ALLOCLEN);
if (is.eof())
read = true;
count = is.gcount();
if (count)
INM_MD5Update(&ctx, (unsigned char*)buffer.get(), count);
}
is.close();
INM_MD5Final(hash, &ctx);
got = true;
}
else
{
DebugPrintf(SV_LOG_ERROR, "Failed to open file %s to calculate md5sum\n", fileNamePath.c_str());
}
return got;
}
std::string GetBytesInArrayAsHexString(const unsigned char *a, const size_t &length)
{
std::stringstream ss;
ss << std::hex << std::setfill('0') << std::uppercase;
for (int i = 0; i < length; i++)
{
ss << std::setw(2) << (unsigned int)a[i];
}
return ss.str();
}
//
// fileTime is 64-bit value representing the number
// of 100-nanosecond intervals since January 1, 1601 (UTC)
//
bool ConvertToSVTime( SV_ULONGLONG fileTime, SV_TIME& svTime )
{
if( fileTime & 0x8000000000000000LL ) {
return false;
}
long long units = fileTime; // initially in 100 nanosecond intervals
// Milliseconds remaining after seconds are accounted for
int const IntervalsPerSecond = 10000000;
int const IntervalsPerMillisecond = IntervalsPerSecond / 1000;
svTime.wMilliseconds = (static_cast<unsigned>( units % IntervalsPerSecond ) ) / IntervalsPerMillisecond;
// Time is now in seconds
units = units / IntervalsPerSecond;
// How many seconds remain after days are subtracted off
// Note: no leap seconds!
int const SecondsPerDay = 86400;
long days = static_cast<long>( units / SecondsPerDay );
int secondsInDay = static_cast<int>( units % SecondsPerDay );
// Calculate hh:mm:ss from seconds
int const SecondsPerHour = 3600;
int const SecondsPerMinute = 60;
svTime.wHour = secondsInDay / SecondsPerHour;
secondsInDay = secondsInDay % SecondsPerHour;
svTime.wMinute = secondsInDay / SecondsPerMinute;
svTime.wSecond = secondsInDay % SecondsPerMinute;
// Calculate day of week
int const EpochDayOfWeek = 1; // Jan 1, 1601 was Monday
int const DaysPerWeek = 7;
//svTime.wDayOfWeek = ( EpochDayOfWeek + days ) % DaysPerWeek;
// Compute year, month, and day
int const DaysPerFourHundredYears = 365 * 400 + 97;
int const DaysPerNormalCentury = 365 * 100 + 24;
int const DaysPerNormalFourYears = 365 * 4 + 1;
long leapCount = ( 3 * ((4 * days + 1227) / DaysPerFourHundredYears) + 3 ) / 4;
days += 28188 + leapCount;
long years = ( 20 * days - 2442 ) / ( 5 * DaysPerNormalFourYears );
long yearDay = days - ( years * DaysPerNormalFourYears ) / 4;
long months = ( 64 * yearDay ) / 1959;
// Resulting month based on March starting the year.
// Adjust for January and February by adjusting year in tandem.
if( months < 14 ) {
svTime.wMonth = static_cast<SV_USHORT>(months - 1);
svTime.wYear = static_cast<SV_USHORT>(years + 1524);
}
else {
svTime.wMonth = static_cast<SV_USHORT>(months - 13);
svTime.wYear = static_cast<SV_USHORT>(years + 1525);
}
// Calculate day of month by using MonthLengths(n)=floor( n * 30.6 ); works for small n
svTime.wDay = static_cast<SV_USHORT>(yearDay - (1959 * months) / 64);
svTime.wMicroseconds = static_cast<SV_USHORT>((fileTime / 10) % 1000);
svTime.wHundrecNanoseconds = static_cast<SV_USHORT>(fileTime % 10);
return true;
}
bool ConvertTimeToString(SV_ULONGLONG ts, std::string & display)
{
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s\n",FUNCTION_NAME);
bool rv = true;
do
{
std::stringstream displaytime;
SV_TIME svtime;
if(!ConvertToSVTime(ts,svtime))
{
std::stringstream l_stdfatal;
l_stdfatal << "Specified Time " << ts << " is invalid\n";
DebugPrintf(SV_LOG_FATAL, "%s", l_stdfatal.str().c_str());
rv = false;
break;
}
displaytime << svtime.wYear << std::setfill('0') << std::setw(2) <<
svtime.wMonth << std::setfill('0') << std::setw(2) <<
svtime.wDay << std::setfill('0') << std::setw(2) <<
svtime.wHour << std::setfill('0') << std::setw(2) <<
svtime.wMinute << std::setfill('0') << std::setw(2) <<
svtime.wSecond;
display = displaytime.str();
} while ( FALSE );
DebugPrintf(SV_LOG_DEBUG,"EXITED %s\n",FUNCTION_NAME);
return rv;
}
void PrintOptions(const Options_t &options)
{
std::stringstream ss;
ss << "options:\n";
InsertIntoStream(options, ss);
DebugPrintf(SV_LOG_DEBUG, "%s", ss.str().c_str());
}
std::string getSystemTimeInUtc(void)
{
time_t t1 = time(NULL);
char gmTime[128];
strftime(gmTime, 128, "%Y%m%d%H%M%S", gmtime(&t1));
return gmTime;
}
void replace_nonsupported_chars(std::string & filename,
const std::string & chars_to_replace, char replaced_char)
{
for(int i = 0; i < chars_to_replace.length() ; ++i)
std::replace(filename.begin(), filename.end(), chars_to_replace[i] , replaced_char);
}
void RecordFilterDrvVolumeBitmapDelMsg(const std::string &msg)
{
DebugPrintf(SV_LOG_ERROR, "NOTE: this is not an error. Filter driver volume bitmap delete message: %s.\n", msg.c_str());
Configurator* TheConfigurator = NULL;
if(GetConfigurator(&TheConfigurator)) {
time_t t = time(NULL);
std::string stime = ctime(&t);
stime.erase(stime.end()-1);
std::string logfilename = TheConfigurator->getVxAgent().getCacheDirectory() + ACE_DIRECTORY_SEPARATOR_STR_A + "FilterDrvVolumeBitmapDelMsg.log";
std::ofstream out(logfilename.c_str(), std::ios::app);
if (out.is_open())
out << stime << ": " << msg << ".\n";
else
DebugPrintf(SV_LOG_ERROR, "Failed to locally record filter driver volume bitmap delete message %s, because could not open log file %s\n",
msg.c_str(), logfilename.c_str());
} else
DebugPrintf(SV_LOG_ERROR, "Failed to locally record filter driver volume bitmap delete message %s, because could not get configurator\n", msg.c_str());
}
///
/// Performs an HTTP POST to the SV server.
///
SVERROR PostToSVServer( const char *pszSVServerName,
SV_INT HttpPort,
const char *pszPostURL,
char *pchPostBuffer,
SV_ULONG dwPostBufferLength,
const bool& pHttps)
{
DebugPrintf(SV_LOG_DEBUG, "Entering %s\n", __FUNCTION__);
SVERROR sve = SVE_FAIL;
DebugPrintf(SV_LOG_DEBUG,"Server = %s\n",pszSVServerName);
DebugPrintf(SV_LOG_DEBUG,"Port = %d\n",HttpPort);
DebugPrintf(SV_LOG_DEBUG,"Secure = %d\n",pHttps);
DebugPrintf(SV_LOG_DEBUG,"PHP URL = %s\n",pszPostURL);
CurlOptions options(pszSVServerName,HttpPort, pszPostURL, pHttps);
try {
CurlWrapper cw;
cw.post(options,pchPostBuffer);
DebugPrintf(SV_LOG_DEBUG,"Successfully post to SVServer %s\n",pszPostURL);
sve = SVS_OK;
} catch(ErrorException& exception )
{
DebugPrintf(SV_LOG_ERROR, "FAILED : %s with error %s\n",FUNCTION_NAME, exception.what());
return sve;
}
DebugPrintf(SV_LOG_DEBUG, "Exiting %s\n", __FUNCTION__);
return sve;
}
std::string GetIOSState(std::ios &stream)
{
std::stringstream ss;
ss << "good = " << STRBOOL(stream.good()) << ", "
<< "eof = " << STRBOOL(stream.eof()) << ", "
<< "fail = " << STRBOOL(stream.fail()) << ", "
<< "bad = " << STRBOOL(stream.bad());
return ss.str();
}
std::string GenerateUuid()
{
DebugPrintf(SV_LOG_DEBUG, "Entering %s\n", __FUNCTION__);
std::stringstream suuid;
try
{
boost::uuids::random_generator uuid_gen;
boost::uuids::uuid new_uuid = uuid_gen();
suuid << new_uuid;
}
catch (const std::exception& e)
{
DebugPrintf(SV_LOG_ERROR, "Could not generate UUID. Exception: %s\n", e.what());
}
catch (...)
{
DebugPrintf(SV_LOG_ERROR, "Could not generate UUID. Unkown exception\n");
}
DebugPrintf(SV_LOG_DEBUG, "Exiting %s\n", __FUNCTION__);
return suuid.str();
}
uint64_t GetTimeInMilliSecSinceEpoch1970()
{
uint64_t msecSinceEpoch = boost::posix_time::time_duration(boost::posix_time::microsec_clock::universal_time()
- boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))).total_milliseconds();
return msecSinceEpoch;
}
uint64_t GetTimeInSecSinceEpoch1970()
{
return GetTimeInMilliSecSinceEpoch1970() / 1000;
}
uint64_t GetTimeInSecSinceAd0001()
{
const uint64_t TIME_IN_SECS_BETWEEN_AD_AND_EPOCH = 62135596800;
uint64_t secSinceEpoch = GetTimeInSecSinceEpoch1970();
secSinceEpoch += TIME_IN_SECS_BETWEEN_AD_AND_EPOCH;
return secSinceEpoch;
}
uint64_t GetSecsBetweenEpoch1970AndEpoch1601()
{
uint64_t diff = boost::gregorian::date_duration(boost::gregorian::date(1970, 1, 1)
- boost::gregorian::date(1601, 1, 1)).days();
diff *= 24 * 60 * 60;
return diff;
}
uint64_t GetTimeInSecSinceEpoch1601()
{
uint64_t secSinceEpoch = GetTimeInSecSinceEpoch1970();
secSinceEpoch += GetSecsBetweenEpoch1970AndEpoch1601();
return secSinceEpoch;
}
void GetHypervisorInfo(HypervisorInfo_t &hypervinfo)
{
DebugPrintf(SV_LOG_DEBUG, "Determining Hypervisor information\n");
bool bisvirtual = IsVirtual(hypervinfo.name, hypervinfo.version);
hypervinfo.state = bisvirtual ? HypervisorInfo_t::HyperVisorPresent :
HypervisorInfo_t::HypervisorNotPresent;
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return;
}
#ifdef SV_WINDOWS
bool PersistPlatformTypeForDriver()
{
return true;
}
#else
bool PersistPlatformTypeForDriver()
{
static bool bstatus = false;
if (bstatus) return bstatus;
boost::system::error_code ec;
std::string platformTypePersistentFile;
LocalConfigurator lc;
if (!LocalConfigurator::getVxPlatformTypeForDriverPersistentFile(platformTypePersistentFile))
{
DebugPrintf(SV_LOG_ERROR,
"%s: failed to get platform type persistent file path from config.\n",
FUNCTION_NAME);
return bstatus;
}
if (boost::filesystem::exists(platformTypePersistentFile, ec))
{
DebugPrintf(SV_LOG_DEBUG,
"%s: platform type persistent file found at %s.\n",
FUNCTION_NAME,
platformTypePersistentFile.c_str());
}
else
{
std::string newDir = dirname_r(platformTypePersistentFile);
if (!boost::filesystem::exists(newDir, ec))
{
boost::filesystem::create_directories(newDir, ec);
if (ec)
{
DebugPrintf(SV_LOG_ERROR,
"%s: creating directory %s failed. Error %d (%s).\n",
FUNCTION_NAME,
ec.value(),
ec.message().c_str());
return bstatus;
}
securitylib::setPermissions(newDir, securitylib::SET_PERMISSIONS_NAME_IS_DIR);
}
}
std::ofstream platFile(platformTypePersistentFile.c_str(), std::ios::trunc);
if (!platFile.is_open())
{
DebugPrintf(SV_LOG_ERROR, "%s: file %s open failed.\n",
FUNCTION_NAME, platformTypePersistentFile.c_str());
return bstatus;
}
std::string vmPlatform = lc.getVmPlatform();
std::string csType = lc.getCSType();
platFile << "VMPLATFORM=" << vmPlatform << std::endl;
platFile << "CS_TYPE=" << csType << std::endl;
platFile.flush();
if (!platFile.good())
{
DebugPrintf(SV_LOG_ERROR, "%s: file %s write failed.\n",
FUNCTION_NAME, platformTypePersistentFile.c_str());
platFile.close();
return bstatus;
}
platFile.close();
securitylib::setPermissions(platformTypePersistentFile);
bstatus = true;
DebugPrintf(SV_LOG_ALWAYS,
"%s: platform type persistent file created at %s.\n",
FUNCTION_NAME,
platformTypePersistentFile.c_str());
return bstatus;
}
#endif
std::string GetImdsMetadata()
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
MemoryStruct chunk = {0};
CURL *curl = curl_easy_init();
try
{
chunk.size = 0;
chunk.memory = NULL;
if(CURLE_OK != curl_easy_setopt(curl, CURLOPT_URL, IMDS_URL)) {
throw ERROR_EXCEPTION << FUNCTION_NAME << ": Failed to set curl options IMDS_URL.\n";
}
if(CURLE_OK != curl_easy_setopt(curl, CURLOPT_NOPROXY, "*")) {
throw ERROR_EXCEPTION << FUNCTION_NAME << ": Failed to set curl options CURLOPT_NOPROXY.\n";
}
struct curl_slist * pheaders = curl_slist_append(NULL, IMDS_HEADERS);
if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_HTTPHEADER, pheaders)) {
throw ERROR_EXCEPTION << FUNCTION_NAME << ": Failed to set curl options CURLOPT_HEADERDATA.\n";
}
if(CURLE_OK != curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallbackFileReplication)) {
throw ERROR_EXCEPTION << FUNCTION_NAME << ": Failed to set curl options CURLOPT_WRITEFUNCTION.\n";
}
if(CURLE_OK != curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void *>( &chunk ))) {
throw ERROR_EXCEPTION << FUNCTION_NAME << ": Failed to set curl options CURLOPT_WRITEDATA.\n";
}
CURLcode curl_code = curl_easy_perform(curl);
if (curl_code == CURLE_ABORTED_BY_CALLBACK)
{
throw ERROR_EXCEPTION << FUNCTION_NAME << ": Failed to perfvorm curl request, request aborted.\n";
}
long response_code = 0L;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code != HTTP_OK)
{
throw ERROR_EXCEPTION << FUNCTION_NAME << ": Failed to perform curl request, curl error "
<< curl_code << ": " << curl_easy_strerror(curl_code)
<< ", status code " << response_code
<< ((chunk.memory != NULL) ? (std::string(", error ") + chunk.memory) : "") << ".\n";
}
}
catch (std::exception& e)
{
DebugPrintf(SV_LOG_ERROR, "%s: Failed with exception: %s.\n", FUNCTION_NAME, e.what());
}
catch (...)
{
DebugPrintf(SV_LOG_ERROR, "%s: Failed with exception.\n", FUNCTION_NAME);
}
std::string ret;
if (chunk.memory != NULL)
{
ret = std::string(chunk.memory, chunk.size);
free(chunk.memory);
}
curl_easy_cleanup(curl);
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return ret;
}
bool IsAzureStackVirtualMachine()
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
static bool s_bIsCheckComplete = false;
static bool s_IsAzureStackVm = false;
if (!s_bIsCheckComplete)
{
LocalConfigurator lc;
s_IsAzureStackVm = lc.getIsAzureStackHubVm();
s_bIsCheckComplete = true;
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return s_IsAzureStackVm;
}
bool HasAzureStackHubFailoverTag(QuitFunction_t qf)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
static bool s_bIsCheckComplete = false;
static bool s_HasFailoverTag = false;
if (s_bIsCheckComplete)
{
return s_HasFailoverTag;
}
if (!IsAzureStackVirtualMachine())
{
return false;
}
while (true)
{
try
{
// Get IMDS information. Always HTTP
std::string imdsMetadata = GetImdsMetadata();
std::istringstream stream(imdsMetadata);
boost::property_tree::ptree pt;
boost::property_tree::read_json(stream, pt);
boost::property_tree::ptree &tagsList = pt.get_child(IMDS_COMPUTE_TAGSLIST);
std::stringstream tagsJson;
boost::property_tree::write_json(tagsJson, tagsList);
DebugPrintf(SV_LOG_DEBUG, "Tags List: %s\n", tagsJson.str().c_str());
for (boost::property_tree::ptree::iterator element = tagsList.begin();
element != tagsList.end();
element++)
{
if (element->second.get<std::string>("name") == IMDS_FAILOVER_TAG_PREFIX
&& element->second.get<std::string>("value") == IMDS_FAILOVER_TAG_SUFFIX)
{
s_HasFailoverTag = true;
DebugPrintf(SV_LOG_DEBUG, "%s: Detected failover tag.\n", FUNCTION_NAME);
break;
}
}
DebugPrintf(SV_LOG_DEBUG, "%s: Finished checking failover tag.\n", FUNCTION_NAME);
break;
}
catch (std::exception& e)
{
DebugPrintf(SV_LOG_ERROR, "%s: Failed with exception: %s. Retrying...\n", FUNCTION_NAME, e.what());
}
catch (...)
{
DebugPrintf(SV_LOG_ERROR, "%s: Failed with exception. Retrying...\n", FUNCTION_NAME);
}
if (qf(IMDS_RETRY_INTERVAL_IN_SECS))
{
throw "Quit requested";
}
}
s_bIsCheckComplete = true;
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return s_HasFailoverTag;
}
bool IsAzureVirtualMachine()
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
static std::string strAssetTag = "";
if (strAssetTag.empty())
{
strAssetTag = GetChassisAssetTag();
}
DebugPrintf(SV_LOG_DEBUG, "Asset Tag: %s\n", strAssetTag.c_str());
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return boost::iequals(strAssetTag, AZURE_ASSET_TAG) && !IsAzureStackVirtualMachine();
}
#ifdef SV_WINDOWS
int GetDeviceNameTypeToReport(const std::string& hypervisorName, const bool isMigrateToRcm)
{
return DEVICE_NAME_TYPE_DISK_SIGNATURE;
}
#else
int GetDeviceNameTypeToReport(const std::string& hypervisorName, const bool isMigrateToRcm)
{
static std::string s_strVmPlatform;
static std::string s_strHypervisorName;
static std::string s_strAssetTag;
static std::string s_strCsType;
if (s_strVmPlatform.empty())
{
LocalConfigurator lc;
s_strVmPlatform = lc.getVmPlatform();
s_strCsType = lc.getCSType();
}
if (hypervisorName.empty())
{
if (s_strHypervisorName.empty())
{
HypervisorInfo_t hypervinfo;
GetHypervisorInfo(hypervinfo);
s_strHypervisorName = hypervinfo.name;
PrintHypervisorInfo(hypervinfo);
}
}
if (s_strAssetTag.empty())
{
s_strAssetTag = GetChassisAssetTag();
}
// for A2A and V2A Failover VM (running on Azure)
if ( boost::iequals(s_strVmPlatform, AZUREPLATFORM) ||
( (boost::iequals(hypervisorName.empty() ? s_strHypervisorName : hypervisorName, MICROSOFTNAME)) &&
boost::iequals(s_strVmPlatform, VMWAREPLATFORM) &&
boost::iequals(s_strAssetTag, AZURE_ASSET_TAG) ) )
{
DebugPrintf(SV_LOG_DEBUG, "EXITED %s with DEVICE_NAME_TYPE_LU_NUMBER\n", FUNCTION_NAME);
return DEVICE_NAME_TYPE_LU_NUMBER;
}
// for V2A VM runnong on VmWare and the CS_TYPE is CS_PRIME
else if (boost::iequals(s_strVmPlatform, VMWAREPLATFORM)
&& (boost::iequals(s_strCsType, CSTYPE_CSPRIME) || isMigrateToRcm))
{
DebugPrintf(SV_LOG_DEBUG, "EXITED %s with DEVICE_NAME_TYPE_FROM_PERSISTENT_MAP\n", FUNCTION_NAME);
return DEVICE_NAME_TYPE_FROM_PERSISTENT_MAP;
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s with DEVICE_NAME_TYPE_OS_NAME\n", FUNCTION_NAME);
return DEVICE_NAME_TYPE_OS_NAME;
}
#endif
bool IsAgentRunningOnAzureVm()
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
static bool s_bIsCheckComplete = false;
static bool s_IsAzureVm = false;
if (s_bIsCheckComplete)
return s_IsAzureVm;
HypervisorInfo_t hypervinfo;
GetHypervisorInfo(hypervinfo);
DebugPrintf(SV_LOG_DEBUG, "agent is running on a VM on hypervisor %s.\n", hypervinfo.name.c_str());
if (hypervinfo.state == HypervisorInfo::HyperVisorPresent)
{
std::string assettag = GetChassisAssetTag();
std::string expectedHyperVName;
#ifdef SV_WINDOWS
expectedHyperVName = HYPERVNAME;
#else
expectedHyperVName = MICROSOFTNAME;
#endif
if (boost::iequals(hypervinfo.name, expectedHyperVName))
{
if (boost::iequals(assettag, AZURE_ASSET_TAG) && !IsAzureStackVirtualMachine())
{
DebugPrintf(SV_LOG_ALWAYS, "Detected agent is running on Azure VM.\n");
s_IsAzureVm = true;
}
else if (assettag.empty())
{
throw ERROR_EXCEPTION << "Asset tag on Microsoft Hyper-V VM is empty.\n";
}
}
}
s_bIsCheckComplete = true;
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return s_IsAzureVm;
}
std::string GetCxIpAddress()
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
LocalConfigurator lc;
std::string ipAddress =
(IsAgentRunningOnAzureVm() && !lc.getCsAddressForAzureComponents().empty()) ?
lc.getCsAddressForAzureComponents() :
lc.getHttp().ipAddress;
DebugPrintf(SV_LOG_DEBUG, "EXITED %s CS IP Addess: %s\n", FUNCTION_NAME, ipAddress.c_str());
return ipAddress;
}
/// \brief Delete the vxprotdevdetails.dat file present either at the old path or new path
/// to be called during the disable protection
bool DeleteProtectedDeviceDetails()
{
bool bstatus = true;
do
{
std::string devDetailsCachePath;
bstatus = LocalConfigurator::getVxProtectedDeviceDetailCachePathname(devDetailsCachePath);
if (!bstatus)
{
DebugPrintf(SV_LOG_ERROR,
"%s: failed to delete protected device details file as failed to get path from config.\n",
FUNCTION_NAME);
break;
}
std::string depDevDetailsCachePath;
bstatus = LocalConfigurator::getDeprecatedVxProtectedDeviceDetailCachePathname(depDevDetailsCachePath);
if (!bstatus)
{
DebugPrintf(SV_LOG_ERROR,
"%s: failed to delete protected device details file as failed to get old path from config.\n",
FUNCTION_NAME);
break;
}
boost::system::error_code ec;
std::vector<std::string> devDetailsCachePaths;
devDetailsCachePaths.push_back(devDetailsCachePath);
devDetailsCachePaths.push_back(depDevDetailsCachePath);
std::vector<std::string>::iterator pathIter = devDetailsCachePaths.begin();
for (/*empty*/; pathIter != devDetailsCachePaths.end(); pathIter++)
{
if (!boost::filesystem::exists(*pathIter, ec))
{
DebugPrintf(SV_LOG_DEBUG,
"%s: file %s is not present.\n",
FUNCTION_NAME,
pathIter->c_str());
continue;
}
boost::filesystem::remove(*pathIter, ec);
if (ec)
{
DebugPrintf(SV_LOG_ERROR,
"%s: failed to delete protected device details file with error %d (%s).\n",
FUNCTION_NAME,
ec.value(),
ec.message().c_str());
bstatus = false;
continue;
}
DebugPrintf(SV_LOG_ALWAYS,
"%s: deleted protected device details file %s.\n",
FUNCTION_NAME,
pathIter->c_str());
}
} while (false);
return bstatus;
}
std::string InmGetFormattedSize(unsigned long long ullSize)
{
std::stringstream ssFormattedSize;
std::string aformats[] = { "GB", "MB", "KB", "Bytes" };
std::vector<std::string> formats(aformats, aformats + INM_ARRAY_SIZE(aformats));
unsigned long long ullFormatShifter = 30;
unsigned long long ullFormattedSize = ullSize;
size_t iFmtIndex = 0;
for (iFmtIndex = 0; iFmtIndex < formats.size() - 1; iFmtIndex++)
{
ullFormattedSize = ullSize >> ullFormatShifter;
if (ullFormattedSize > 0) break;
ullFormatShifter -= 10;
ullFormattedSize = ullSize;
}
ssFormattedSize << ullFormattedSize << formats[iFmtIndex];
return ssFormattedSize.str();
}
void ExtractCacheStorageNameFromBlobContainerSasUrl(const std::string& blobContainerSasUrl, std::string& cacheStorageAccountName)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
try {
//extracting according to the standard sas format: https://{myaccount}.blob.core.windows.net/{sascontainer}/sasblob.txt
size_t offset = 2;
size_t first = blobContainerSasUrl.find("//");
size_t last = blobContainerSasUrl.find(".blob.");
if (first == std::string::npos || last == std::string::npos || first >= last)
{
std::string blobSasUriToBeLogged = blobContainerSasUrl.substr(
0, blobContainerSasUrl.find("?"));
DebugPrintf(SV_LOG_ERROR, "%s: Failed to extract cache storage account name as the blobContainerSasUri %s is not in known format.\n", FUNCTION_NAME, blobSasUriToBeLogged.c_str());
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return;
}
{
cacheStorageAccountName = blobContainerSasUrl.substr(first + offset, last - first - offset);
}
}
catch (const std::exception& e)
{
DebugPrintf(SV_LOG_ERROR, "%s Failed with an exception : %s.\n", FUNCTION_NAME, e.what());
}
catch (...)
{
DebugPrintf(SV_LOG_ERROR, "%s Failed with an unnknown exception.\n", FUNCTION_NAME);
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}