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

Generated by: LCOV version 1.14