1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ------------------------------------------- */
24 extern string hostname; // namne of the current host
26 static string int_to_string(int i){
29 sprintf(tmpstr,"%d",i);
35 // Interface for the res parser
36 extern int ResParserparse(void);
37 extern FILE *ResParserin;
38 extern int ResParserdebug;
39 void ResParser_setfileinput(FILE *f);
40 void ResParser_setstringinput(char *s);
41 extern int flex_res_lineno;
43 resparse_data *rpd_ptr;
44 vector<string> res_val_vec, res_attr_vec;
47 ///////////////////////////////////////
50 void iface_t::add_property(const char *name, const char *att){
52 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
53 vals[nm].push_back(att);
56 void iface_t::add_property(const char *name, const char **atts){
59 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
60 if(atts[0]) val = atts[1];
62 vals[nm].push_back(val);
65 void iface_t::add_property(const char *name, vector<string> &val_vec){
68 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
69 if(val_vec.size()) val = val_vec[0];
71 vals[nm].push_back(val);
74 // Add in more consistency checks
75 int iface_t::finalize(string &errs){
76 string tag ="ERROR in interface starting at line "+int_to_string(lineno)+", ";
78 if(vals.count("name") == 0){
79 e += "Name not specified. ";
81 if(vals["name"].size() > 1){
82 e+="More than one name specified. ";
87 errs += tag + e + "\n";
93 string iface_t::to_string(){
95 string ret = "Interface "+vals["name"][0]+":\n";
96 map<string, vector<string> >::iterator svmi;
97 for(svmi=vals.begin();svmi!=vals.end();++svmi){
98 ret += "\t"+(*svmi).first + " : ";
99 for(i=0;i<((*svmi).second).size();++i){
101 ret += (*svmi).second[i];
109 string iface_t::get_name(){
110 if(vals.count("name") == 0) return (string)"";
111 return (vals["name"])[0];
114 string iface_t::get_host(){
115 if(vals.count("host") == 0) return (string)"";
116 return (vals["host"])[0];
119 bool iface_t::has_multiple_schemas(){
120 if(vals.count("interfacetype") == 0) return true;
121 string iface_type = vals["interfacetype"][0];
122 if(iface_type=="GDAT" || iface_type=="CSV")
128 bool iface_t::eval_Contains(string prop, string val){
129 // convert to lowercase
130 std::transform(prop.begin(), prop.end(), prop.begin(), (int(*)(int))std::tolower);
132 if(vals.count(prop) == 0) return false;
134 for(i=0;i<vals[prop].size();++i){
135 if((vals[prop])[i] == val) return true;
140 bool iface_t::eval_Equals(string prop, string val){
141 // convert to lowercase
142 std::transform(prop.begin(), prop.end(), prop.begin(), (int(*)(int))std::tolower);
143 if(vals.count(prop) == 0) return false;
144 if(vals[prop].size() != 1) return false;
146 for(i=0;i<vals[prop].size();++i){
147 if((vals[prop])[i] == val) return true;
152 bool iface_t::eval_Exists(string prop){
153 // convert to lowercase
154 std::transform(prop.begin(), prop.end(), prop.begin(), (int(*)(int))std::tolower);
155 if(vals.count(prop) == 0) return false;
160 ///////////////////////////////////////
161 /// gs_host_t methods
163 void gs_host_t::add_property(const char *name, const char *att){
165 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
166 vals[nm].push_back(att);
169 void gs_host_t::add_property(const char *name, vector<string> &val_vec){
172 std::transform(nm.begin(), nm.end(), nm.begin(), (int(*)(int))std::tolower);
173 if(val_vec.size()) val = val_vec[0];
175 vals[nm].push_back(val);
178 int gs_host_t::finalize(string &errs){
179 string tag ="ERROR in host starting at line "+int_to_string(lineno)+", ";
181 if(vals.count("name") == 0){
182 e += "Name not specified. ";
184 if(vals["name"].size() > 1){
185 e+="More than one name specified. ";
190 errs += tag + e + "\n";
197 /////////////////////////////////////////////////////////////////
198 /// reparse_data methods
200 int resparse_data::finalize_iface(string &errs){
201 int ret = curr_iface->finalize(errs);
206 curr_host->add_interface(curr_iface);
212 int resparse_data::finalize_host(string &errs){
213 int ret = curr_host->finalize(errs);
219 string host = curr_host->vals["name"][0];
220 // in non-distributed case we will ignore all other hosts
221 if (!distributed_mode) {
223 if (host != hostname)
226 // we need to exclude failed hosts
227 if (!use_live_hosts_file || live_hosts->count(hostname)) {
228 hosts.push_back(curr_host);
230 // push the host name to every interface
231 curr_host->propagate_name();
233 // add all interfaces into interface list
234 for(int i=0;i<curr_host->ifaces.size();i++)
235 ifaces.push_back(curr_host->ifaces[i]);
241 string resparse_data::to_string(){
244 for(i=0;i<ifaces.size();i++)
245 ret += ifaces[i]->to_string();
249 vector<pair<string,string> > resparse_data::find_ifaces(predicate_t *pr){
251 vector<pair<string,string> > ret;
252 for(i=0;i<ifaces.size();++i){
253 if(this->eval_pred(i,pr)){
254 pair<string,string> p(ifaces[i]->get_host(), ifaces[i]->get_name());
262 vector<int> resparse_data::get_ifaces_by_Name(std::string host_name, std::string if_name){
265 for(i=0;i<ifaces.size();++i){
266 if(ifaces[i]->get_host() == host_name && ifaces[i]->get_name() == if_name)
274 bool resparse_data::eval_pred(int i, predicate_t *pr){
275 vector<scalarexp_t *> op_list;
278 switch(pr->get_operator_type()){
280 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, IN not supported. %d\n",
281 pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
284 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, comparison predicate not supported. %d\n",
285 pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
288 if(pr->get_op() == "NOT")
289 return(! eval_pred(i, pr->get_left_pr()) );
290 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, unknown unary pred operator %s.\n",
291 pr->get_lineno(), pr->get_charno(), pr->get_op().c_str() );
294 if(pr->get_op() == "AND"){
295 if(! eval_pred(i, pr->get_left_pr()) ) return false;
296 return eval_pred(i, pr->get_right_pr()) ;
298 if(pr->get_op() == "OR"){
299 if( eval_pred(i, pr->get_left_pr()) ) return true;
300 return eval_pred(i, pr->get_right_pr()) ;
302 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, unknown binary pred operator %s.\n",
303 pr->get_lineno(), pr->get_charno(), pr->get_op().c_str() );
306 op_list = pr->get_op_list();
307 if(op_list[0]->get_operator_type() != SE_PARAM){
308 fprintf(stderr,"INTERNAL ERROR : ifq parameters are supposed to be of type SE_PARAM, found %s at position 0\n",op_list[0]->get_op().c_str());
311 prop=op_list[0]->get_op();
313 if(op_list.size() > 1){
314 if(op_list[1]->get_operator_type() != SE_PARAM){
315 fprintf(stderr,"INTERNAL ERROR : ifq parameters are supposed to be of type SE_PARAM, found %s at position 1\n",op_list[0]->get_op().c_str());
318 val=op_list[1]->get_op();
322 if(pr->get_op() == "Contains"){
323 if(op_list.size() != 2){
324 fprintf(stderr,"INTERNAL ERROR : predicate Contains expects 2 parameters, received %lu\n",op_list.size());
327 return ifaces[i]->eval_Contains(prop,val);
330 if(pr->get_op() == "Equals"){
331 if(op_list.size() != 2){
332 fprintf(stderr,"INTERNAL ERROR : predicate Equals expects 2 parameters, received %lu\n",op_list.size());
335 return ifaces[i]->eval_Equals(prop,val);
338 if(pr->get_op() == "Exists"){
339 if(op_list.size() != 1){
340 fprintf(stderr,"INTERNAL ERROR : predicate Exists expects 1 parameter, received %lu\n",op_list.size());
343 return ifaces[i]->eval_Exists(prop);
346 fprintf(stderr,"INTERNAL ERROR : Unknown predicate %s in reparse_date::eval_pred.\n",pr->get_op().c_str());
350 fprintf(stderr,"INTERNAL ERROR in reparse_date::eval_pred, line %d, character %d, unknown predicate operator type %d\n",
351 pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
360 ///////////////////////////////////////////
361 /// XML parser callbacks for parsing interface resources
363 void startElement(void *userData, const char *name, const char **atts) {
366 resparse_data *rpd = (resparse_data *)userData;
367 rpd->level.push_back(name);
369 if(rpd->level.size() == 1 && rpd->level[0] == "Resources")
370 rpd->in_Resources = true;
372 if(rpd->in_Resources && rpd->level.size() == 2 && rpd->level[1] == "Interface"){
373 // rpd->new_iface(XML_GetCurrentLineNumber(rpd->parser));
375 rpd->in_Iface = true;
378 if(rpd->in_Iface && rpd->level.size() == 3){
379 rpd->add_property(name, atts);
383 // for(i=0;i<rpd->level.size();++i) printf("%s, ",rpd->level[i].c_str());
387 void startElement(void *userData, const char *name, vector<string> &attr_vec, vector<string> &val_vec){
390 resparse_data *rpd = (resparse_data *)userData;
391 rpd->level.push_back(name);
393 if(rpd->level.size() == 1 && rpd->level[0] == "Resources")
394 rpd->in_Resources = true;
396 if(rpd->in_Resources && rpd->level.size() == 2 && rpd->level[1] == "Host"){
397 // rpd->new_iface(XML_GetCurrentLineNumber(rpd->parser));
399 rpd->new_host(flex_res_lineno);
400 for (int i = 0; i < attr_vec.size(); ++i)
401 rpd->curr_host->add_property(attr_vec[i].c_str(), val_vec[i].c_str());
405 if(rpd->in_Host && rpd->level.size() == 3) {
406 if ( rpd->level[2] == "Interface"){
407 // rpd->new_iface(XML_GetCurrentLineNumber(rpd->parser));
408 rpd->new_iface(flex_res_lineno);
409 for (int i = 0; i < attr_vec.size(); ++i)
410 rpd->add_property(attr_vec[i].c_str(), val_vec[i].c_str());
411 rpd->in_Iface = true;
413 rpd->curr_host->add_property(name, val_vec);
417 if(rpd->in_Iface && rpd->level.size() == 4){
418 rpd->add_property(name, val_vec);
422 // for(i=0;i<rpd->level.size();++i) printf("%s, ",rpd->level[i].c_str());
427 void endElement(void *userData, const char *name) {
428 resparse_data *rpd = (resparse_data *)userData;
430 if(rpd->in_Iface && rpd->level.size() == 3){
432 int err = rpd->finalize_iface(err_msg);
433 if(err) fprintf(stderr,"%s\n",err_msg.c_str());
434 } else if (rpd->in_Host && rpd->level.size() == 2) {
436 int err = rpd->finalize_host(err_msg);
437 if(err) fprintf(stderr,"%s\n",err_msg.c_str());
440 rpd->level.pop_back();
444 // Interface to ifq definition lexer and parser ...
446 extern int IfqParserparse(void);
447 extern FILE *IfqParserin;
448 extern int IfqParserdebug;
449 void IfqParser_setfileinput(FILE *f);
450 void IfqParser_setstringinput(char *s);
453 fta_parse_t *ifq_parse_result;
455 int ifq_t::load_ifaces(string fname, bool use_live_hosts_file, bool disributed_mode, string &err){
456 char buf[1000], errbuf[1000];
457 // XML_Parser parser = XML_ParserCreate(NULL);
463 // open the list of failed hosts
464 set<string> live_hosts;
465 if (use_live_hosts_file) {
466 FILE* live_hosts_file = fopen("live_hosts.txt", "r");
467 if (!live_hosts_file) {
468 err="Error, can't open live_hosts.txt, error is ";
469 err+=strerror(errno); err+="\n";
473 while(fgets(buf, 1000, live_hosts_file)) {
474 char* host = strtok(buf, " \t\n\r"); // strip the line
476 live_hosts.insert(host);
479 fclose(live_hosts_file);
484 // IfqParserdebug = 1;
486 FILE *resfile = fopen(fname.c_str(),"r");
488 err="Error, can't open "+fname+", error is ";
489 err+=strerror(errno); err+="\n";
493 // rpd = new resparse_data(parser);
494 rpd = new resparse_data(use_live_hosts_file, &live_hosts, disributed_mode);
497 ResParser_setfileinput(resfile);
498 if(ResParserparse()){
499 err = "ERROR, interface query parse failed.\n";
504 XML_SetUserData(parser, rpd);
505 XML_SetElementHandler(parser, startElement, endElement);
507 size_t len = fread(buf, 1, sizeof(buf), resfile);
508 done = len < sizeof(buf);
509 if (!XML_Parse(parser, buf, len, done)) {
512 XML_ErrorString(XML_GetErrorCode(parser)),
513 XML_GetCurrentLineNumber(parser));
518 XML_ParserFree(parser);
521 err = "Interface resource parse failed, exiting.\n";
531 int ifq_t::load_ifqs(string fname, string &err){
535 FILE *qfile = fopen(fname.c_str(),"r");
537 sprintf(err_buf, "ERROR, can't open %s, error is %s\n",fname.c_str(),strerror(errno));
542 ifq_parse_result = new fta_parse_t();
543 IfqParser_setfileinput(qfile);
544 if(IfqParserparse()){
545 err = "ERROR, interface query parse failed.\n";
549 vector<table_exp_t *> ifqlist = ifq_parse_result->parse_tree_list->qlist;
552 for(i=0;i<ifqlist.size();++i){
553 string nm = ifqlist[i]->nmap["name"];
554 if(ifq_map.count(nm)){
555 err += "ERROR, Duplicate interface query "+nm+"\n";
558 ifq_map[nm] = ifqlist[i]->wh;
567 vector<pair<string,string> > ifq_t::eval(string qname, int &err_no){
568 vector<pair<string,string> > retval;
571 if(ifq_map.count(qname) == 0){
580 return rpd->find_ifaces(ifq_map[qname]);
584 vector<string> ifq_t::get_iface_vals(string host_name, string basic_if_name, string property, int &err_no, string &err_str){
585 vector<string> retval;
588 char *cdat = strdup(basic_if_name.c_str());
590 string virtual_iface = "0";
591 string iface_name = basic_if_name;
592 for(pos=strlen(cdat)-1;pos>=0 && isdigit(cdat[pos]);--pos);
593 if(pos>0 && cdat[pos] == 'X' && pos<=strlen(cdat)-2){
595 virtual_iface = cdat+pos+1;
600 if(property == "virtual_interface_id"){
601 retval.push_back(virtual_iface);
607 err_no = 1; err_str = "interface resource parse failed.";
611 vector<int> ifi = rpd->get_ifaces_by_Name(host_name, iface_name);
613 err_no = 1; err_str="interface not found.";
617 err_no = 1; err_str="multiple interfaces found.";
621 return rpd->get_property(ifi[0], property);
625 vector<string> ifq_t::get_iface_properties(string host_name, string basic_if_name, int &err_no, string &err_str){
626 vector<string> retval;
629 char *cdat = strdup(basic_if_name.c_str());
631 string virtual_iface = "0";
632 string iface_name = basic_if_name;
633 for(pos=strlen(cdat)-1;pos>=0 && isdigit(cdat[pos]);--pos);
634 if(pos>0 && cdat[pos] == 'X' && pos<=strlen(cdat)-2){
636 virtual_iface = cdat+pos+1;
642 err_no = 1; err_str = "interface resource parse failed.";
646 vector<int> ifi = rpd->get_ifaces_by_Name(host_name, iface_name);
648 err_no = 1; err_str="interface not found.";
652 err_no = 1; err_str="multiple interfaces found.";
656 return rpd->get_properties(ifi[0]);
661 iface_t *ifq_t::get_interface(string host_name, string basic_if_name, int &err_no, string &err_str){
662 iface_t *retval = NULL;
665 char *cdat = strdup(basic_if_name.c_str());
667 string virtual_iface = "0";
668 string iface_name = basic_if_name;
669 for(pos=strlen(cdat)-1;pos>=0 && isdigit(cdat[pos]);--pos);
670 if(pos>0 && cdat[pos] == 'X' && pos<=strlen(cdat)-2){
672 virtual_iface = cdat+pos+1;
678 err_no = 1; err_str = "interface resource parse failed.";
682 vector<int> ifi = rpd->get_ifaces_by_Name(host_name, iface_name);
684 err_no = 1; err_str="interface not found.";
688 err_no = 1; err_str="multiple interfaces found.";
692 return rpd->get_interface(ifi[0]);