text:
package org.apache.xpath;

public class XPathVisitor
{
  // Constructors

  public XPathVisitor(){
  }
  // Methods

  public boolean visitFunction(ExpressionOwner arg1, org.apache.xpath.functions.Function arg2){
    return false;
  }
  public boolean visitVariableRef(ExpressionOwner arg1, org.apache.xpath.operations.Variable arg2){
    return false;
  }
  public boolean visitLocationPath(ExpressionOwner arg1, org.apache.xpath.axes.LocPathIterator arg2){
    return false;
  }
  public boolean visitStep(ExpressionOwner arg1, org.apache.xpath.patterns.NodeTest arg2){
    return false;
  }
  public boolean visitPredicate(ExpressionOwner arg1, Expression arg2){
    return false;
  }
  public boolean visitBinaryOperation(ExpressionOwner arg1, org.apache.xpath.operations.Operation arg2){
    return false;
  }
  public boolean visitMatchPattern(ExpressionOwner arg1, org.apache.xpath.patterns.StepPattern arg2){
    return false;
  }
  public boolean visitUnaryOperation(ExpressionOwner arg1, org.apache.xpath.operations.UnaryOperation arg2){
    return false;
  }
  public boolean visitUnionPath(ExpressionOwner arg1, org.apache.xpath.axes.UnionPathIterator arg2){
    return false;
  }
  public boolean visitUnionPattern(ExpressionOwner arg1, org.apache.xpath.patterns.UnionPattern arg2){
    return false;
  }
  public boolean visitStringLiteral(ExpressionOwner arg1, org.apache.xpath.objects.XString arg2){
    return false;
  }
  public boolean visitNumberLiteral(ExpressionOwner arg1, org.apache.xpath.objects.XNumber arg2){
    return false;
  }
}


text:
(function() {
  'use strict';

  var filesToCache = [
    '.',
    'style/main.css',
    'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700',
    'images/still_life-1600_large_2x.jpg',
    'images/still_life-800_large_1x.jpg',
    'images/still_life_small.jpg',
    'images/still_life_medium.jpg',
    'index.html',
    'pages/offline.html',
    'pages/404.html'
  ];

  var staticCacheName = 'pages-cache-v1';

  self.addEventListener('install', function(event) {
    console.log('Attempting to install service worker and cache static assets');
    event.waitUntil(
      caches.open(staticCacheName)
      .then(function(cache) {
        return cache.addAll(filesToCache);
      })
    );
  });

  self.addEventListener('fetch', function(event) {
    console.log('Fetch event for ', event.request.url);
    event.respondWith(
      caches.match(event.request).then(function(response) {
        if (response) {
          console.log('Found ', event.request.url, ' in cache');
          return response;
        }
        console.log('Network request for ', event.request.url);
        return fetch(event.request).then(function(response) {
          if (response.status === 404) {
            return caches.match('pages/404.html');
          }
          return caches.open(staticCacheName).then(function(cache) {
            if (event.request.url.indexOf('test') < 0) {
              cache.put(event.request.url, response.clone());
            }
            return response;
          });
        });
      }).catch(function(error) {

        // TODO 6 - Respond with custom offline page

      })
    );
  });

  // TODO 7 - delete unused caches

})();

redpajama_set_name: RedPajamaGithub


text:
package com.redhat.ceylon.compiler.java.runtime.metamodel.decl;

import java.util.List;

import ceylon.language.DeprecationAnnotation;
import ceylon.language.Sequence;
import ceylon.language.Sequential;
import ceylon.language.SharedAnnotation;
import ceylon.language.Singleton;
import ceylon.language.ThrownExceptionAnnotation;
import ceylon.language.empty_;
import ceylon.language.meta.declaration.CallableConstructorDeclaration;
import ceylon.language.meta.declaration.ConstructorDeclaration;
import ceylon.language.meta.declaration.FunctionOrValueDeclaration;
import ceylon.language.meta.model.Type;

import com.redhat.ceylon.compiler.java.metadata.Ceylon;
import com.redhat.ceylon.compiler.java.metadata.Ignore;
import com.redhat.ceylon.compiler.java.metadata.Name;
import com.redhat.ceylon.compiler.java.metadata.TypeInfo;
import com.redhat.ceylon.compiler.java.runtime.metamodel.Metamodel;
import com.redhat.ceylon.compiler.java.runtime.metamodel.Predicates;
import com.redhat.ceylon.compiler.java.runtime.metamodel.Predicates.Predicate;
import com.redhat.ceylon.compiler.java.runtime.model.TypeDescriptor;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.ParameterList;

@Ceylon(major = 8)
@com.redhat.ceylon.compiler.java.metadata.Class
public class ClassWithInitializerDeclarationImpl
        extends ClassDeclarationImpl
        implements ceylon.language.meta.declaration.ClassWithInitializerDeclaration {

    @Ignore
    public final static TypeDescriptor $TypeDescriptor$ = TypeDescriptor.klass(ClassWithInitializerDeclarationImpl.class);

    public ClassWithInitializerDeclarationImpl(com.redhat.ceylon.model.typechecker.model.Class declaration) {
        super(declaration);
    }

    @Override
    @Ignore
    public ceylon.language.meta.declaration.ClassWithInitializerDeclaration$impl
    $ceylon$language$meta$declaration$ClassWithInitializerDeclaration$impl() {
        return new ceylon.language.meta.declaration.ClassWithInitializerDeclaration$impl(this);
    }

    @Ignore
    @Override
    public TypeDescriptor $getType$() {
        return $TypeDescriptor$;
    }

    @TypeInfo("ceylon.language::ConstructorDeclaration[]")
    @Override
    public Sequence<? extends CallableConstructorDeclaration> constructorDeclarations() {
        return new Singleton<CallableConstructorDeclaration>(CallableConstructorDeclaration.$TypeDescriptor$, getDefaultConstructor());
    }

    @TypeInfo("ceylon.language::ConstructorDeclaration[]")
    @Override
    public <A extends java.lang.annotation.Annotation> Sequential<? extends CallableConstructorDeclaration> annotatedConstructorDeclarations(TypeDescriptor reified$Annotation) {
        Type<?> at = Metamodel.getAppliedMetamodel(reified$Annotation);
        if (at.subtypeOf(Metamodel.getAppliedMetamodel(
                TypeDescriptor.union(SharedAnnotation.$TypeDescriptor$,
                        DeprecationAnnotation.$TypeDescriptor$,
                        ThrownExceptionAnnotation.$TypeDescriptor$)))) {
            Predicate<Declaration> p = Predicates.isDeclarationAnnotatedWith(reified$Annotation, at);
            p.accept(declaration);
            return constructorDeclarations();
        } else {
            return (Sequential)empty_.get_();
        }
    }

    @Override
    public CallableConstructorDeclaration getDefaultConstructor() {
        return new ClassWithInitializerDeclarationConstructor((com.redhat.ceylon.model.typechecker.model.Class)declaration);
    }

    @TypeInfo("ceylon.language.meta.declaration::CallableConstructorDeclaration")
    @Override
    public ceylon.language.meta.declaration.CallableConstructorDeclaration getConstructorDeclaration(String name) {
        return name.isEmpty() ? getDefaultConstructor() : null;
    }

    @Override
    @TypeInfo("ceylon.language::Sequential<ceylon.language.meta.declaration::FunctionOrValueDeclaration>")
    public Sequential<? extends ceylon.language.meta.declaration.FunctionOrValueDeclaration> getParameterDeclarations(){
        return super.getParameterDeclarations();
    }

    @Override
    @TypeInfo("ceylon.language.meta.declaration::FunctionOrValueDeclaration|ceylon.language::Null")
    public ceylon.language.meta.declaration.FunctionOrValueDeclaration getParameterDeclaration(@Name("name") String name){
        return super.getParameterDeclaration(name);
    }

}


text:
package org.jivesoftware.sparkimpl.settings;

import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.iqprivate.PrivateDataManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.log.Log;

import java.util.Map;

public class UserSettings {
    public static final String NAMESPACE = "jive:user:settings";
    public static final String ELEMENT_NAME = "personal_settings";
    private final PrivateDataManager privateDataManager;
    private SettingsData settingsData;
    private static UserSettings singleton;
    private static final Object LOCK = new Object();

    public static UserSettings getInstance() {
        synchronized (LOCK) {
            if (null == singleton) {
                UserSettings controller = new UserSettings();
                singleton = controller;
                return controller;
            }
        }
        return singleton;
    }

    private UserSettings() {
        privateDataManager = PrivateDataManager.getInstanceFor(SparkManager.getConnection());
        PrivateDataManager.addPrivateDataProvider("personal_settings", "jive:user:settings", new SettingsDataProvider());

        try {
            settingsData = (SettingsData)privateDataManager.getPrivateData("personal_settings", "jive:user:settings");
        }
        catch (XMPPException | SmackException | InterruptedException e) {
            Log.error("Error in User Settings", e);
        }
    }

    public Map<String,String> getSettings() {
        try {
            return settingsData.getMap();
        }
        catch (Exception ex) {
            Log.error("Error in User Settings.", ex);
        }
        return null;
    }

    public void setProperty(String name, String value) {
        getSettings().put(name, value);
    }

    public void setProperty(String name, boolean showtime) {
        getSettings().put(name, Boolean.toString(showtime));
    }

    public void setProperty(String name, int value) {
        getSettings().put(name, Integer.toString(value));
    }

    public String getProperty(String name) {
        return getSettings().get(name);
    }

    public String getEmptyPropertyIfNull(String name) {
        return ModelUtil.nullifyIfEmpty(getSettings().get(name));
    }

    public void save() {
        try {
            privateDataManager.setPrivateData(settingsData);
        }
        catch (XMPPException | SmackException | InterruptedException e) {
            Log.error("Error in User Settings.", e);
        }
    }

}


text:
function UserFaqsCtrl($scope, User, $http, $filter, showFormMessage, $compile) {

}


text:
package h2spec

// These types have been copied from h2spec.

import (
	"encoding/xml"
)

// JUnitReport represents the JUnit XML format.
type JUnitTestReport struct {
	XMLName    xml.Name          `xml:"testsuites"`
	TestSuites []*JUnitTestSuite `xml:"testsuite"`
}

// JUnitTestSuite represents the testsuite element of JUnit XML format.
type JUnitTestSuite struct {
	XMLName   xml.Name         `xml:"testsuite"`
	Name      string           `xml:"name,attr"`
	Package   string           `xml:"package,attr"`
	ID        string           `xml:"id,attr"`
	Tests     int              `xml:"tests,attr"`
	Skipped   int              `xml:"skipped,attr"`
	Failures  int              `xml:"failures,attr"`
	Errors    int              `xml:"errors,attr"`
	TestCases []*JUnitTestCase `xml:"testcase"`
}

