std::map DiskDependDefault::GetPhysicalDevices()

in source/code/scxsystemlib/disk/diskdepend.cpp [936:1110]


    std::map<std::wstring, std::wstring> DiskDependDefault::GetPhysicalDevices(const std::wstring& device)
    {
        std::map<std::wstring, std::wstring> devices;

        SCXCoreLib::SCXFilePath path(device);
        std::wstring name = path.GetFilename();
#if defined(aix)
        // Since we do not have the associaction between logical and physical disks - return them all
        perfstat_id_t id;
        perfstat_disk_t data;
        strcpy(id.name, FIRST_DISKPATH);
        do {
            int r = perfstat_disk(&id, &data, sizeof(data), 1);
            if (1 == r && 0 != strncmp(data.name, "cd", 2)) // TODO: better way to exclude CD/DVD!
            {
                name = SCXCoreLib::StrFromUTF8(data.name);

                devices[name] = L"/dev/" + name;
            }
            // TODO: Error handling?
        } while (0 != strcmp(id.name, FIRST_DISKPATH));
#elif defined(hpux)
        size_t vg_idx;
        for (vg_idx = 0; vg_idx < GetLVMTab().GetVGCount(); ++vg_idx)
        {
            // Stored name is without trailing slash.
            if (SCXCoreLib::StrAppend(GetLVMTab().GetVG(vg_idx),L"/") == path.GetDirectory())
            {
                for (size_t pidx = 0; pidx < GetLVMTab().GetPartCount(vg_idx); ++pidx)
                {
                    path.Set(GetLVMTab().GetPart(vg_idx, pidx));
                    name = path.GetFilename();
                    if (0 == SCXCoreLib::StrCompare(name.substr(0,4),L"disk",true))
                    { // New style: disk1_p2 (or just disk3)
                        name = name.substr(0, name.find_last_of(L"_"));
                    }
                    else
                    { // "sun" style: c1t2d3s4
                        if (name.substr(name.find_last_not_of(L"0123456789"),1) == L"s")
                        { // Remove partition identifier
                            name = name.substr(0,name.find_last_not_of(L"0123456789"));
                        }
                    }
                    path.SetFilename(name);
                    // Bug 6755 & 6883: partial discoveries of disks.
                    // Using algorithm from static PAL for exclusion.
                    std::wstring rawDevice = path.Get();
                    if (std::wstring::npos != rawDevice.find(L"/dsk/"))
                    {
                        rawDevice = SCXCoreLib::StrAppend(L"/dev/rdsk/", path.GetFilename());
                    }
                    else
                    {
                        rawDevice = SCXCoreLib::StrAppend(L"/dev/rdisk/", path.GetFilename());
                    }
                    if (this->open(SCXCoreLib::StrToUTF8(rawDevice).c_str(), O_RDONLY))
                    {
                        devices[name] = path.Get();
                        this->close();
                    }
                }
                break;
            }
        }
#elif defined(linux)
        // Given a device path to a partition (for example /dev/hda5 or /dev/cciss/c0d0p1), convert
        // it to a path to the base device (for example /dev/hda or /dev/cciss/c0d0).

        try
        {
            static SCXLVMUtils lvmUtils;

            // Try to convert the potential LVM device path into its matching
            // device mapper (dm) device path.
            std::wstring dmDevice = lvmUtils.GetDMDevice(device);
            if (dmDevice.empty())
            {
                // device is a normal partition device path
                path = GuessPhysicalFromLogicalDevice(device);
                name = path.GetFilename();
                devices[name] = path.Get();
            }
            else
            {
                // device was an LVM device path and dmDevice is the path to
                // the same device using the device mapper name.  The dm device
                // is located on one or more normal devices, known as slaves.
                std::vector< std::wstring > slaves = lvmUtils.GetDMSlaves(dmDevice);
                if (slaves.size() == 0)
                {
                    // this condition can only be reached on RHEL4/SLES9 systems
                    std::wstringstream               out;
                    static SCXCoreLib::LogSuppressor suppressor(SCXCoreLib::eInfo, SCXCoreLib::eHysterical);

                    out << L"Because of limited support for LVM on "
#   if defined(PF_DISTRO_SUSE)
                        << L"SuSE Linux Enterprise Server 9"
#   else
                        << L"Red Hat Enterprise Linux 4"
#   endif
                        << L", the logical device " << device << L": cannot be mapped to the physical device(s) that contain it.";
                    SCX_LOG(m_log, suppressor.GetSeverity(device), out.str());
                }
                else
                {
                    for (std::vector< std::wstring >::const_iterator iter = slaves.begin();
                         iter != slaves.end(); iter++)
                    {
                        if ((*iter).empty() || !isdigit((int)(*iter)[(*iter).size() - 1]))
                        {
                            path = *iter;
                        }
                        else
                        {
                            path = GuessPhysicalFromLogicalDevice(*iter);
                        }
                        name = path.GetFilename();
                        
                        devices[name] = path.Get();
                    }
                }
            }
        }
        catch (SCXCoreLib::SCXException& e)
        {
            static SCXCoreLib::LogSuppressor suppressor(SCXCoreLib::eError, SCXCoreLib::eTrace);
            std::wstringstream               out;

            out << L"An exception occurred resolving the physical devices that contain the LVM device " << device << L": " << e.What();
            SCX_LOG(m_log, suppressor.GetSeverity(out.str()), out.str());
        }
#elif defined(sun)
        std::vector<std::wstring> devs;

        if (device.find(L"/md/") != std::wstring::npos)
        {
            // meta devices can be built from multiple normal devices
            if (0 == m_pRaid)
            {
                SCXCoreLib::SCXHandle<SCXSystemLib::SCXRaidCfgParser> raidCfgParser( new SCXSystemLib::SCXRaidCfgParserDefault() );
                m_pRaid = new SCXRaid(raidCfgParser);
            }

            m_pRaid->GetDevices(name, devs);

            // rewrite the path for mapping physical devices kstat module, instance and name
            path.SetDirectory(L"/dev/dsk/");
        }
        else
        {
            // normal device
            devs.push_back(name);
        }

        for (std::vector<std::wstring>::const_iterator it = devs.begin(); it != devs.end(); ++it)
        {
            name = it->substr(0,it->find_last_not_of(L"0123456789"));

            std::wstring dev = SCXCoreLib::StrAppend(L"/dev/dsk/", *it);

            try
            {
                if (IsDiskInKstat(path.GetDirectory() + L"/" + name))
                {
                    devices[name] = dev.substr(0,dev.find_last_not_of(L"0123456789"));
                }
            }
            catch (SCXCoreLib::SCXException& )
            {

            }
        }
#endif
        return devices;
    }