host/common/aix/portablehelpersminor.cpp (1,980 lines of code) (raw):
#include <string>
#include <sstream>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/procfs.h>
#include <sys/mntctl.h>
#include <sys/vmount.h>
#include <sys/devinfo.h>
#include <sys/scsi.h>
#include <sys/ioctl.h>
#include <alloca.h>
#include <stdlib.h>
#include <odmi.h>
#include <sys/cfgodm.h>
#include <sys/cfgdb.h>
#include <sys/sysmacros.h>
#include "portablehelpers.h"
#include "portablehelperscommonheaders.h"
#include "portablehelpersmajor.h"
#include "portablehelpersminor.h"
#include "configwrapper.h"
#include "boost/algorithm/string/replace.hpp"
#include "cdplock.h"
#include <ace/Guard_T.h>
#include "ace/Thread_Mutex.h"
#include "ace/Recursive_Thread_Mutex.h"
#include "inmsafecapis.h"
#include "inmsafeint.h"
#include "inmageex.h"
#define SIZE_LIMIT_TOP 0x100000000000LL
#define NUM_SECTORS_PER_TB (1LL << 31)
#define PSNAMELEN 100
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define SIZE(p) MAX((p).sa_len, sizeof(p))
ACE_Recursive_Thread_Mutex g_lockforgetbasicvolinfo;
#define THRSHOLD_NUM_FIELDSINFSTAB 7
#define FLAG_FIELD_IN_FSTAB 6
bool ShouldCollectNicInfo(const int &sockfd, struct ifreq *pifr, const char *ipaddr);
bool FillNicInfos(const int &sockfd, struct ifconf *pifc, size_t sizeofifreq, NicInfos_t & nicInfos);
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);
void UpdateNicInfoAttr(const std::string &attr, const std::string &value, NicInfos_t &nicinfos);
void GetNetIfParameters(const std::string &ifrName, std::string& hardwareAddress, std::string &netmask);
void CollectDhcpEnabledInterfaces(std::set<std::string> &dhcpenabledinterfaces);
SVERROR GetFsVolSize(const char *volName, unsigned long long *pfsSize)
{
SVERROR sv = SVE_FAIL;
if(volName && pfsSize)
{
*pfsSize = GetRawVolSize(volName);
if(*pfsSize)
{
sv = SVS_OK;
}
else
{
DebugPrintf(SV_LOG_ERROR,"@ LINE %d in FILE %s, GetRawVolSize failed for volume %s\n", LINE_NO, FILE_NAME, volName);
}
}
else
{
DebugPrintf(SV_LOG_ERROR,"@ LINE %d in FILE %s, invalid arguements supplied\n", LINE_NO, FILE_NAME);
}
return sv;
}
SV_ULONGLONG GetRawVolSize(const std::string sVolume)
{
DebugPrintf(SV_LOG_DEBUG,"ENTERED %s with sVolume = %s\n",FUNCTION_NAME, sVolume.c_str());
SV_ULONGLONG rawsize = 0;
SV_ULONGLONG mulfactor;
unsigned int low, high;
std::stringstream ss;
if(sVolume.empty() == false)
{
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(g_lockforgetbasicvolinfo);
if(guard.locked())
{
std::string sRawVolName = GetRawVolumeName(sVolume);
int fd;
fd = open(sRawVolName.c_str(), O_NDELAY | O_RDONLY);
if(fd != 0)
{
struct devinfo devinfo;
if (ioctl(fd, IOCINFO, &devinfo) != -1)
{
switch(devinfo.devtype)
{
case DD_DISK: /* disk */
if (devinfo.flags & DF_LGDSK)
{
ss << "For DD_DISK, DF_LGDSK is set. "
<< " devinfo.flags = " << (unsigned int)devinfo.flags
<< " bytpsec = " << devinfo.un.dk64.bytpsec
<< " secptrk = " << devinfo.un.dk64.secptrk
<< " trkpcyl = " << devinfo.un.dk64.trkpcyl
<< " lo_numblks = " << devinfo.un.dk64.lo_numblks
<< " segment_size = " << devinfo.un.dk64.segment_size
<< " segment_count = " << devinfo.un.dk64.segment_count
<< " byte_count = " << devinfo.un.dk64.byte_count
<< " hi_numblks = " << devinfo.un.dk64.hi_numblks;
mulfactor = pow(2, sizeof(devinfo.un.dk64.lo_numblks)*8);
low = (unsigned int)devinfo.un.dk64.lo_numblks;
high = (unsigned int)devinfo.un.dk64.hi_numblks;
rawsize = ((mulfactor*high) + low) * devinfo.un.dk64.bytpsec;
}
else
{
ss << "For DD_DISK, DF_LGDSK is not set. "
<< " devinfo.flags = " << (unsigned int)devinfo.flags
<< " bytpsec = " << devinfo.un.dk.bytpsec
<< " secptrk = " << devinfo.un.dk.secptrk
<< " trkpcyl = " << devinfo.un.dk.trkpcyl
<< " numblks = " << devinfo.un.dk.numblks
<< " segment_size = " << devinfo.un.dk.segment_size
<< " segment_count = " << devinfo.un.dk.segment_count
<< " byte_count = " << devinfo.un.dk.byte_count;
low = (unsigned int)devinfo.un.dk.numblks;
rawsize = low * devinfo.un.dk.bytpsec;
}
DebugPrintf(SV_LOG_DEBUG, "For device %s, %s\n", sVolume.c_str(), ss.str().c_str());
break;
case DD_SCDISK: /* scsi disk */
if (devinfo.flags & DF_LGDSK)
{
ss << "For DD_SCDISK, DF_LGDSK is set. "
<< " devinfo.flags = " << (unsigned int)devinfo.flags
<< " blksize = " << devinfo.un.scdk64.blksize
<< " lo_numblks = " << devinfo.un.scdk64.lo_numblks
<< " lo_max_request = " << devinfo.un.scdk64.lo_max_request
<< " segment_size = " << devinfo.un.scdk64.segment_size
<< " segment_count = " << devinfo.un.scdk64.segment_count
<< " byte_count = " << devinfo.un.scdk64.byte_count
<< " hi_numblks = " << devinfo.un.scdk64.hi_numblks
<< " hi_max_request = " << devinfo.un.scdk64.hi_max_request;
mulfactor = pow(2, sizeof(devinfo.un.scdk64.lo_numblks)*8);
low = (unsigned int)devinfo.un.scdk64.lo_numblks;
high = (unsigned int)devinfo.un.scdk64.hi_numblks;
rawsize = ((mulfactor*high) + low) * devinfo.un.scdk64.blksize;
}
else
{
ss << "For DD_SCDISK, DF_LGDSK is not set. "
<< " devinfo.flags = " << (unsigned int)devinfo.flags
<< " blksize = " << devinfo.un.scdk.blksize
<< " numblks = " << devinfo.un.scdk.numblks
<< " max_request = " << devinfo.un.scdk.max_request
<< " segment_size = " << devinfo.un.scdk.segment_size
<< " segment_count = " << devinfo.un.scdk.segment_count
<< " byte_count = " << devinfo.un.scdk.byte_count;
low = (unsigned int)devinfo.un.scdk.numblks;
rawsize = low * devinfo.un.scdk.blksize;
}
DebugPrintf(SV_LOG_DEBUG, "For device %s, %s\n", sVolume.c_str(), ss.str().c_str());
break;
default: /* unknown */
break;
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "ioctl IOCINFO Failed volumepath: %s, error: %s\n", sRawVolName.c_str(), strerror(errno));
}
(void)close(fd);
}
else
{
DebugPrintf(SV_LOG_ERROR, "open() failed for raw volume %s at line %d in file %s with errno = %d\n", sRawVolName.c_str(),
__LINE__, __FILE__, errno);
}
}
else
{
DebugPrintf(SV_LOG_WARNING, "@LINE %d in FILE %s unable to apply lock\n", __LINE__, __FILE__);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid arguement VolumeName\n",
LINE_NO, FILE_NAME);
}
if( rawsize == 0 )
{
std::list<std::string> vgs ;
std::stringstream stream ;
executePipe("lsvg", stream) ;
std::string lvname = sVolume.substr(sVolume.find_last_of("/")+1) ;
while( stream.good() && !stream.eof() )
{
std::string str ;
stream >> str ;
if( str.empty() )
{
break ;
}
vgs.push_back(str) ;
}
stream.clear() ;
stream.str("") ;
int ppsize ;
std::list<std::string>::iterator begIter = vgs.begin() ;
std::list<std::string>::iterator endIter = vgs.end() ;
while(begIter != endIter )
{
std::string cmd = "lsvg -l " ;
cmd += *begIter ;
cmd += " |grep " ;
cmd += lvname ;
executePipe(cmd, stream) ;
if( stream.str().compare("") != 0 )
{
DebugPrintf(SV_LOG_DEBUG, "lv %s belongs to vg %s\n", lvname.c_str(), begIter->c_str()) ;
break ;
}
begIter++ ;
}
stream.str("") ;
stream.clear() ;
executePipe("lsvg " + *begIter+ " |grep 'PP SIZE:' | awk '{print $6}'", stream) ;
stream >> ppsize ;
stream.clear() ;
stream.str("") ;
executePipe("/usr/sbin/lsvg -l " + *begIter+ "| /usr/bin/grep -v " + *begIter+ " | /usr/bin/grep -v 'LV NAME'" + "| /usr/bin/grep " + lvname , stream) ;
std::string name, lvtype, lvstate, mountPt , lps, pps, pvs ;
stream >> name >> lvtype >> lps >> pps >> pvs >> lvstate >> mountPt ;
rawsize = (long)ppsize * boost::lexical_cast<long>(lps) * 1024 * 1024 ;
}
DebugPrintf(SV_LOG_DEBUG,"EXITED %s with rawsize = " ULLSPEC "\n",FUNCTION_NAME, rawsize);
return rawsize;
}
SVERROR GetFsSectorSize(const char *volName, unsigned int *psectorSize)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s with sVolume = %s\n",FUNCTION_NAME, volName);
SVERROR retStatus = SVS_FALSE;
*psectorSize = 512;
if(volName != NULL)
{
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(g_lockforgetbasicvolinfo);
if(guard.locked())
{
std::string sRawVolName = GetRawVolumeName(volName);
int fd;
fd = open(sRawVolName.c_str(), O_NDELAY | O_RDONLY);
if(fd != -1)
{
struct devinfo devinfo;
if(ioctl(fd, IOCINFO, &devinfo) != -1)
{
switch(devinfo.devtype)
{
case DD_DISK: /* disk */
*psectorSize = (devinfo.flags&DF_LGDSK) ? devinfo.un.dk64.bytpsec : devinfo.un.dk.bytpsec;
break;
case DD_SCDISK: /* scsi disk */
*psectorSize = (devinfo.flags&DF_LGDSK) ? devinfo.un.scdk64.blksize : devinfo.un.scdk.blksize;
break;
default: /* unknown */
break;
}
retStatus = SVS_OK;
}
else
{
DebugPrintf(SV_LOG_ERROR, "ioctl IOCINFO Failed volumepath: %s, error: %s\n", sRawVolName.c_str(), strerror(errno));
}
(void)close(fd);
}
else
{
DebugPrintf(SV_LOG_ERROR, "open() failed for raw volume %s at line %d in file %s with errno = %d\n", sRawVolName.c_str(),
__LINE__, __FILE__, errno);
}
}
else
{
DebugPrintf(SV_LOG_WARNING, "@LINE %d in FILE %s unable to apply lock\n", __LINE__, __FILE__);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid arguement volName = %p\n",
LINE_NO, FILE_NAME, volName);
}
DebugPrintf(SV_LOG_DEBUG,"EXITED %s with sectorsize = %d \n", FUNCTION_NAME, *psectorSize);
return retStatus;
}
bool addFSEntryWithOptions(const std::string& device1, const std::string& label, const std::string& mountpoint1, const std::string& type,
bool readonlyflag,std::vector<std::string>& fsents)
{
bool bRet = true;
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s for device %s\n", FUNCTION_NAME, device1.c_str());
std::string device = device1;
std::string mountPoint = mountpoint1;
removeStringSpaces(device);
removeStringSpaces(mountPoint);
do
{
if(device.empty() || mountPoint.empty())
{
DebugPrintf(SV_LOG_ERROR, "DeviceName and Mount Point Names are empty. %s, %s", device.c_str(), mountPoint.c_str());
bRet = false;
break;
}
std::string realDevice = device;
if(!GetDeviceNameFromSymLink(realDevice))
{
DebugPrintf(SV_LOG_ERROR, "GetDeviceNameFromSymLink Failed for device %s \n. ", realDevice.c_str());
bRet = false;
break;
}
if(!removeFSEntry(device,"",fsents))
{
DebugPrintf(SV_LOG_INFO, "Unable to add FS entry.\n");
bRet = false;
break;
}
std::string lineStr = "\n";
lineStr += mountPoint;
lineStr += ":";
fsents.push_back(lineStr);
lineStr = "\n dev = ";
lineStr += device;
fsents.push_back(lineStr);
lineStr = "\n vfs = ";
lineStr += type;
fsents.push_back(lineStr);
lineStr = " \n log = INLINE";
fsents.push_back(lineStr);
lineStr = "\n mount = true";
fsents.push_back(lineStr);
if(readonlyflag)
lineStr = "\n options = ro";
else
lineStr = "\n options = rw";
fsents.push_back(lineStr);
lineStr = "\n account = false\n";
fsents.push_back(lineStr);
break;
}while(false);
DebugPrintf(SV_LOG_DEBUG, "EXITED %s for device %s\n", FUNCTION_NAME, device1.c_str());
return bRet;
}
bool addRWFSEntry(const std::string& device1, const std::string& label, const std::string& mountpoint1, const std::string& type,
std::vector<std::string>& fsents)
{
return addFSEntryWithOptions(device1,label,mountpoint1,type,false,fsents);
}
bool addROFSEntry(const std::string& device1, const std::string& label, const std::string& mountpoint1, const std::string& type,
std::vector<std::string>& fsents)
{
return addFSEntryWithOptions(device1,label,mountpoint1,type,true,fsents);
}
bool MountVolume(const std::string& device,const std::string& mountPoint,const std::string& fsType,bool bSetReadOnly)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
int exitCode = 0;
std::string errorMsg = "";
bool bmounted = MountDevice(device, mountPoint, fsType, bSetReadOnly, exitCode, errorMsg);
std::string flags = "ro";
if(!bSetReadOnly)
flags="rw ";
std::string filepath;
if (bmounted )
{
bool new_sparsefile_format = false;
bool is_volpack = IsVolPackDevice(device.c_str(),filepath,new_sparsefile_format);
if(!is_volpack)
{
if(AddFSEntry(device.c_str(), mountPoint.c_str(), fsType.c_str(), flags.c_str(), false))
{
DebugPrintf(SV_LOG_DEBUG, "/etc/filesystem was updated successfully. \n");
}
else
{
DebugPrintf(SV_LOG_INFO, "Note: /etc/filesystem was not updated. please update it manually.\n");
}
}
else
{
DebugPrintf(SV_LOG_INFO, "IsVolPackDevice() failed \n");
}
}
else
{
DebugPrintf(SV_LOG_INFO, "MountDevice() failed \n");
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return bmounted;
}
int posix_fadvise_wrapper(ACE_HANDLE fd, SV_ULONGLONG offset, SV_ULONGLONG len, int advice)
{
return 0; //SUCCESS
}
void setdirectmode(unsigned long int &access)
{
access |= O_DIRECT;
}
void setdirectmode(int &mode)
{
mode |= O_DIRECT;
}
bool removeFSEntry(const std::string& device, const std::string& label, std::vector<std::string>& fsents)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bRet = true;
std::string deviceName = device;
std::vector<std::string>::iterator fsents_mntpt_start_iter;
std::vector<std::string>::iterator fsents_iter = fsents.begin();
std::vector<std::string>::iterator fsents_end_iter = fsents.end();
bool found = false;
for(;fsents_iter != fsents_end_iter;++fsents_iter)
{
std::string fsent = *fsents_iter;
removeStringSpaces(fsent);
std::string::size_type index = std::string::npos;
index = fsent.find("=");
/* Mount point found and store in mountpoint iter */
if((!fsent.empty()) && (index == std::string::npos) && (fsent.find_last_of(":") == fsent.size()-1))
{
if(found)
{
break;
}
fsents_mntpt_start_iter = fsents_iter;
}
/* checking for dev entry if the entry their and the value of the entry match with the device
then the device found*/
else if(index != std::string::npos)
{
std::string leftString = fsent.substr(0, index);
std::string rightString = fsent.substr(index+1);
removeStringSpaces(leftString);
removeStringSpaces(rightString);
if((leftString.compare("dev") == 0) && (rightString.compare(deviceName) == 0))
{
found = true;
}
}
}
if(found)
{
fsents.erase(fsents_mntpt_start_iter,fsents_iter);
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return bRet;
}
bool getMountPointName(const std::string& deviceName, std::string& mountPoint, bool bFromFileSytemFile)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bFound = false;
if(bFromFileSytemFile == false)
{
// discover from mount api
std::vector<mount_info> mountinfovector;
if(getMountedInfo(mountinfovector) == SVS_OK)
{
std::string mountpoint = "";
std::vector<mount_info>::iterator mountinfolistbegiter = mountinfovector.begin();
std::vector<mount_info>::iterator mountinfolistienditer = mountinfovector.end();
while(mountinfolistbegiter != mountinfolistienditer)
{
if(mountinfolistbegiter->m_deviceName.compare(deviceName)== 0)
{
mountpoint = mountinfolistbegiter->m_mountedOver;
bFound = true;
break;
}
mountinfolistbegiter++;
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :getMountedInfo failed.\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
}
else
{
// discover from /etc/filesytems file.
CDPLock lock(SV_FSTAB,10);
if(lock.acquire())
{
std::ifstream ifstab(SV_FSTAB, std::ifstream::in);
if(ifstab.is_open())
{
std::string line = "";
std::string currentMountPoint = "";
while(std::getline(ifstab, line))
{
removeStringSpaces(line);
if(line.empty() == false)
{
std::string::size_type index = std::string::npos;
index = line.find("=");
if(index == std::string::npos && line.find_last_of(":") == line.size()-1)
{
currentMountPoint = line;
}
else if(index != std::string::npos)
{
std::string leftString = line.substr(0, index);
removeStringSpaces(leftString);
if(leftString.compare("dev") == 0)
{
std::string rightString = line.substr(index+1);
removeStringSpaces(rightString);
if(rightString.compare(deviceName) == 0)
{
bFound = true;
break;
}
}
}
}
}
if(bFound == true && currentMountPoint.empty() == false)
{
mountPoint = currentMountPoint.substr(0, currentMountPoint.size()-1);
}
ifstab.close();
}
else
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :failed to open %s \n",
FUNCTION_NAME, LINE_NO, FILE_NAME, SV_FSTAB);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :failed to aquire read lock for /etc/filesytems file %s \n",
FUNCTION_NAME, LINE_NO, FILE_NAME, SV_FSTAB);
}
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return bFound;
}
bool GetMountPoints(const char * dev, std::vector<std::string> &mountPoints)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bRet = false;
if(dev != NULL)
{
std::string realdev = dev;
if (GetDeviceNameFromSymLink(realdev))
{
std::string deviceName = dev;
std::vector<mount_info> mountInfoVector;
if(getMountedInfo(mountInfoVector) == SVS_OK)
{
std::vector<mount_info>::iterator mountInfoListBegIter = mountInfoVector.begin();
std::vector<mount_info>::iterator mountInfoListiEndIter = mountInfoVector.end();
while(mountInfoListBegIter != mountInfoListiEndIter)
{
if(mountInfoListBegIter->m_deviceName.compare(deviceName) == 0)
{
mountPoints.push_back(mountInfoListBegIter->m_mountedOver);
break;
}
mountInfoListBegIter++;
}
bRet = true;
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :getMountedInfo failed.\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :GetDeviceNameFromSymLink failed.\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s : invalid arguement dev is NULL\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return bRet;
}
SVERROR getMountedInfo(std::vector<mount_info>& mountInfoVector)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
SVERROR retStatus = SVS_OK;
int num, size;
num = mntctl(MCTL_QUERY, sizeof(size), (char *) &size);
if(num >= 0)
{
INM_SAFE_ARITHMETIC(size *= InmSafeInt<int>::Type(2), INMAGE_EX(size))
/*
* Double the needed size, so that even when the user mounts a
* filesystem between the previous and the next call to mntctl
* the buffer still is large enough.
*/
char * buf;
buf = (char *)alloca(size);
num = mntctl(MCTL_QUERY, size, buf);
if(num >= 0)
{
DebugPrintf(SV_LOG_DEBUG, "No of file systems found %d \n", num);
struct vmount * vm;
int i, dataLength;
char *data;
for (vm = ( struct vmount *)buf, i = 0; i < num; i++)
{
if(vm != NULL)
{
dataLength = vm->vmt_data[VMT_OBJECT].vmt_size;
data = NULL;
size_t dataalloclen;
INM_SAFE_ARITHMETIC(dataalloclen = InmSafeInt<int>::Type(dataLength) + 1, INMAGE_EX(dataLength))
data = (char*)malloc(dataalloclen);
inm_strncpy_s(data, (dataLength + 1), (char *)vm + vm->vmt_data[VMT_OBJECT].vmt_off, dataLength);
mount_info mInfo;
mInfo.m_deviceName = data;
if(data != NULL)
{
free(data);
}
dataLength = vm->vmt_data[VMT_STUB].vmt_size;
INM_SAFE_ARITHMETIC(dataalloclen = InmSafeInt<int>::Type(dataLength) + 1, INMAGE_EX(dataLength))
data = (char*)malloc(dataalloclen);
inm_strncpy_s(data, (dataLength + 1), (char *)vm + vm->vmt_data[VMT_STUB].vmt_off, dataLength);
mInfo.m_mountedOver = data;
if(data != NULL)
{
free(data);
}
dataLength = vm->vmt_data[VMT_ARGS].vmt_size;
INM_SAFE_ARITHMETIC(dataalloclen = InmSafeInt<int>::Type(dataLength) + 1, INMAGE_EX(dataLength))
data = (char*)malloc(dataalloclen);
inm_strncpy_s(data, (dataLength + 1), (char *)vm + vm->vmt_data[VMT_ARGS].vmt_off, dataLength);
mInfo.m_options = data;
if(data != NULL)
{
free(data);
}
mInfo.m_flag = getPermissionType(mInfo.m_options);
dataLength = vm->vmt_data[VMT_HOSTNAME].vmt_size;
INM_SAFE_ARITHMETIC(dataalloclen = InmSafeInt<int>::Type(dataLength) + 1, INMAGE_EX(dataLength))
data = (char*)malloc(dataalloclen);
inm_strncpy_s(data, (dataLength + 1), (char *)vm + vm->vmt_data[VMT_HOSTNAME].vmt_off, dataLength);
mInfo.m_nodeName = data;
if(data != NULL)
{
free(data);
}
mInfo.m_vfs = getFSString(vm->vmt_gfstype);
mountInfoVector.push_back(mInfo);
}
vm = (struct vmount *)((char *)vm + vm->vmt_length);
}
//dumpMountInfo(mountInfoVector); //debugging purpose.
}
else
{
DebugPrintf(SV_LOG_ERROR, "Failed to get the size i. mntctl() failed \n");
retStatus = SVS_FALSE;
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "Failed to get the size. mntctl() failed \n");
retStatus = SVS_FALSE;
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return retStatus;
}
SVERROR MakeReadOnly(const char *drive, void *VolumeGUID, etBitOperation ReadOnlyBitFlag)
{
DebugPrintf("MakeReadOnly (AIX) on %s: not implemented\n", drive);
return SVE_FAIL;
}
SVERROR isReadOnly(const char * drive, bool & bReadOnly)
{
SVERROR retrunStatus = SVS_OK;
if(drive != NULL)
{
VOLUME_STATE volState = GetVolumeState(drive);
if(volState == VOLUME_VISIBLE_RW)
{
bReadOnly = false;
}
else if(volState == VOLUME_VISIBLE_RO)
{
bReadOnly = true;
}
else if(volState == VOLUME_HIDDEN)
{
bReadOnly = false;
}
else
{
DebugPrintf(SV_LOG_ERROR, "UnKnown Volume: %s .\n", drive);
retrunStatus = SVS_FALSE;
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "Empty Drive name passed.\n");
retrunStatus = SVS_FALSE;
}
return retrunStatus;
}
VOLUME_STATE GetVolumeState(const char * drive)
{
DebugPrintf( SV_LOG_DEBUG, "Entered GetVolumeState\n");
// Algorithm:
// Get actual device name.
// Get all current mount points associated with the device.
// If mount points empty, return HIDDEN
// For each mount point...
// Is it mounted read write, return UNHIDDEN_RW
//
// Return UNHIDDEN_RO
//
bool rv = false;
bool mounted = false;
bool rw = false;
VOLUME_STATE vs = VOLUME_UNKNOWN;
std::string realdevname = drive;
std::string devname = drive;
do
{
if(!IsVolpackDriverAvailable())
{
std::string sparsefile;
bool new_sparsefile_format = false;
bool is_volpack = IsVolPackDevice(devname.c_str(),sparsefile,new_sparsefile_format);
if(is_volpack)
{
vs = VOLUME_HIDDEN;
break;
}
}
rv = GetDeviceNameFromSymLink(realdevname);
if(!rv)
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :invalid device name %s\n", FUNCTION_NAME, LINE_NO, FILE_NAME,realdevname.c_str());
vs = VOLUME_UNKNOWN;
break;
}
rv = IsValidDevfile(realdevname);
if(!rv)
{
DebugPrintf(SV_LOG_ERROR, "Function %s @LINE %d in FILE %s :invalid device name %s\n", FUNCTION_NAME, LINE_NO, FILE_NAME,realdevname.c_str());
vs = VOLUME_UNKNOWN;
break;
}
std::vector<mount_info> mountInfoVector;
if(getMountedInfo(mountInfoVector) == SVS_OK)
{
std::vector<mount_info>::iterator mountInfoVectorBegIter = mountInfoVector.begin();
std::vector<mount_info>::iterator mountInfoVectorEndIter = mountInfoVector.end();
while(mountInfoVectorBegIter != mountInfoVectorEndIter)
{
std::string procdevName = mountInfoVectorBegIter->m_deviceName;
std::string realprocdevName = procdevName;
if(GetDeviceNameFromSymLink(realprocdevName) &&
IsValidDevfile(realprocdevName))
{
if(realprocdevName == realdevname)
{
mounted = true;
if( mountInfoVectorBegIter->m_flag == MOUNT_RW ||
mountInfoVectorBegIter->m_flag == MOUNT_RBW ||
mountInfoVectorBegIter->m_flag == MOUNT_RBRW )
{
rw = true;
break;
}
}
}
mountInfoVectorBegIter++;
}
if(mounted)
{
if(rw)
vs = VOLUME_VISIBLE_RW;
else
vs = VOLUME_VISIBLE_RO;
}
else
{
vs = VOLUME_HIDDEN;
}
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :getMountedInfo failed.\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
} while (0);
DebugPrintf( SV_LOG_DEBUG, "Exited GetVolumeState\n");
return vs;
}
bool IsVolumeMounted(const std::string volume,std::string& sMountPoint, std::string &mode)
{
bool bMounted = false;
sMountPoint = "";
if(volume.empty())
{
DebugPrintf(SV_LOG_ERROR,"Null volume name passed.\n");
return false;
}
std::string devName = volume;
std::string realdevName = volume;
std::string proc_fsname = "";
if(GetDeviceNameFromSymLink(realdevName) && IsValidDevfile(realdevName))
{
std::vector<mount_info> mountInfoVector;
if(getMountedInfo(mountInfoVector) == SVS_OK)
{
size_t lenthOfmntdir = 0;
std::vector<mount_info>::iterator mountInfoVectorBegIter = mountInfoVector.begin();
std::vector<mount_info>::iterator mountInfoVectorEndIter = mountInfoVector.end();
while(mountInfoVectorBegIter != mountInfoVectorEndIter)
{
std::string realproc_fsname = mountInfoVectorBegIter->m_deviceName;
if(GetDeviceNameFromSymLink(realproc_fsname) && IsValidDevfile(realdevName))
{
if(realproc_fsname == realdevName)
{
bMounted = true;
sMountPoint = mountInfoVectorBegIter->m_mountedOver;
break;
}
}
mountInfoVectorBegIter++;
}
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :getMountedInfo failed.\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :GetDeviceNameFromSymLink()|IsValidDevfile() failed.\n", FUNCTION_NAME, LINE_NO, FILE_NAME);
}
return bMounted;
}
SVERROR FlushFileSystemBuffers(const char *Volume)
{
std::string volName;
ACE_HANDLE hVolume = ACE_INVALID_HANDLE;
SVERROR sve = SVS_OK;
do
{
SV_UINT flags = 0;
volName = Volume;
flags = O_RDWR | O_SYNC | O_RSYNC ;
hVolume = ACE_OS::open(getLongPathName(volName.c_str()).c_str(), flags, ACE_DEFAULT_OPEN_PERMS);
if(ACE_INVALID_HANDLE == hVolume)
{
sve = ACE_OS::last_error();
DebugPrintf( SV_LOG_ERROR, "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
DebugPrintf( SV_LOG_ERROR, "ACE_OS::open failed in FlushFileSystemBuffers.We still proceed %s, err = %s\n", volName.c_str(), sve.toString());
break;
}
if (ACE_OS::fsync(hVolume) == -1)
{
sve = ACE_OS::last_error();
DebugPrintf(SV_LOG_WARNING, "FlushFileBuffers for Volume %s did not succeed, err = %s\n", volName.c_str(), sve.toString());
}
else
DebugPrintf(SV_LOG_DEBUG, "FlushFileBuffers for Volume %s Succeeded\n", volName.c_str());
ACE_OS::close(hVolume);
} while (FALSE);
return sve;
}
bool GetVolumeRootPath(const std::string & path, std::string & root)
{
bool found = false;
std::vector<mount_info> mountInfoVector;
if(getMountedInfo(mountInfoVector) == SVS_OK)
{
size_t lenthOfmntdir = 0;
std::vector<mount_info>::iterator mountInfoVectorBegIter = mountInfoVector.begin();
std::vector<mount_info>::iterator mountInfoVectorEndIter = mountInfoVector.end();
while(mountInfoVectorBegIter != mountInfoVectorEndIter)
{
lenthOfmntdir = strlen(mountInfoVectorBegIter->m_mountedOver.c_str());
if(!strncmp(mountInfoVectorBegIter->m_mountedOver.c_str(), path.c_str(), lenthOfmntdir)) {
if ( lenthOfmntdir > root.size())
{
root = mountInfoVectorBegIter->m_mountedOver;
found = true;
}
}
mountInfoVectorBegIter++;
}
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :getMountedInfo failed.\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
return found;
}
//
// Function: GetDeviceNameForMountPt
// given a mount point, convert it to corresponding device name
//
bool GetDeviceNameForMountPt(const std::string & mtpt, std::string & devName)
{
bool bRet = false;
std::vector<mount_info> mountInfoVector;
if(getMountedInfo(mountInfoVector) == SVS_OK)
{
std::vector<mount_info>::iterator mountInfoListBegIter = mountInfoVector.begin();
std::vector<mount_info>::iterator mountInfoListiEndIter = mountInfoVector.end();
while(mountInfoListBegIter != mountInfoListiEndIter)
{
if(mountInfoListBegIter->m_mountedOver.compare(mtpt)== 0)
{
devName = mountInfoListBegIter->m_deviceName;
bRet = true;
break;
}
mountInfoListBegIter++;
}
}
else
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :getMountedInfo failed.\n",
FUNCTION_NAME, LINE_NO, FILE_NAME);
}
return bRet;
}
bool mountedvolume( const std::string& pathname, std::string& mountpoints )
{
return false;
}
bool FormVolumeLabel(const std::string device, std::string &label)
{
bool bretval = true;
label = "";
return bretval;
}
std::string GetCommandPath(const std::string &cmd)
{
/* APART FROM COMMON PATHS, WE SHOULD FIND AN EQUIVALENT OF "which" COMMAND */
return "/bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin";
}
bool GetVolSizeWithOpenflag(const std::string vol, const int oflag, SV_ULONGLONG &refvolsize)
{
bool bretval = true;
refvolsize = GetRawVolSize(vol);
if (!refvolsize)
{
DebugPrintf(SV_LOG_ERROR,"@ LINE %d in FILE %s, GetRawVolSize failed for volume %s\n", LINE_NO, FILE_NAME, vol.c_str());
bretval = false;
}
return bretval;
}
void FormatVolumeNameForCxReporting(std::string& volumeName)
{
// we need to strip off any leading \, ., ? if they exists
std::string::size_type idx = volumeName.find_first_not_of("\\.?");
if (std::string::npos != idx){
volumeName.erase(0, idx);
}
// strip off trailing :\ or : if they exist
std::string::size_type len = volumeName.length();
idx = len;
if('\\' == volumeName[len - 1] || ':' == volumeName[len - 1]) {
--idx;
}
if (idx < len){
volumeName.erase(idx);
}
}
bool GetSectorSizeWithFd(int fd, const std::string vol, SV_ULONG &SectorSize)
{
bool bretval = false;
SectorSize = 512;
if (fd <= 0)
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid fd = %d\n", LINE_NO, FILE_NAME, fd);
}
else
{
unsigned int volsectorsize = 0;
if (vol.empty() == false)
{
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(g_lockforgetbasicvolinfo);
if(guard.locked())
{
struct devinfo devinfo;
if (ioctl(fd, IOCINFO, &devinfo) != -1)
{
switch (devinfo.devtype)
{
case DD_DISK: /* disk */
SectorSize = (devinfo.flags&DF_LGDSK) ? devinfo.un.dk64.bytpsec : devinfo.un.dk.bytpsec;
break;
case DD_SCDISK: /* scsi disk */
SectorSize = (devinfo.flags&DF_LGDSK) ? devinfo.un.scdk64.blksize : devinfo.un.scdk.blksize;
break;
default: /* unknown */
break;
}
bretval = true;
}
else
{
DebugPrintf(SV_LOG_ERROR, "ioctl IOCINFO Failed volumepath: %s, error: %s\n", vol.c_str(), strerror(errno));
}
}
else
{
DebugPrintf(SV_LOG_WARNING, "@LINE %d in FILE %s unable to apply lock\n", __LINE__, __FILE__);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid arguement vol = %s\n", LINE_NO, FILE_NAME, vol.c_str());
}
}
return bretval;
}
bool GetNumBlocksWithFd(int fd, const std::string vol, SV_ULONGLONG &NumBlks)
{
bool bretval = false;
SV_ULONGLONG mulfactor;
unsigned int low, high;
if(fd <= 0)
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid fd = %d\n", LINE_NO, FILE_NAME, fd);
}
else
{
if(vol.empty() == false)
{
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(g_lockforgetbasicvolinfo);
if(guard.locked())
{
struct devinfo devinfo;
if (ioctl(fd, IOCINFO, &devinfo) != -1)
{
switch (devinfo.devtype)
{
case DD_DISK: /* disk */
if (devinfo.flags & DF_LGDSK)
{
mulfactor = pow(2, sizeof(devinfo.un.dk64.lo_numblks)*8);
low = (unsigned int)devinfo.un.dk64.lo_numblks;
high = (unsigned int)devinfo.un.dk64.hi_numblks;
NumBlks = ((mulfactor*high) + low);
}
else
{
NumBlks = (unsigned int)devinfo.un.dk.numblks;
}
break;
case DD_SCDISK: /* scsi disk */
if (devinfo.flags & DF_LGDSK)
{
mulfactor = pow(2, sizeof(devinfo.un.scdk64.lo_numblks)*8);
low = (unsigned int)devinfo.un.scdk64.lo_numblks;
high = (unsigned int)devinfo.un.scdk64.hi_numblks;
NumBlks = ((mulfactor*high) + low);
}
else
{
NumBlks = (unsigned int)devinfo.un.scdk.numblks;
}
break;
default: /* unknown */
NumBlks = 0;
break;
}
bretval = true;
}
else
{
DebugPrintf(SV_LOG_ERROR, "ioctl IOCINFO Failed volumepath: %s, error: %s\n", vol.c_str(), strerror(errno));
}
}
else
{
DebugPrintf(SV_LOG_WARNING, "@LINE %d in FILE %s unable to apply lock\n", __LINE__, __FILE__);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, invalid arguement vol = %p\n",
LINE_NO, FILE_NAME, vol.c_str());
}
}
return bretval;
}
bool GetDeviceNameFromSymLink(std::string &deviceName)
{
bool bretval = false;
const std::string saveDeviceName = deviceName;
struct stat64 st_buf;
if (NULL == deviceName.c_str())
{
DebugPrintf(SV_LOG_ERROR, "@ LINE %d in FILE %s, no device name supplied\n", LINE_NO, FILE_NAME);
}
else if(stat64(deviceName.c_str(), &st_buf))
{
DebugPrintf(SV_LOG_WARNING, "@ LINE %d in FILE %s, stat failed on %s with errno = %d\n", LINE_NO, FILE_NAME, deviceName.c_str(), errno);
}
else
{
/**
*
* Commenting below debug printf since it fills in the log file.
* Can be uncommented when needed.
*
*/
/* DebugPrintf(SV_LOG_DEBUG, "ENTERED %s with deviceName = %s\n",FUNCTION_NAME, deviceName.c_str()); */
const char UNIXROOTDIR = '/';
const char UNIXDIRSEPARATOR = '/';
// make sure device is valid
struct stat64 volStat;
// make sure device file exists
if (0 == lstat64(deviceName.c_str(), &volStat))
{
if (S_ISLNK(volStat.st_mode))
{
ssize_t len;
/* Not initialized since terminating finally with \0 */
char symlnk[PATH_MAX + 1];
do
{
len = readlink(deviceName.c_str(), symlnk, sizeof(symlnk) - 1);
if (-1 == len)
{
/* This is the final device. so return true */
if (0 == lstat64(deviceName.c_str(), &volStat))
{
bretval = true;
}
break;
}
symlnk[len] = '\0';
if (UNIXROOTDIR != symlnk[0])
{
/* This is a relative path */
char dirnameofdevice[PATH_MAX + 1] = {'\0'};
SVERROR sv = DirName(deviceName.c_str(), dirnameofdevice);
if (sv.failed())
{
DebugPrintf(SV_LOG_ERROR,"DirName failed @ LINE %d in FILE %s.\n", LINE_NO, FILE_NAME);
break;
}
std::string catenatedlinkname = dirnameofdevice;
catenatedlinkname += UNIXDIRSEPARATOR;
catenatedlinkname += symlnk;
char absolutename[PATH_MAX + 1] = {'\0'};
if (NULL == realpath(catenatedlinkname.c_str(), absolutename))
{
DebugPrintf(SV_LOG_ERROR,"realpath failed @ LINE %d in FILE %s for file %s with errno = %d.\n", LINE_NO, FILE_NAME,
deviceName.c_str(), errno);
break;
}
deviceName = absolutename;
}
else
{
/* symlink is in absolute form */
deviceName = symlnk;
}
} while (true);
}
else
{
/* This is not a link file */
bretval = true;
}
}
} /* else */
if (!bretval)
{
DebugPrintf(SV_LOG_WARNING, "Unable to determine attributes of file %s @LINE %d in FILE %s\n",saveDeviceName.c_str(),
LINE_NO, FILE_NAME);
}
/**
*
* Commenting below debug printf since it fills in the log file.
* Can be uncommented when needed.
*
*/
/* DebugPrintf(SV_LOG_DEBUG,"EXITING %s with deviceName = %s and bretval = %s\n",FUNCTION_NAME, deviceName.c_str(), bretval?"true":"false"); */
return bretval;
}
bool IsReportingRealNameToCx(void)
{
return false;
}
bool GetLinkNameIfRealDeviceName(const std::string sVolName, std::string &sLinkName)
{
bool bretval = false;
sLinkName = sVolName;
//pending ... need to find in aix that whether the link name is sane as volume name.
sLinkName = sVolName ;
return true ;
}
std::string GetRawVolumeName(const std::string &dskname)
{
std::string rdskname = dskname;
boost::algorithm::replace_first(rdskname, "/dev/hdisk", "/dev/rhdisk");
boost::algorithm::replace_first(rdskname, DMPDIR, RDMPDIR);
boost::algorithm::replace_first(rdskname, DSKDIR, RDSKDIR);
return rdskname;
}
bool IsProcessRunning(const std::string &sProcessName)
{
bool rv = false;
const char *procdir = "/proc"; /* standard /proc directory */
psinfo_t info; /* process information structure from /proc */
DIR *dirp;
size_t pdlen;
char psname[PSNAMELEN];
struct dirent *dentp;
int cnt = 0;
do
{
if ((dirp = opendir(procdir)) == NULL)
{
DebugPrintf(SV_LOG_ERROR,"Failed Opening proc directory \n");
rv = false;
break;
}
(void) inm_strcpy_s(psname, ARRAYSIZE(psname), procdir);
pdlen = strlen(psname);
psname[pdlen++] = '/';
/* for each active process --- */
while (dentp = readdir(dirp))
{
int psfd; /* file descriptor for /proc/nnnnn/stat */
if (dentp->d_name[0] == '.') /* skip . and .. */
continue;
(void) inm_strcpy_s(psname + pdlen, (ARRAYSIZE(psname) - pdlen), dentp->d_name);
(void) inm_strcat_s(psname, ARRAYSIZE(psname), "/psinfo");
if ((psfd = open(psname, O_RDONLY)) == -1)
continue;
memset(&info, 0, sizeof info);
ssize_t bytesread = read(psfd, &info, sizeof (info));
(void) close(psfd);
if (bytesread == sizeof(info))
{
if (0 == strcmp(sProcessName.c_str(), info.pr_fname))
{
cnt++;
if (cnt > 1)
{
rv = true;
break;
}
}
}
}
closedir(dirp);
}while(0);
return rv;
}
bool MountDevice(const std::string& device,const std::string& mountPoint,const std::string& fsType, bool bSetReadOnly, int &exitCode,
std::string &errorMsg)
{
bool bRet = true;
do
{
if(mountPoint.empty() || device.empty())
{
std::stringstream strErr;
strErr << "empty mountpoint specified.";
strErr << "cannot mount device " << device << '\n';
DebugPrintf(SV_LOG_ERROR,"%s", strErr.str().c_str());
errorMsg = strErr.str();
bRet = false;
break;
}
std::string sFileSystem = fsType;
if(sFileSystem.empty())
{
std::stringstream strErr;
strErr << "the filesystem supplied to mount is empty.";
strErr << "hence cannot mount device " << device << '\n';
DebugPrintf(SV_LOG_ERROR,"%s", strErr.str().c_str());
errorMsg = strErr.str();
bRet = false;
break;
}
sFileSystem = ToLower(sFileSystem);
if(SVMakeSureDirectoryPathExists(mountPoint.c_str()).failed())
{
std::stringstream strErr;
strErr << "failed to create mount point directory " << mountPoint
<< '\n';
DebugPrintf(SV_LOG_ERROR,"%s", strErr.str().c_str());
errorMsg = strErr.str();
bRet = false;
break;
}
std::string sMount = "";
std::string mode;
std::string flags = "ro";
if(!bSetReadOnly)
{
flags = "rw";
}
if(IsVolumeMounted(device, sMount, mode))
{
flags += ",remount";
}
std::string fsMount;
fsMount = MOUNT_COMMAND;
fsMount += " ";
fsMount += OPTION_TO_SPECIFY_FILESYSTEM;
fsMount += " ";
fsMount += sFileSystem.c_str();
fsMount += " ";
fsMount += "-o ";
fsMount += flags;
fsMount += ",log=INLINE ";
fsMount += " ";
fsMount += device.c_str() ;
fsMount += " ";
fsMount += "\"";
fsMount += mountPoint.c_str() ;
fsMount += "\"";
DebugPrintf(SV_LOG_DEBUG, "@ line %d in file %s the mount command formed is %s\n", LINE_NO, FILE_NAME, fsMount.c_str());
int retires = 0;
std::string fsck_replay;
bool bfsck_replay_done = true;
if(bSetReadOnly)
{
bfsck_replay_done = false;
fsck_replay = FSCK_COMMAND;
fsck_replay += " ";
fsck_replay += FSCK_FS_OPTION ;
fsck_replay += " -y ";
fsck_replay += device.c_str() ;
}
while( retires < RETRIES_FOR_MOUNT)
{
DebugPrintf(SV_LOG_INFO, "executing %s...\n", fsMount.c_str());
if(ExecuteInmCommand(fsMount, errorMsg, exitCode))
{
bRet = true;
break;
}
else
{
bRet = false;
DebugPrintf(SV_LOG_DEBUG, "mount %s with filesystem %s failed on %s with error message = %s. \n", device.c_str(), sFileSystem.c_str(), mountPoint.c_str(), errorMsg.c_str());
if(!bfsck_replay_done)
{
DebugPrintf(SV_LOG_INFO, "executing %s...\n", fsck_replay.c_str());
if(!ExecuteInmCommand(fsck_replay, errorMsg, exitCode))
{
DebugPrintf(SV_LOG_INFO, "%s failed with exit code (%d) error message = %s.\n", fsck_replay.c_str(), exitCode, errorMsg.c_str());
}
bfsck_replay_done = true;
}
}
retires++;
}
} while(false);
return bRet;
}
std::string GetExecdName(void)
{
std::string ExecdName;
psinfo_t info;
memset(&info, 0, sizeof info);
pid_t pid = getpid();
std::stringstream proccessfile;
proccessfile << "/proc/" << pid << "/psinfo";
int psfd;
do
{
if ((psfd = open(proccessfile.str().c_str(), O_RDONLY)) == -1)
break;
if (read(psfd, &info, sizeof (info)) == sizeof (info))
{
ExecdName = info.pr_fname;
}
(void) close(psfd);
}while(false);
return ExecdName;
}
bool IsOpenVzVM(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
bool bisvm = false;
return bisvm;
}
bool IsVMFromCpuInfo(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
bool bisvm = false;
return bisvm;
}
bool IsXenVm(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
bool bisvm = false;
return bisvm;
}
bool IsNativeVm(Pats &pats, std::string &hypervisorname, std::string &hypervisorvers)
{
return false;
}
void GetNicInfos(NicInfos_t & nicInfos)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bretStatus = true;
struct ifconf l_ifc;
struct ifconf *ifc = &l_ifc;
int bsz = sizeof(struct ifreq);
int sd = -1;
int prevsz=bsz;
ifc->ifc_req = NULL;
ifc->ifc_len = bsz;
do
{
ifc->ifc_req = (struct ifreq *)realloc(ifc->ifc_req, bsz);
if(!ifc->ifc_req)
{
DebugPrintf(SV_LOG_ERROR, "Malloc failed :\n");
bretStatus = false;
break;
}
ifc->ifc_len=bsz;
if (-1 != sd)
{
close(sd);
}
sd = socket(PF_INET,SOCK_DGRAM,0);
if(ioctl(sd, SIOCGIFCONF, (caddr_t)ifc)==-1)
{
DebugPrintf(SV_LOG_ERROR, "Error getting size of interface :\n");
bretStatus = false;
break;
}
if(prevsz==ifc->ifc_len)
break;
else
{
INM_SAFE_ARITHMETIC(bsz *= InmSafeInt<int>::Type(2), INMAGE_EX(bsz))
prevsz=(0 == ifc->ifc_len ? bsz : ifc->ifc_len);
}
}while(true);
if(bretStatus == true)
{
ifc->ifc_req=(struct ifreq *)realloc(ifc->ifc_req,prevsz);
bretStatus = FillNicInfos(sd, ifc, sizeof(struct ifreq), nicInfos);
close(sd);
std::string gws = GetDefaultGateways(NSNicInfo::DELIM);
DebugPrintf(SV_LOG_DEBUG, "gateways = %s\n", gws.c_str());
if (!gws.empty())
{
UpdateNicInfoAttr(NSNicInfo::DEFAULT_IP_GATEWAYS, gws, nicInfos);
}
std::string nameservers = GetNameServerAddresses(NSNicInfo::DELIM);
DebugPrintf(SV_LOG_DEBUG, "nameserver ip addresses = %s\n", nameservers.c_str());
if (!nameservers.empty())
{
UpdateNicInfoAttr(NSNicInfo::DNS_SERVER_ADDRESSES, nameservers, nicInfos);
}
}
DebugPrintf( SV_LOG_DEBUG, "EXITING %s\n", FUNCTION_NAME);
}
bool FillNicInfos(const int &sockfd, struct ifconf *pifc, size_t sizeofifreq, NicInfos_t & nicInfos)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bcollect;
bool bretStatus = true;
char *cp, *cplim, addr[INET6_ADDRSTRLEN];
std::set<std::string> dhcpenabledinterfaces;
CollectDhcpEnabledInterfaces(dhcpenabledinterfaces);
DebugPrintf(SV_LOG_DEBUG, "dhcp enabled interaces:\n");
for (std::set<std::string>::const_iterator it = dhcpenabledinterfaces.begin(); it != dhcpenabledinterfaces.end(); it++)
{
DebugPrintf("%s\n", it->c_str());
}
E_INM_TRISTATE e;
struct ifreq *ifr = pifc->ifc_req;
cp = (char *)pifc->ifc_req;
cplim = cp+pifc->ifc_len;
for( ; cp < cplim;cp += (sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr)))
{
ifr = (struct ifreq *)cp;
struct sockaddr *sa;
sa = (struct sockaddr *)&(ifr->ifr_addr);
if(sa->sa_family == AF_INET)
{
inet_ntop(AF_INET,(struct in_addr *)&(((struct sockaddr_in *)sa)->sin_addr),
addr,INET_ADDRSTRLEN);
bcollect = ShouldCollectNicInfo(sockfd, ifr, addr);
if(bcollect)
{
std::string hardwareaddress;
std::string netmask;
GetNetIfParameters(ifr->ifr_name, hardwareaddress, netmask);
if (hardwareaddress.empty())
{
continue;
}
e = (dhcpenabledinterfaces.end() == dhcpenabledinterfaces.find(ifr->ifr_name)) ?
E_INM_TRISTATE_FALSE : E_INM_TRISTATE_TRUE;
InsertNicInfo(nicInfos, ifr->ifr_name, hardwareaddress, addr, netmask, e);
}
else
{
DebugPrintf(SV_LOG_DEBUG, "Not collecting information for nic %s\n", ifr->ifr_name);
}
}
}
DebugPrintf( SV_LOG_DEBUG, "EXITING %s\n", FUNCTION_NAME);
return bretStatus;
}
void CollectDhcpEnabledInterfaces(std::set<std::string> &dhcpenabledinterfaces)
{
const char *file = "/etc/dhcpcd.ini";
std::ifstream in(file);
if (in.is_open())
{
const char COMMENTCHAR = '#';
const char IFTOK[] = "interface";
std::string line;
std::string tok, ifc;
while (!in.eof())
{
line.clear();
tok.clear();
ifc.clear();
std::getline(in, line);
if (!line.empty() && (COMMENTCHAR == line[0]))
{
continue;
}
std::stringstream ss(line);
ss >> tok >> ifc;
if ((tok == IFTOK) && !ifc.empty())
{
dhcpenabledinterfaces.insert(ifc);
}
}
in.close();
}
else
{
DebugPrintf(SV_LOG_DEBUG, "could not open file %s to find dhcp enabled interfaces\n", file);
}
}
void GetNetIfParameters(const std::string &ifrName, std::string& hardwareAddress, std::string &netmask)
{
/* not ioctl to get hardware address */
hardwareAddress = ifrName;
int fd = socket(PF_INET, SOCK_DGRAM, 0);
if (-1 == fd)
{
DebugPrintf(SV_LOG_DEBUG, "For getting hardware address for network interface %s, "
"creating socked failed with error %s\n", ifrName.c_str(),
strerror(errno));
return;
}
struct ifreq ifr;
inm_strncpy_s(ifr.ifr_name, ARRAYSIZE(ifr.ifr_name), ifrName.c_str(), IFNAMSIZ-1);
if (0 == ioctl(fd, SIOCGIFNETMASK, &ifr))
{
char mask[INET_ADDRSTRLEN] = "\0";
struct sockaddr_in *sa = (struct sockaddr_in *)&(ifr.ifr_addr);
const char *prval = inet_ntop(AF_INET, (struct in_addr *)&(((struct sockaddr_in *)sa)->sin_addr), mask, sizeof mask);
if (prval)
{
netmask = mask;
DebugPrintf(SV_LOG_DEBUG, "Interface Name %s subnet mask %s\n", ifrName.c_str(), mask);
}
else
{
DebugPrintf(SV_LOG_DEBUG, "For getting netmask for network interface %s, converting to dotted form failed\n", ifrName.c_str());
}
}
else
{
DebugPrintf(SV_LOG_DEBUG, "For getting netmask for network interface %s, "
"ioctl SIOCGIFNETMASK failed with error: %s\n", ifrName.c_str(),
strerror(errno));
}
close(fd);
}
bool ShouldCollectNicInfo(const int &sockfd, struct ifreq *pifr, const char *ipaddr)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
bool bshouldcollect = false;
int ioctlrval = -1;
ioctlrval = ioctl(sockfd, SIOCGIFFLAGS, pifr);
if (!ioctlrval)
{
if (pifr->ifr_flags & IFF_UP)
{
bshouldcollect = !(pifr->ifr_flags & IFF_LOOPBACK);
}
}
else
{
DebugPrintf(SV_LOG_ERROR, "ioctl SIOCGIFFLAGS failed on interface %s."
" However trying to report IP and Interface name\n", pifr->ifr_name);
bshouldcollect = true;
}
if (bshouldcollect)
{
bshouldcollect = IsValidIP(ipaddr);
}
DebugPrintf( SV_LOG_DEBUG, "EXITING %s\n", FUNCTION_NAME);
return bshouldcollect;
}
SV_ULONGLONG GetTotalFileSystemSpace(const struct statvfs64 &vfs)
{
SV_ULONGLONG space = ((SV_ULONGLONG)vfs.f_blocks) * ((SV_ULONGLONG)vfs.f_frsize);
return space;
}
SV_ULONGLONG GetFreeFileSystemSpace(const struct statvfs64 &vfs)
{
SV_ULONGLONG space = ((SV_ULONGLONG)vfs.f_bavail) * ((SV_ULONGLONG)vfs.f_frsize);
return space;
}
MOUNT_FLAGS getPermissionType( std::string& optionsStr )
{
MOUNT_FLAGS flag = MOUNT_UNKNOWN;
std::string::size_type index = optionsStr.find_first_of(",");
if( index != std::string::npos)
{
std::string permStr = optionsStr.substr(0, index);
if(strcmp(permStr.c_str(), "ro") == 0)
{
flag = MOUNT_RO;
}
else if(strcmp(permStr.c_str(), "rw") == 0)
{
flag = MOUNT_RW;
}
else if(strcmp(permStr.c_str(), "rbr") == 0)
{
flag = MOUNT_RBR;
}
else if(strcmp(permStr.c_str(), "rbw") == 0)
{
flag = MOUNT_RBW;
}
else if(strcmp(permStr.c_str(), "rbrw") == 0)
{
flag = MOUNT_RBRW;
}
}
return flag;
}
void dumpMountInfo(const std::vector<mount_info>& mountInfoList)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
DebugPrintf(" node mounted mounted over vfs date options \n");
DebugPrintf("===================================================================================");
std::vector<mount_info>::const_iterator mountInfoListBegIter = mountInfoList.begin();
std::vector<mount_info>::const_iterator mountInfoListiEndIter = mountInfoList.end();
while(mountInfoListBegIter != mountInfoListiEndIter)
{
DebugPrintf("\n");
DebugPrintf(" Node Name: %s \n Device Name: %s \n Mounted Over: %s \n FS: %s \n Date: %s \n Falg: %d \n Options: %s \n\n", mountInfoListBegIter->m_nodeName.c_str(), mountInfoListBegIter->m_deviceName.c_str(), mountInfoListBegIter->m_mountedOver.c_str(), mountInfoListBegIter->m_vfs.c_str(), mountInfoListBegIter->m_date.c_str(), mountInfoListBegIter->m_flag, mountInfoListBegIter->m_options.c_str());
mountInfoListBegIter++;
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}
std::string getFSString( int code)
{
std::string fsType = "";
switch(code)
{
case 0: fsType = "JFS2";
break;
case 1: fsType = "NAMEFS";
break;
case 2: fsType = "NFS";
break;
case 3: fsType = "JFS";
break;
case 5: fsType = "CDROM";
break;
case 6: fsType = "PROCFS";
break;
case 8: fsType = "USRVFS";
break;
case 16: fsType = "SFS";
break;
case 17: fsType = "CACHEFS";
break;
case 18: fsType = "NFS3";
break;
case 19: fsType = "AUTOFS";
break;
case 20: fsType = "POOLFS";
break;
case 31: fsType = "USRLAST";
break;
case 32: fsType = "VXFS";
break;
case 33: fsType = "VXODM";
break;
case 34: fsType = "UDF";
break;
case 35: fsType = "NFS4";
break;
case 36: fsType = "RFS4";
break;
case 37: fsType = "CIFS";
break;
case 38: fsType = "PMEMFS";
break;
case 39: fsType = "AHAFS";
break;
case 40: fsType = "STNFS";
break;
case 41: fsType = "ASMFS";
break;
case 47: fsType = "AIXLAST";
break;
case -1: fsType = "BADVFS";
break;
}
return fsType;
}
std::string GetCustomizedAttributeValue(const std::string &name, const std::string &attribute, std::string &errmsg)
{
std::string value;
odm_initialize();
struct CuAt stCuAt;
std::string criteria;
criteria = "name = \'";
criteria += name;
criteria += '\'';
criteria += " and attribute = \'";
criteria += attribute;
criteria += '\'';
struct CuAt *ret = (struct CuAt *)odm_get_obj(CuAt_CLASS, (char *)criteria.c_str(), &stCuAt, ODM_FIRST);
if (ret == ( struct CuAt *)-1)
{
std::stringstream ss;
ss << odmerrno;
errmsg = "querying value from odm for name ";
errmsg += name;
errmsg += " and attribute ";
errmsg += attribute;
errmsg += " failed with odm error ";
errmsg += ss.str();
}
else if (ret == 0)
{
errmsg = std::string("value does not exist in odm for name ") + name + " and attribute " + attribute;
}
else
{
value = stCuAt.value;
}
odm_terminate();
return value;
}
std::string GetCustomizedDeviceParent(const std::string &device, std::string &errmsg)
{
std::string parent;
odm_initialize();
struct CuDv stCuDv;
std::string criteria;
criteria = "name = \'";
criteria += device;
criteria += '\'';
struct CuDv *ret = (struct CuDv *)odm_get_obj(CuDv_CLASS, (char *)criteria.c_str(), &stCuDv, ODM_FIRST);
if (ret == ( struct CuDv *)-1)
{
std::stringstream ss;
ss << odmerrno;
errmsg = "querying parent from odm for ";
errmsg += device;
errmsg += " failed with odm error ";
errmsg += ss.str();
}
else if (ret == 0)
{
errmsg = std::string("parent does not exist in odm for ") + device;
}
else
{
parent = stCuDv.parent;
}
odm_terminate();
return parent;
}
/*
INPUT: pvname
OUTPUT: vgname and the return value indicate whether the vgexist or not
Description:
executing lspv <pvname>
-bash-4.2# lspv cli10in
PHYSICAL VOLUME: cli10in VOLUME GROUP: vg1
PV IDENTIFIER: 000d772cf1c91f57 VG IDENTIFIER 000d772c00004c0000000136f1c94160
PV STATE: active
STALE PARTITIONS: 0 ALLOCATABLE: yes
PP SIZE: 8 megabyte(s) LOGICAL VOLUMES: 2
TOTAL PPs: 524 (4192 megabytes) VG DESCRIPTORS: 2
FREE PPs: 137 (1096 megabytes) HOT SPARE: no
USED PPs: 387 (3096 megabytes) MAX REQUEST: 256 kilobytes
FREE DISTRIBUTION: 105..00..00..00..32
USED DISTRIBUTION: 00..105..104..105..73
*/
bool GetVgNameForPvIfExist(const std::string & pvname,std::string & vgname)
{
bool rv = true;
vgname.clear();
do
{
std::string volstr("VOLUME");
std::string grpstr("GROUP:");
std::string vgcmdforpv = LISTALLPVSCMD;
vgcmdforpv += pvname;
vgcmdforpv += " 2>/dev/null";
std::stringstream pvinfo;
if(!executePipe(vgcmdforpv.c_str(),pvinfo))
{
rv = false;
break;
}
if(!pvinfo.good() || pvinfo.eof())
{
rv = false;
break;
}
std::string str1,str2,str3,str4,str5,str6;
std::string line;
std::getline(pvinfo,line);
if(line.empty())
{
rv = false;
break;
}
std::stringstream linestream(line) ;
linestream >> str1 >> str2 >> str3 >> str4 >> str5 >> str6;
if((str4 == volstr) && (str5 == grpstr))
{
vgname = str6;
}
else
{
rv = false;
break;
}
if(vgname.empty())
{
rv = false;
break;
}
}while(false);
return rv;
}
/*
INPUT: vgname
OUTPUT: list of lvs
Description:
Getting all the lv for the vg by executing "lsvg -l <vgname>"
-bash-4.2# lsvg -l mytest
mytest:
LV NAME TYPE LPs PPs PVs LV STATE MOUNT POINT
fsoratgtLV1 jfs2 386 386 1 closed/syncd /fs/home/tgtmount1
fsoratgtlogLV1 jfs2log 1 1 1 closed/syncd N/A
-bash-4.2#
*/
bool GetAllLvsForVg(const std::string & vgname,std::vector<std::string> & lvs)
{
bool rv = true;
do
{
std::stringstream lvlist;
std::string lvcmd = LISTLVSFROMVGCMD;
lvcmd += vgname;
lvcmd += " 2>/dev/null";
if(!executePipe(lvcmd.c_str(),lvlist))
{
rv = false;
break;
}
int linecnt = 0;
while(!lvlist.eof() )
{
std::string line;
std::getline(lvlist, line);
++linecnt;
if(linecnt > 2)
{
if(line.empty())
break;
std::stringstream linestream(line) ;
std::string str ;
linestream >> str ;
if( str.empty() )
{
break ;
}
lvs.push_back(str);
}
}
}while(false);
return rv;
}
/*
INPUT: list of lvs
Description:
Calling hide drive for each of the lvs in the list
*/
bool HideAllLvs(std::vector<std::string> & lvs,std::string& output, std::string& error)
{
bool rv = true;
std::vector<std::string>::iterator lviter = lvs.begin();
for(;lviter != lvs.end(); ++lviter)
{
std::string lvname = AIX_DEVICE_DIR;
lvname += (*lviter);
if(HideDrive(lvname.c_str(),"",output,error,false).failed())
{
rv = false;
break;
}
}
return rv;
}
/*
INPUT: Device
Description:
get the vgname
get all lvs to the vgname
unmount all lvs
deactivate the vg
export the vg
*/
bool RemoveVgWithAllLvsForVsnap(const std::string & device,std::string& output, std::string& error,bool needvgcleanup)
{
bool rv = true;
std::string pvname = basename_r(device.c_str());
do
{
std::string vgname;
std::vector<std::string> lvs;
if(!GetVgNameForPvIfExist(pvname,vgname))
{
break;
}
if(!GetAllLvsForVg(vgname,lvs))
{
rv = false;
error = "Unable to get the logivcal volume information for the volume group ";
error += vgname;
error += "\n";
break;
}
if(!HideAllLvs(lvs,output,error))
{
rv = false;
break;
}
DebugPrintf(SV_LOG_INFO,"Deactivating the VG %s\n",vgname.c_str());
std::stringstream result;
std::string command = DEACTIVATEVGCMD;
command += vgname;
if(!executePipe(command.c_str(),result))
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :failed to remove VG %s\n",
FUNCTION_NAME, LINE_NO, FILE_NAME,vgname.c_str());
error = "Failed to execute the command ";
error += command;
error += command;
rv = false;
break;
}
if(needvgcleanup)
{
DebugPrintf(SV_LOG_INFO,"Exporting the VG %s\n",vgname.c_str());
command = CLEANUPVGANDLVSCMD;
command += vgname;
if(!executePipe(command.c_str(),result))
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :failed to export VG %s\n",
FUNCTION_NAME, LINE_NO, FILE_NAME,vgname.c_str());
error = "Failed to execute the command ";
error += command;
rv = false;
break;
}
}
}while(false);
return rv;
}
/*
INPUT: Devicename
Description: This function will delete the stalevg for the vsnap
and recreate the vg in case vsnap remount
-bash-4.2# /usr/sbin/lqueryvg -tAp cli10in
Max LVs: 256
PP Size: 23
Free PPs: 137
LV count: 2
PV count: 1
Total VGDAs: 2
Conc Allowed: 0
MAX PPs per PV 1016
MAX PVs: 32
Conc Autovaryo 0
Varied on Conc 0
Logical: 000d772c00004c0000000136f1c94160.1 fsoratgtLV1 1
000d772c00004c0000000136f1c94160.2 fsoratgtlogLV1 1
Physical: 000d772cf1c91f57 2 0
Total PPs: 524
LTG size: 128
HOT SPARE: 0
AUTO SYNC: 0
VG PERMISSION: 0
SNAPSHOT VG: 0
IS_PRIMARY VG: 0
PSNFSTPP: 4352
VARYON MODE: 0
VG Type: 0
Max PPs: 32512
-bash-4.2# /usr/sbin/getlvodm -t 000d772c00004c0000000136f1c94160
vg1
-bash-4.2#
*/
bool CleanStaleVgAndRecreateVgForVsnapOnReboot(const std::string & devname)
{
bool rv = true;
std::string pvname = basename_r(devname.c_str());
do
{
std::string cmd = QUERYVGFROMPVCMD;
cmd += pvname;
cmd += " 2>/dev/null | grep '^Logical:' ";
std::stringstream out;
if(!executePipe(cmd.c_str(),out))
{
break;
}
std::string tag, id, lv,value;
if(out.good() && !out.eof())
{
out >> tag >> id >> lv >> value;
}
if(tag.empty() || id.empty())
{
break;
}
if(tag != "Logical:")
{
break;
}
std::string::size_type idx = id.rfind(".");
id.erase(idx,id.length());
cmd = VGNAMEFROMVGIDCMD;
cmd += id;
cmd += " 2>/dev/null";
std::string vgname;
out.str("");
if(!executePipe(cmd.c_str(),out))
{
break;
}
if(out.good() && !out.eof())
{
out >> vgname;
}
if(vgname.empty())
{
break;
}
out.str("");
cmd = DEACTIVATEVGCMD;
cmd += vgname;
executePipe(cmd.c_str(),out);
cmd = CLEANUPVGANDLVSCMD;
cmd += vgname;
executePipe(cmd.c_str(),out);
out.str("");
cmd = RECREATEVGCMD;
cmd += vgname;
cmd += " ";
cmd += " -Y NA -L / ";
cmd += pvname;
if(!executePipe(cmd.c_str(),out))
{
DebugPrintf(SV_LOG_ERROR,
"Function %s @LINE %d in FILE %s :failed to execute %s\n",
FUNCTION_NAME, LINE_NO, FILE_NAME,cmd.c_str());
rv = false;
break;
}
}while(false);
return rv;
}