Neutron/LBaaS/CommonAgentDriver

Rationale
Haproxy-on-host reference implementation which is using agents is quite specific:
 * with haproxy it is easier to deploy the whole loadbalancer config from scratch every time then to create/update/delete separate components
 * namespace driver needs virtual interface driver on init, other drivers may have their own specific parameters

So it is useful to unify reference agent implementation to:
 * make it suite any driver which wants to use async mechanism
 * have single lbaas agent type and hense single agent scheduling mechanism

What is required

 * 1) Revision of agent API
 * 2) Revision of agent loading device driver(s) mechanism

Agent API changes
Current lbaas agent API is specific for haproxy but it doesn't fit well with other loadbalancers where deploying the whole config from scratch every time is unacceptable. Need to modify agent API as well as device driver API to make them almost a duplication of plugin driver API (quantum.services.loadbalancer.drivers.abstract_driver.LoadBalancerAbstractDriver). In addition a create_pool call to agent should contain a device driver reference (according to service provider choosen by tenant): class LbaasAgentManager(periodic_task.PeriodicTasks): ...   def create_pool(self, context, pool, driver_name): if driver_name not in self.device_drivers: LOG.error(_('No device driver on agent: %s.') % driver_name) return driver = self.device_drivers[driver_name] try: driver.create_pool(pool) self.plugin_rpc.update_status('pool', pool['id'], constants.ACTIVE) self.devices[pool['id']] = driver_name except Exception: LOG.exception(_('create pool failed on device driver')) self.plugin_rpc.update_status('pool', pool['id'], constants.ERROR) ... Every time agent sends a request to plugin to update status of the object (active or error). Also agent saves pool_id to its cache of known devices (self.devices) to determine which driver to use for handling subsequent objects related to that pool: ...   def _get_driver(self, pool_id): if pool_id not in self.devices: msg = _('Unknown device with pool_id %s') % pool_id LOG.error(msg) raise n_exc.Invalid(msg) driver_name = self.devices[pool_id] return self.device_drivers[driver_name]

def create_vip(self, context, vip): driver = self._get_driver(vip['pool_id']) try: driver.create_vip(vip) self.plugin_rpc.update_status('vip', vip['id'], constants.ACTIVE) except Exception: LOG.exception(_('create vip failed on device driver')) self.plugin_rpc.update_status('vip', vip['id'], constants.ERROR) ...

Loading drivers in agent
Different device drivers may require different initial parameters (like vif_driver for haproxy namespace_driver). Current solution will be to have special sections in lbaas_agent.ini for every device driver so that it can read those parameters itself when loading.