update to use Quantum rpc sync state

This commit is contained in:
Mark McClain 2013-02-20 13:10:26 -05:00
parent 5936b0bd71
commit 6e78e4ca2d
4 changed files with 113 additions and 54 deletions

View File

@ -1,10 +1,14 @@
import socket
import time
import uuid
import netaddr
from quantumclient.v2_0 import client
from akanda.rug.openstack.common import importutils
from akanda.rug.openstack.common import cfg
from akanda.rug.openstack.common import context
from akanda.rug.openstack.common.rpc import proxy
# copied from Quantum source
@ -12,8 +16,8 @@ DEVICE_OWNER_ROUTER_MGT = "network:router_management"
DEVICE_OWNER_ROUTER_INT = "network:router_interface"
DEVICE_OWNER_ROUTER_GW = "network:router_gateway"
DEVICE_OWNER_FLOATINGIP = "network:floatingip"
DEVICE_OWNER_RUG = "akanda:rug"
DEVICE_OWNER_RUG = "network:akanda"
PLUGIN_RPC_TOPIC = 'q-plugin'
class Router(object):
@ -266,28 +270,53 @@ class AkandaExtClientWrapper(client.Client):
params=params)
class L3PluginApi(proxy.RpcProxy):
"""Agent side of the Qunatum l3 agent RPC API."""
BASE_RPC_API_VERSION = '1.0'
def __init__(self, topic, host):
super(L3PluginApi, self).__init__(
topic=topic, default_version=self.BASE_RPC_API_VERSION)
self.host = host
def get_routers(self, router_id=None):
"""Make a remote process call to retrieve the sync data for routers."""
router_ids = [router_id] if router_id else None
retval = self.call(context.get_admin_context(),
self.make_msg('sync_routers', host=self.host,
router_ids=router_ids),
topic=self.topic)
return retval
class Quantum(object):
def __init__(self, conf):
self.conf = conf
self.client = AkandaExtClientWrapper(
self.api_client = AkandaExtClientWrapper(
username=conf.admin_user,
password=conf.admin_password,
tenant_name=conf.admin_tenant_name,
auth_url=conf.auth_url,
auth_strategy=conf.auth_strategy,
auth_region=conf.auth_region)
auth_region=conf.auth_region
)
self.rpc_client = L3PluginApi(PLUGIN_RPC_TOPIC, cfg.CONF.host)
def get_routers(self):
"""Return a list of routers."""
return [Router.from_dict(r) for r in
self.client.list_routers()['routers']]
self.rpc_client.get_routers()]
def get_router_detail(self, router_id):
"""Return detailed information about a router and it's networks."""
return Router.from_dict(self.client.show_router(router_id)['router'])
return Router.from_dict(
self.rpc_client.get_routers(router_id=router_id)[0]
)
def get_router_for_tenant(self, tenant_id):
routers = self.client.list_routers(tenant_id=tenant_id)['routers']
routers = self.api_client.list_routers(tenant_id=tenant_id)['routers']
if routers:
return Router.from_dict(routers[0])
@ -296,25 +325,25 @@ class Quantum(object):
def get_network_ports(self, network_id):
return [Port.from_dict(p) for p in
self.client.list_ports(network_id=network_id)['ports']]
self.api_client.list_ports(network_id=network_id)['ports']]
def get_network_subnets(self, network_id):
return [Subnet.from_dict(s) for s in
self.client.list_subnets(network_id=network_id)['subnets']]
self.api_client.list_subnets(network_id=network_id)['subnets']]
def get_addressgroups(self, tenant_id):
return [AddressGroup.from_dict(g) for g in
self.client.list_addressgroups(
self.api_client.list_addressgroups(
tenant_id=tenant_id)['addressgroups']]
def get_filterrules(self, tenant_id):
return [FilterRule.from_dict(r) for r in
self.client.list_filterrules(
self.api_client.list_filterrules(
tenant_id=tenant_id)['filterrules']]
def get_portforwards(self, tenant_id):
return [PortForward.from_dict(f) for f in
self.client.list_portforwards(
self.api_client.list_portforwards(
tenant_id=tenant_id)['portforwards']]
def create_router_management_port(self, router_id):
@ -322,16 +351,16 @@ class Quantum(object):
network_id=self.conf.management_network_id,
device_owner=DEVICE_OWNER_ROUTER_MGT
)
response = self.client.create_port(dict(port=port_dict))
response = self.api_client.create_port(dict(port=port_dict))
port = Port.from_dict(response['port'])
args = dict(port_id=port.id, owner=DEVICE_OWNER_ROUTER_MGT)
self.client.add_interface_router(router_id, args)
self.api_client.add_interface_router(router_id, args)
return port
def delete_router_management_port(self, router_id, port_id):
args = dict(port_id=port_id, owner=DEVICE_OWNER_ROUTER_MGT)
self.client.remove_interface_router(router_id, args)
self.api_client.remove_interface_router(router_id, args)
def create_router_external_port(self, router):
network_args = {'network_id': self.conf.external_network_id}
@ -341,7 +370,7 @@ class Quantum(object):
'external_gateway_info': network_args
}
r = self.client.update_router(router.id, body=dict(router=update_args))
r = self.api_client.update_router(router.id, body=dict(router=update_args))
return Router.from_dict(r['router']).external_port
def ensure_local_service_port(self):
@ -353,27 +382,36 @@ class Quantum(object):
query_dict = dict(device_owner=DEVICE_OWNER_RUG,
device_id=host_id)
ports = self.client.list_ports(**query_dict)['ports']
ports = self.api_client.list_ports(**query_dict)['ports']
ip_address = get_local_service_ip(self.conf)
if ports:
port = Port.from_dict(ports[0])
else:
# create the missing local port
port_dict = dict(admin_state_up=True,
network_id=self.conf.management_network_id,
device_owner=DEVICE_OWNER_RUG,
device_id=host_id)
port_dict = dict(
admin_state_up=True,
network_id=self.conf.management_network_id,
device_owner=DEVICE_OWNER_RUG,
device_id=host_id,
fixed_ips=[{
'ip_address': ip_address.split('/')[0],
'subnet_id': self.conf.management_subnet_id
}]
)
port = Port.from_dict(
self.client.create_port(dict(port=port_dict))['port'])
self.api_client.create_port(dict(port=port_dict))['port'])
driver.plug(port.network_id,
port.id,
driver.get_device_name(port),
port.mac_address)
# add sleep to ensure that port is setup before use
time.sleep(1)
driver.init_l3(driver.get_device_name(port),
[get_local_service_ip(self.conf)])
driver.init_l3(driver.get_device_name(port), [ip_address])
return port

