OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
service_instance.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <sstream>
6 #include "service_instance.h"
7 
8 #include "ifmap/ifmap_node.h"
9 #include "schema/vnc_cfg_types.h"
10 
12 #include "oper/operdb_init.h"
13 #include <cfg/cfg_init.h>
14 #include <cmn/agent.h>
15 #include <init/agent_param.h>
16 #include <oper/agent_sandesh.h>
17 #include <oper/agent_types.h>
18 #include "oper/instance_manager.h"
19 
20 using boost::uuids::uuid;
21 
22 /*
23  * ServiceInstanceTable create requests contain the IFMapNode that this
24  * entry corresponds to.
25  */
27  public:
29  node_(node) {
30  }
31  IFMapNode *node() { return node_; }
32 
33  private:
35 };
36 
38 public:
39  static const std::string kOtherType;
40  static int StrServiceTypeToInt(const std::string &type);
41  static const std::string &IntServiceTypeToStr(
43  static int StrVirtualizationTypeToInt(const std::string &type);
44  static const std::string &IntVirtualizationTypeToStr(
46  static int StrVRouterInstanceTypeToInt(const std::string &type);
47  static const std::string &IntVRouterInstanceTypeToStr(
49 
50 private:
51  typedef std::map<std::string, int> StrTypeToIntMap;
52  typedef std::pair<std::string, int> StrTypeToIntPair;
56 
58  StrTypeToIntMap types;
59  types.insert(StrTypeToIntPair("source-nat", ServiceInstance::SourceNAT));
60  types.insert(StrTypeToIntPair("loadbalancer", ServiceInstance::LoadBalancer));
61 
62  return types;
63  };
64 
66  StrTypeToIntMap types;
67  types.insert(StrTypeToIntPair("virtual-machine", ServiceInstance::VirtualMachine));
68  types.insert(StrTypeToIntPair("network-namespace", ServiceInstance::NetworkNamespace));
69  types.insert(StrTypeToIntPair("vrouter-instance", ServiceInstance::VRouterInstance));
70 
71  return types;
72  };
73 
75  StrTypeToIntMap types;
76  types.insert(StrTypeToIntPair("libvirt-qemu", ServiceInstance::KVM));
77  types.insert(StrTypeToIntPair("docker", ServiceInstance::Docker));
78  return types;
79  };
80 };
81 
82 static uuid IdPermsGetUuid(const autogen::IdPermsType &id) {
83  uuid uuid;
84  CfgUuidSet(id.uuid.uuid_mslong, id.uuid.uuid_lslong, uuid);
85  return uuid;
86 }
87 
88 static bool IsNodeType(IFMapNode *node, const char *node_typename) {
89  return (strcmp(node->table()->Typename(), node_typename) == 0);
90 }
91 
92 /*
93  * Walks through the graph starting from the service instance in order to
94  * find the Virtual Machine associated. Set the vm_id of the ServiceInstanceData
95  * object and return the VM node.
96  */
98  DBGraph *graph, IFMapNode *si_node,
99  ServiceInstance::Properties *properties) {
100 
101  for (DBGraphVertex::adjacency_iterator iter = si_node->begin(graph);
102  iter != si_node->end(graph); ++iter) {
103  IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
104  if (IsNodeType(adj, "virtual-machine")) {
105  autogen::VirtualMachine *vm =
106  static_cast<autogen::VirtualMachine *>(adj->GetObject());
107  properties->instance_id = IdPermsGetUuid(vm->id_perms());
108  return adj;
109  }
110  }
111  return NULL;
112 }
113 
114 static IFMapNode *FindNetworkIpam(DBGraph *graph, IFMapNode *vn_ipam_node) {
115  for (DBGraphVertex::adjacency_iterator iter = vn_ipam_node->begin(graph);
116  iter != vn_ipam_node->end(graph); ++iter) {
117  IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
118 
119  if (IsNodeType(adj, "network-ipam")) {
120  return adj;
121  }
122  }
123  return NULL;
124 }
125 
126 static IFMapNode *FindNetwork(DBGraph *graph, IFMapNode *vmi_node) {
127  /*
128  * Lookup for VirtualNetwork nodes
129  */
130  for (DBGraphVertex::adjacency_iterator iter = vmi_node->begin(graph);
131  iter != vmi_node->end(graph); ++iter) {
132  IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
133  if (IsNodeType(adj, "virtual-network")) {
134  return adj;
135  }
136  }
137  return NULL;
138 }
139 
140 
141 static std::string FindInterfaceIp(DBGraph *graph, IFMapNode *vmi_node) {
142  for (DBGraphVertex::adjacency_iterator iter = vmi_node->begin(graph);
143  iter != vmi_node->end(graph); ++iter) {
144  IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
145  if (IsNodeType(adj, "instance-ip")) {
146  autogen::InstanceIp *ip =
147  static_cast<autogen::InstanceIp *>(adj->GetObject());
148  return ip->address();
149  }
150  }
151  return std::string();
152 }
153 
154 static bool SubNetContainsIpv4(const autogen::IpamSubnetType &subnet,
155  const std::string &ip) {
156  typedef boost::asio::ip::address_v4 Ipv4Address;
157  std::string prefix = subnet.subnet.ip_prefix;
158  int prefix_len = subnet.subnet.ip_prefix_len;
159 
160  boost::system::error_code ec;
161  Ipv4Address ipv4 = Ipv4Address::from_string(ip, ec);
162  Ipv4Address ipv4_prefix = Ipv4Address::from_string(prefix, ec);
163  unsigned long mask = (0xFFFFFFFF << (32 - prefix_len)) & 0xFFFFFFFF;
164 
165  if ((ipv4.to_ulong() & mask) == (ipv4_prefix.to_ulong() & mask)) {
166  return true;
167  }
168  return false;
169 }
170 
172  DBGraph *graph, IFMapNode *vm_node,
173  autogen::ServiceInstance *svc_instance,
174  ServiceInstance::Properties *properties) {
175 
176  /*
177  * The outside virtual-network is always specified (by the
178  * process that creates the service-instance).
179  * The inside virtual-network is optional for loadbalancer.
180  * For VRouter instance there can be up to 3 interfaces.
181  * TODO: support more than 3 interfaces for VRouter instances.
182  * Lookup for VMI nodes
183  */
184  properties->interface_count = 0;
185  for (DBGraphVertex::adjacency_iterator iter = vm_node->begin(graph);
186  iter != vm_node->end(graph); ++iter) {
187  IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
188  if (!IsNodeType(adj, "virtual-machine-interface")) {
189  continue;
190  }
191  autogen::VirtualMachineInterface *vmi =
192  static_cast<autogen::VirtualMachineInterface *>(
193  adj->GetObject());
194 
195  const autogen::VirtualMachineInterfacePropertiesType &vmi_props =
196  vmi->properties();
197 
198  IFMapNode *vn_node = FindNetwork(graph, adj);
199  if (vn_node == NULL) {
200  continue;
201  }
202 
203  properties->interface_count++;
204  if(vmi_props.service_interface_type == "left") {
205  properties->vmi_inside = IdPermsGetUuid(vmi->id_perms());
206  if (vmi->mac_addresses().size())
207  properties->mac_addr_inside = vmi->mac_addresses().at(0);
208  properties->ip_addr_inside = FindInterfaceIp(graph, adj);
209  }
210  else if(vmi_props.service_interface_type == "right") {
211  properties->vmi_outside = IdPermsGetUuid(vmi->id_perms());
212  if (vmi->mac_addresses().size())
213  properties->mac_addr_outside = vmi->mac_addresses().at(0);
214  properties->ip_addr_outside = FindInterfaceIp(graph, adj);
215  }
216  else if(vmi_props.service_interface_type == "management") {
217  properties->vmi_management = IdPermsGetUuid(vmi->id_perms());
218  if (vmi->mac_addresses().size())
219  properties->mac_addr_management = vmi->mac_addresses().at(0);
220  properties->ip_addr_management = FindInterfaceIp(graph, adj);
221  }
222 
223  for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
224  iter != vn_node->end(graph); ++iter) {
225  IFMapNode *vn_ipam_node =
226  static_cast<IFMapNode *>(iter.operator->());
227  if (!IsNodeType(vn_ipam_node, "virtual-network-network-ipam")) {
228  continue;
229  }
230  autogen::VirtualNetworkNetworkIpam *ipam =
231  static_cast<autogen::VirtualNetworkNetworkIpam *>
232  (vn_ipam_node->GetObject());
233  IFMapNode *ipam_node = FindNetworkIpam(graph, vn_ipam_node);
234  if (ipam_node == NULL) {
235  continue;
236  }
237  autogen::NetworkIpam *network_ipam =
238  static_cast<autogen::NetworkIpam *>(ipam_node->GetObject());
239  const std::string subnet_method =
240  boost::to_lower_copy(network_ipam->ipam_subnet_method());
241  const std::vector<autogen::IpamSubnetType> &subnets =
242  (subnet_method == "flat-subnet") ?
243  network_ipam->ipam_subnets() : ipam->data().ipam_subnets;
244  for (unsigned int i = 0; i < subnets.size(); ++i) {
245  int prefix_len = subnets[i].subnet.ip_prefix_len;
246  int service_type = properties->service_type;
247  if (vmi_props.service_interface_type == "left") {
248  std::string &ip_addr = properties->ip_addr_inside;
249  if (SubNetContainsIpv4(subnets[i], ip_addr)) {
250  properties->ip_prefix_len_inside = prefix_len;
251  if (service_type == ServiceInstance::SourceNAT)
252  properties->gw_ip = subnets[i].default_gateway;
253  }
254  } else if (vmi_props.service_interface_type == "right") {
255  std::string &ip_addr = properties->ip_addr_outside;
256  if (SubNetContainsIpv4(subnets[i], ip_addr)) {
257  properties->ip_prefix_len_outside = prefix_len;
258  if (service_type == ServiceInstance::LoadBalancer)
259  properties->gw_ip = subnets[i].default_gateway;
260  }
261  } else if (vmi_props.service_interface_type == "management") {
262  std::string &ip_addr = properties->ip_addr_management;
263  if (SubNetContainsIpv4(subnets[i], ip_addr))
264  properties->ip_prefix_len_management = prefix_len;
265  }
266  }
267  }
268  }
269 }
270 
271 /*
272  * Walks through the graph in order to get the template associated to the
273  * Service Instance Node and set the types in the ServiceInstanceData object.
274  */
275 static void FindAndSetTypes(DBGraph *graph, IFMapNode *si_node,
276  ServiceInstance::Properties *properties) {
277  IFMapNode *st_node = NULL;
278 
279  for (DBGraphVertex::adjacency_iterator iter = si_node->begin(graph);
280  iter != si_node->end(graph); ++iter) {
281  IFMapNode *adj = static_cast<IFMapNode *>(iter.operator->());
282  if (IsNodeType(adj, "service-template")) {
283  st_node = adj;
284  break;
285  }
286  }
287 
288  if (st_node == NULL) {
289  return;
290  }
291 
292  autogen::ServiceTemplate *svc_template =
293  static_cast<autogen::ServiceTemplate *>(st_node->GetObject());
294  autogen::ServiceTemplateType svc_template_props =
295  svc_template->properties();
296 
297  properties->service_type =
299  svc_template_props.service_type);
300 
301  properties->virtualization_type =
303  svc_template_props.service_virtualization_type);
304 
305  properties->vrouter_instance_type =
307  svc_template_props.vrouter_instance_type);
308 
309  properties->image_name = svc_template_props.image_name;
310  properties->instance_data = svc_template_props.instance_data;
311 }
312 
314  const std::vector<autogen::KeyValuePair> &kvps = properties->instance_kvps;
315  std::vector<autogen::KeyValuePair>::const_iterator iter;
316  for (iter = kvps.begin(); iter != kvps.end(); ++iter) {
317  autogen::KeyValuePair kvp = *iter;
318  if (kvp.key == "lb_uuid") {
319  properties->loadbalancer_id = kvp.value;
320  break;
321  }
322  }
323 }
324 
325 /*
326  * ServiceInstance Properties
327  */
329  service_type = 0;
332 
333  instance_id = boost::uuids::nil_uuid();
334 
335  vmi_inside = boost::uuids::nil_uuid();
336  vmi_outside = boost::uuids::nil_uuid();
337  vmi_management = boost::uuids::nil_uuid();
338 
339  mac_addr_inside.clear();
340  mac_addr_outside.clear();
341  mac_addr_management.clear();
342 
343  ip_addr_inside.clear();
344  ip_addr_outside.clear();
345  ip_addr_management.clear();
346 
347  gw_ip.clear();
348  image_name.clear();
349 
353 
354  interface_count = 0;
355 
356  instance_data.clear();
357  std::vector<autogen::KeyValuePair>::const_iterator iter;
358  for (iter = instance_kvps.begin(); iter != instance_kvps.end(); ++iter) {
359  autogen::KeyValuePair kvp = *iter;
360  kvp.Clear();
361  }
362 
363  loadbalancer_id.clear();
364 }
365 
366 static int compare_kvps(const std::vector<autogen::KeyValuePair> &lhs,
367  const std::vector<autogen::KeyValuePair> &rhs) {
368  int ret = 0;
369  int match;
370  int remining_rhs_items;
371  std::vector<autogen::KeyValuePair>::const_iterator iter1;
372  std::vector<autogen::KeyValuePair>::const_iterator iter2;
373 
374  iter1 = lhs.begin();
375  iter2 = rhs.begin();
376  match = 0;
377  remining_rhs_items = rhs.end() - rhs.begin();
378  while (iter1 != lhs.end()) {
379  while (iter2 != rhs.end()) {
380  if (iter1->key.compare(iter2->key) == 0) {
381  if ((ret = iter1->value.compare(iter2->value)) != 0) {
382  return ret;
383  }
384  remining_rhs_items--;
385  match = 1;
386  break;
387  }
388  iter2++;
389  }
390  if (match == 0) {
391  return 1;
392  }
393  match = 0;
394  iter2 = rhs.begin();
395  iter1++;
396  }
397 
398  if (remining_rhs_items)
399  return -1;
400 
401  return 0;
402 }
403 
404 template <typename Type>
405 static int compare(const Type &lhs, const Type &rhs) {
406  if (lhs < rhs) {
407  return -1;
408  }
409  if (rhs < lhs) {
410  return 1;
411  }
412  return 0;
413 }
414 
416  int cmp = 0;
417  cmp = compare(service_type, rhs.service_type);
418  if (cmp != 0) {
419  return cmp;
420  }
421  cmp = compare(vrouter_instance_type, rhs.vrouter_instance_type);
422  if (cmp != 0) {
423  return cmp;
424  }
425  cmp = compare(virtualization_type, rhs.virtualization_type);
426  if (cmp != 0) {
427  return cmp;
428  }
429  cmp = compare(instance_id, rhs.instance_id);
430  if (cmp != 0) {
431  return cmp;
432  }
433  cmp = compare(vmi_inside, rhs.vmi_inside);
434  if (cmp != 0) {
435  return cmp;
436  }
437  cmp = compare(vmi_outside, rhs.vmi_outside);
438  if (cmp != 0) {
439  return cmp;
440  }
441  cmp = compare(ip_addr_inside, rhs.ip_addr_inside);
442  if (cmp != 0) {
443  return cmp;
444  }
445  cmp = compare(ip_addr_outside, rhs.ip_addr_outside);
446  if (cmp != 0) {
447  return cmp;
448  }
449  cmp = compare(ip_prefix_len_inside, rhs.ip_prefix_len_inside);
450  if (cmp != 0) {
451  return cmp;
452  }
453  cmp = compare(ip_prefix_len_outside, rhs.ip_prefix_len_outside);
454  if (cmp != 0) {
455  return cmp;
456  }
457  cmp = compare(interface_count, rhs.interface_count);
458  if (cmp != 0) {
459  return cmp;
460  }
461 
462  cmp = compare(gw_ip, rhs.gw_ip);
463  if (cmp != 0) {
464  return cmp;
465  }
466  cmp = compare(image_name, rhs.image_name);
467  if (cmp != 0) {
468  return cmp;
469  }
470 
471  cmp = compare(instance_data, rhs.instance_data);
472  if (cmp != 0) {
473  return cmp;
474  }
475 
476  cmp = compare_kvps(instance_kvps, rhs.instance_kvps);
477  if (cmp != 0) {
478  return cmp;
479  }
480 
481  cmp = compare(loadbalancer_id, rhs.loadbalancer_id);
482  if (cmp != 0) {
483  return cmp;
484  }
485  return cmp;
486 }
487 
488 void InstanceKvpsDiffString(const std::vector<autogen::KeyValuePair> &lhs,
489  const std::vector<autogen::KeyValuePair> &rhs,
490  std::stringstream *ss) {
491  int ret = 0;
492  int match;
493  int remining_rhs_items;
494  std::vector<autogen::KeyValuePair>::const_iterator iter1;
495  std::vector<autogen::KeyValuePair>::const_iterator iter2;
496 
497  iter1 = lhs.begin();
498  iter2 = rhs.begin();
499  match = 0;
500  remining_rhs_items = rhs.size();
501  while (iter1 != lhs.end()) {
502  while (iter2 != rhs.end()) {
503  if (iter1->key.compare(iter2->key) == 0) {
504  remining_rhs_items--;
505  match = 1;
506  if ((ret = iter1->value.compare(iter2->value)) != 0) {
507  *ss << iter1->key << ": -" << iter1->value;
508  *ss << " +" << iter2->value;
509  break;
510  }
511  }
512  iter2++;
513  }
514  if (match == 0) {
515  *ss << " -" << iter1->key << ": " << iter1->value;
516  }
517  match = 0;
518  iter2 = rhs.begin();
519  iter1++;
520  }
521 
522  if (remining_rhs_items == 0)
523  return;
524 
525  iter1 = rhs.begin();
526  iter2 = lhs.begin();
527  match = 0;
528  while (iter1 != rhs.end()) {
529  while (iter2 != lhs.end()) {
530  if (iter1->key.compare(iter2->key) == 0) {
531  match = 1;
532  break;
533  }
534  iter2++;
535  }
536  if (match == 0) {
537  *ss << " +" << iter1->key << ": " << iter1->value;
538  }
539  match = 0;
540  iter2 = lhs.begin();
541  iter1++;
542  }
543 }
544 
546  const Properties &rhs) const {
547  std::stringstream ss;
548 
549  if (compare(service_type, rhs.service_type)) {
550  ss << " type: -" << service_type << " +" << rhs.service_type;
551  }
552  if (compare(virtualization_type, rhs.virtualization_type)) {
553  ss << " virtualization: -" << virtualization_type
554  << " +" << rhs.virtualization_type;
555  }
556  if (compare(vrouter_instance_type, rhs.vrouter_instance_type)) {
557  ss << " vrouter-instance-type: -" << vrouter_instance_type
558  << " +" << rhs.vrouter_instance_type;
559  }
560  if (compare(instance_id, rhs.instance_id)) {
561  ss << " id: -" << instance_id << " +" << rhs.instance_id;
562  }
563  if (compare(vmi_inside, rhs.vmi_inside)) {
564  ss << " vmi-inside: -" << vmi_inside << " +" << rhs.vmi_inside;
565  }
566  if (compare(vmi_outside, rhs.vmi_outside)) {
567  ss << " vmi-outside: -" << vmi_outside << " +" << rhs.vmi_outside;
568  }
569  if (compare(ip_addr_inside, rhs.ip_addr_inside)) {
570  ss << " ip-inside: -" << ip_addr_inside
571  << " +" << rhs.ip_addr_inside;
572  }
573  if (compare(ip_addr_outside, rhs.ip_addr_outside)) {
574  ss << " ip-outside: -" << ip_addr_outside
575  << " +" << rhs.ip_addr_outside;
576  }
577  if (compare(ip_prefix_len_inside, rhs.ip_prefix_len_inside)) {
578  ss << " pfx-inside: -" << ip_prefix_len_inside
579  << " +" << rhs.ip_prefix_len_inside;
580  }
581  if (compare(ip_prefix_len_outside, rhs.ip_prefix_len_outside)) {
582  ss << " pfx-outside: -" << ip_prefix_len_outside
583  << " +" << rhs.ip_prefix_len_outside;
584  }
585 
586  if (compare(loadbalancer_id, rhs.loadbalancer_id)) {
587  ss << " loadbalancer_id: -" << loadbalancer_id << " +"
588  << rhs.loadbalancer_id;
589  }
590 
591  if (compare(gw_ip, rhs.gw_ip)) {
592  ss << " gw_ip: -" << gw_ip << " +" << rhs.gw_ip;
593  }
594  if (compare(image_name, rhs.image_name)) {
595  ss << " image: -" << image_name << " +" << rhs.image_name;
596  }
597  if (compare(instance_data, rhs.instance_data)) {
598  ss << " image: -" << instance_data << " +" << rhs.instance_data;
599  }
600  if (compare_kvps(instance_kvps, rhs.instance_kvps)) {
601  InstanceKvpsDiffString(instance_kvps, rhs.instance_kvps, &ss);
602  }
603  return ss.str();
604 }
605 
607  if (instance_id.is_nil()) {
608  return false;
609  }
610 
611  if (virtualization_type == ServiceInstance::VRouterInstance) {
612  //TODO: investigate for docker
613  return true;
614  }
615 
616  bool common = (!vmi_outside.is_nil() &&
617  !ip_addr_outside.empty() &&
618  (ip_prefix_len_outside >= 0));
619  if (!common) {
620  return false;
621  }
622 
623  if (service_type == SourceNAT || interface_count == 2) {
624  bool outside = (!vmi_inside.is_nil() &&
625  !ip_addr_inside.empty() &&
626  (ip_prefix_len_inside >= 0));
627  if (!outside) {
628  return false;
629  }
630  }
631 
632  if (gw_ip.empty())
633  return false;
634 
635  if (service_type == LoadBalancer) {
636  if (loadbalancer_id.empty())
637  return false;
638  }
639 
640  return true;
641 }
642 
645  static_cast<ServiceType>(service_type));
646 }
647 
648 /*
649  * ServiceInstance class
650  */
652  properties_.Clear();
653 }
654 
655 bool ServiceInstance::IsLess(const DBEntry &rhs) const {
656  const ServiceInstance &si = static_cast<const ServiceInstance &>(rhs);
657  return uuid_ < si.uuid_;
658 }
659 
660 std::string ServiceInstance::ToString() const {
661  return UuidToString(uuid_);
662 }
663 
665  const ServiceInstanceKey *si_key =
666  static_cast<const ServiceInstanceKey *>(key);
667  uuid_ = si_key->instance_id();
668 }
669 
672  return KeyPtr(key);
673 }
674 
675 bool ServiceInstance::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
676  ServiceInstanceResp *resp = static_cast<ServiceInstanceResp *> (sresp);
677 
678  std::string str_uuid = UuidToString(uuid_);
679  if (! name.empty() && str_uuid != name) {
680  return false;
681  }
682 
683  ServiceInstanceSandeshData data;
684 
685  data.set_uuid(str_uuid);
686  data.set_instance_id(UuidToString(properties_.instance_id));
687 
689  static_cast<ServiceType>(properties_.service_type)));
690  data.set_virtualization_type(
692  static_cast<VirtualizationType>(
694 
695  data.set_vmi_inside(UuidToString(properties_.vmi_inside));
696  data.set_vmi_outside(UuidToString(properties_.vmi_outside));
697 
698  Agent *agent = Agent::GetInstance();
699  DBTableBase *si_table = agent->db()->FindTable("db.service-instance.0");
700  assert(si_table);
701 
702  InstanceManager *manager = agent->oper_db()->instance_manager();
703  assert(manager);
704 
705  InstanceState *state = manager->GetState(const_cast<ServiceInstance *>(this));
706  if (state != NULL) {
707  NamespaceStateSandeshData state_data;
708 
709  state_data.set_cmd(state->cmd());
710  state_data.set_errors(state->errors());
711  state_data.set_pid(state->pid());
712  state_data.set_status(state->status());
713  state_data.set_status_type(state->status_type());
714 
715  data.set_ns_state(state_data);
716  }
717 
718  std::vector<ServiceInstanceSandeshData> &list =
719  const_cast<std::vector<ServiceInstanceSandeshData>&>
720  (resp->get_service_instance_list());
721  list.push_back(data);
722 
723  return true;
724 }
725 
727  return properties_.Usable();
728 }
729 
730 void ServiceInstanceReq::HandleRequest() const {
731  AgentSandeshPtr sand(new AgentServiceInstanceSandesh(context(),
732  get_uuid()));
733  sand->DoSandesh(sand);
734 }
735 
737 (const AgentSandeshArguments *args, const std::string &context){
738  return AgentSandeshPtr
739  (new AgentServiceInstanceSandesh(context, args->GetString("name")));
740 }
741 
742 /*
743  * ServiceInstanceTable class
744  */
745 ServiceInstanceTable::ServiceInstanceTable(DB *db, const std::string &name)
746  : AgentDBTable(db, name),
747  graph_(NULL), dependency_manager_(NULL) {
748 }
749 
750 std::unique_ptr<DBEntry> ServiceInstanceTable::AllocEntry(
751  const DBRequestKey *key) const {
752  std::unique_ptr<DBEntry> entry(new ServiceInstance());
753  entry->SetKey(key);
754  return entry;
755 }
756 
758  **svc_instancep, const DBRequest *request) {
759 
760  ServiceInstanceCreate *data =
761  static_cast<ServiceInstanceCreate *>(request->data.get());
762  if (!data)
763  return false;
764 
765  IFMapNode *node = data->node();
766  ServiceInstance *svc_instance = *svc_instancep;
767 
768  assert(graph_);
769  ServiceInstance::Properties properties;
770  properties.Clear();
771  CalculateProperties(graph_, node, &properties);
772 
773  assert(dependency_manager_);
774 
775  if (!svc_instance) {
776  svc_instance = new ServiceInstance();
777  *svc_instancep = svc_instance;
778  }
779 
780  if (!svc_instance->ifmap_node()) {
781  svc_instance->SetKey(request->key.get());
782  svc_instance->SetIFMapNodeState
783  (dependency_manager_->SetState(node));
784  dependency_manager_->SetObject(node, svc_instance);
785  }
786 
787  if (properties.CompareTo(svc_instance->properties()) == 0)
788  return false;
789 
790  if (svc_instance->properties().Usable() != properties.Usable()) {
791  LOG(DEBUG, "service-instance properties change" <<
792  svc_instance->properties().DiffString(properties));
793  }
794 
795  svc_instance->set_properties(properties);
796  return true;
797 }
798 
799 
801  ServiceInstance *svc_instance = NULL;
802  HandleAddChange(&svc_instance, request);
803  return svc_instance;
804 }
805 
806 bool ServiceInstanceTable::Delete(DBEntry *entry, const DBRequest *request) {
807  ServiceInstance *svc_instance = static_cast<ServiceInstance *>(entry);
808  assert(dependency_manager_);
809  if (svc_instance->ifmap_node()) {
810  dependency_manager_->SetObject(svc_instance->ifmap_node(), NULL);
811  svc_instance->SetIFMapNodeState(NULL);
812  }
813  return true;
814 }
815 
816 bool ServiceInstanceTable::OnChange(DBEntry *entry, const DBRequest *request) {
817  ServiceInstance *svc_instance = static_cast<ServiceInstance *>(entry);
818 
819  return HandleAddChange(&svc_instance, request);
820 }
821 
823  DBGraph *graph, IFMapDependencyManager *dependency_manager) {
824 
825  graph_ = graph;
826  dependency_manager_ = dependency_manager;
827 
829  "service-instance",
830  boost::bind(&ServiceInstanceTable::ChangeEventHandler, this, _1, _2));
831 }
832 
834  &request, const boost::uuids::uuid &id) {
835 
836  assert(!id.is_nil());
837 
838  request.key.reset(new ServiceInstanceKey(id));
839  if ((request.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
841  return true;
842  }
843 
845  request.data.reset(new ServiceInstanceCreate(node));
846  return true;
847 }
848 
850  DBGraph *graph, IFMapNode *node, ServiceInstance::Properties *properties) {
851 
852  properties->Clear();
853 
854  if (node->IsDeleted()) {
855  return;
856  }
857 
858  FindAndSetTypes(graph, node, properties);
859 
860  /*
861  * The vrouter agent is only interest in the properties of service
862  * instances that are implemented as a network-namespace.
863  */
866  return;
867  }
868 
869  IFMapNode *vm_node = FindAndSetVirtualMachine(graph, node, properties);
870  if (vm_node == NULL) {
871  return;
872  }
873 
874  autogen::ServiceInstance *svc_instance =
875  static_cast<autogen::ServiceInstance *>(node->GetObject());
876  properties->instance_kvps = svc_instance->bindings();
877  FindAndSetInterfaces(graph, vm_node, svc_instance, properties);
878 
879  if (properties->service_type == ServiceInstance::LoadBalancer) {
880  FindAndSetLoadbalancer(properties);
881  }
882 }
883 
885  autogen::ServiceInstance *svc_instance =
886  static_cast<autogen::ServiceInstance *>(node->GetObject());
887  const autogen::IdPermsType &id = svc_instance->id_perms();
888  idperms_uuid = IdPermsGetUuid(id);
889  return true;
890 }
892 
893  DBRequest req;
894  boost::uuids::uuid new_uuid;
895  IFNodeToUuid(node, new_uuid);
897  boost::uuids::uuid old_uuid = state->uuid();
898 
899  if (!node->IsDeleted()) {
900  if (entry) {
901  if ((old_uuid != new_uuid)) {
902  if (old_uuid != boost::uuids::nil_uuid()) {
904  if (IFNodeToReq(node, req, old_uuid) == true) {
905  assert(req.oper == DBRequest::DB_ENTRY_DELETE);
906  Enqueue(&req);
907  }
908  }
909  }
910  }
911  assert(new_uuid != boost::uuids::nil_uuid());
912  state->set_uuid(new_uuid);
914  } else {
915  if (old_uuid == boost::uuids::nil_uuid()) {
916  //Node was never added so no point sending delete
917  return;
918  }
920  new_uuid = old_uuid;
921  }
922 
923  if (IFNodeToReq(node, req, new_uuid) == true) {
924  Enqueue(&req);
925  }
926 }
927 
929  DB *db, const std::string &name) {
930  ServiceInstanceTable *table = new ServiceInstanceTable(db, name);
931  table->Init();
932  return table;
933 }
934 
935 /*
936  * ServiceInstanceTypeMapping class
937  */
941 ServiceInstanceTypesMapping::virtualization_type_map_ = InitVirtualizationTypeMap();
943 ServiceInstanceTypesMapping::vrouter_instance_type_map_ = InitVRouterInstanceTypeMap();
944 const std::string ServiceInstanceTypesMapping::kOtherType = "Other";
945 
947  StrTypeToIntMap::const_iterator it = service_type_map_.find(type);
948  if (it != service_type_map_.end()) {
949  return it->second;
950  }
951  return 0;
952 }
953 
955  const std::string &type) {
956  StrTypeToIntMap::const_iterator it = virtualization_type_map_.find(type);
957  if (it != virtualization_type_map_.end()) {
958  return it->second;
959  }
960  return 0;
961 }
962 
964  const std::string &type) {
965  StrTypeToIntMap::const_iterator it = vrouter_instance_type_map_.find(type);
966  if (it != vrouter_instance_type_map_.end()) {
967  return it->second;
968  }
969  return 0;
970 }
971 
974  for (StrTypeToIntMap::const_iterator it = service_type_map_.begin();
975  it != service_type_map_.end(); ++it) {
976  if (it->second == type) {
977  return it->first;
978  }
979  }
980  return kOtherType;
981 }
982 
985  for (StrTypeToIntMap::const_iterator it = virtualization_type_map_.begin();
986  it != virtualization_type_map_.end(); ++it) {
987  if (it->second == type) {
988  return it->first;
989  }
990  }
991  return kOtherType;
992 }
993 
996  for (StrTypeToIntMap::const_iterator it = vrouter_instance_type_map_.begin();
997  it != virtualization_type_map_.end(); ++it) {
998  if (it->second == type) {
999  return it->first;
1000  }
1001  }
1002  return kOtherType;
1003 }
boost::uuids::uuid uuid()
IFMapNode * ifmap_node()
static StrTypeToIntMap vrouter_instance_type_map_
static StrTypeToIntMap InitVirtualizationTypeMap()
IFMapDependencyManager * dependency_manager_
void Initialize(DBGraph *graph, IFMapDependencyManager *dependency_manager)
static Agent * GetInstance()
Definition: agent.h:436
static void CfgUuidSet(uint64_t ms_long, uint64_t ls_long, boost::uuids::uuid &u)
Definition: agent_cmn.h:67
static DBTableBase * CreateTable(DB *db, const std::string &name)
static void FindAndSetLoadbalancer(ServiceInstance::Properties *properties)
void SetObject(IFMapNode *node, DBEntry *entry)
std::string GetString(const std::string &key) const
static StrTypeToIntMap virtualization_type_map_
static int StrServiceTypeToInt(const std::string &type)
IFMapNodeState * IFMapNodeGet(IFMapNode *node)
static std::string FindInterfaceIp(DBGraph *graph, IFMapNode *vmi_node)
static StrTypeToIntMap InitServiceTypeMap()
static void FindAndSetTypes(DBGraph *graph, IFMapNode *si_node, ServiceInstance::Properties *properties)
DB * db() const
Definition: agent.h:1118
static bool IsNodeType(IFMapNode *node, const char *node_typename)
void set_uuid(const boost::uuids::uuid &u)
static StrTypeToIntMap service_type_map_
bool IsDeleted() const
Definition: db_entry.h:49
void Register(const std::string &type, ChangeEventHandler handler)
void CalculateProperties(DBGraph *graph, IFMapNode *node, ServiceInstance::Properties *properties)
static int compare_kvps(const std::vector< autogen::KeyValuePair > &lhs, const std::vector< autogen::KeyValuePair > &rhs)
bool IsUsable() const
const std::string & ServiceTypeString() const
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
static IFMapNode * FindNetworkIpam(DBGraph *graph, IFMapNode *vn_ipam_node)
virtual const char * Typename() const =0
bool HandleAddChange(ServiceInstance **svc_instance, const DBRequest *key)
static bool SubNetContainsIpv4(const autogen::IpamSubnetType &subnet, const std::string &ip)
bool Enqueue(DBRequest *req)
Definition: db_table.cc:194
boost::uuids::uuid uuid
void set_cmd(const std::string &cmd)
adjacency_iterator end(DBGraph *graph)
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
virtual KeyPtr GetDBRequestKey() const
IFMapTable * table()
Definition: ifmap_node.h:29
virtual bool OnChange(DBEntry *entry, const DBRequest *request)
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *key) const
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
static void FindAndSetInterfaces(DBGraph *graph, IFMapNode *vm_node, autogen::ServiceInstance *svc_instance, ServiceInstance::Properties *properties)
std::string cmd() const
static StrTypeToIntMap InitVRouterInstanceTypeMap()
OperDB * oper_db() const
Definition: agent.cc:1013
static IFMapNode * FindNetwork(DBGraph *graph, IFMapNode *vmi_node)
Definition: db.h:24
int CompareTo(const Properties &rhs) const
void Init()
Definition: db_table.cc:387
Properties properties_
InstanceManager * instance_manager()
Definition: operdb_init.h:64
InstanceState * GetState(ServiceInstance *) const
uint8_t type
Definition: load_balance.h:109
Definition: agent.h:358
pid_t pid() const
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
boost::uuids::uuid instance_id
virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &id)
boost::uuids::uuid vmi_outside
boost::uuids::uuid vmi_management
DBOperation oper
Definition: db_table.h:42
void set_properties(const Properties &properties)
static uuid IdPermsGetUuid(const autogen::IdPermsType &id)
virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args, const std::string &context)
std::vector< autogen::KeyValuePair > instance_kvps
std::string errors() const
class boost::shared_ptr< AgentSandesh > AgentSandeshPtr
Definition: agent_db.h:18
static const std::string & IntServiceTypeToStr(const ServiceInstance::ServiceType &type)
boost::uuids::uuid uuid_
static const std::string & IntVRouterInstanceTypeToStr(const ServiceInstance::VRouterInstanceType &type)
virtual bool Delete(DBEntry *entry, const DBRequest *request)
bool DBEntrySandesh(Sandesh *sresp, std::string &name) const
ServiceInstanceTable(DB *db, const std::string &name)
IFMapNodePtr SetState(IFMapNode *node)
const Properties & properties() const
virtual void SetKey(const DBRequestKey *key)
IFMapObject * GetObject()
Definition: ifmap_node.cc:63
static const std::string & IntVirtualizationTypeToStr(const ServiceInstance::VirtualizationType &type)
virtual DBEntry * Add(const DBRequest *request)
const boost::uuids::uuid & instance_id() const
static IFMapNode * FindAndSetVirtualMachine(DBGraph *graph, IFMapNode *si_node, ServiceInstance::Properties *properties)
static int compare(const Type &lhs, const Type &rhs)
void InstanceKvpsDiffString(const std::vector< autogen::KeyValuePair > &lhs, const std::vector< autogen::KeyValuePair > &rhs, std::stringstream *ss)
virtual bool IsLess(const DBEntry &rhs) const
static const std::string kOtherType
std::string DiffString(const Properties &rhs) const
std::pair< std::string, int > StrTypeToIntPair
#define LOG(_Level, _Msg)
Definition: logging.h:33
static int StrVRouterInstanceTypeToInt(const std::string &type)
static int StrVirtualizationTypeToInt(const std::string &type)
virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req, const boost::uuids::uuid &u)
ServiceInstanceCreate(IFMapNode *node)
void ChangeEventHandler(IFMapNode *node, DBEntry *entry)
void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr ref)
boost::uuids::uuid vmi_inside
adjacency_iterator begin(DBGraph *graph)
pid_t status() const
virtual std::string ToString() const
int status_type() const
DBTableBase * FindTable(const std::string &name)
Definition: db.cc:68
std::map< std::string, int > StrTypeToIntMap