OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
config_json_parser.cc
Go to the documentation of this file.
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 
12 #include "ifmap/ifmap_log.h"
13 #include "ifmap/ifmap_log_types.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"
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 
45 }
46 
48 }
49 
51  ObjectTypeList FilterList;
52  bgp_schema_Server_GenerateObjectTypeList(&FilterList);
53  vnc_cfg_Server_GenerateObjectTypeList(&FilterList);
54  for (ObjectTypeList::iterator it = FilterList.begin();
55  it != FilterList.end(); it++) {
56  AddObjectType(*it);
57  }
58 }
59 
61  vnc_cfg_FilterInfo vnc_filter_info;
62  bgp_schema_FilterInfo bgp_schema_filter_info;
63 
64  bgp_schema_Server_GenerateGraphFilter(&bgp_schema_filter_info);
65  vnc_cfg_Server_GenerateGraphFilter(&vnc_filter_info);
66 
67  for (vnc_cfg_FilterInfo::iterator it = vnc_filter_info.begin();
68  it != vnc_filter_info.end(); it++) {
69  if (it->is_ref_) {
70  AddLinkName(make_pair(it->left_, it->right_),
71  make_pair(it->metadata_, it->linkattr_));
72  } else {
73  AddParentName(make_pair(it->left_, it->right_),
74  it->metadata_);
75  }
76  }
77 
78  for (bgp_schema_FilterInfo::iterator it = bgp_schema_filter_info.begin();
79  it != bgp_schema_filter_info.end(); it++) {
80  if (it->is_ref_) {
81  AddLinkName(make_pair(it->left_, it->right_),
82  make_pair(it->metadata_, it->linkattr_));
83  } else {
84  AddParentName(make_pair(it->left_, it->right_),
85  it->metadata_);
86  }
87  }
88 }
89 
91  WrapperFieldMap wrapper_field_map;
92  bgp_schema_Server_GenerateWrapperPropertyInfo(&wrapper_field_map);
93  vnc_cfg_Server_GenerateWrapperPropertyInfo(&wrapper_field_map);
94  for (WrapperFieldMap::iterator it = wrapper_field_map.begin();
95  it != wrapper_field_map.end(); it++) {
96  AddWrapperField(it->first, it->second);
97  }
98 }
99 
104 }
107 }
108 
109 void ConfigJsonParser::MetadataRegister(const string &metadata,
110  MetadataParseFn parser) {
111  pair<MetadataParseMap::iterator, bool> result =
112  metadata_map_.insert(make_pair(metadata, parser));
113  assert(result.second);
114 }
115 
116 void ConfigJsonParser::MetadataClear(const string &module) {
117  metadata_map_.clear();
118 }
119 
121  const IFMapTable::RequestKey &src) const {
123  retkey->id_type = src.id_type;
124  retkey->id_name = src.id_name;
125  // Tag each DB Request with current generation number
126  retkey->id_seq_num = GetGenerationNumber();
127  return retkey;
128 }
129 
131  IFMapTable::RequestKey *key) const {
132  // Type is the name of the document.
133  Value::ConstMemberIterator itr = adapter.document().MemberBegin();
134  CONFIG_PARSE_ASSERT(Type, autogen::ParseString(itr->name, &key->id_type),
135  "Name", "Bad name");
136 
137  key->id_type = itr->name.GetString();
138 
139  // Name is the fq_name field in the document.
140  const Value &value_node = itr->value;
141  CONFIG_PARSE_ASSERT(FqName, value_node.HasMember("fq_name"), key->id_type,
142  "Missing FQ name");
143  const Value &fq_name_node = value_node["fq_name"];
144  CONFIG_PARSE_ASSERT(FqName, fq_name_node.IsArray(), key->id_type,
145  "FQ name is not an array");
146  CONFIG_PARSE_ASSERT(FqName, fq_name_node.Size(),
147  key->id_type, "FQ name array is empty");
148 
149  size_t i = 0;
150 
151  // Iterate over all items except the last one.
152  for (; i < fq_name_node.Size() - 1; ++i) {
153  key->id_name += fq_name_node[i].GetString();
154  key->id_name += string(":");
155  }
156  key->id_name += fq_name_node[i].GetString();
157 
158  return true;
159 }
160 
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  string metaname = key_node.GetString();
166  MetadataParseMap::const_iterator loc = metadata_map_.find(metaname);
167  if (loc == metadata_map_.end()) {
168  return true;
169  }
170 
171  // Treat updates with NULL value as deletes.
172  if (add_change && value_node.IsNull())
173  add_change = false;
174  std::unique_ptr<AutogenProperty> pvalue;
175  if (add_change) {
176  bool success = (loc->second)(value_node, &pvalue);
177  CONFIG_PARSE_ASSERT(Property, success, metaname,
178  "No entry in metadata map");
179  } else {
180  const string key = metaname;
181  if (!IsListOrMapPropEmpty(adapter.uuid(), key)) {
182  return true;
183  }
184  }
185  std::replace(metaname.begin(), metaname.end(), '_', '-');
186  InsertRequestIntoQ(origin, "", "", metaname, pvalue, key,
187  add_change, req_list);
188  return true;
189 }
190 
192  const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
193  RequestList *req_list, bool add_change) const {
194 
195  Value::ConstMemberIterator doc_itr = adapter.document().MemberBegin();
196  const Value &value_node = doc_itr->value;
197  for (Value::ConstMemberIterator itr = value_node.MemberBegin();
198  itr != value_node.MemberEnd(); ++itr) {
199  ParseOneProperty(adapter, itr->name, itr->value, key, origin,
200  req_list, add_change);
201  }
202 
203  return true;
204 }
205 
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  const Value& to_node = ref_entry["to"];
211 
212  string from_underscore = key.id_type;
213  std::replace(from_underscore.begin(), from_underscore.end(), '-', '_');
214  string link_name =
215  GetLinkName(from_underscore, refer);
216  CONFIG_PARSE_ASSERT(Reference, !link_name.empty(), refer,
217  "Link name is empty");
218  string metaname = link_name;
219  std::replace(metaname.begin(), metaname.end(), '-', '_');
220 
221  MetadataParseMap::const_iterator loc = metadata_map_.find(metaname);
222  CONFIG_PARSE_ASSERT(Reference, loc != metadata_map_.end(), metaname,
223  "No entry in metadata map");
224 
225  std::unique_ptr<AutogenProperty> pvalue;
226  if (ref_entry.HasMember("attr")) {
227  const Value& attr_node = ref_entry["attr"];
228  bool success = (loc->second)(attr_node, &pvalue);
229  CONFIG_PARSE_ASSERT(ReferenceLinkAttributes, success, metaname,
230  "Link attribute parse error");
231  }
232 
233  string neigh_name;
234  neigh_name += to_node.GetString();
235 
236  InsertRequestIntoQ(origin, refer, neigh_name,
237  link_name, pvalue, key, add_change, req_list);
238 
239  return true;
240 }
241 
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  string refer = key_str.substr(0, pos);
247  CONFIG_PARSE_ASSERT(Reference, arr.IsArray(), refer, "Invalid referene");
248  for (size_t i = 0; i < arr.Size(); ++i)
249  ParseRef(adapter, arr[i], origin, refer, key, req_list, add_change);
250  return true;
251 }
252 
254  const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
255  RequestList *req_list, bool add_change) const {
256  Value::ConstMemberIterator doc_itr = adapter.document().MemberBegin();
257  const Value &properties = doc_itr->value;
258  for (Value::ConstMemberIterator itr = properties.MemberBegin();
259  itr != properties.MemberEnd(); ++itr) {
260  string key_str = itr->name.GetString();
261  // Skip all the back-refs.
262  if (key_str.find("back_refs") != string::npos) {
263  continue;
264  }
265  size_t pos = key_str.find("_refs");
266  if (pos != string::npos) {
267  ParseOneRef(adapter, itr->value, key, origin, req_list, key_str,
268  pos, add_change);
269  continue;
270  }
271  if (key_str.compare("parent_type") == 0) {
272  const Value& ptype_node = itr->value;
273  CONFIG_PARSE_ASSERT(Parent, ptype_node.IsString(), key_str,
274  "Invalid parent type");
275  pos = key.id_name.find_last_of(":");
276  if (pos != string::npos) {
277  string parent_type = ptype_node.GetString();
278  // Get the parent name from our name.
279  string parent_name = key.id_name.substr(0, pos);
280  string metaname =
281  GetParentName(parent_type,key.id_type);
282  CONFIG_PARSE_ASSERT(Parent, !metaname.empty(), parent_type,
283  "Missing link name");
284  std::unique_ptr<AutogenProperty > pvalue;
285  InsertRequestIntoQ(origin, parent_type,
286  parent_name, metaname, pvalue, key, add_change, req_list);
287  } else {
288  continue;
289  }
290  }
291  }
292 
293  return true;
294 }
295 
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  if (!ParseNameType(adapter, key)) {
301  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  if (!ParseProperties(adapter, *key, origin, req_list, add_change)){
307  return false;
308  }
309 
310  if (!ParseLinks(adapter, *key, origin, req_list, add_change)) {
311  return false;
312  }
313 
314  return true;
315 }
316 
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 
324  new IFMapServerTable::RequestData(origin, neigh_type, neigh_name);
325  data->metadata = metaname;
326  data->content.reset(pvalue.release());
327 
328  DBRequest *db_request = new DBRequest();
329  db_request->oper = (add_change ? DBRequest::DB_ENTRY_ADD_CHANGE :
331  db_request->key.reset(CloneKey(key));
332  db_request->data.reset(data);
333 
334  req_list->push_back(db_request);
335 }
336 
338  while (!req_list->empty()) {
339  unique_ptr<DBRequest> req(req_list->front());
340  req_list->pop_front();
342  static_cast<IFMapTable::RequestKey *>(req->key.get());
343 
345  key->id_type);
346  if (table != NULL) {
347  table->Enqueue(req.get());
348  } else {
349  IFMAP_TRACE(IFMapTblNotFoundTrace, "Cant find table", key->id_type);
350  }
351  }
352 }
353 
355  bool add_change) {
356  RequestList req_list;
357 
358  if (adapter.document().HasParseError() || !adapter.document().IsObject()) {
359  size_t pos = adapter.document().GetErrorOffset();
360  // GetParseError returns const char *
361  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  return false;
367  } else {
368  unique_ptr<IFMapTable::RequestKey> key(new IFMapTable::RequestKey());
369  if (!ParseDocument(adapter, IFMapOrigin::CASSANDRA, &req_list, key.get(), add_change)) {
370  STLDeleteValues(&req_list);
371  return false;
372  }
373  EnqueueListToTables(&req_list);
374  }
375  return true;
376 }
377 
379  const RequestPipeline::PipeSpec ps,
380  int stage, int instNum,
382  const ConfigClientInfoReq *request =
383  static_cast<const ConfigClientInfoReq *>(ps.snhRequest_.get());
384  ConfigClientInfoResp *response = new ConfigClientInfoResp();
385  IFMapSandeshContext *sctx =
386  static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
387 
388  ConfigClientManager *config_mgr =
389  sctx->ifmap_server()->get_config_manager();
390 
391  if (config_mgr->config_amqp_client()) {
392  ConfigAmqpConnInfo amqp_conn_info;
393  config_mgr->config_amqp_client()->GetConnectionInfo(amqp_conn_info);
394  response->set_amqp_conn_info(amqp_conn_info);
395  }
396 
397  ConfigDBConnInfo db_conn_info;
398  config_mgr->config_db_client()->GetConnectionInfo(db_conn_info);
399 
400  ConfigClientManagerInfo client_mgr_info;
401  config_mgr->GetClientManagerInfo(client_mgr_info);
402 
403  response->set_client_manager_info(client_mgr_info);
404  response->set_db_conn_info(db_conn_info);
405  response->set_context(request->context());
406  response->set_more(false);
407  response->Response();
408  return true;
409 }
410 
411 void ConfigClientInfoReq::HandleRequest() const {
414 
415  s0.taskId_ = scheduler->GetTaskId("config::SandeshCmd");
417  s0.instances_.push_back(0);
418 
419  RequestPipeline::PipeSpec ps(this);
420  ps.stages_= boost::assign::list_of(s0).convert_to_container<
421  std::vector<RequestPipeline::StageSpec> >();
422  RequestPipeline rp(ps);
423 }
424 
426  const RequestPipeline::PipeSpec ps,
427  int stage, int instNum,
429  const ConfigClientReinitReq *request =
430  static_cast<const ConfigClientReinitReq *>(ps.snhRequest_.get());
431  ConfigClientReinitResp *response = new ConfigClientReinitResp();
432  IFMapSandeshContext *sctx =
433  static_cast<IFMapSandeshContext *>(request->module_context("IFMap"));
434 
435  ConfigClientManager *config_mgr =
436  sctx->ifmap_server()->get_config_manager();
437 
438  config_mgr->ReinitConfigClient();
439 
440  response->set_success(true);
441  response->set_context(request->context());
442  response->set_more(false);
443  response->Response();
444  return true;
445 }
446 
447 void ConfigClientReinitReq::HandleRequest() const {
450 
451  s0.taskId_ = scheduler->GetTaskId("config::SandeshCmd");
453  s0.instances_.push_back(0);
454 
455  RequestPipeline::PipeSpec ps(this);
456  ps.stages_= boost::assign::list_of(s0).convert_to_container<
457  std::vector<RequestPipeline::StageSpec> >();
458  RequestPipeline rp(ps);
459 }
void AddParentName(LinkMemberPair member_pair, std::string s)
void AddLinkName(LinkMemberPair member_pair, LinkDataPair data_pair)
std::vector< int > instances_
MetadataParseMap metadata_map_
IFMapServer * ifmap_server()
void STLDeleteValues(Container *container)
Definition: util.h:101
ConfigClientManager * get_config_manager()
Definition: ifmap_server.h:92
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
virtual void GetConnectionInfo(ConfigDBConnInfo &status) const
bool IsListOrMapPropEmpty(const std::string &uuid_key, const std::string &lookup_key) const
boost::function< bool(const contrail_rapidjson::Value &, std::unique_ptr< AutogenProperty > *) > MetadataParseFn
void CleanupStaleEntries()
bool ParseOneProperty(const ConfigCass2JsonAdapter &adapter, const contrail_rapidjson::Value &key_node, const contrail_rapidjson::Value &value_node, const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin, RequestList *req_list, bool add_change) const
ConfigDbClient * config_db_client() const
bool ParseOneRef(const ConfigCass2JsonAdapter &adapter, const contrail_rapidjson::Value &arr, const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin, RequestList *req_list, const std::string &key_str, size_t pos, bool add_change) const
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
ConfigAmqpClient * config_amqp_client() const
const std::string & uuid() const
bool Enqueue(DBRequest *req)
Definition: db_table.cc:194
void MetadataRegister(const std::string &metadata, MetadataParseFn parser)
void ReinitConfigClient(const ConfigClientOptions &config)
void AddWrapperField(std::string key, std::string value)
std::set< std::string > ObjectTypeList
std::unique_ptr< AutogenProperty > content
IFMapServer * ifmap_server_
std::string GetParentName(const std::string &left, const std::string &right) const
std::map< std::string, std::string > WrapperFieldMap
int GetTaskId(const std::string &name)
Definition: task.cc:856
std::string GetLinkName(const std::string &left, const std::string &right) const
bool ParseDocument(const ConfigCass2JsonAdapter &adapter, IFMapOrigin::Origin origin, RequestList *req_list, IFMapTable::RequestKey *key, bool add_change) const
void GetConnectionInfo(ConfigAmqpConnInfo &info) const
const contrail_rapidjson::Document & document() const
DB * database()
Definition: ifmap_server.h:82
bool ParseLinks(const ConfigCass2JsonAdapter &adapter, const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin, RequestList *req_list, bool add_change) const
static TaskScheduler * GetInstance()
Definition: task.cc:547
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
bool ParseRef(const ConfigCass2JsonAdapter &adapter, const contrail_rapidjson::Value &ref_entry, IFMapOrigin::Origin origin, const std::string &refer, const IFMapTable::RequestKey &key, RequestList *req_list, bool add_change) const
bool ParseProperties(const ConfigCass2JsonAdapter &adapter, const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin, RequestList *req_list, bool add_change) const
DBOperation oper
Definition: db_table.h:42
void SetupSchemaWrapperPropertyInfo()
static bool ConfigClientInfoHandleRequest(const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage, int instNum, RequestPipeline::InstData *data)
void EnqueueListToTables(RequestList *req_list) const
IFMapTable::RequestKey * CloneKey(const IFMapTable::RequestKey &src) const
uint64_t GetGenerationNumber() const
bool ParseNameType(const ConfigCass2JsonAdapter &adapter, IFMapTable::RequestKey *key) const
virtual bool Receive(const ConfigCass2JsonAdapter &adapter, bool add_change)
#define CONFIG_PARSE_ASSERT(t, condition, key, value)
void MetadataClear(const std::string &module)
std::list< struct DBRequest * > RequestList
static bool ConfigClientReinitHandleRequest(const Sandesh *sr, const RequestPipeline::PipeSpec ps, int stage, int instNum, RequestPipeline::InstData *data)
#define IFMAP_WARN(obj,...)
Definition: ifmap_log.h:72
void GetClientManagerInfo(ConfigClientManagerInfo &info) const
static IFMapTable * FindTable(DB *db, const std::string &element_type)
Definition: ifmap_table.cc:39
boost::shared_ptr< const SandeshRequest > snhRequest_
#define IFMAP_TRACE(obj,...)
Definition: ifmap_log.h:26
virtual void SetupGraphFilter()
void InsertRequestIntoQ(IFMapOrigin::Origin origin, const std::string &neigh_type, const std::string &neigh_name, const std::string &metaname, std::unique_ptr< AutogenProperty > &pvalue, const IFMapTable::RequestKey &key, bool add_change, RequestList *req_list) const
static bool ParseString(const contrail_rapidjson::Value &node, std::string *s)
Definition: autogen_util.h:31
virtual void EndOfConfig()
void AddObjectType(std::string object)