// JUnitTestCase represents the testcase element of JUnit XML format.
type JUnitTestCase struct {
	XMLName   xml.Name      `xml:"testcase"`
	Package   string        `xml:"package,attr"`
	ClassName string        `xml:"classname,attr"`
	Time      string        `xml:"time,attr"`
	Failure   *JUnitFailure `xml:"failure"`
	Skipped   *JUnitSkipped `xml:"skipped"`
	Error     *JUnitError   `xml:"error"`
}

// JUnitFailure represents the failure element of JUnit XML format.
type JUnitFailure struct {
	XMLName xml.Name `xml:"failure"`
	Content string   `xml:",innerxml"`
}

// JUnitSkipped represents the skipped element of JUnit XML format.
type JUnitSkipped struct {
	XMLName xml.Name `xml:"skipped"`
	Content string   `xml:",innerxml"`
}

// JUnitSkipped represents the error element of JUnit XML format.
type JUnitError struct {
	XMLName xml.Name `xml:"error"`
	Content string   `xml:",innerxml"`
}


text:
FROM debian:11

ARG DEBIAN_FRONTEND=noninteractive

# install: php / mysql / postgres / sqlite / tools / mssql deps
RUN apt-get update && apt-get -y install \
php-cli php-xml php-mbstring \
mariadb-server mariadb-client php-mysql \
postgresql php-pgsql \
postgresql-13-postgis-3 \
sqlite3 php-sqlite3 \
git wget

# install run script
ADD run.sh /usr/sbin/docker-run
CMD docker-run


text:
<!-- This file was autogenerated via cilium cmdref, do not edit manually-->

## cilium prefilter update

Update CIDR filters

```
cilium prefilter update [flags]
```

### Options

```
      --cidr strings    List of CIDR prefixes to block
  -h, --help            help for update
      --revision uint   Update revision
```

### Options inherited from parent commands

```
      --config string   config file (default is $HOME/.cilium.yaml)
  -D, --debug           Enable debug messages
  -H, --host string     URI to server-side API
```

### SEE ALSO

* [cilium prefilter](cilium_prefilter.md)	 - Manage XDP CIDR filters


text:
/**
 * Created by osei on 6/30/15.
 */
angular.module('fm.controllers')
    .controller('SettingsCtrl', function (Core, $scope) {

    });


text:
module DnsService
  class ZonesController < DnsService::ApplicationController
    before_action ->(id = params[:id]) { load_zone id }, except: %i[index]
    before_action :load_pools, only: %i[index show update create new]
    before_action :load_shared_zones, only: %i[index update create]

    authorization_context 'dns_service'
    authorization_required

    def index
      per_page = params[:per_page] || 20

      filter = {}
      @search = nil
      @searchfor = nil

      if params.include?(:search)
        if not params[:search].blank?
          @search = params[:search]
          @searchfor = "#{params[:searchfor]}"
          filter = {@searchfor.downcase() => @search}
        else
          params.delete(:search)
          params.delete(:searchfor)
        end
      end

      @zones = paginatable(per_page: per_page.to_i) do |pagination_options|
        services.dns_service.zones(
          @admin_option.merge(pagination_options).merge(filter)
        )[:items]
      end

      active_requests = services.dns_service.zone_transfer_requests(status: 'ACTIVE')

      @zone_transfer_requests = active_requests.select do |r|
        r.project_id.nil? or r.project_id != @scoped_project_id
      end

      @active_zone_transfer_requests = active_requests.inject({}) do |hash,r|
        hash[r.zone_id] = r if r.project_id == @scoped_project_id
        hash
      end

      # this is relevant in case an ajax paginate call is made.
      # in this case we don't render the layout, only the list!
      if request.xhr?
        render partial: 'list', locals: { zones: @zones, active_zone_transfer_requests: @active_zone_transfer_requests, pools: @pools}
      else
        # comon case, render index page with layout
        render action: :index
      end
    end

    def show

      per_page = params[:per_page] || 20

      filter = {}
      @search = nil
      @searchfor = nil

      if params.include?(:search)
        if not params[:search].blank?
          @search = params[:search]
          @searchfor = "#{params[:searchfor]}"
          filter = {@searchfor.downcase() => @search}
        else
          params.delete(:search)
          params.delete(:searchfor)
        end
      end

      @zone = services.dns_service.find_zone(params[:id], all_projects: @all_projects)
      all_shared_zones = services.dns_service.shared_zones()

      @shared_with_projects = []
      all_shared_zones.each do | shared_zone |
        if @zone.id == shared_zone.zone_id && @scoped_project_id != shared_zone.target_project_id
          project = ObjectCache.where(id: shared_zone.target_project_id).first
          if project
            @shared_with_projects << project.name
          else
            @shared_with_projects << shared_zone.target_project_id
          end
        end
      end

      @recordsets = paginatable(per_page: per_page.to_i) do |pagination_options|
        services.dns_service.recordsets(
          params[:id],
          {
            sort_key: 'name'
          }.merge(@impersonate_option).merge(pagination_options).merge(filter)
        )[:items]
      end

      ns_options = { type: 'NS' }
      ns_options[:name] = @zone.name if @zone

      @nameservers = services.dns_service.recordsets(
        params[:id],
        ns_options.merge(@impersonate_option)
      )[:items]

      # this is relevant in case an ajax paginate call is made.
      # in this case we don't render the layout, only the list!
      if request.xhr?
        zone = services.dns_service.find_zone(params[:id], @impersonate_option)
        render partial: 'dns_service/zones/recordsets/recordsets', locals: { recordsets: @recordsets, zone: zone }
      else
        # comon case, render index page with layout
        render action: :show
      end
    end

    def new
      @zone = services.dns_service.new_zone
      # this needs to be removed when migration is done
      @pools.reject!{|pool| pool.attributes["attributes"]["label"] == "New External SAP Hosted Zone" }
    end

    def create

      # check for existing zone
      zone_name = params[:zone][:name]
      @zone = services.dns_service.zones(name: zone_name)[:items].first
      if @zone
        @zone.errors.add('Error', 'Zone already existing')
        render action: :new
        return
      else
        @zone = services.dns_service.new_zone(params[:zone])
      end

      update_limes_data(@scoped_domain_id, @scoped_project_id)
      # check that subzones are not exsisting in other projects
      zone_transfer = check_parent_zone(zone_name,@scoped_project_id)
      # check and increase zone quota for destination project
      check_and_increase_quota(@scoped_domain_id, @scoped_project_id, 'zones')
      # make sure that recordset quota is increased at least by 2 as there are two recrodsets are created (NS + SOA)
      check_and_increase_quota(@scoped_domain_id, @scoped_project_id, 'recordsets', 2)

      if @zone.save

        # if zone_transfer
        #   # try to find existing zone transfer request
        #   @zone_transfer_request = services.dns_service.zone_transfer_requests(
        #     status: 'ACTIVE'
        #   ).select do |zone_transfer_request|
        #     zone_transfer_request.target_project_id == @scoped_project_id &&
        #       zone_transfer_request.zone_id == @zone.id
        #   end.first

        #   # create a new zone transfer request if not exists
        #   @zone_transfer_request ||= services.dns_service.new_zone_transfer_request(
        #     @zone.id, target_project_id: @scoped_project_id, source_project_id: @zone.project_id
        #   )
        #   @zone_transfer_request.description = "create new zone via elektra"

        #   unless @zone_transfer_request.save && @zone_transfer_request.accept(@scoped_project_id)
        #     # catch errors for transfer zone request
        #     @zone_transfer_request.errors.each { |k, m| @zone_request.errors.add(k,m) }
        #   end
        # end

        flash.now[:notice] = "Zone successfully created."
        respond_to do |format|
          format.html{redirect_to zones_url}
          format.js {render 'create.js'}
        end
      else
        render action: :new
      end
    end

    def edit
    end

    def update
      @zone.attributes = params[:zone].merge(@impersonate_option)

      if @zone.save
        flash.now[:notice] = "Zone successfully updated."
        respond_to do |format|
          format.html{redirect_to zones_url}
          format.js {render 'update.js'}
        end
      else
        render action: :edit
      end
    end

    def destroy
      # TODO: if zone cannot be deleted like subzones are existing the error is not handled
      @deleted = services.dns_service.delete_zone(params[:id], @impersonate_option)
      respond_to do |format|
        format.js {}
        format.html { redirect_to zones_url }
      end
    end

    private

    def load_pools
      @pools = []
      return unless current_user.is_allowed?("dns_service:pool_list")
      @pools = services.dns_service.pools[:items]
    end

    def load_shared_zones
      @shared_zones = services.dns_service.shared_zones()
    end
  end
end


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-menu-management',
  templateUrl: './menu-management.component.html',
  styleUrls: ['./menu-management.component.css']
})
export class MenuManagementComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
"""
Given a sorted linked list, delete all duplicates such that each element appear only once.

For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.
"""
__author__ = 'Danyang'
# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def deleteDuplicates(self, head):
        """
        Two pointers, closed_ptr and open_ptr, to find the next non-duplicate
        O(n)
        :param head: ListNode
        :return: ListNode
        """
        # trivial
        if not head:
            return head
        # main
        closed_ptr = head
        open_ptr = head.next
        while open_ptr:
            # find the non-duplicate
            while open_ptr and closed_ptr.val==open_ptr.val:
                open_ptr = open_ptr.next

            closed_ptr.next = open_ptr
            closed_ptr = closed_ptr.next
            open_ptr = open_ptr.next if open_ptr else None

        return head

if __name__=="__main__":
    nodes = [ListNode(1) for _ in range(2)]
    for i in range(len(nodes)-1):
        nodes[i].next = nodes[i+1]

    Solution().deleteDuplicates(nodes[0])


text:
from . import asg
import billow
import boto
from boto.exception import BotoServerError
from contextlib import closing
import itertools
import json
import sys
import time
import urllib2

