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

Generated by: LCOV version 1.14