View File

@ -22,7 +22,7 @@ LOG = logging.getLogger(__name__)
OPTIONS = [
cfg.StrOpt('admin_user'),
cfg.StrOpt('admin_password'),
cfg.StrOpt('admin_password', secret=True),
cfg.StrOpt('admin_tenant_name'),
cfg.StrOpt('auth_url'),
cfg.StrOpt('auth_strategy', default='keystone'),
@ -41,22 +41,20 @@ OPTIONS = [
cfg.StrOpt('interface_driver'),
cfg.StrOpt('ovs_integration_bridge', default='br-int'),
cfg.BoolOpt('ovs_use_veth', default=False),
cfg.StrOpt('root_helper', default='sudo'),
cfg.IntOpt('network_device_mtu'),
# listen for Quantum notification events
cfg.StrOpt('notification_topic',
default='notifications.info',
help='Quantum notification topic name'),
cfg.StrOpt('quantum_control_exchange',
default='openstack',
help='Quantum control exchange name'),
cfg.StrOpt('control_exchange',
default='akanda',
help='Akanda control exchange name')
help='Quantum notification topic name')
]
AGENT_OPTIONS = [
cfg.StrOpt('root_helper', default='sudo'),
]
cfg.CONF.register_opts(OPTIONS)
cfg.CONF.register_opts(AGENT_OPTIONS, 'AGENT')
class AkandaL3Manager(notification.NotificationMixin,
@ -66,39 +64,38 @@ class AkandaL3Manager(notification.NotificationMixin,
self.quantum = quantum.Quantum(cfg.CONF)
self.nova = nova.Nova(cfg.CONF)
self.task_mgr = task.TaskManager()
self.quantum.ensure_local_service_port()
def init_host(self):
def initialize_service_hook(self, started_by):
self.sync_state()
self.task_mgr.start()
self.create_notification_listener(
cfg.CONF.notification_topic,
cfg.CONF.quantum_control_exchange)
cfg.CONF.control_exchange)
self.metadata = metadata.create_metadata_signing_proxy(
quantum.get_local_service_ip(cfg.CONF).split('/')[0]
)
@periodic_task.periodic_task
def begin_health_check(self):
def begin_health_check(self, context):
LOG.info('start health check queueing')
for rtr in self.cache.routers():
self.task_mgr.put(self.check_health, rtr)
@periodic_task.periodic_task(ticks_between_runs=1)
def report_bandwidth_usage(self):
def report_bandwidth_usage(self, context):
LOG.info('start bandwidth usage reporting')
for rtr in self.cache.routers():
self.task_mgr.put(self.report_bandwidth, rtr)
@periodic_task.periodic_task(ticks_between_runs=10)
def janitor(self):
def janitor(self, context):
"""Periodically do a full state resync."""
LOG.debug('resync router state')
self.sync_state()
@periodic_task.periodic_task(ticks_between_runs=15)
def refresh_configs(self):
def refresh_configs(self, context):
LOG.debug('resync configuration state')
for rtr_id in self.cache.keys():
self.task_mgr.put(self.update_config, rtr_id)
@ -113,7 +110,10 @@ class AkandaL3Manager(notification.NotificationMixin,
@notification.handles('subnet.create.end',
'subnet.change.end',
'subnet.delete.end')
'subnet.delete.end',
'port.create.end',
'port.change.end',
'port.delete.end')
def handle_router_subnet_change(self, tenant_id, payload):
rtr = self.cache.get_by_tenant_id(tenant_id)
if not rtr:

View File

@ -1,3 +1,4 @@
import socket
import sys
import eventlet
@ -5,24 +6,39 @@ import eventlet
from akanda.rug import manager
from akanda.rug.openstack.common import cfg
from akanda.rug.openstack.common import log
from akanda.rug.openstack.common import rpc
from akanda.rug.openstack.common.rpc import service as rpc_service
from akanda.rug.openstack.common import service
cfg.CONF.register_opts([
cfg.IntOpt('periodic_interval',
default=60,
help='seconds between running periodic tasks (ie health check)')
help='seconds between periodic task runs (ie health check)'),
cfg.StrOpt('host',
default=socket.getfqdn(),
help=_("The hostname Quantum is running on")),
])
class PeriodicService(rpc_service.Service):
def start(self):
super(PeriodicService, self).start()
self.tg.add_timer(
cfg.CONF.periodic_interval,
self.manager.run_periodic_tasks,
None,
None
)
def main():
eventlet.monkey_patch()
cfg.CONF(sys.argv[1:])
cfg.CONF(sys.argv[1:], project='akanda')
log.setup('akanda')
mgr = manager.AkandaL3Manager()
svc = service.Service('akanda', mgr, cfg.CONF.periodic_interval, None)
svc.start()
svc.wait()
svc = PeriodicService(host=cfg.CONF.host, topic='akanda', manager=mgr)
service.launch(svc).wait()
if __name__ == '__main__':