class billowRotate(object):
    """
    Rotate instance within a billowService
    """

    def __init__(self, service, region='us-east-1'):
        if not isinstance(service, billow.billowService):
            raise TypeError

        self.service = service
        self.instances = list()
        self.priority = list()
        self.__logger = self.consolelogger
        self.private_secondary_failures = list()
        self.urltimeout = 60

    def consolelogger(self, msg):
        sys.stderr.write("billowRotate %s: %s\n" % (self.service.service, msg))
        sys.stderr.flush()

    def set_logger(self, logfunction):
        self.__logger = logfunction

    def log(self, msg):
        self.__logger(msg)

    def safety(self):
        """
        1. Check for no instances
        2. Check for redundancy reduction in each zone
        3. Check for (cur == max <= 1)
        4. Check CrossZoneLB disabled and empty AZ
        5. Check instances for secondary Private IPs and multi-subnet
        """
        warnings = list()
        for g in self.service.groups:
            instances = g.instances

            # 1. Check for no instances
            if len(instances) == 0:
                warnings.append("%s no instances to rotate" % g.group)

            # 2. Check for redundancy reduction in each zone
            zones = dict()
            for i in instances:
                if i.zone not in zones:
                    zones[ i.zone ] = 0
                zones[ i.zone ] += 1
            for k, v in zones.iteritems():
                if v <= 2:
                    warnings.append('%s reduced redundancy, single instance ' \
                            'will remain in zone %s' % (g.group, k))

            # 3. Check for (cur == max == 1)
            if g.cur_size == 1 and g.max_size == 1:
                warnings.append('%s temporary outage, single instance in ' \
                        'group' % g.group)

            # 4. Check CrossZoneLB disabled and empty AZ
            for b in self.service.balancers:
                if ('crosszone' in b.options and
                        b.options['crosszone'] == False):
                    for z in b.zones:
                        if z in zones and zones[z] <= 1:
                            warnings.append("%s deadend traffic, zoned ' \
                                    'balancer without cross-zone in %s" % \
                                    (g.group, z))

            # 5. Check instances for secondary Private IPs and multi-subnet
            for i in instances:
                for ni in i.interfaces:
                    if (len(g.subnets) > 1 and \
                            'private_ip_addresses' in ni and \
                            len(ni['private_ip_addresses']) > 0):
                        warnings.append('%s instance %s has secondary ' \
                                'private IP address %s but group has ' \
                                'multiple subnets' \
                                % (g.group, i.id,
                                    ni['private_ip_addresses'][0]))

        return warnings

    def roundrobin(self, *iterables):
        "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
        # https://docs.python.org/2/library/itertools.html#recipes
        # Recipe credited to George Sakkis
        pending = len(iterables)
        nexts = itertools.cycle(iter(it).next for it in iterables)
        while pending:
            try:
                for next in nexts:
                    yield next()
            except StopIteration:
                pending -= 1
                nexts = itertools.cycle(itertools.islice(nexts, pending))

    def order(self):
        """
        1. UnHealthy Group instances
        2. Degraded Balancer instances
        3. All instances
        4. Round-robin interleave Groups
        """
        self.instances = list()
        degraded = list()
        instances = list()

        # 1. UnHealthy Group instances
        for g in self.service.groups:
            for i in g.instances:
                if i.group_health != 'Healthy' and i.id not in degraded:
                    degraded.append(i.id)

        # 2. Degraded Balancer instances
        for b in self.service.balancers:
            for i in b.instances:
                if i.balancer_state != 'InService' and i.id not in degraded:
                    degraded.append(i.id)

        # 3. All instances
        for g in self.service.groups:
            instlist = list()
            for i in g.instances:
                if i.id not in degraded and i.group_state == 'InService':
                    instlist.append(i.id)
            instances.append(instlist)

        # Build rotation order
        self.instances.extend(degraded)
        self.instances.extend(self.roundrobin(*instances))

        return self.instances

    def find_group_by_instance(self, instance_id):
        for g in self.service.groups:
            if instance_id in g.instances:
                return g
        return None

    def find_balancer(self, balancer_name):
        for b in self.service.balancers:
            if b.name == balancer_name:
                return b
        return None

    def find_balancer_instance(self, balancer, instance_id):
        for i in balancer.instances:
            if i.id == instance_id:
                return i
        return None

    def find_group_instance(self, group, instance_id):
        for i in group.instances:
            if i.id == instance_id:
                return i
        return None

    def wait_timeout(self, timeout, starttime):
        waittime = timeout - (time.time() - starttime)
        if waittime <= 0:
            self.log('timed out, aborting')
            return 0
        return waittime

    def wait_elb_registered(self, instance_id, sleep=5, timeout=None):
        """
        Wait for instance to become registered to balancer
        Registration means 'InService' or 'OutOfService'
        Ignore 'Unknown' and consider it unregistered in Unknown state
        """
        starttime = 0
        if timeout:
            if timeout < 0:
                self.log('timed out waiting for balancer registration')
                return False
            starttime = time.time()

        healthy = False
        while not healthy:
            group = self.find_group_by_instance(instance_id)
            if not group:
                self.log('no group found, cannot wait for instance %s ' \
                        'balancer registration' % instance_id)
                return False

            healthycnt = 0
            for balancer_name in group.load_balancers:
                balancer = self.find_balancer(balancer_name)
                if not balancer:
                    self.log('no balancer found, cannot wait for instance ' \
                            '%s registration to balancer %s' \
                            % (instance_id, balancer_name))
                    return False

                # Refresh ELB info
                balancer.refresh()

                instance = self.find_balancer_instance(balancer, instance_id)
                if not instance:
                    continue

                if instance.balancer_state == 'InService' or \
                        instance.balancer_state == 'OutOfService':
                    healthycnt += 1

            if healthycnt == len(group.load_balancers):
                return True

            if timeout and (time.time() - starttime) > timeout:
                self.log('timed out waiting for instance %s balancer ' \
                        'deregistration' % instance_id)
                return False

            if not healthy:
                timeoutstr = ''
                if timeout:
                    timeoutstr = ' timeout %ds' \
                            % int(timeout - (time.time() - starttime))
                self.log('sleeping %ds waiting for instance %s to register ' \
                        'with %d/%d balancers%s' % (
                            sleep,
                            instance_id,
                            healthycnt,
                            len(group.load_balancers),
                            timeoutstr)
                        )
                time.sleep(sleep)

        return True

    def wait_elb_deregistered(self, instance_id, sleep=5, timeout=None):
        """
        Wait for instance to deregister from balancer
        Consider 'Unknown' as deregistered
        """
        starttime = 0
        if timeout:
            if timeout < 0:
                self.log('timed out waiting for balancer deregistration')
                return False
            starttime = time.time()

        healthy = True
        while healthy:
            drainmax = 0

            group = self.find_group_by_instance(instance_id)
            if not group:
                self.log('no group found, cannot wait for instance %s ' \
                        'balancer deregistration' % instance_id)
                return False

            unhealthycnt = 0
            for balancer_name in group.load_balancers:
                balancer = self.find_balancer(balancer_name)
                if not balancer:
                    self.log('balancer not found, cannot wait for instance ' \
                            '%s deregistration from balancer %s' \
                            % (instance_id, balancer_name))
                    return False

                # Refresh ELB info
                balancer.refresh()

                instance = self.find_balancer_instance(balancer, instance_id)
                if not instance:
                    unhealthycnt += 1
                    continue

                if (balancer.connection_draining and \
                        instance.balancer_state == 'InService: Instance ' \
                        'deregistration currently in progress'):
                    drainmax = max(drainmax,
                            balancer.connection_draining_timeout)

                if (instance.balancer_state == 'OutOfService' or \
                        instance.balancer_state == 'OutOfService: Instance ' \
                            'is not currently registered with the '
                            'LoadBalancer' or \
                         instance.balancer_state == 'Unknown'):
                    unhealthycnt += 1
                    continue

            if unhealthycnt == len(group.load_balancers):
                return True

            if timeout and (time.time() - starttime) > timeout:
                self.log('timed out waiting for instance %s balancer ' \
                        'deregistration' % instance_id)
                return False

            if healthy:
                timeoutstr = ''
                if timeout:
                    timeoutstr = ' timeout %ds' \
                            % int(timeout - (time.time() - starttime))
                drainstr = ''
                if drainmax:
                    drainstr = ' draining connections %ds' % drainmax
                self.log('sleeping %ds waiting for instance %s to ' \
                        'deregister with %d/%d balancers%s%s' % (
                            sleep,
                            instance_id,
                            unhealthycnt,
                            len(group.load_balancers),
                            timeoutstr,
                            drainstr)
                        )
                time.sleep(sleep)

        return True

    def wait_elb_healthy(self, instance_id, sleep=5, timeout=None):
        starttime = time.time()
        if timeout:
            if timeout < 0:
                self.log('timed out waiting for balancer health check')
                return False

        healthchecks = dict()
        healthtimes = dict()
        healthy = False
        while not healthy:
            group = self.find_group_by_instance(instance_id)
            if not group:
                self.log('no group found, cannot wait for instance %s ' \
                        'balancer health check')
                return False

            healthycnt = 0
            healthchecks = dict()
            for balancer_name in group.load_balancers:
                balancer = self.find_balancer(balancer_name)
                if not balancer:
                    self.log('no balancer found, cannot wait for instance ' \
                            '%s health check to balancer %s' \
                            % (instance_id, balancer_name))
                    return False

                # Refresh ELB info
                balancer.refresh()

                instance = self.find_balancer_instance(balancer, instance_id)
                if not instance:
                    continue

                if instance.balancer_state == 'InService':
                    healthycnt += 1
                else:
                    healthchecks[balancer.name] = balancer.health_target
                    healthtimes[balancer.name] = \
                            balancer.health_timeout * balancer.health_threshold

            if healthycnt == len(group.load_balancers):
                return True

            if timeout and (time.time() - starttime) > timeout:
                self.log('timed out waiting for instance %s health check' \
                        % instance_id)
                return False

            if not healthy:
                timeoutstr = ''
                if timeout:
                    timeoutstr = ' timeout %ds' \
                            % int(timeout - (time.time() - starttime))
                self.log('sleeping %ds waiting for instance %s health check ' \
                        'with %d/%d balancers%s' % (
                            sleep,
                            instance_id,
                            healthycnt,
                            len(group.load_balancers),
                            timeoutstr)
                        )
                now = time.time()
                for balancer_name, target in healthchecks.iteritems():
                    if (now - starttime) > healthtimes[balancer_name]:
                        self.log('instance %s failing balancer %s health ' \
                                'check %s' \
                                % (instance_id, balancer_name, target))
                time.sleep(sleep)

        return True

    def wait_group_terminated(self, instance_id, sleep=5, timeout=None):
        """
        Wait for instance to terminate from group
        """
        starttime = 0
        if timeout:
            if timeout < 0:
                self.log('timed out waiting for instance group termination')
                return False
            starttime = time.time()

        healthy = True
        while healthy:
            group = self.find_group_by_instance(instance_id)
            if not group:
                self.log('no group found, cannot wait for instance %s ' \
                        'group termination' % instance_id)
                return False

            # Refresh Group info
            group.refresh()

            instance = self.find_group_instance(group, instance_id)
            if not instance:
                return True

            if instance.group_state == 'Terminated' or \
                    instance.instance_state == 'terminated':
                return True

            if timeout and (time.time() - starttime) > timeout:
                self.log('timed out waiting for instance %s termination ' \
                        'from group %s' % (instance_id, group.name))
                return False

            timeoutstr = ''
            if timeout:
                timeoutstr = ' timeout %ds' \
                        % int(timeout - (time.time() - starttime))
            self.log('sleeping %ds waiting for instance %s in state %s to ' \
                    'terminate from group %s%s' % (
                        sleep,
                        instance_id,
                        instance.group_state,
                        group.name,
                        timeoutstr)
                    )
            time.sleep(sleep)

        return True

    def wait_group_launched(self, group, instances,
            count=1, sleep=5, timeout=None):
        """
        Wait for new instance(s) to start
        """
        if not isinstance(instances, list):
            instances = [instances]

        starttime = 0
        if timeout:
            if timeout < 0:
                self.log('timed out waiting for instance group launch')
                return False
            starttime = time.time()

        healthy = False
        while not healthy:
            healthycnt = 0
            healthytext = None
            healthyinstances = list()

            # Refresh Group info
            group.refresh()

            # Look for new instances not in previous list
            for i in group.instances:
                if i.id not in instances:
                    # Warn when unexpectate state discovered
                    if (i.group_state == 'Terminated' or \
                            i.group_state == 'Terminating' or \
                            i.group_state == 'Standby' or \
                            i.group_state.startswith('Terminating:') or \
                            i.instance_state == 'shutting-down' or \
                            i.instance_state == 'terminated' or \
                            i.instance_state == 'stopping' or \
                            i.instance_state == 'stopped'):
                        self.log('degraded instance %s found in ' \
                                'group state %s instance state %s' \
                                % (i.id, i.group_state, i.instance_state))
                        continue

                    # Display Pending if any are pending
                    if i.group_state == 'Pending':
                        healthytext = i.group_state

                    # Only display InService if no Pending
                    if not healthytext and i.group_state == 'InService':
                        healthytext = i.group_state

                    if i.group_state == 'InService':
                        healthycnt += 1
                        healthyinstances.append(i.id)

            if healthycnt >= count:
                return healthyinstances

            if timeout and (time.time() - starttime) > timeout:
                self.log('timed out waiting for instance start ' \
                        'from group %s' % group.name)
                return False

            timeoutstr = ''
            if timeout:
                timeoutstr = ' timeout %ds' \
                        % int(timeout - (time.time() - starttime))
            statestr = ''
            if healthytext:
                statestr = ' in state %s' % healthytext
            self.log('sleeping %ds launched %d, waiting for %d instances%s ' \
                    'to start in group %s%s' % (
                        sleep,
                        healthycnt,
                        count,
                        statestr,
                        group.name,
                        timeoutstr)
                    )
            time.sleep(sleep)

        return list()

    def wait_launch(self, group, instlist, timeout=None):
        """
        Wait for a newly launched instance to come into service
        """
        if timeout and timeout < 0:
            self.log('timed out waiting for instance launch')
            return False

        # Wait for new instance to enter Group
        ret = self.wait_group_launched(group, instlist, timeout=timeout)
        if not ret:
            return False

        # Wait for all instances to register with Balancer
        for i in ret:
            if not self.wait_elb_registered(i, timeout=timeout):
                return False

        # Wait for all instances to pass health checks
        for i in ret:
            if not self.wait_elb_healthy(i, timeout=timeout):
                return False

        # list of instance_id
        return ret

    def launch(self, group, wait=True, timeout=None):
        """
        launch a new instance
        """
        # Capture current group list to detect new instance
        instlist = group.instances

        if not group.increment():
            self.log('group launch instance failed')
            return False

        if wait:
            if not self.wait_lauch(group, instlist, timeout=timeout):
                return False

        return True

    def deregister(self, instance_id, wait=True, timeout=None):
        ret = True
        for b in self.service.balancers:
            if instance_id not in b.instances:
                self.log('instance %s already deregistered from balancer %s' \
                        % (instance_id, b.name))
                continue
            if not b.deregister(instance_id):
                ret = False

        if wait:
            if not self.wait_elb_deregistered(instance_id, timeout=timeout):
                ret = False

        return ret

    def register(self, instance_id, wait=True, healthy=False, timeout=None):
        if timeout:
            starttime = time.time()

        ret = True
        group = self.find_group_by_instance(instance_id)
        if not group:
            self.log('no group found, cannot register instance %s to ' \
                    'balancer' % instance_id)
            return False

        for balancer_name in group.load_balancers:
            balancer = self.find_balancer(balancer_name)
            if not balancer:
                self.log('balancer %s not found, cannot wait for ' \
                        'balancer deregistration' % balancer_name)
                return False

            if not balancer.register(instance_id):
                ret = False

        if wait:
            waittime = timeout
            if timeout:
                waittime = self.wait_timeout(timeout, starttime)
            if not self.wait_elb_registered(instance_id, timeout=waittime):
                ret = False

            if healthy:
                if timeout:
                    waittime = self.wait_timeout(timeout, starttime)
                if not self.wait_elb_healthy(instance_id, timeout=waittime):
                    ret = False

        return ret

    def terminate(self, instance_id, decrement_capacity=False, wait=True,
            timeout=None):
        ret = True
        group = self.find_group_by_instance(instance_id)
        if not group:
            self.log('no group found, cannot terminate instance %s' \
                    % instance_id)
            return False

        try:
            if not group.terminate(
                    instance_id,
                    decrement_capacity=decrement_capacity
                    ):
                self.log('failed terminating instance %s from group %s' \
                        % (instance_id, group.name))
                return False
        except BotoServerError as e:
            if e.error_code == 'ValidationError':
                self.log('instance %s not managed, failed terminating from ' \
                        'group %s' % (instance_id, group.name))
                return False
            elif e.error_code == 'ScalingActivityInProgress':
                self.log('instance %s scaling activity in progress, failed ' \
                        'terminating from group %s' \
                        % (instance_id, group.name))
                return False
            else:
                raise e

        if wait:
            if not self.wait_group_terminated(instance_id, timeout=timeout):
                ret = False

        return ret

    def notify_terminate(self, group, instance_id, timeout=None):
        if 'urlterminate' not in group.settings:
            return True
        split = group.settings['urlterminate'].split(':')
        if len(split) != 2:
            self.log("instance %s terminate url invalid config")
            return False
        port = int(split[0])
        path = split[1]

        if port == 0 or path[0] != '/':
            self.log("instance %s terminate url invalid config")
            return False

        instance = self.find_group_instance(group, instance_id)
        if not instance:
            return False

        # Always require a timeout
        if not timeout:
            timeout = self.urltimeout

        url = 'http://%s:%d%s' % (instance.private_ip_address, port, path)
        data = '{}'
        header = {'Content-Type': 'application/json;charset=UTF-8'}
        req = urllib2.Request(url, data, header)

        self.log("instance %s terminate url %s" % (instance_id, url))
        retcode = True
        try:
            with closing(urllib2.urlopen(req, timeout=timeout)) as f:
                raw = f.read()
        except urllib2.HTTPError, e:
            self.log("instance %s terminate url failure code %d reason %s" % \
                    (instance_id, e.code, e.reason))
            raw = e.read()
            retcode = False
        except urllib2.URLError, e:
            self.log("instance %s terminate url failure %s" % \
                    (instance_id, e.reason))
            if "timed out" in str(e.reason) \
                    or "Connection refused" in str(e.reason):
                return False
            raise

        if raw and len(raw) > 0:
            self.log("instance %s terminate url response %s" % \
                    (instance_id, raw))
        return retcode

    def status_check(self, group, instance_id, sleep=5, timeout=None):
        """
        Check /status endpoint, return (True/False, code)
        """
        if 'urlstatus' not in group.settings:
            return (True, None)
        split = group.settings['urlstatus'].split(':')
        if len(split) != 2:
            self.log("instance %s status url invalid config" % instance_id)
            return (False, None)
        port = int(split[0])
        path = split[1]

        successcode = 'OK'
        if 'urlsuccess' in group.settings:
            successcode = group.settings['urlsuccess']

        if port == 0 or path[0] != '/':
            self.log("instance %s status url invalid config" % instance_id)
            return (False, None)

        # Always require a timeout
        urltimeout = timeout
        if not timeout:
            urltimeout = self.urltimeout

        instance = self.find_group_instance(group, instance_id)
        if not instance:
            self.log('no instance found, cannot status check instance %s ' \
                    'url status' % instance_id)
            return (False, None)

        url = 'http://%s:%d%s' % (instance.private_ip_address, port, path)
        data = None
        header = {'Content-Type': 'application/json;charset=UTF-8'}
        req = urllib2.Request(url, data, header)

        healthy = True
        status = ''
        raw = ''
        try:
            with closing(urllib2.urlopen(req, timeout=urltimeout)) as f:
                raw = f.read()
        except urllib2.HTTPError, e:
            # HTTP reply 3xx-5xx, not ready
            self.log("instance %s status url failure (code %d)" % \
                    (instance_id, e.code))
            raw = e.read()
            healthy = False
        except urllib2.URLError, e:
            # Connection error, must assume service is gone
            self.log("instance %s status url gone, continuing (%s)" % \
                    (instance_id, e.reason))
            raw = str(e.reason)
            # XXX wait on timed out?
            if str(e.reason) == "timed out":
                healthy = False

        if raw and len(raw):
            # Parse response, just raw response if not JSON
            try:
                status = json.loads(raw)
            except:
                # Invalid JSON
                status = raw

        if isinstance(status, dict) and 'status' in status:
            if (len(status['status']) > 0 and \
                    status['status'] != successcode):
                healthy = False

        return (healthy, status)

    def status_check_service(self, group, sleep=5, timeout=None):
        """
        Check service /status endpoint, return (True/False, code)
        """
        if 'urlservicestatus' not in group.settings:
            return (True, None)
        split = group.settings['urlservicestatus'].split(':')
        if len(split) != 2:
            self.log("service status url invalid config")
            return (False, None)
        port = int(split[0])
        path = split[1]

        successcode = 'OK'
        if 'urlsuccess' in group.settings:
            successcode = group.settings['urlsuccess']

        if port == 0 or path[0] != '/':
            self.log("service status url invalid config")
            return (False, None)

        # Always require a timeout
        urltimeout = timeout
        if not timeout:
            urltimeout = self.urltimeout

        # Find ELB, or exit
        if len(group.load_balancers) < 1:
            return (True, None)
        balancer = self.find_balancer(group.load_balancers[0])
        if not balancer:
            self.log('no balancer found, cannot wait for service status from '
                    'balancer %s' % group.load_balancers[0])
            return (False, None)

        url = 'http://%s:%d%s' % (balancer.dns_name, port, path)
        data = None
        header = {'Content-Type': 'application/json;charset=UTF-8'}
        req = urllib2.Request(url, data, header)

        healthy = True
        status = ''
        raw = ''
        try:
            with closing(urllib2.urlopen(req, timeout=urltimeout)) as f:
                raw = f.read()
        except urllib2.HTTPError, e:
            # HTTP reply 3xx-5xx, not ready
            self.log("balancer %s status url failure (code %d)" % \
                    (balancer.name, e.code))
            raw = e.read()
            healthy = False
        except urllib2.URLError, e:
            # Connection error, must assume service is gone
            self.log("balancer %s status url gone, continuing (%s)" % \
                    (balancer.name, e.reason))
            raw = str(e.reason)
            # XXX wait on timed out?
            if str(e.reason) == "timed out":
                healthy = False

        if raw and len(raw):
            # Parse response, just raw response if not JSON
            try:
                status = json.loads(raw)
            except:
                # Invalid JSON
                status = raw

        if isinstance(status, dict) and 'status' in status:
            if (len(status['status']) > 0 and \
                    status['status'] != successcode):
                healthy = False

        return (healthy, status)

    def wait_notify(self, group, instance_id, sleep=5, timeout=None):
        """
        Wait for GET to 'urlstatus' to return "OK" or '{"status": "OK"}'
        """
        starttime = 0
        if timeout:
            starttime = time.time()

        healthy = False
        while not healthy:
            (healthy, status) = self.status_check(group, instance_id, sleep,
                    timeout)

            if not healthy and timeout and (time.time() - starttime) > timeout:
                self.log('timed out waiting for instance %s status url' \
                        % instance_id)
                return False

            if not healthy:
                timeoutstr = ''
                if timeout:
                    timeoutstr = ' timeout %ds' \
                            % int(timeout - (time.time() - starttime))
                responsestr = ''
                if status and 'status' in status:
                    responsestr = ' notify %s' % status['status']
                self.log('sleeping %ds waiting for instance %s status' \
                        '%s%s' % (sleep, instance_id, timeoutstr, responsestr))
                time.sleep(sleep)

        return True

    def wait_service(self, group, sleep=5, timeout=None):
        """
        Wait for GET to balancer 'urlservicestatus' to return "OK" or
        '{"status": "OK"}'
        """
        starttime = 0
        if timeout:
            starttime = time.time()

        healthy = False
        while not healthy:
            (healthy, status) = self.status_check_service(group, sleep,
                    timeout)

            if not healthy and timeout and (time.time() - starttime) > timeout:
                self.log('timed out waiting for service status url')
                return False

            if not healthy:
                timeoutstr = ''
                if timeout:
                    timeoutstr = ' timeout %ds' \
                            % int(timeout - (time.time() - starttime))
                responsestr = ''
                if status and 'status' in status:
                    responsestr = ' notify %s' % status['status']
                self.log('sleeping %ds waiting for service status' \
                        '%s%s' % (sleep, timeoutstr, responsestr))
                time.sleep(sleep)

        return True

    def rotate_instance(self, instance_id, wait=True, timeout=None):
        """
        Rotate a single instance in a Group
        """
        terminate_after = True
        if timeout:
            starttime = time.time()

        group = self.find_group_by_instance(instance_id)
        if not group:
            self.log('no group found, cannot rotate instance %s' \
                    % instance_id)
            return False

        if 'rotate' in group.settings and group.settings['rotate'] == False:
            self.log('skipping rotation of instance %s due to tag ' \
                    'rotate=false' % instance_id)
            return True

        # Capture current group list to detect new instance
        instlist = group.instances

        #
        # URL NOTIFY - HTTP request to instance endpoint for termination
        #
        if not self.notify_terminate(group, instance_id, timeout=timeout):
            return False
        if not self.wait_notify(group, instance_id, timeout=timeout):
            return False

        elasticips = self.get_elasticips(instance_id)
        for e in elasticips:
            self.log('disassociating static IP %s association %s ' \
                    'allocation %s interface %s' \
                    % (e['public_ip_address'], e['association_id'],
                        e['allocation_id'], e['network_interface_id']))
            group.asg.disassociate_address(e['association_id'])

        privateips = self.get_secondaryips(instance_id)
        for p in privateips:
            self.log('unassigning private IP %s interface %s' \
                    % (p['private_ip_address'], p['network_interface_id']))
            group.asg.unassign_private_ip_addresses(
                    network_interface_id=p['network_interface_id'],
                    private_ip_addresses=p['private_ip_address']
                    )

        # Terminate before launch
        if group.cur_size == group.max_size:
            terminate_after = False

            self.log('terminating instance %s' % instance_id)

            # Do not wait for termination, instead wait for launched instance
            if not self.terminate(instance_id, wait=False):
                return False

        # Increase Group size
        else:
            self.log('launching instance')

            if not group.increment():
                self.log('group launch instance failed')
                return False

        # Wait for new instance to enter Group
        ret = self.wait_group_launched(group, instlist, timeout=timeout)
        if not ret:
            return False
        if len(ret) > 1:
            self.log('expected 1 instance launch, found %d' % len(ret))

        # Put back Elastic / Private IPs
        newinstance = ret[0]
        for e in elasticips:
            self.log('associating static IP %s allocation %s' \
                    % (e['public_ip_address'], e['allocation_id']))
            ret = self.put_elasticip(newinstance, e['allocation_id'])
            if not ret:
                self.log('failed associating static IP %s allocation %s' \
                        % (e['public_ip_address'], e['allocation_id']))
                return False

        for p in privateips:
            self.log('assigning private IP %s' % p['private_ip_address'])
            ret = self.put_secondaryip(newinstance, p['private_ip_address'])
            if not ret:
                self.private_secondary_failures.append(p['private_ip_address'])

        # Full launch wait after addresses associated
        waittime = timeout
        if timeout:
            waittime = self.wait_timeout(timeout, starttime)
        ret = self.wait_launch(group, instlist, timeout=waittime)
        if ret == False:
            return False

        # Wait for service /status
        if not self.wait_service(group, timeout=timeout):
            return False

        if terminate_after:
            if timeout:
                waittime = self.wait_timeout(timeout, starttime)

            self.log('terminating instance %s' % instance_id)

            # Terminate and wait
            if not self.terminate(instance_id, decrement_capacity=True,
                    wait=True, timeout=waittime):
                return False

        return True

    def rotate(self, wait=True, timeout=None):
        if timeout:
            starttime = time.time()

        errors = 0

        rotatelist = self.order()
        for instance in rotatelist:
            waittime = timeout
            if timeout:
                waittime = self.wait_timeout(timeout, starttime)
                # Abort rotation if no time left on the clock
                if waittime <= 0:
                    return False
            ret = self.rotate_instance(instance, timeout=timeout)
            if not ret:
                self.log('failed rotating %s' % instance)
                errors += 1
                continue

        # Post-rotation attempt to associate orphaned private IPs
        if self.private_secondary_failures:
            self.finalize_secondaryip()
            errors += len(self.private_secondary_failures)

        if errors > 0:
            self.log('finished: %d FAILURES' % errors)
            return False

        self.log('finished: success')
        return True

    def get_elasticips(self, instance_id):
        elasticips = list()

        group = self.find_group_by_instance(instance_id)
        if not group:
            return list()

        instance = self.find_group_instance(group, instance_id)
        if not instance:
            return list()

        addrlist = list()
        for n in instance.interfaces:
            # ElasticIPs are owned by account number, standard by 'amazon'
            if 'owner' in n and n['owner'] != 'amazon':
                addrlist.append(n['public_ip_address'])

        if not addrlist:
            return list()

        addrs = group.asg.get_addresses(addrlist)
        for a in addrs:
            addr = {
                    'public_ip_address': a.public_ip,
                    'private_ip_address': a.private_ip_address,
                    'instance_id': a.instance_id,
                    'allocation_id': a.allocation_id,
                    'association_id': a.association_id,
                    'network_interface_id': a.network_interface_id
                    }
            elasticips.append(addr)

        return elasticips

    def put_elasticip(self, instance_id, allocation_id):
        group = self.find_group_by_instance(instance_id)
        if not group:
            return False

        instance = self.find_group_instance(group, instance_id)
        if not instance:
            return False

        if not instance.interfaces:
            return False

        ret = group.asg.associate_address(
                allocation_id,
                instance_id=instance_id,
                network_interface_id=instance.interfaces[0]['id'])

        return ret

    def get_secondaryips(self, instance_id):
        group = self.find_group_by_instance(instance_id)
        if not group:
            return list()

        instance = self.find_group_instance(group, instance_id)
        if not instance:
            return list()

        addrlist = list()
        for n in instance.interfaces:
            if 'private_ip_addresses' in n:
                for a in n['private_ip_addresses']:
                    if a != n['private_ip_address']:
                        addr = {
                                'private_ip_address': a,
                                'instance_id': instance.id,
                                'network_interface_id': n['id']
                                }
                        addrlist.append(addr)

        return addrlist

    def put_secondaryip(self, instance_id, private_ip_address):
        if not private_ip_address:
            return False
        if not isinstance(private_ip_address, list):
            private_ip_address = [private_ip_address]

        group = self.find_group_by_instance(instance_id)
        if not group:
            return False

        instance = self.find_group_instance(group, instance_id)
        if not instance:
            return False

        if not instance.interfaces:
            return False

        try:
            ret = group.asg.assign_private_ip_addresses(
                    network_interface_id=instance.interfaces[0]['id'],
                    private_ip_addresses=private_ip_address
                    )
        except BotoServerError as e:
            if e.error_code == 'InvalidParameterValue':
                self.log('failed assigning secondary private IP %s to ' \
                        'instance %s interface %s' \
                        % (private_ip_address[0], instance_id,
                            instance.interfaces[0]['id']))
                return False
            else:
                raise e

        return ret

    def finalize_secondaryip(self):
        for g in self.service.groups:
            for i in g.instances:
                if not self.private_secondary_failures:
                    return
                for ni in i.interfaces:
                    if ('private_ip_addresses' not in ni or \
                            len(ni['private_ip_addresses']) == 0):
                        for p in self.private_secondary_failures:
                            ret = self.put_secondaryip(i.id, p)
                            if ret:
                                self.log('repair assigned private IP %s ' \
                                        'to instance %s' % (p, i.id))
                                self.private_secondary_failures.remove(p)
                                break

        for p in self.private_secondary_failures:
            self.log('failed repairing assignment of private IP %s' % p)


