/* * Copyright (c) 2015 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 * */ /** * @file * Wind River CGTS Platform Host Base Class Member Implementation. */ #include #include #include #include #include /* for ENODEV, EFAULT and ENXIO */ #include /* for close and usleep */ using namespace std; #ifdef __AREA__ #undef __AREA__ #define __AREA__ "~~~" #endif #include "nodeBase.h" #include "hostClass.h" #include "nodeUtil.h" hostBaseClass::hostBaseClass() /* constructor */ { for(unsigned int i = 0; i < MAX_HOSTS; ++i) { host_ptrs[i] = NULL; } bm_provisioned= false; head = tail = NULL; memory_allocs = 0 ; memory_used = 0 ; hosts = 0 ; service = 0 ; /* Start with null identity */ my_hostname.clear() ; my_local_ip.clear() ; my_float_ip.clear() ; } hostBaseClass::~hostBaseClass() /* destructor */ { host * ptr = head ; host * temp_ptr = ptr ; while ( ptr != NULL ) { temp_ptr = ptr ; ptr = ptr->next ; delHost (temp_ptr); } if ( memory_used != 0 ) { elog ( "Apparent Memory Leak - Allocs:%d and Bytes:%d\n", memory_allocs, memory_used ); } else { dlog ( "No Memory Leaks\n\n"); } } /* * Allocates memory for a new host and stores its the address in host_ptrs * * @param void * @return pointer to the newly allocted host memory */ struct hostBaseClass::host * hostBaseClass::newHost ( void ) { struct hostBaseClass::host * host_ptr = NULL ; if ( memory_allocs == 0 ) { memset ( host_ptrs, 0 , sizeof(struct host *)*MAX_HOSTS); } // find an empty spot for ( int i = 0 ; i < MAX_HOSTS ; i++ ) { if ( host_ptrs[i] == NULL ) { host_ptrs[i] = host_ptr = new host ; memory_allocs++ ; memory_used += sizeof (struct hostBaseClass::host); // ilog ("%p:%p - mem after new: allocs:%d used:%d\n", host_ptr , host_ptrs[i], memory_allocs, memory_used); return host_ptr ; } } elog ( "Failed to save new host pointer address\n" ); return host_ptr ; } /* Frees the memory of a pre-allocated host and removes * it from the host_ptrs list * @param host * pointer to the host memory address to be freed * @return int return code { PASS or -EINVAL } */ int hostBaseClass::delHost ( struct hostBaseClass::host * host_ptr ) { if ( memory_allocs > 0 ) { for ( int i = 0 ; i < MAX_NODES ; i++ ) { if ( host_ptrs[i] == host_ptr ) { // ilog ("%p:%p - mem before del: allocs:%d used:%d\n", host_ptr , host_ptrs[i], memory_allocs, memory_used); delete host_ptr ; host_ptrs[i] = NULL ; memory_allocs-- ; memory_used -= sizeof (struct hostBaseClass::host); return PASS ; } } elog ( "Error: Unable to validate memory address being freed\n" ); } else elog ( "Error: Free memory called when there is no memory to free\n" ); return -EINVAL ; } /* * Allocate new host and tack it on the end of the host_list */ struct hostBaseClass::host* hostBaseClass::addHost( string hostname ) { /* verify host is not already provisioned */ struct host * ptr = getHost ( hostname ); if ( ptr ) { if ( remHost ( hostname ) ) { /* Should never get here but if we do then */ /* something is seriously wrong */ elog ("Error: Unable to remove host during reprovision\n"); return static_cast(NULL); } } /* allocate memory for new host */ ptr = newHost (); if( ptr == NULL ) { elog ( "Error: Failed to allocate memory for new host\n" ); return static_cast(NULL); } /* Init the new host */ ptr->hostname = hostname ; /* If the host list is empty add it to the head */ if( head == NULL ) { head = ptr ; tail = ptr ; ptr->prev = NULL ; ptr->next = NULL ; } else { /* link the new_host to the tail of the host_list * then mark the next field as the end of the host_list * adjust tail to point to the last host */ tail->next = ptr ; ptr->prev = tail ; ptr->next = NULL ; tail = ptr ; } hosts++ ; return ptr ; } struct hostBaseClass::host* hostBaseClass::getHost ( string hostname ) { /* check for empty list condition */ if ( head == NULL ) return NULL ; for ( struct host * ptr = head ; ; ptr = ptr->next ) { if ( !hostname.compare ( ptr->hostname )) { // ilog ("%s %p\n", hostname.c_str(), ptr ); return ptr ; } else if ( !hostname.compare ( ptr->uuid )) { // ilog ("%s %p\n", hostname.c_str(), ptr ); return ptr ; } if (( ptr->next == NULL ) || ( ptr == tail )) break ; } return static_cast(NULL); } /* Remove a hist from the linked list of hosts - may require splice action */ int hostBaseClass::remHost( string hostname ) { if ( hostname.c_str() == NULL ) return -ENODEV ; if ( head == NULL ) return -ENXIO ; struct host * ptr = getHost ( hostname ); if ( ptr == NULL ) return -EFAULT ; /* If the host is the head host */ if ( ptr == head ) { /* only one host in the list case */ if ( head == tail ) { dlog ("Single Host -> Head Case\n"); head = NULL ; tail = NULL ; } else { dlog ("Multiple Hosts -> Head Case\n"); head = head->next ; head->prev = NULL ; } } /* if not head but tail then there must be more than one * host in the list so go ahead and chop the tail. */ else if ( ptr == tail ) { dlog ("Multiple Host -> Tail Case\n"); tail = tail->prev ; tail->next = NULL ; } else { dlog ("Multiple Host -> Full Splice Out\n"); ptr->prev->next = ptr->next ; ptr->next->prev = ptr->prev ; } delHost ( ptr ); hosts-- ; return (PASS) ; } /****************************************************************************************** ****************************************************************************************** *****************************************************************************************/ int hostBaseClass::add_host ( node_inv_type & inv ) { int rc = FAIL ; struct hostBaseClass::host * host_ptr = static_cast(NULL); if (( inv.name.empty()) || ( !inv.name.compare ("none")) || ( !inv.name.compare ("None"))) { wlog ("Refusing to add host with 'null' or 'invalid' hostname (%s)\n", inv.uuid.c_str()); return (FAIL_INVALID_HOSTNAME) ; } host_ptr = hostBaseClass::getHost(inv.name); if ( host_ptr ) { dlog ("%s Already provisioned\n", host_ptr->hostname.c_str()); /* Send back a retry in case the add needs to be converted to a modify */ return (RETRY); } /* Otherwise add it as a new host */ else { if ( daemon_get_cfg_ptr()->debug_level > 1 ) print_inv ( inv ); host_ptr = hostBaseClass::addHost(inv.name); if ( host_ptr ) { host_ptr->ip = inv.ip ; host_ptr->mac = inv.mac ; host_ptr->uuid = inv.uuid ; host_ptr->type = inv.type ; host_ptr->nodetype = CGTS_NODE_NULL ; host_ptr->retries = 0 ; host_ptr->toggle = false ; /* Add to the end of inventory */ hostlist.push_back ( host_ptr->hostname ); dlog ("%s Added Host Base\n", inv.name.c_str()); rc = PASS ; } else { elog ("%s Host Base Add Failed\n", inv.name.c_str()); rc = FAIL_NULL_POINTER ; } } return (rc); } int hostBaseClass::rem_host ( string hostname ) { int rc = FAIL ; if ( ! hostname.empty() ) { hostlist.remove ( hostname ); rc = hostBaseClass::remHost ( hostname ); } return ( rc ); } int hostBaseClass::del_host ( string hostname ) { int rc = FAIL_DEL_UNKNOWN ; hostBaseClass::host * host_ptr = hostBaseClass::getHost( hostname ); if ( host_ptr ) { rc = rem_host ( host_ptr->hostname ); if ( rc == PASS ) { dlog ("%s Deleted\n", host_ptr->hostname.c_str()); print_node_info(); } else { elog ("%s Delete Failed (rc:%d)\n", hostname.c_str(), rc ); } } else { wlog ("Unknown hostname: %s\n", hostname.c_str()); } return (rc); } /** Get this hosts uuid address */ string hostBaseClass::get_uuid ( string hostname ) { hostBaseClass::host * host_ptr ; host_ptr = hostBaseClass::getHost ( hostname ); if ( host_ptr != NULL ) { return (host_ptr->uuid ); } elog ("%s uuid lookup failed\n", hostname.c_str() ); return (""); } /** Get this hosts uuid address */ string hostBaseClass::get_hostname ( string uuid ) { hostBaseClass::host * host_ptr ; host_ptr = hostBaseClass::getHost ( uuid ); if ( host_ptr != NULL ) { return (host_ptr->hostname ); } elog ("%s hostname lookup failed\n", uuid.c_str() ); return (""); } /** Get this hosts ip address */ string hostBaseClass::get_ip ( string hostname ) { hostBaseClass::host * host_ptr ; host_ptr = hostBaseClass::getHost ( hostname ); if ( host_ptr != NULL ) { return (host_ptr->ip ); } elog ("%s ip lookup failed\n", hostname.c_str() ); return (""); } static string null_str = "" ; string hostBaseClass::get_hostaddr ( string hostname ) { hostBaseClass::host* host_ptr ; host_ptr = hostBaseClass::getHost ( hostname ); if ( host_ptr != NULL ) { return ( host_ptr->ip ); } return ( null_str ); } void hostBaseClass::print_node_info ( void ) { fflush (stdout); fflush (stderr); } void hostBaseClass::memLogDelimit ( void ) { char str[MAX_MEM_LOG_DATA] ; snprintf (&str[0], MAX_MEM_LOG_DATA, "-------------------------------------------------------------\n"); mem_log (str); } void hostBaseClass::mem_log_host ( struct hostBaseClass::host * host_ptr ) { char str[MAX_MEM_LOG_DATA] ; snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\t%s - %s - %s - %s\n", host_ptr->hostname.c_str(), host_ptr->ip.c_str(), host_ptr->mac.c_str(), host_ptr->uuid.c_str(), host_ptr->type.c_str()); mem_log (str); } void hostBaseClass::memDumpNodeState ( string hostname ) { hostBaseClass::host* host_ptr ; host_ptr = hostBaseClass::getHost ( hostname ); if ( host_ptr == NULL ) { mem_log ( hostname, ": ", "Not Found hostBaseClass\n" ); return ; } else { mem_log_host ( host_ptr ); // memLogDelimit (); } }