LCOV - code coverage report
Current view: top level - vnsw/agent/oper - service_instance.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 28 578 4.8 %
Date: 2026-06-08 02:02:55 Functions: 6 52 11.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14