text:
describe '...' do
  before do
    @saved_path = ENV['PATH']
    @bobo_url = 'http://example.com'
  end

  after do
    ENV['PATH'] = @saved_path
  end

  def ask_for_copy
    Gist.on_success({'html_url' => @bobo_url}.to_json, :copy => true, :output => :html_url)
  end
  def gist_but_dont_ask_for_copy
    Gist.on_success({'html_url' => 'http://example.com/'}.to_json, :output => :html_url)
  end

  it 'should try to copy the url when the clipboard option is passed' do
    Gist.should_receive(:copy).with(@bobo_url)
    ask_for_copy
  end

  it 'should try to copy the embed url when the clipboard-js option is passed' do
    js_link = %Q{<script src="#{@bobo_url}.js"></script>}
    Gist.should_receive(:copy).with(js_link)
    Gist.on_success({'html_url' => @bobo_url}.to_json, :copy => true, :output => :javascript)
  end

  it "should not copy when not asked to" do
    Gist.should_not_receive(:copy).with(@bobo_url)
    gist_but_dont_ask_for_copy
  end

  it "should raise an error if no copying mechanisms are available" do
    ENV['PATH'] = ''
    lambda{
      ask_for_copy
    }.should raise_error(/Could not find copy command.*http/m)
  end
