LCOV - code coverage report
Current view: top level - ifmap/client - config_json_parser.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 186 254 73.2 %
Date: 2026-11-09 02:10:49 Functions: 20 25 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "config_json_parser.h"
       7             : 
       8             : #include <boost/lexical_cast.hpp>
       9             : #include <sandesh/request_pipeline.h>
      10             : #include <string>
      11             : 
      12             : #include "config-client-mgr/config_client_manager.h"
      13             : #include "ifmap/ifmap_log.h"
      14             : #include "ifmap/ifmap_log_types.h"
      15             : #include "ifmap/ifmap_sandesh_context.h"
      16             : #include "ifmap/ifmap_server_show_types.h"
      17             : #include "base/autogen_util.h"
      18             : #include "schema/bgp_schema_types.h"
      19             : #include "schema/vnc_cfg_types.h"
      20             : #include "config-client-mgr/config_client_show_types.h"
      21             : #include "config-client-mgr/config_client_log_types.h"
      22             : #include "config-client-mgr/config_cass2json_adapter.h"
      23             : #include "config-client-mgr/config_amqp_client.h"
      24             : #include "config-client-mgr/config_db_client.h"
      25             : 
      26             : using contrail_rapidjson::Value;
      27             : using std::cout;
      28             : using std::endl;
      29             : using std::string;
      30             : 
      31             : #define CONFIG_PARSE_ASSERT(t, condition, key, value)                          \
      32             :     do {                                                                       \
      33             :         if (condition)                                                         \
      34             :             break;                                                             \
      35             :         IFMAP_WARN_LOG(ConfigurationMalformed ## t ## Warning ## Log,          \
      36             :                        Category::IFMAP, key, value, adapter.type(),            \
      37             :                        adapter.uuid());                                        \
      38             :         IFMAP_TRACE(ConfigurationMalformed ## t ## Warning ## Trace,           \
      39             :                     key, value, adapter.type(), adapter.uuid());               \
      40             :         if (ConfigCass2JsonAdapter::assert_on_parse_error())                   \
      41             :             assert(false);                                                     \
      42             :         return false;                                                          \
      43             :     } while (false)
      44             : 
      45         161 : ConfigJsonParser::ConfigJsonParser() {
      46         161 : }
      47             : 
      48         322 : ConfigJsonParser::~ConfigJsonParser() {
      49         322 : }
      50             : 
      51         161 : void ConfigJsonParser::SetupObjectFilter() {
      52         161 :     ObjectTypeList FilterList;
      53         161 :     bgp_schema_Server_GenerateObjectTypeList(&FilterList);
      54         161 :     vnc_cfg_Server_GenerateObjectTypeList(&FilterList);
      55         161 :     for (ObjectTypeList::iterator it = FilterList.begin();
      56       19159 :         it != FilterList.end(); it++) {
      57       18998 :         AddObjectType(*it);
      58             :     }
      59         161 : }
      60             : 
      61         161 : void ConfigJsonParser::SetupSchemaGraphFilter(){
      62         161 :     vnc_cfg_FilterInfo vnc_filter_info;
      63         161 :     bgp_schema_FilterInfo bgp_schema_filter_info;
      64             : 
      65         161 :     bgp_schema_Server_GenerateGraphFilter(&bgp_schema_filter_info);
      66         161 :     vnc_cfg_Server_GenerateGraphFilter(&vnc_filter_info);
      67             : 
      68         161 :     for (vnc_cfg_FilterInfo::iterator it = vnc_filter_info.begin();
      69       62307 :          it != vnc_filter_info.end(); it++) {
      70       62146 :         if (it->is_ref_) {
      71       43470 :             AddLinkName(make_pair(it->left_, it->right_),
      72       86940 :                             make_pair(it->metadata_, it->linkattr_));
      73             :         } else {
      74       18676 :             AddParentName(make_pair(it->left_, it->right_),
      75       18676 :                                               it->metadata_);
      76             :         }
      77             :     }
      78             : 
      79         161 :     for (bgp_schema_FilterInfo::iterator it = bgp_schema_filter_info.begin();
      80        1932 :          it != bgp_schema_filter_info.end(); it++) {
      81        1771 :         if (it->is_ref_) {
      82        1288 :             AddLinkName(make_pair(it->left_, it->right_),
      83        2576 :                              make_pair(it->metadata_, it->linkattr_));
      84             :         } else {
      85         483 :             AddParentName(make_pair(it->left_, it->right_),
      86         483 :                                               it->metadata_);
      87             :         }
      88             :     }
      89         161 : }
      90             : 
      91         161 : void ConfigJsonParser::SetupSchemaWrapperPropertyInfo() {
      92         161 :     WrapperFieldMap wrapper_field_map;
      93         161 :     bgp_schema_Server_GenerateWrapperPropertyInfo(&wrapper_field_map);
      94         161 :     vnc_cfg_Server_GenerateWrapperPropertyInfo(&wrapper_field_map);
      95         161 :     for (WrapperFieldMap::iterator it = wrapper_field_map.begin();
      96       23023 :         it != wrapper_field_map.end(); it++) {
      97       22862 :         AddWrapperField(it->first, it->second);
      98             :     }
      99         161 : }
     100             : 
     101         161 : void ConfigJsonParser::SetupGraphFilter() {
     102         161 :     SetupObjectFilter();
     103         161 :     SetupSchemaGraphFilter();
     104         161 :     SetupSchemaWrapperPropertyInfo();
     105         161 : }
     106           0 : void ConfigJsonParser::EndOfConfig() {
     107           0 :     ifmap_server_->CleanupStaleEntries();
     108           0 : }
     109             : 
     110      120267 : void ConfigJsonParser::MetadataRegister(const string &metadata,
     111             :                                         MetadataParseFn parser) {
     112             :     pair<MetadataParseMap::iterator, bool> result =
     113      120267 :             metadata_map_.insert(make_pair(metadata, parser));
     114      120267 :     assert(result.second);
     115      120267 : }
     116             : 
     117         158 : void ConfigJsonParser::MetadataClear(const string &module) {
     118         158 :     metadata_map_.clear();
     119         158 : }
     120             : 
     121        8093 : IFMapTable::RequestKey *ConfigJsonParser::CloneKey(
     122             :         const IFMapTable::RequestKey &src) const {
     123        8093 :     IFMapTable::RequestKey *retkey = new IFMapTable::RequestKey();
     124        8093 :     retkey->id_type = src.id_type;
     125        8094 :     retkey->id_name = src.id_name;
     126             :     // Tag each DB Request with current generation number
     127        8093 :     retkey->id_seq_num = GetGenerationNumber();
     128        8093 :     return retkey;
     129             : }
     130             : 
     131        2752 : bool ConfigJsonParser::ParseNameType(const ConfigCass2JsonAdapter &adapter,
     132             :                                      IFMapTable::RequestKey *key) const {
     133             :     // Type is the name of the document.
     134        2752 :     Value::ConstMemberIterator itr = adapter.document().MemberBegin();
     135        2752 :     CONFIG_PARSE_ASSERT(Type, autogen::ParseString(itr->name, &key->id_type),
     136             :                         "Name", "Bad name");
     137             : 
     138        2752 :     key->id_type = itr->name.GetString();
     139             : 
     140             :     // Name is the fq_name field in the document.
     141        2752 :     const Value &value_node = itr->value;
     142        2752 :     CONFIG_PARSE_ASSERT(FqName, value_node.HasMember("fq_name"), key->id_type,
     143             :                         "Missing FQ name");
     144        2752 :     const Value &fq_name_node = value_node["fq_name"];
     145        2752 :     CONFIG_PARSE_ASSERT(FqName, fq_name_node.IsArray(), key->id_type,
     146             :                         "FQ name is not an array");
     147        2752 :     CONFIG_PARSE_ASSERT(FqName, fq_name_node.Size(),
     148             :                         key->id_type, "FQ name array is empty");
     149             : 
     150        2752 :     size_t i = 0;
     151             : 
     152             :     // Iterate over all items except the last one.
     153        6841 :     for (; i < fq_name_node.Size() - 1; ++i) {
     154        4089 :         key->id_name += fq_name_node[i].GetString();
     155        4089 :         key->id_name += string(":");
     156             :     }
     157        2752 :     key->id_name += fq_name_node[i].GetString();
     158             : 
     159        2752 :     return true;
     160             : }
     161             : 
     162       10842 : bool ConfigJsonParser::ParseOneProperty(const ConfigCass2JsonAdapter &adapter,
     163             :         const Value &key_node, const Value &value_node,
     164             :         const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
     165             :         RequestList *req_list, bool add_change) const {
     166       10842 :     string metaname = key_node.GetString();
     167       10842 :     MetadataParseMap::const_iterator loc = metadata_map_.find(metaname);
     168       10842 :     if (loc == metadata_map_.end()) {
     169        5574 :         return true;
     170             :     }
     171             : 
     172             :     // Treat updates with NULL value as deletes.
     173        5270 :     if (add_change && value_node.IsNull())
     174           8 :         add_change = false;
     175        5270 :     std::unique_ptr<AutogenProperty> pvalue;
     176        5270 :     if (add_change) {
     177        5080 :         bool success = (loc->second)(value_node, &pvalue);
     178        5080 :         CONFIG_PARSE_ASSERT(Property, success, metaname,
     179             :                         "No entry in metadata map");
     180             :     } else {
     181         190 :         const string key = metaname;
     182         190 :         if (!IsListOrMapPropEmpty(adapter.uuid(), key)) {
     183          32 :             return true;
     184             :         }
     185         190 :     }
     186        5238 :     std::replace(metaname.begin(), metaname.end(), '_', '-');
     187        5238 :     InsertRequestIntoQ(origin, "", "", metaname, pvalue, key,
     188             :                                      add_change, req_list);
     189        5237 :     return true;
     190       10843 : }
     191             : 
     192        2752 : bool ConfigJsonParser::ParseProperties(const ConfigCass2JsonAdapter &adapter,
     193             :         const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
     194             :         RequestList *req_list, bool add_change) const {
     195             : 
     196        2752 :     Value::ConstMemberIterator doc_itr = adapter.document().MemberBegin();
     197        2752 :     const Value &value_node = doc_itr->value;
     198        2752 :     for (Value::ConstMemberIterator itr = value_node.MemberBegin();
     199       13595 :          itr != value_node.MemberEnd(); ++itr) {
     200       10842 :         ParseOneProperty(adapter, itr->name, itr->value, key, origin,
     201             :                          req_list, add_change);
     202             :     }
     203             : 
     204        2752 :     return true;
     205             : }
     206             : 
     207        1224 : bool ConfigJsonParser::ParseRef(const ConfigCass2JsonAdapter &adapter,
     208             :         const Value &ref_entry, IFMapOrigin::Origin origin,
     209             :         const string &refer, const IFMapTable::RequestKey &key,
     210             :         RequestList *req_list, bool add_change) const {
     211        1224 :     const Value& to_node = ref_entry["to"];
     212             : 
     213        1223 :     string from_underscore = key.id_type;
     214        1223 :     std::replace(from_underscore.begin(), from_underscore.end(), '-', '_');
     215             :     string link_name =
     216        1223 :         GetLinkName(from_underscore, refer);
     217        1223 :     CONFIG_PARSE_ASSERT(Reference, !link_name.empty(), refer,
     218             :                         "Link name is empty");
     219        1224 :     string metaname = link_name;
     220        1224 :     std::replace(metaname.begin(), metaname.end(), '-', '_');
     221             : 
     222        1224 :     MetadataParseMap::const_iterator loc = metadata_map_.find(metaname);
     223        1224 :     CONFIG_PARSE_ASSERT(Reference, loc != metadata_map_.end(), metaname,
     224             :                         "No entry in metadata map");
     225             : 
     226        1224 :     std::unique_ptr<AutogenProperty> pvalue;
     227        1224 :     if (ref_entry.HasMember("attr")) {
     228        1224 :         const Value& attr_node = ref_entry["attr"];
     229        1224 :         bool success = (loc->second)(attr_node, &pvalue);
     230        1224 :         CONFIG_PARSE_ASSERT(ReferenceLinkAttributes, success, metaname,
     231             :                             "Link attribute parse error");
     232             :     }
     233             : 
     234        1224 :     string neigh_name;
     235        1224 :     neigh_name += to_node.GetString();
     236             : 
     237        1224 :     InsertRequestIntoQ(origin, refer, neigh_name,
     238             :                                  link_name, pvalue, key, add_change, req_list);
     239             : 
     240        1224 :     return true;
     241        1224 : }
     242             : 
     243        1190 : bool ConfigJsonParser::ParseOneRef(const ConfigCass2JsonAdapter &adapter,
     244             :         const Value &arr, const IFMapTable::RequestKey &key,
     245             :         IFMapOrigin::Origin origin, RequestList *req_list,
     246             :         const string &key_str, size_t pos, bool add_change) const {
     247        1190 :     string refer = key_str.substr(0, pos);
     248        1190 :     CONFIG_PARSE_ASSERT(Reference, arr.IsArray(), refer, "Invalid referene");
     249        2414 :     for (size_t i = 0; i < arr.Size(); ++i)
     250        1224 :         ParseRef(adapter, arr[i], origin, refer, key, req_list, add_change);
     251        1190 :     return true;
     252        1190 : }
     253             : 
     254        2752 : bool ConfigJsonParser::ParseLinks(const ConfigCass2JsonAdapter &adapter,
     255             :         const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
     256             :         RequestList *req_list, bool add_change) const {
     257        2752 :     Value::ConstMemberIterator doc_itr = adapter.document().MemberBegin();
     258        2752 :     const Value &properties = doc_itr->value;
     259        2752 :     for (Value::ConstMemberIterator itr = properties.MemberBegin();
     260       13595 :          itr != properties.MemberEnd(); ++itr) {
     261       10842 :         string key_str = itr->name.GetString();
     262             :         // Skip all the back-refs.
     263       10841 :         if (key_str.find("back_refs") != string::npos) {
     264           0 :             continue;
     265             :         }
     266       10841 :         size_t pos = key_str.find("_refs");
     267       10843 :         if (pos != string::npos) {
     268        1190 :             ParseOneRef(adapter, itr->value, key, origin, req_list, key_str,
     269             :                         pos, add_change);
     270        1190 :             continue;
     271             :         }
     272        9653 :         if (key_str.compare("parent_type") == 0) {
     273        1632 :             const Value& ptype_node = itr->value;
     274        1632 :             CONFIG_PARSE_ASSERT(Parent, ptype_node.IsString(), key_str,
     275             :                                 "Invalid parent type");
     276        1632 :             pos = key.id_name.find_last_of(":");
     277        1632 :             if (pos != string::npos) {
     278        1632 :                 string parent_type = ptype_node.GetString();
     279             :                 // Get the parent name from our name.
     280        1632 :                 string parent_name = key.id_name.substr(0, pos);
     281             :                 string metaname =
     282        1632 :                     GetParentName(parent_type,key.id_type);
     283        1632 :                 CONFIG_PARSE_ASSERT(Parent, !metaname.empty(), parent_type,
     284             :                                     "Missing link name");
     285        1632 :                 std::unique_ptr<AutogenProperty > pvalue;
     286        1632 :                 InsertRequestIntoQ(origin, parent_type,
     287             :                      parent_name, metaname, pvalue, key, add_change, req_list);
     288        1632 :             } else {
     289           0 :                 continue;
     290             :             }
     291             :         }
     292       10843 :     }
     293             : 
     294        2752 :     return true;
     295             : }
     296             : 
     297        2752 : bool ConfigJsonParser::ParseDocument(const ConfigCass2JsonAdapter &adapter,
     298             :         IFMapOrigin::Origin origin, RequestList *req_list,
     299             :         IFMapTable::RequestKey *key, bool add_change) const {
     300             :     // Update the name and the type into 'key'.
     301        2752 :     if (!ParseNameType(adapter, key)) {
     302           0 :         return false;
     303             :     }
     304             : 
     305             :     // For each property, we will clone 'key' to create our DBRequest's i.e.
     306             :     // 'key' will never become part of any DBRequest.
     307        2752 :     if (!ParseProperties(adapter, *key, origin, req_list, add_change)){
     308           0 :         return false;
     309             :     }
     310             : 
     311        2752 :     if (!ParseLinks(adapter, *key, origin, req_list, add_change)) {
     312           0 :         return false;
     313             :     }
     314             : 
     315        2752 :     return true;
     316             : }
     317             : 
     318        8093 : void ConfigJsonParser::InsertRequestIntoQ(IFMapOrigin::Origin origin,
     319             :         const string &neigh_type, const string &neigh_name,
     320             :         const string &metaname, std::unique_ptr<AutogenProperty> &pvalue,
     321             :         const IFMapTable::RequestKey &key, bool add_change,
     322             :         RequestList *req_list) const {
     323             : 
     324             :     IFMapServerTable::RequestData *data =
     325        8093 :         new IFMapServerTable::RequestData(origin, neigh_type, neigh_name);
     326        8094 :     data->metadata = metaname;
     327        8094 :     data->content.reset(pvalue.release());
     328             : 
     329        8093 :     DBRequest *db_request = new DBRequest();
     330        8093 :     db_request->oper = (add_change ? DBRequest::DB_ENTRY_ADD_CHANGE :
     331             :                         DBRequest::DB_ENTRY_DELETE);
     332        8093 :     db_request->key.reset(CloneKey(key));
     333        8093 :     db_request->data.reset(data);
     334             : 
     335        8093 :     req_list->push_back(db_request);
     336        8093 : }
     337             : 
     338        2751 : void ConfigJsonParser::EnqueueListToTables(RequestList *req_list) const {
     339       10845 :     while (!req_list->empty()) {
     340        8094 :         unique_ptr<DBRequest> req(req_list->front());
     341        8093 :         req_list->pop_front();
     342             :         IFMapTable::RequestKey *key =
     343        8093 :             static_cast<IFMapTable::RequestKey *>(req->key.get());
     344             : 
     345        8092 :         IFMapTable *table = IFMapTable::FindTable(ifmap_server_->database(),
     346        8093 :                                                   key->id_type);
     347        8092 :         if (table != NULL) {
     348        8092 :             table->Enqueue(req.get());
     349             :         } else {
     350           0 :             IFMAP_TRACE(IFMapTblNotFoundTrace, "Cant find table", key->id_type);
     351             :         }
     352        8094 :     }
     353        2752 : }
     354             : 
     355        2752 : bool ConfigJsonParser::Receive(const ConfigCass2JsonAdapter &adapter,
     356             :                                bool add_change) {
     357        2752 :     RequestList req_list;
     358             : 
     359        2752 :     if (adapter.document().HasParseError() || !adapter.document().IsObject()) {
     360           0 :         size_t pos = adapter.document().GetErrorOffset();
     361             :         // GetParseError returns const char *
     362           0 :         IFMAP_WARN(IFMapJsonLoadError,
     363             :                    "Error in parsing JSON message at position",
     364             :                    pos, "with error description",
     365             :                    boost::lexical_cast<string>(
     366             :                        adapter.document().GetParseError()), adapter.uuid());
     367           0 :         return false;
     368             :     } else {
     369        2752 :         unique_ptr<IFMapTable::RequestKey> key(new IFMapTable::RequestKey());
     370        2752 :         if (!ParseDocument(adapter, IFMapOrigin::CASSANDRA, &req_list, key.get(), add_change)) {
     371           0 :             STLDeleteValues(&req_list);
     372           0 :             return false;
     373             :         }
     374        2752 :         EnqueueListToTables(&req_list);
     375        2752 :     }
     376        2752 :     return true;
     377        2752 : }
     378             : 
     379           0 : static bool ConfigClientInfoHandleRequest(const Sandesh *sr,
     380             :                                          const RequestPipeline::PipeSpec ps,
     381             :                                          int stage, int instNum,
     382             :                                          RequestPipeline::InstData *data) {
     383             :     const ConfigClientInfoReq *request =
     384           0 :         static_cast<const ConfigClientInfoReq *>(ps.snhRequest_.get());
     385           0 :     ConfigClientInfoResp *response = new ConfigClientInfoResp();
     386             :     IFMapSandeshContext *sctx =
     387           0 :         static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
     388             : 
     389             :     ConfigClientManager *config_mgr =
     390           0 :         sctx->ifmap_server()->get_config_manager();
     391             : 
     392           0 :     if (config_mgr->config_amqp_client()) {
     393           0 :         ConfigAmqpConnInfo amqp_conn_info;
     394           0 :         config_mgr->config_amqp_client()->GetConnectionInfo(amqp_conn_info);
     395           0 :         response->set_amqp_conn_info(amqp_conn_info);
     396           0 :     }
     397             : 
     398           0 :     ConfigDBConnInfo db_conn_info;
     399           0 :     config_mgr->config_db_client()->GetConnectionInfo(db_conn_info);
     400             : 
     401           0 :     ConfigClientManagerInfo client_mgr_info;
     402           0 :     config_mgr->GetClientManagerInfo(client_mgr_info);
     403             : 
     404           0 :     response->set_client_manager_info(client_mgr_info);
     405           0 :     response->set_db_conn_info(db_conn_info);
     406           0 :     response->set_context(request->context());
     407           0 :     response->set_more(false);
     408           0 :     response->Response();
     409           0 :     return true;
     410           0 : }
     411             : 
     412           0 : void ConfigClientInfoReq::HandleRequest() const {
     413           0 :     RequestPipeline::StageSpec s0;
     414           0 :     TaskScheduler *scheduler = TaskScheduler::GetInstance();
     415             : 
     416           0 :     s0.taskId_ = scheduler->GetTaskId("config::SandeshCmd");
     417           0 :     s0.cbFn_ = ConfigClientInfoHandleRequest;
     418           0 :     s0.instances_.push_back(0);
     419             : 
     420           0 :     RequestPipeline::PipeSpec ps(this);
     421           0 :     ps.stages_= boost::assign::list_of(s0).convert_to_container<
     422           0 :                               std::vector<RequestPipeline::StageSpec> >();
     423           0 :     RequestPipeline rp(ps);
     424           0 : }
     425             : 
     426           0 : static bool ConfigClientReinitHandleRequest(const Sandesh *sr,
     427             :                                          const RequestPipeline::PipeSpec ps,
     428             :                                          int stage, int instNum,
     429             :                                          RequestPipeline::InstData *data) {
     430             :     const ConfigClientReinitReq *request =
     431           0 :         static_cast<const ConfigClientReinitReq *>(ps.snhRequest_.get());
     432           0 :     ConfigClientReinitResp *response = new ConfigClientReinitResp();
     433             :     IFMapSandeshContext *sctx =
     434           0 :         static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
     435             : 
     436             :     ConfigClientManager *config_mgr =
     437           0 :         sctx->ifmap_server()->get_config_manager();
     438             : 
     439           0 :     config_mgr->ReinitConfigClient();
     440             : 
     441           0 :     response->set_success(true);
     442           0 :     response->set_context(request->context());
     443           0 :     response->set_more(false);
     444           0 :     response->Response();
     445           0 :     return true;
     446             : }
     447             : 
     448           0 : void ConfigClientReinitReq::HandleRequest() const {
     449           0 :     RequestPipeline::StageSpec s0;
     450           0 :     TaskScheduler *scheduler = TaskScheduler::GetInstance();
     451             : 
     452           0 :     s0.taskId_ = scheduler->GetTaskId("config::SandeshCmd");
     453           0 :     s0.cbFn_ = ConfigClientReinitHandleRequest;
     454           0 :     s0.instances_.push_back(0);
     455             : 
     456           0 :     RequestPipeline::PipeSpec ps(this);
     457           0 :     ps.stages_= boost::assign::list_of(s0).convert_to_container<
     458           0 :                               std::vector<RequestPipeline::StageSpec> >();
     459           0 :     RequestPipeline rp(ps);
     460           0 : }

Generated by: LCOV version 1.14