View File

@ -1,27 +1,32 @@
[DEFAULT]
debug=True
versbose=True
admin_user=quantum
admin_password=password
admin_tenant_name=service
auth_url=http://192.168.57.100:35357/v2.0/
auth_url=http://192.168.57.200:35357/v2.0/
auth_strategy=keystone
auth_region=RegionOne
management_prefix=fdca:3ba5:a17a:acda::/64
akanda_mgt_service_port=5000
management_network_id=7860030c-fc43-45d1-88d1-5863a04e9ebf
management_subnet_id=25f3586d-fa0a-434a-8001-d4849ab514fd
external_network_id=3a9a71ce-8bea-4b6f-82ca-d74ee672895c
management_network_id=fff4bc78-4a54-49ad-b4e8-5ccc5a61e10d
management_subnet_id=9e08721d-1709-4966-8c14-d6b2bcf6ac80
external_network_id=bc42a9fa-2c54-4940-b521-d48055eaf42f
router_image_uuid=27334edd-49b8-4a2d-8dae-2f37af5126c7
router_image_uuid=f32484e8-6d1f-4ab5-9e3b-95b8d0759e52
router_instance_flavor=1
# to plug in rug interface
root_helper=sudo
interface_driver=quantum.agent.linux.interface.OVSInterfaceDriver
ovs_integration_bridge=br-int
rabbit_password = yetanothersecret
rabbit_host = 192.168.57.100
rabbit_host = 192.168.57.200
provider_rules_path=/opt/stack/akanda-rug/akanda/rug/provider_rules.json
provider_rules_path=/opt/stack/akanda-rug/etc/provider_rules.json
control_exchange = quantum
[AGENT]
root_helper=sudo