end


text:
/* Adapted from https://github.com/json-path/JsonPath/blob/master/json-path/src/main/java/com/jayway/jsonpath/internal/Utils.java */

#import "SMJUtils.h"

NS_ASSUME_NONNULL_BEGIN

/*
** Prototypes
*/
#pragma mark - Prototypes

static NSString * hexadecimal(uint16_t value);

/*
** SMJUtils
*/
#pragma mark - SMJUtils

@implementation SMJUtils

+ (NSString *)stringByConcatenatingStrings:(NSArray <NSString *> *)strings
{
	if (strings.count == 0)
		return @"";

	if (strings.count == 1)
		return [strings[0] copy];

	NSInteger length = 0;
	// -1 = no result, -2 = multiple results
	NSInteger indexOfSingleNonEmptyString = -1;

	for (NSInteger i = 0; i < strings.count; i++)
	{
		NSString *charSequence = strings[i];
		NSInteger len = charSequence.length;

		length += len;

		if (indexOfSingleNonEmptyString != -2 && len > 0)
		{
			if (indexOfSingleNonEmptyString == -1)
				indexOfSingleNonEmptyString = i;
			else
				indexOfSingleNonEmptyString = -2;
		}
	}

	if (length == 0)
		return @"";

	if (indexOfSingleNonEmptyString > 0) {
		return [strings[indexOfSingleNonEmptyString] copy];
	}

	NSMutableString *sb = [[NSMutableString alloc] init];

	for (NSString *charSequence in strings)
		[sb appendString:charSequence];

	return sb;
}

