int RegisterHost()

in host/common/portablehelpers.cpp [1317:1647]


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;
}