private synchronized boolean enableAutoScaleConfig()

in plugins/network-elements/netscaler/src/main/java/com/cloud/network/resource/NetscalerResource.java [2954:3282]


    private synchronized boolean enableAutoScaleConfig(final LoadBalancerTO loadBalancerTO, final boolean isCleanUp) throws Exception {
        final String vmGroupIdentifier = generateAutoScaleVmGroupIdentifier(loadBalancerTO);
        final String srcIp = loadBalancerTO.getSrcIp();
        final int srcPort = loadBalancerTO.getSrcPort();

        final String nsVirtualServerName = generateNSVirtualServerName(srcIp, srcPort);
        final String serviceGroupName = generateAutoScaleServiceGroupName(loadBalancerTO);
        final String profileName = generateAutoScaleProfileName(vmGroupIdentifier);
        final String timerName = generateAutoScaleTimerName(vmGroupIdentifier);
        final String scaleDownActionName = generateAutoScaleScaleDownActionName(vmGroupIdentifier);
        final String scaleUpActionName = generateAutoScaleScaleUpActionName(vmGroupIdentifier);
        final String mtName = generateSnmpMetricTableName(vmGroupIdentifier);
        final String monitorName = generateSnmpMonitorName(vmGroupIdentifier);
        final AutoScaleVmGroupTO vmGroupTO = loadBalancerTO.getAutoScaleVmGroupTO();
        final AutoScaleVmProfileTO profileTO = vmGroupTO.getProfile();
        final List<AutoScalePolicyTO> policies = vmGroupTO.getPolicies();
        final int interval = vmGroupTO.getInterval();
        String snmpCommunity = null;
        int snmpPort = DEFAULT_SNMP_PORT;
        long cur_prirotiy = 1;

        // get the session persistence parameters
        final List<Pair<String, String>> paramsList = profileTO.getCounterParamList();
        for (final Pair<String, String> param : paramsList) {
            if ("snmpcommunity".equalsIgnoreCase(param.first())) {
                snmpCommunity = param.second();
            } else if ("snmpport".equalsIgnoreCase(param.first())) {
                snmpPort = Integer.parseInt(param.second());
            }
        }

        try {
            // Set min and max autoscale members;
            // add lb vserver lb  http 10.102.31.100 80 -minAutoscaleMinMembers 3 -maxAutoscaleMembers 10
            final int minAutoScaleMembers = vmGroupTO.getMinMembers();
            final int maxAutoScaleMembers = vmGroupTO.getMaxMembers();
            final lbvserver vserver = new lbvserver();
            try {
                vserver.set_name(nsVirtualServerName);
                vserver.set_minautoscalemembers(minAutoScaleMembers);
                vserver.set_maxautoscalemembers(maxAutoScaleMembers);
                lbvserver.update(_netscalerService, vserver);
            } catch (final Exception e) {
                // Ignore Exception on cleanup
                if (!isCleanUp) {
                    throw e;
                }
            }

            /* AutoScale Config */
            // Add AutoScale Profile
            // add autoscale profile lb_asprofile CLOUDSTACK -url -http:// 10.102.31.34:8080/client/api- -apiKey abcdef
            // -sharedSecret xyzabc
            final String apiKey = profileTO.getAutoScaleUserApiKey();
            final String secretKey = profileTO.getAutoScaleUserSecretKey();
            final String url = profileTO.getCloudStackApiUrl();

            final autoscaleprofile autoscaleProfile = new autoscaleprofile();
            try {
                autoscaleProfile.set_name(profileName);
                autoscaleProfile.set_type("CLOUDSTACK");
                autoscaleProfile.set_apikey(apiKey);
                autoscaleProfile.set_sharedsecret(secretKey);
                autoscaleProfile.set_url(url);
                autoscaleprofile.add(_netscalerService, autoscaleProfile);
            } catch (final Exception e) {
                // Ignore Exception on cleanup
                if (!isCleanUp) {
                    throw e;
                }
            }

            // Add Timer
            final nstimer timer = new nstimer();
            try {
                timer.set_name(timerName);
                timer.set_interval(interval);
                nstimer.add(_netscalerService, timer);
            } catch (final Exception e) {
                // Ignore Exception on cleanup
                if (!isCleanUp) {
                    throw e;
                }
            }

            // AutoScale Actions
            Integer scaleUpQuietTime = null;
            Integer scaleDownQuietTime = null;
            for (final AutoScalePolicyTO autoScalePolicyTO : policies) {
                if (scaleUpQuietTime == null) {
                    if (isScaleUpPolicy(autoScalePolicyTO)) {
                        scaleUpQuietTime = autoScalePolicyTO.getQuietTime();
                        if (scaleDownQuietTime != null) {
                            break;
                        }
                    }
                }
                if (scaleDownQuietTime == null) {
                    if (isScaleDownPolicy(autoScalePolicyTO)) {
                        scaleDownQuietTime = autoScalePolicyTO.getQuietTime();
                        if (scaleUpQuietTime != null) {
                            break;
                        }
                    }
                }
            }

            // Add AutoScale ScaleUp action
            // add autoscale action lb_scaleUpAction provision -vserver lb -profilename lb_asprofile -params
            // -lbruleid=1234&command=deployvm&zoneid=10&templateid=5&serviceofferingid=3- -quiettime 300
            final com.citrix.netscaler.nitro.resource.config.autoscale.autoscaleaction scaleUpAction =
                    new com.citrix.netscaler.nitro.resource.config.autoscale.autoscaleaction();
            try {
                scaleUpAction.set_name(scaleUpActionName);
                scaleUpAction.set_type("SCALE_UP"); // TODO: will this be called provision?
                scaleUpAction.set_vserver(nsVirtualServerName); // Actions Vserver, the one that is autoscaled, with CS
                // now both are same. Not exposed in API.
                scaleUpAction.set_profilename(profileName);
                if(scaleUpQuietTime != null) {
                    scaleUpAction.set_quiettime(scaleUpQuietTime);
                }
                final String scaleUpParameters =
                        "command=deployVirtualMachine" + "&" + ApiConstants.ZONE_ID + "=" + profileTO.getZoneId() + "&" + ApiConstants.SERVICE_OFFERING_ID + "=" +
                                profileTO.getServiceOfferingId() + "&" + ApiConstants.TEMPLATE_ID + "=" + profileTO.getTemplateId() + "&" + ApiConstants.DISPLAY_NAME + "=" +
                                profileTO.getVmName() + "&" + (profileTO.getNetworkId() == null ? "" : ApiConstants.NETWORK_IDS + "=" + profileTO.getNetworkId() + "&") +
                                (profileTO.getOtherDeployParams() == null ? "" : profileTO.getOtherDeployParams() + "&") + "lbruleid=" + loadBalancerTO.getUuid();
                scaleUpAction.set_parameters(scaleUpParameters);
                autoscaleaction.add(_netscalerService, scaleUpAction);
            } catch (final Exception e) {
                // Ignore Exception on cleanup
                if (!isCleanUp) {
                    throw e;
                }
            }

            final com.citrix.netscaler.nitro.resource.config.autoscale.autoscaleaction scaleDownAction =
                    new com.citrix.netscaler.nitro.resource.config.autoscale.autoscaleaction();
            final Integer expungeVmGracePeriod = profileTO.getExpungeVmGracePeriod();
            try {
                scaleDownAction.set_name(scaleDownActionName);
                scaleDownAction.set_type("SCALE_DOWN"); // TODO: will this be called de-provision?
                scaleDownAction.set_vserver(nsVirtualServerName); // TODO: no global option as of now through Nitro.
                // Testing cannot be done.
                scaleDownAction.set_profilename(profileName);
                scaleDownAction.set_quiettime(scaleDownQuietTime);
                final String scaleDownParameters = "command=destroyVirtualMachine" + "&" + "lbruleid=" + loadBalancerTO.getUuid();
                scaleDownAction.set_parameters(scaleDownParameters);
                scaleDownAction.set_vmdestroygraceperiod(expungeVmGracePeriod);
                autoscaleaction.add(_netscalerService, scaleDownAction);
            } catch (final Exception e) {
                // Ignore Exception on cleanup
                if (!isCleanUp) {
                    throw e;
                }
            }

            /* Create min member policy */
            final String minMemberPolicyName = generateAutoScaleMinPolicyName(vmGroupIdentifier);
            final String minMemberPolicyExp =
                    "SYS.VSERVER(\"" + nsVirtualServerName + "\").ACTIVESERVICES.LT(SYS.VSERVER(\"" + nsVirtualServerName + "\").MINAUTOSCALEMEMBERS)";
            addAutoScalePolicy(timerName, minMemberPolicyName, cur_prirotiy++, minMemberPolicyExp, scaleUpActionName, interval, interval, isCleanUp);

            /* Create max member policy */
            final String maxMemberPolicyName = generateAutoScaleMaxPolicyName(vmGroupIdentifier);
            final String maxMemberPolicyExp =
                    "SYS.VSERVER(\"" + nsVirtualServerName + "\").ACTIVESERVICES.GT(SYS.VSERVER(\"" + nsVirtualServerName + "\").MAXAUTOSCALEMEMBERS)";
            addAutoScalePolicy(timerName, maxMemberPolicyName, cur_prirotiy++, maxMemberPolicyExp, scaleDownActionName, interval, interval, isCleanUp);

            /* Create Counters */
            final HashMap<String, Integer> snmpMetrics = new HashMap<String, Integer>();
            for (final AutoScalePolicyTO autoScalePolicyTO : policies) {
                final List<ConditionTO> conditions = autoScalePolicyTO.getConditions();
                String policyExpression = "";
                int snmpCounterNumber = 0;
                for (final ConditionTO conditionTO : conditions) {
                    final CounterTO counterTO = conditionTO.getCounter();
                    String counterName = counterTO.getName();
                    final Condition.Operator operator = conditionTO.getRelationalOperator();
                    final long threshold = conditionTO.getThreshold();

                    final StringBuilder conditionExpression = new StringBuilder();
                    try(Formatter formatter = new Formatter(conditionExpression, Locale.US);) {

                        if (counterTO.getSource().equals(Counter.Source.SNMP)) {
                            counterName = generateSnmpMetricName(counterName);
                            if (snmpMetrics.size() == 0) {
                                // Create Metric Table
                                //add lb metricTable lb_metric_table
                                final lbmetrictable metricTable = new lbmetrictable();
                                try {
                                    metricTable.set_metrictable(mtName);
                                    lbmetrictable.add(_netscalerService, metricTable);
                                } catch (final Exception e) {
                                    // Ignore Exception on cleanup
                                    if (!isCleanUp) {
                                        throw e;
                                    }
                                }

                                // Create Monitor
                                // add lb monitor lb_metric_table_mon LOAD -destPort 161 -snmpCommunity public -metricTable
                                // lb_metric_table -interval <policy_interval == 80% >
                                final lbmonitor monitor = new lbmonitor();
                                try {
                                    monitor.set_monitorname(monitorName);
                                    monitor.set_type("LOAD");
                                    monitor.set_destport(snmpPort);
                                    monitor.set_snmpcommunity(snmpCommunity);
                                    monitor.set_metrictable(mtName);
                                    monitor.set_interval((int)(interval * 0.8));
                                    lbmonitor.add(_netscalerService, monitor);
                                } catch (final Exception e) {
                                    // Ignore Exception on cleanup
                                    if (!isCleanUp) {
                                        throw e;
                                    }
                                }

                                // Bind monitor to servicegroup.
                                // bind lb monitor lb_metric_table_mon lb_autoscaleGroup -passive
                                final servicegroup_lbmonitor_binding servicegroup_monitor_binding = new servicegroup_lbmonitor_binding();
                                try {
                                    servicegroup_monitor_binding.set_servicegroupname(serviceGroupName);
                                    servicegroup_monitor_binding.set_monitor_name(monitorName);

                                    // Use the monitor for autoscaling purpose only.
                                    // Don't mark service members down when metric breaches threshold
                                    servicegroup_monitor_binding.set_passive(true);

                                    servicegroup_lbmonitor_binding.add(_netscalerService, servicegroup_monitor_binding);
                                } catch (final Exception e) {
                                    // Ignore Exception on cleanup
                                    if (!isCleanUp) {
                                        throw e;
                                    }
                                }
                            }

                            final boolean newMetric = !snmpMetrics.containsKey(counterName);
                            if (newMetric) {
                                snmpMetrics.put(counterName, snmpCounterNumber++);
                            }

                            if (newMetric) {
                                // bind lb metricTable lb_metric_table mem 1.3.6.1.4.1.2021.11.9.0
                                final String counterOid = counterTO.getValue();
                                final lbmetrictable_metric_binding metrictable_metric_binding = new lbmetrictable_metric_binding();
                                try {
                                    metrictable_metric_binding.set_metrictable(mtName);
                                    metrictable_metric_binding.set_metric(counterName);
                                    metrictable_metric_binding.set_Snmpoid(counterOid);
                                    lbmetrictable_metric_binding.add(_netscalerService, metrictable_metric_binding);
                                } catch (final Exception e) {
                                    // Ignore Exception on cleanup
                                    if (!isCleanUp) {
                                        throw e;
                                    }
                                }

                                // bind lb monitor lb_metric_table_mon -metric cpu -metricThreshold 1
                                final lbmonitor_metric_binding monitor_metric_binding = new lbmonitor_metric_binding();

                                try {
                                    monitor_metric_binding.set_monitorname(monitorName);
                                    monitor_metric_binding.set_metric(counterName);
                                    /*
                                     * Setting it to max to make sure traffic is not affected due to 'LOAD' monitoring.
                                     * For Ex. if CPU is tracked and CPU is greater than 80, it is still < than Integer.MAX_VALUE
                                     * so traffic will continue to flow.
                                     */
                                    monitor_metric_binding.set_metricthreshold(Integer.MAX_VALUE);
                                    lbmonitor_metric_binding.add(_netscalerService, monitor_metric_binding);
                                } catch (final Exception e) {
                                    // Ignore Exception on cleanup
                                    if (!isCleanUp) {
                                        throw e;
                                    }
                                }
                            }
                            // SYS.VSERVER("abcd").SNMP_TABLE(0).AVERAGE_VALUE.GT(80)
                            final int counterIndex = snmpMetrics.get(counterName); // TODO: temporary fix. later on counter name
                            // will be added as a param to SNMP_TABLE.
                            formatter.format("SYS.VSERVER(\"%s\").SNMP_TABLE(%d).AVERAGE_VALUE.%s(%d)", nsVirtualServerName, counterIndex, operator, threshold);
                        } else if (counterTO.getSource().equals(Counter.Source.NETSCALER)) {
                            //SYS.VSERVER("abcd").RESPTIME.GT(10)
                            formatter.format("SYS.VSERVER(\"%s\").%s.%s(%d)", nsVirtualServerName, counterTO.getValue(), operator, threshold);
                        }
                    } finally {
                        // closing formatter
                    }
                    if (policyExpression.length() != 0) {
                        policyExpression += " && ";
                    }
                    policyExpression += conditionExpression;
                }
                policyExpression = "(" + policyExpression + ")";

                final String policyId = Long.toString(autoScalePolicyTO.getId());
                final String policyName = generateAutoScalePolicyName(vmGroupIdentifier, policyId);
                String action = null;
                if (isScaleUpPolicy(autoScalePolicyTO)) {
                    action = scaleUpActionName;
                    final String scaleUpCondition =
                            "SYS.VSERVER(\"" + nsVirtualServerName + "\").ACTIVESERVICES.LT(SYS.VSERVER(\"" + nsVirtualServerName + "\").MAXAUTOSCALEMEMBERS)";
                    policyExpression = scaleUpCondition + " && " + policyExpression;
                } else {
                    action = scaleDownActionName;
                    final String scaleDownCondition =
                            "SYS.VSERVER(\"" + nsVirtualServerName + "\").ACTIVESERVICES.GT(SYS.VSERVER(\"" + nsVirtualServerName + "\").MINAUTOSCALEMEMBERS)";
                    policyExpression = scaleDownCondition + " && " + policyExpression;
                }

                addAutoScalePolicy(timerName, policyName, cur_prirotiy++, policyExpression, action, autoScalePolicyTO.getDuration(), interval, isCleanUp);

            }
        } catch (final Exception ex) {
            if (!isCleanUp) {
                // Normal course, exception has occurred
                disableAutoScaleConfig(loadBalancerTO, true);
                throw ex;

            } else {
                // Programming error. Exception should never be thrown afterall.
                throw ex;
            }
        }

        return true;
    }