+ (NSString *)stringByJoiningStrings:(NSArray <NSString *> *)strings delimiter:(NSString *)delimiter wrap:(NSString *)wrap
{
	if (strings.count == 0)
		return @"";

	NSMutableString *buffer = [[NSMutableString alloc] init];

	[strings enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

		if (idx > 0)
			[buffer appendString:delimiter];

		[buffer appendString:wrap];
		[buffer appendString:obj];
		[buffer appendString:wrap];
	}];

	return buffer;
}

+ (NSString *)stringByEscapingString:(NSString *)str escapeSingleQuote:(BOOL)escapeSingleQuote
{
	NSInteger len = str.length;
	NSMutableString *writer = [NSMutableString string];

	for (NSInteger i = 0; i < len; i++)
	{
		unichar ch = [str characterAtIndex:i];

		// handle unicode
		if (ch > 0xfff)
			[writer appendFormat:@"\\u%@", hexadecimal(ch)];
		else if (ch > 0xff)
			[writer appendFormat:@"\\u0%@", hexadecimal(ch)];
		else if (ch > 0x7f)
			[writer appendFormat:@"\\u00%@", hexadecimal(ch)];
		else if (ch < 32)
		{
			switch (ch)
			{
				case '\b':
					[writer appendString:@"\\b"];
					break;

				case '\n':
					[writer appendString:@"\\n"];
					break;

				case '\t':
					[writer appendString:@"\\t"];
					break;

				case '\f':
					[writer appendString:@"\\f"];
					break;

				case '\r':
					[writer appendString:@"\\r"];
					break;

				default :
					if (ch > 0xf)
						[writer appendFormat:@"\\u00%@", hexadecimal(ch)];
					else
						[writer appendFormat:@"\\u000%@", hexadecimal(ch)];
					break;
			}
		}
		else
		{
			switch (ch)
			{
				case '\'':
					if (escapeSingleQuote)
						[writer appendString:@"\\"];
					[writer appendString:@"'"];
					break;

				case '"':
					[writer appendString:@"\\\""];
					break;

				case '\\':
					[writer appendString:@"\\\\"];
					break;

				case '/':
					[writer appendString:@"\\/"];
					break;

				default :
					[writer appendString:[NSString stringWithCharacters:&ch length:1]];
					break;
			}
		}
	}

	return writer;
}

+ (NSString *)stringByUnescapingString:(NSString *)str
{
	if (!str)
		return nil;

	NSInteger len = str.length;

	NSMutableString *writer = [NSMutableString string];
	NSMutableString *unicode = [NSMutableString string];

	BOOL hadSlash = false;
	BOOL inUnicode = false;

	for (NSInteger i = 0; i < len; i++)
	{
		unichar ch = [str characterAtIndex:i];

		if (inUnicode)
		{
			[unicode appendString:[NSString stringWithCharacters:&ch length:1]];

			if (unicode.length == 4)
			{
				unichar value = (unichar)[unicode integerValue];

				[unicode setString:@""];

				inUnicode = NO;
				hadSlash = NO;

				[writer appendString:[NSString stringWithCharacters:&value length:1]];
			}

			continue;
		}

		if (hadSlash)
		{
			unichar final = -1;

			hadSlash = NO;

			switch (ch)
			{
				case '\\':
					final = '\\';
					break;
				case '\'':
					final = '\'';
					break;
				case '\"':
					final = '"';
					break;
				case 'r':
					final = '\r';
					break;
				case 'f':
					final = '\f';
					break;
				case 't':
					final = '\t';
					break;
				case 'n':
					final = '\n';
					break;
				case 'b':
					final = '\b';
					break;
				case 'u':
				{
					inUnicode = true;
					break;
				}
				default :
					final = ch;
					break;
			}

			if (!inUnicode)
				[writer appendString:[NSString stringWithCharacters:&final length:1]];

			continue;
		}
		else if (ch == '\\')
		{
			hadSlash = YES;
			continue;
		}

		[writer appendString:[NSString stringWithCharacters:&ch length:1]];
	}

	if (hadSlash)
		[writer appendString:@"\\"];

	return writer;
}

+ (nullable NSNumber *)numberWithString:(NSString *)string
{
	NSScanner *scanner;

#if TARGET_OS_OSX // scanUnsignedLongLong is not available in GNUstep yet

	// Test unsigned long long int.
	unsigned long long unsignedLongLong = 0;

	scanner = [NSScanner scannerWithString:string];

	scanner.charactersToBeSkipped = [NSCharacterSet whitespaceCharacterSet];

	if ([scanner scanUnsignedLongLong:&unsignedLongLong] && scanner.isAtEnd)
		return @(unsignedLongLong);

#endif /* TARGET_OS_OSX */

	// Test signed long long int.
	long long signedLongLong = 0;

	scanner = [NSScanner scannerWithString:string];

	scanner.charactersToBeSkipped = [NSCharacterSet whitespaceCharacterSet];

	if ([scanner scanLongLong:&signedLongLong] && scanner.isAtEnd)
		return @(signedLongLong);

	// Test double.
	double doubleValue = 0.0;

	scanner = [NSScanner scannerWithString:string];

	scanner.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];
	scanner.charactersToBeSkipped = [NSCharacterSet whitespaceCharacterSet];

	if ([scanner scanDouble:&doubleValue] && scanner.isAtEnd)
		return @(doubleValue);

	return nil;
}

@end

/*
** C Tools
*/
#pragma mark - C Tools

static NSString * hexadecimal(uint16_t value)
{
	const char	hexTable[] = "0123456789ABCDEF";
	char 		buffer[50];
	NSUInteger	index = sizeof(buffer) - 1;

	do
	{
		buffer[index] = hexTable[value % 16];
		value /= 16;
		index--;
	} while (value != 0 && index > 0);

	return [[NSString alloc] initWithBytes:buffer + index + 1 length:sizeof(buffer) - index - 1 encoding:NSASCIIStringEncoding];
}

NS_ASSUME_NONNULL_END


text:
author: slowe
comments: true
date: 2007-07-10 13:20:33+00:00
layout: post
slug: esx-server-ad-integration
title: ESX Server-AD Integration
wordpress_id: 488
categories: Tutorial
tags:
- ActiveDirectory
- ESX
- Interoperability
- Kerberos
- LDAP
- SSH
- Virtualization
- VMware
---

Although much of the administration of servers running [VMware ESX Server 3.0](http://www.vmware.com/products/vi/esx/) will occur in the Windows-based Virtual Infrastructure client connected to a [VirtualCenter](http://www.vmware.com/products/vi/vc/) server, there are times when it is quicker or easier to perform an administrative task directly on the ESX Server itself---either via the command-line interface (CLI) or via the VI client authenticating directly against the ESX Server. The problem with this is that, by default, administrators will have to use different credentials when connecting the VI client to ESX Server directly. In addition, these credentials must be managed separately from Active Directory, and separately on each individual ESX Server. As the number of ESX Servers in a farm grows, this can quickly become an administrative nightmare.

Fortunately, we can fairly easily integrate ESX authentication into Active Directory, so that the same account used in VirtualCenter is also used when logging in to the ESX Server directly. While VMware took the step of automating a portion of this process for us in the `esxcfg-auth` command, it only takes us part of the way.

Let's take a look at what part esxcfg-auth does accomplish for us, then look at how to accomplish the rest of the task.

## Using esxcfg-auth

The `esxcfg-auth` command will help automate a good portion of the work required to integrate ESX Server into Active Directory; specifically, it will automate the Kerberos configuration. To use `esxcfg-auth` to enable AD authentication, use the following command:

	esxcfg-auth --enablead --addomain=example.com --addc=dc1.example.com

Obviously, you'll want to substitute the appropriate values for "example.com" and "dc1.example.com" on the command above. So what does this command do, exactly? Here's the breakdown:

* Modifies the `/etc/krb5.conf` file to use example.com as the default Kerberos realm, and to use dc1.example.com as a KDC for that realm. In this same file, the domain "example.com" is mapped to the realm "EXAMPLE.COM" (keep in mind Kerberos realms are always specified in UPPERCASE).

* The `/etc/pam.d/system-auth` file is modified to use pam_krb5.so for Kerberos authentication.

What does this command _not_ do? Well, for one it doesn't configure the ESX Server for anything other than pure authentication. This means that although users will be forced to authenticate against Active Directory, ESX Server still expects to find the accounts defined in the local `/etc/passwd` file. This means that password management is centralized, but account management is still decentralized. (Some might see this as a security advantage, in that we must manually define an account in order to allow that account to log in to that server.)

To fully centralize account management, we'll need to step outside of the `esxcfg-auth` framework and get our hands dirty. Ready?

## Finishing esxcfg-auth's Work

To fully round out the authentication/account management configuration, Active Directory will have to be made aware of some UNIX-specific attributes. This means extending the schema. If you are running Windows 2000 or Windows Server 2003 pre-R2, this means installing Services for UNIX (SfU) 3.5; for Windows Server 2003 R2 or later, this means installing Identity Management for UNIX.

I'll refer you to this [article for Windows 2003 and Windows Server 2003 pre-R2][1] and this [article for Windows Server 2003 R2][2] or later for more information. (Because the ESX Server service console is based on Red Hat Enterprise Linux, these Linux-AD integration guides are very applicable here.)

Once Active Directory has been configured, the only tasks left for us to do are 1) to configure the nss_ldap libraries; 2) to configure `/etc/nsswitch.conf` to enable LDAP for naming services; and 3) verify time synchronization.

