/**
   * Global load balancing virtual server and its bound services
   *
   * @param vServer
   * @return
   */
  private VirtualApplication parseGslbServer(gslbvserver vServer) {
    if (logger.isTraceEnabled()) logger.trace(logPrefix + vServer);

    // Retrieve the gslb virtual server information
    String vServerName, vServerUuid, vServerType;
    try {
      vServerName =
          vServer.get_name(); // name of the loading balancing virtual server, is changeable
      vServerUuid = "VirtualApplicationUuid" + "_" + vServerName; // create UUID, no target address
      // because the same service could be configured on multiple targets
      vServerType =
          vServer.get_servicetype(); // Protocol used by the service (also called the service type)
      if (logger.isDebugEnabled())
        logger.debug(
            logPrefix
                + "GSLB Load Balancing Server service name "
                + vServerName
                + "::service type "
                + vServerType
                + "::uuid "
                + vServerUuid);
    } catch (Exception e) {
      exceptions = true;
      logger.error(
          logPrefix
              + "Failed retrieving gslb virtual server information on target "
              + target.getNameOrAddress(),
          e);
      return null;
    }

    // Get the binding objects for the services bound to each load balancer virtual server on the
    // appliance
    gslbvserver_gslbservice_binding[] bindObjs =
        NetScalerUtil.getBoundGslbServices(session, vServerName, target, logPrefix);
    if (logger.isTraceEnabled()) {
      int length = (bindObjs == null) ? 0 : bindObjs.length;
      logger.trace(logPrefix + "GSLB Server " + vServerName + " has " + length + " bound services");
    }

    List<String> lbvServers = new ArrayList<String>();
    if (bindObjs != null) {
      try {
        for (gslbvserver_gslbservice_binding svcBinding : bindObjs) {
          // save all the  lb virtual server's ip addresses configured in the gslbvserver in this
          // list
          // we will encounter the local lb virtual server while parsing the lbvServers in the
          // target
          // VIP address of the load balancing virtual server
          lbvServers.add(svcBinding.get_ipaddress());
        }
      } catch (Exception ex) {
        exceptions = true;
        logger.error(
            logPrefix + "Failed retrieving  information for services bound to gslb " + vServerName,
            ex);
        ex.printStackTrace();
      }
    }
    if (logger.isDebugEnabled())
      logger.debug(
          logPrefix
              + "GSLB Server "
              + vServerName
              + " has these local LB virtual server VIPs "
              + lbvServers);

    VirtualApplication gslb;
    NetScalerGslbVirtualAppDiscExt vServerExt;
    synchronized (REPOSMAN) {
      // Create the VirtualApplication object
      gslb =
          (VirtualApplication)
              createObject(
                  AbstractionPackage.eINSTANCE.getVirtualApplication(),
                  NetScalerUtil.VAPP_PREFIX + vServerName,
                  vServerUuid);
      // create VirtualApp Discovery extension
      vServerExt =
          (NetScalerGslbVirtualAppDiscExt)
              gslb.createExtension(
                  DiscoveryExtensionsPackage.eINSTANCE.getNetScalerGslbVirtualAppDiscExt());

      for (String vserver :
          lbvServers) { // add instead of allAll, so the ones added by another target are not
                        // overwritten
        if (!vServerExt.getLbvServers().contains(vserver)) vServerExt.getLbvServers().add(vserver);
      }
      if (logger.isDebugEnabled())
        logger.debug(
            logPrefix
                + "GSLB Server "
                + vServerName
                + " saved LB virtual server VIPs "
                + vServerExt.getLbvServers());
      // create a map of the lbvservers and the gslb that it is bound to on this target
      // we use this to determine if we need to create vApps for
      // lbvservers when we encounter them on this target
      for (String lbvServer : lbvServers) {
        lbvServerVIPToGslbVAppMap.put(lbvServer, gslb);
      }

      // set properties in the virtual app and the discovery extension
      // and create the transaction commodity sold
      gslb =
          createGslbVirtualApplication(
              gslb,
              target,
              vServerExt,
              vServerName, // service name as the local name);
              vServerUuid, // uuid for the gslb vapp containing its service name only
              vServerType, // service type
              NetScalerUtil.GSLB_VSERVER, // class name for the poller
              lbvServers // list of lbvservers configured in the gslb on this target
              );
    }
    return gslb;
  }
  /**
   * parse Server - Parse load balancing virtual server configuration object obtained from the
   * NetScaler appliance and create a VirtualApplication and discovery extension.
   *
   * @param vServer Configuration for Load Balancing Virtual Server resource from the NetScaler
   *     appliance
   * @return VirtualApplication object
   */
  private VirtualApplication parseServer(lbvserver vServer) {

    if (logger.isTraceEnabled()) logger.trace(logPrefix + vServer);

    // Retrieve load balancing virtual server information
    String vServerName, vServerUuid, vServerIP, vServerType;
    int vServerPort;
    try {
      vServerName =
          vServer.get_name(); // name of the loading balancing virtual server, is changeable
      vServerIP = vServer.get_ipv46(); // IPv4 or IPv6 address assigned to the virtual server
      vServerPort = vServer.get_port(); // Port number for the virtual server
      vServerUuid = NetScalerUtil.getServerUuid(vServerIP, vServerPort, target); // create uuid
      vServerType =
          vServer.get_servicetype(); // Protocol used by the service (also called the service type)
      lbvserver_ip2serviceName.put(vServerIP, vServerName);
      if (logger.isDebugEnabled())
        logger.debug(
            logPrefix
                + "Load Balancing Server IP:: "
                + vServerIP
                + "::port "
                + vServerPort
                + "::service name "
                + vServerName
                + "::service type "
                + vServerType);
    } catch (Exception e) {
      exceptions = true;
      if (logger.isDebugEnabled())
        logger.error(logPrefix + "Failed retrieving virtual server information ", e);
      else logger.error(logPrefix + "Failed retrieving virtual server information " + e);
      NotificationsManagerImpl.vmtMANAGER.createException(
          target, e, NotificationCategory.DISCOVERY, VMTSeverity.MAJOR);
      return null;
    }

    // Get the binding objects for the services bound to each load balancer virtual server on the
    // appliance
    lbvserver_service_binding[] bindObjs =
        NetScalerUtil.getBoundServices(
            session, vServerName,
            target, logPrefix);
    if (logger.isTraceEnabled()) {
      int length = (bindObjs == null) ? 0 : bindObjs.length;
      logger.trace(
          logPrefix
              + "Load Balancing Server "
              + vServerName
              + " has "
              + length
              + " bound services");
    }

    // get application services information
    ip2port2serviceName.clear();
    ip2NameIPPort.clear();
    if (bindObjs != null) {
      for (lbvserver_service_binding bind : bindObjs) {
        String serviceIP, serviceName;
        Integer servicePort;
        try {
          serviceIP = bind.get_ipv46();
          serviceName = bind.get_servicename();
          servicePort = bind.get_port();
          // this info is needed to find and attach the applications objects
          // from the topology during post processing
          Map<Integer, String> port2name = new HashMap<Integer, String>();
          ip2port2serviceName.put(serviceIP, port2name);
          port2name.put(servicePort, serviceName);
          // we need this info (app service name::IP::Port) for saving in the gslb vApp
          ip2NameIPPort.put(serviceIP, serviceName + "::" + serviceIP + "::" + servicePort);
        } catch (Exception e) {
          exceptions = true;
          if (logger.isDebugEnabled())
            logger.error(
                logPrefix
                    + "Failed retrieving services information for virtual server with name "
                    + vServerName
                    + " ",
                e);
          else
            logger.error(
                logPrefix
                    + "Failed retrieving services information for virtual server with name "
                    + vServerName
                    + " "
                    + e);
          NotificationsManagerImpl.vmtMANAGER.createException(
              target, e, NotificationCategory.DISCOVERY, VMTSeverity.MINOR);
          continue;
        }
      }
    }
    if (logger.isDebugEnabled()) {
      logger.debug(
          logPrefix + "on lbvserver: " + vServerName + " app services ---> " + ip2NameIPPort);
      logger.debug(
          logPrefix + "on lbvserver: " + vServerName + " app services ---> " + ip2port2serviceName);
    }
    // whether to create vApp for this lbvserver VIP or not depends if it is managed by the gslb,
    // check if this VIP is in the service bindings for the gslb service configured on this target
    boolean createVApp = true;
    if (lbvServerVIPToGslbVAppMap.containsKey(vServerIP)) {
      // found this Virtual IP on this target
      // don't create the vApp for this lbvserver,
      createVApp = false;
      // Save all the application services info in the associated gslb vApp
      updateGslbVAppAgent(vServerIP, vServerPort);
    }

    // ------------ create objects ----------
    if (createVApp) {
      // Create the VirtualApplication object corresponding to the load balancing virtual server
      // discovered in NetScaler
      VirtualApplication lb =
          (VirtualApplication)
              createObject(
                  AbstractionPackage.eINSTANCE.getVirtualApplication(),
                  "VApp-" + vServerName,
                  vServerUuid);
      // create VirtualApp Discovery extension
      NetScalerVirtualAppDiscExt vServerExt =
          (NetScalerVirtualAppDiscExt)
              lb.createExtension(
                  DiscoveryExtensionsPackage.eINSTANCE.getNetScalerVirtualAppDiscExt());
      // set the properties for the vApp and discovery extension and also save the app services info
      // in the discovery extension
      return createVirtualApplication(
          lb,
          target,
          vServerExt,
          vServerName,
          vServerIP,
          vServerPort, // lbverserver's service name, ip and port
          vServerUuid,
          vServerType,
          ip2port2serviceName, // mappings of the connected services
          NetScalerUtil.LB_VSERVER // "lbvserver"
          );
    }

    return null;
  } // end parse server