To configure the nss_ldap libraries, you'll need to modify the `/etc/ldap.conf` file as described in Step 5 of the "Prepare Each Linux Server" section of [this article][2] (assuming you are using Windows Server 2003 R2). This sets up the connection to Active Directory via LDAP and configures the attribute maps accordingly.

Please note that you'll need to create an account in Active Directory (a Domain Guest is fine) that the nss_ldap libraries may use for LDAP queries. You'll specify that account information when configuring `/etc/ldap.conf`.

Next, you'll need to configure `/etc/nsswitch.conf`. You only need to modify the passwd, group, and shadow lines, and you only need to add "ldap" at the end of the lines. The lines will end up looking something like this:

	group: files ldap
	passwd: files ldap
	shadow: files ldap

At this point, you should be able to test the nss_ldap configuration. Run `getent passwd <AD user account>` and you should get back information about that account's home directory, login shell, UID, and name. If you don't get back any information, go back and double-check your configuration.

To verify time synchronization, have a look at the NTP configuration found in `/etc/ntp.conf`. Make the changes you need here to be sure that both Active Directory (the forest root PDC emulator, specifically) and ESX Server are both synchronizing time and will stay in sync. Otherwise, the Kerberos authentication process will fail. Keep in mind that you may need to adjust the Service Console firewall using `esxcfg-firewall` in order to allow the appropriate traffic outbound. (Thanks to KentA for reminding me about this step!)

Once `getent passwd` is working as expected and time is in sync, then you should be able to SSH into the ESX Server with any appropriately configured AD account (i.e., any AD account that has the "UNIX Attributes" tab completed with valid information). This gives you a similar level of control over who is allowed to login and who isn't; accounts that don't have any UNIX attributes won't be able to authenticate and gain access to the ESX Servers.

In addition, you should be able to configure some level of access control as described [here][3].

## Summary

To summarize, the process for integrating ESX Server into Active Directory looks like this:

1. Use `esxcfg-auth` to set up the Kerberos authentication.

2. Extend the AD schema (if necessary) to include UNIX attributes such as login shell, UNIX home directory, UID, UID number, etc. This is accomplished in different ways depending upon the version of Windows in use.

3. Populate the UNIX attributes for those user accounts that should be allowed to access the ESX Server(s).

4. Configure `/etc/ldap.conf` on the ESX Server to configure LDAP connectivity back to Active Directory for name service lookups.

5. Configure `/etc/nsswitch.conf` to use LDAP for name service lookups.

6. Verify (and configure, if needed) time synchronization via NTP on the ESX Server.

7. Test the configuration using `getent passwd`, `getent group`, or both.

This configuration will centralize not only authentication for the ESX Servers but will also centralize account management in Active Directory as well.

Please feel free to add any corrections or suggestions for improvement in the comments below. Thanks!

[1]: {% post_url 2005-12-22-complete-linux-ad-authentication-details %}
[2]: {% post_url 2007-01-15-linux-ad-integration-version-4 %}
[3]: {% post_url 2006-09-08-ldap-based-access-control %}


text:
package radlab.rain.workload.olio;

import java.io.File;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger;

import radlab.rain.Generator;
import radlab.rain.LoadProfile;
import radlab.rain.Operation;
import radlab.rain.ScenarioTrack;
import radlab.rain.util.HttpTransport;
import radlab.rain.util.NegativeExponential;

/**
 * The OlioGenerator class generates operations for a single user thread by
 * producing the next operation to execute given the last operation. The next
 * operation is decided through the use of a load mix matrix.

 *

 * This class also provides accessors to many static parameters such as the
 * HTTP client, and it generates other potentially dynamic values such as the
 * think/cycle times.
 */
public class OlioGenerator extends Generator
{
	/** Static URLs loaded as part of the layout. */
	protected static final String[] LAYOUT_STATICS = {
		"/js/validateform.js",
		"/js/starrating.js",
		"/js/prototype.js",
		"/js/httpobject.js",
		"/js/effects.js",
		"/js/dragdrop.js",
		"/js/controls.js",
		"/css/scaffold.css",
		"/css/site.css",
		"/css/reset.css",
		"/images/bg_main.png",
		"/images/php_bg_header.gif",
		"/images/php_main_nav_link_bg.gif",
		"/images/php_main_nav_link_bg.gif",
		"/images/RSS-icon-large.gif",
		"/images/php_main_nav_link_bg.gif",
		"/images/php_main_nav_link_bg.gif",
		"/images/php_corner_top_right.gif",
		"/images/php_corner_top_left.gif",
		"/images/php_corner_bottom_right.gif",
		"/images/php_corner_bottom_left.gif",
		"/images/php_reflec_tile.gif",
		"/images/php_reflec_right.gif",
		"/images/php_reflec_left.gif",
		"/images/php_main_nav_hover_bg.gif"
	};

	/*
	 * @Row({  0, 11, 52, 36,  0, 1,  0 }), // Home Page
	 * @Row({  0,  0, 60, 20,  0, 0, 20 }), // Login
	 * @Row({ 21,  6, 41, 31,  0, 1,  0 }), // Tag Search
	 * @Row({ 72, 21,  0,  0,  6, 1,  0 }), // Event Detail
	 * @Row({ 52,  6,  0, 31, 11, 0,  0 }), // Person Detail
	 * @Row({  0,  0,  0,  0,100, 0,  0 }), // Add Person
	 * @Row({  0,  0,  0,100,  0, 0,  0 })  // Add Event
	 */
	public static final int HOME_PAGE     = 0;
	public static final int LOGIN         = 1;
	public static final int TAG_SEARCH    = 2;
	public static final int EVENT_DETAIL  = 3;
	public static final int PERSON_DETAIL = 4;
	public static final int ADD_PERSON    = 5;
	public static final int ADD_EVENT     = 6;

	// URL roots/anchors for each request
	public String baseURL;
	public String personDetailURL;
	public String tagSearchURL;
	public String homepageURL;
	public String loginURL;
	public String logoutURL;
	public String addEventURL;
	public String addPersonURL;
	public String eventDetailURL;
	public String addEventResultURL;
	public String addPersonResultURL;
	public String addAttendeeURL;
	public String checkNameURL;
	public String fileServiceURL;
	public String tagCloudURL;

	// Statics URLs
	public String[] homepageStatics;
	public String[] personStatics;
	public String[] personGets;
	public String[] tagSearchStatics;
	public String[] eventDetailStatics;
	public String[] addPersonStatics;
	public String[] addEventStatics;

	// Login header collection
	public LinkedHashMap<String,String> loginHeaders = new LinkedHashMap<String,String>();

	// Local file resources used when creating people and events
	public File eventImg;
	public File eventThumb;
	public File eventPdf;
	public File personImg;
	public File personThumb;
	public String type = "php";

	/** The number of users created during the benchmark run. */
	public AtomicLong _personsAdded = new AtomicLong(0L);

	private boolean _isLoggedOn = false;
	private HashSet<String> _cachedURLs = new HashSet<String>();

	private NegativeExponential _thinkTimeGenerator  = null;
	private NegativeExponential _cycleTimeGenerator = null;

	/**
	 * Updates the current "logged in" status.
	 */
	public void setIsLoggedOn( boolean val )
	{
		this._isLoggedOn = val;
	}

	/**
	 * Returns the current "logged on" status.
	 *
	 * @return      True if this user is "logged on"; otherwise false.
	 */
	public boolean isLoggedOn() {
		return this._isLoggedOn;
	}

	/**
	 * Returns the set of cached URLs.
	 *
	 * @return      A set of cached URLs.
	 */
	public HashSet<String> getCachedURLs()
	{
		return this._cachedURLs;
	}

	private java.util.Random _randomNumberGenerator;
	private radlab.rain.workload.olio.Random _randomUtil;
	private HttpTransport _http;
	private Logger _logger;

	/**
	 * Returns an instance of the Olio random utility.
	 *
	 * @return          A random number generator.
	 */
	public radlab.rain.workload.olio.Random getOlioRandomUtil()
	{
		return getOlioRandomUtil(false);
	}

	/**
	 * Returns an instance of the Olio random utility.
	 *
	 * @param clone     If true, a clone is returned.
	 * @return          A random number generator.
	 */
	public radlab.rain.workload.olio.Random getOlioRandomUtil( boolean clone )
	{
		if( clone )
		{
			// TODO: Implement cloning of random number generator.
			return null;
		}
		else
		{
			return this._randomUtil;
		}
	}

	/**
	 * Returns the pre-existing HTTP transport.
	 *
	 * @return          An HTTP transport.
	 */
	public HttpTransport getHttpTransport()
	{
		return getHttpTransport(false);
	}

	/**
	 * Returns an HTTP transport.
	 *
	 * @param clone     If true, a clone is returned.
	 * @return          An HTTP transport.
	 */
	public HttpTransport getHttpTransport( boolean clone )
	{
		if( clone )
		{
			// TODO: Implement cloning of HTTP transport.
			return null;
		}
		else
		{
			return this._http;
		}
	}

	/**
	 * Returns the Logger associated with this generator.
	 *
	 * @return      A Logger object.
	 */
	public Logger getLogger()
	{
		return this._logger;
	}

	/**
	 * Initialize a OlioGenerator given a ScenarioTrack.
	 *
	 * @param track     The track configuration with which to run this generator.
	 */
	public OlioGenerator( ScenarioTrack track )
	{
		super( track );

		this.initializeUrlAnchors();
		this.initializeLocalFileResources();
		this.initializeLoginHeaders();
		this.initializeStaticUrls();

		// Initialize random utility generators and HttpTransport instances.
		this._randomNumberGenerator = new java.util.Random();
		this._randomUtil = new radlab.rain.workload.olio.Random();
		this._http = new HttpTransport();
		// Initialize the cycle time and think time generators. If you want non-stop
		// activity, then set mean cycle time, and mean think times to 0 and the
		// number generators should just *always* return 0 for the think/cycle time
		this._cycleTimeGenerator = new NegativeExponential( track.getMeanCycleTime()*1000 );
		this._thinkTimeGenerator = new NegativeExponential( track.getMeanThinkTime()*1000 );
		ScaleFactors.setActiveUsers( this.getTrack().getMaxUsers() );
		this._cycleTime = (long) track.getMeanCycleTime()*1000;
		this._thinkTime = (long) track.getMeanThinkTime()*1000;
	}

	/**
	 * Initialize this generator.
	 */
	public void initialize()
	{
		this._logger = Logger.getLogger( this._name );
	}

	/**
	 * Initialize the fully qualified static URLs for the operations.
	 */
	public void initializeStaticUrls()
	{
		this.homepageStatics    = joinStatics( LAYOUT_STATICS );
		this.personStatics      = joinStatics( LAYOUT_STATICS );
		this.personGets         = joinStatics( LAYOUT_STATICS );
		this.tagSearchStatics   = joinStatics( LAYOUT_STATICS );
		this.eventDetailStatics = joinStatics( LAYOUT_STATICS);
		this.addPersonStatics   = joinStatics( LAYOUT_STATICS);
		this.addEventStatics    = joinStatics( LAYOUT_STATICS);
	}

	/**
	 * Joins any number of arrays of relative static URLs and fully qualifies
	 * them by prepending the base URL. Duplicate static URLs are removed.
	 *
	 * Copied from original UIDriver.java file.
	 *
	 * @param staticsLists  Arrays of relative static URLs.
	 * @return              An array of unique, full qualified static URLs.
	 */
	private String[] joinStatics( String[] ... staticsLists )
	{
		LinkedHashSet<String> urlSet = new LinkedHashSet<String>();

		for ( String[] staticList : staticsLists )
		{
			for ( int i = 0; i < staticList.length; i++ )
			{
				String url = baseURL + staticList[i].trim();
				urlSet.add( url );
			}
		}

		return (String[]) urlSet.toArray(new String[0]);
	}

	/**
	 * Initialize the login header information.
	 */
	public void initializeLoginHeaders()
	{
		String host = this._loadTrack.getTargetHostName() + ":" + this._loadTrack.getTargetHostPort();

		this.loginHeaders.clear();
		this.loginHeaders.put("Host", host );
		this.loginHeaders.put("User-Agent", "Mozilla/5.0");
		this.loginHeaders.put("Accept", "text/xml.application/xml,application/" +
		        "xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;" +
		        "q=0.5");
		this.loginHeaders.put("Accept-Language", "en-us,en;q=0.5");
		this.loginHeaders.put("Accept-Encoding", "gzip,deflate");
		this.loginHeaders.put("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
		this.loginHeaders.put("Keep-Alive", "300");
		this.loginHeaders.put("Connection", "keep-alive");
		this.loginHeaders.put("Referer", this.homepageURL);
	}

	/**
	 * Initialize local resources (e.g. files that we need to submit).
	 */
	public void initializeLocalFileResources()
	{
		String resourcePath = this._loadTrack.getResourcePath();
		if( !resourcePath.endsWith( File.separator ) )
		{
			resourcePath += File.separator;
		}

		this.eventImg    = new File(resourcePath + "event.jpg");
		this.eventThumb  = new File(resourcePath + "event_thumb.jpg");
		this.eventPdf    = new File(resourcePath + "event.pdf");
		this.personImg   = new File(resourcePath + "person.jpg");
		this.personThumb = new File(resourcePath + "person_thumb.jpg");
	}

	/**
	 * Initialize the roots/anchors of the URLs.
	 */
	public void initializeUrlAnchors()
	{
		this.baseURL = "http://" + this._loadTrack.getTargetHostName() + ":" + this._loadTrack.getTargetHostPort();
		this.personDetailURL    = this.baseURL + "/users.php";
		this.tagSearchURL       = this.baseURL + "/taggedEvents.php";
		this.tagCloudURL        = this.baseURL + "/tagCloud." + type;
		this.addEventURL        = this.baseURL + "/addEvent.php";
		this.addEventResultURL  = this.baseURL + "/addEventResult.php";
		this.addPersonURL       = this.baseURL + "/addPerson.php";
		this.addPersonResultURL = this.baseURL + "/addPersonResult.php";
		this.homepageURL        = this.baseURL + "/";
		this.loginURL           = this.baseURL + "/login.php";
		this.logoutURL          = this.baseURL + "/logout.php";
		this.addAttendeeURL     = this.baseURL + "/addAttendee.php";
		this.eventDetailURL     = this.baseURL + "/events.php";
		this.fileServiceURL     = this.baseURL + "/fileService." + type + '?';
		this.checkNameURL       = this.baseURL + "/checkUser.php";
	}

	/**
	 * Returns the next Operation given the lastOperation
	 * according to the current mix matrix.
	 *
	 * @param lastOperation     The last Operation that was executed.
	 */
	public Operation nextRequest( int lastOperation )
	{
		LoadProfile currentLoad = this.getTrack().getCurrentLoadProfile();
		this._latestLoadProfile = currentLoad;
		int nextOperation = -1;

		if( lastOperation == -1 )
		{
			nextOperation = 0;
		}
		else
		{
			// Get the selection matrix
			double[][] selectionMix = this.getTrack().getMixMatrix(currentLoad.getMixName()).getSelectionMix();
			double rand = this._randomNumberGenerator.nextDouble();

			int j;
			for ( j = 0; j < selectionMix.length; j++ )
			{
				if ( rand <= selectionMix[lastOperation][j] )
				{
					break;
				}
			}
			nextOperation = j;
		}
		return getOperation( nextOperation );
	}

	/**
	 * Returns the current think time. The think time is duration between
	 * receiving the response of an operation and the execution of its
	 * succeeding operation during synchronous execution (i.e. closed loop).
	 */
	public long getThinkTime()
	{
		long nextThinkTime = (long) this._thinkTimeGenerator.nextDouble();
		// Truncate at 5 times the mean (arbitrary truncation)
		return Math.min( nextThinkTime, (5*this._thinkTime) );
	}

	/**
	 * Returns the current cycle time. The cycle time is duration between
	 * the execution of an operation and the execution of its succeeding
	 * operation during asynchronous execution (i.e. open loop).
	 */
	public long getCycleTime()
	{
		long nextCycleTime = (long) this._cycleTimeGenerator.nextDouble();
		// Truncate at 5 times the mean (arbitrary truncation)
		return Math.min( nextCycleTime, (5*this._cycleTime) );
	}

	/**
	 * Disposes of unnecessary objects at the conclusion of a benchmark run.
	 */
	public void dispose()
	{
		this._http.dispose();
	}

	/**
	 * Creates a newly instantiated, prepared operation.
	 *
	 * @param opIndex   The type of operation to instantiate.
	 * @return          A prepared operation.
	 */
	public Operation getOperation( int opIndex )
	{
		switch( opIndex )
		{
			case HOME_PAGE:     return this.createHomePageOperation();
			case LOGIN:         return this.createLoginOperation();
			case TAG_SEARCH:    return this.createTagSearchOperation();
			case EVENT_DETAIL:  return this.createEventDetailOperation();
			case PERSON_DETAIL: return this.createPersonDetailOperation();
			case ADD_PERSON:    return this.createAddPersonOperation();
			case ADD_EVENT:     return this.createAddEventOperation();
			default:            return null;
		}
	}

	/**
	 * Factory method.
	 *
	 * @return  A prepared HomePageOperation.
	 */
	public HomePageOperation createHomePageOperation()
	{
		HomePageOperation op = new HomePageOperation( this.getTrack().getInteractive(), this.getScoreboard() );
		op.prepare( this );
		return op;
	}

	/**
	 * Factory method.
	 *
	 * @return  A prepared LoginOperation.
	 */
	public LoginOperation createLoginOperation()
	{
		LoginOperation op = new LoginOperation( this.getTrack().getInteractive(), this.getScoreboard() );
		op.prepare( this );
		return op;
	}

	/**
	 * Factory method.
	 *
	 * @return  A prepared TagSearchOperation.
	 */
	public TagSearchOperation createTagSearchOperation()
	{
		TagSearchOperation op = new TagSearchOperation( this.getTrack().getInteractive(), this.getScoreboard() );
		op.prepare( this );
		return op;
	}

	/**
	 * Factory method.
	 *
	 * @return  A prepared EventDetailOperation.
	 */
	public EventDetailOperation createEventDetailOperation()
	{
		EventDetailOperation op = new EventDetailOperation( this.getTrack().getInteractive(), this.getScoreboard() );
		op.prepare( this );
		return op;
	}

	/**
	 * Factory method.
	 *
	 * @return  A prepared PersonDetailOperation.
	 */
	public PersonDetailOperation createPersonDetailOperation()
	{
		PersonDetailOperation op = new PersonDetailOperation( this.getTrack().getInteractive(), this.getScoreboard() );
		op.prepare( this );
		return op;
	}

	/**
	 * Factory method.
	 *
	 * @return  A prepared AddPersonOperation.
	 */
	public AddPersonOperation createAddPersonOperation()
	{
		AddPersonOperation op = new AddPersonOperation( this.getTrack().getInteractive(), this.getScoreboard() );
		op.prepare( this );
		return op;
	}

	/**
	 * Factory method.
	 *
	 * @return  A prepared AddEventOperation.
	 */
	public AddEventOperation createAddEventOperation()
	{
		AddEventOperation op = new AddEventOperation( this.getTrack().getInteractive(), this.getScoreboard() );
		op.prepare( this );
		return op;
	}
}


text:
package grpc

import (
	"context"

	"github.com/wejick/tego/example/autocomplete/autocompleteService/pb"
	"github.com/wejick/tego/transport/grpc"

	goGRPC "google.golang.org/grpc"
)

// ServerBinder Implement server interface from the protobuf definition
// it will be called by grpc server
// Why the name is server binder, it bind the tego server with the pb serve,
// hence the name is server binder
type ServerBinder struct {
	suggestionHandler grpc.Handler
	popularSuggestion grpc.Handler
}

// MakeServerBinder returns autocomplete service grpc server binder
func MakeServerBinder(suggestionHandler grpc.Handler, popularHandler grpc.Handler) ServerBinder {
	return ServerBinder{
		suggestionHandler: suggestionHandler,
		popularSuggestion: popularHandler,
	}
}

//RegisterAutocompleteServer register pb service to grpc server
func RegisterAutocompleteServer(grpcServer *goGRPC.Server, autocompleteServer ServerBinder) {
	pb.RegisterAutocompleteServer(grpcServer, autocompleteServer)
}

// GetSuggestion handler for suggestion service
func (s ServerBinder) GetSuggestion(ctx context.Context, req *pb.AutocompleteRequest) (*pb.SuggestionResponse, error) {
	_, resp, err := s.suggestionHandler.ServeGRPC(ctx, req)
	if err != nil {
		return nil, err
	}

	response := resp.(*pb.SuggestionResponse)
	return response, err
}

// GetPopular handler for popular service
func (s ServerBinder) GetPopular(ctx context.Context, req *pb.AutocompleteRequest) (*pb.PopularResponse, error) {
	_, resp, err := s.popularSuggestion.ServeGRPC(ctx, req)
	if err != nil {
		return nil, err
	}

	response := resp.(*pb.PopularResponse)
	return response, err
}