vmware-nsx/neutron/plugins/nuage/syncmanager.py

423 lines
17 KiB
Python

# Copyright 2014 Alcatel-Lucent USA Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from oslo.config import cfg
from oslo.utils import importutils
import sqlalchemy.orm.exc as db_exc
from neutron import context as ncontext
from neutron.db import db_base_plugin_v2
from neutron.db import extraroute_db
from neutron.db import securitygroups_db
from neutron.openstack.common import log
from neutron.openstack.common.gettextutils import _LE, _LI, _LW
from neutron.plugins.nuage.common import config
from neutron.plugins.nuage import nuagedb
LOG = log.getLogger(__name__)
NUAGE_CONFIG_FILE = '/etc/neutron/plugins/nuage/nuage_plugin.ini'
class SyncManager(db_base_plugin_v2.NeutronDbPluginV2,
extraroute_db.ExtraRoute_db_mixin,
securitygroups_db.SecurityGroupDbMixin):
"""
This class provides functionality to sync data between OpenStack and VSD.
"""
def __init__(self, nuageclient):
self.context = ncontext.get_admin_context()
self.nuageclient = nuageclient
def synchronize(self, fipquota):
LOG.info(_LI("Starting the sync between Neutron and VSD"))
try:
# Get all data to determine the resources to sync
data = self._get_all_data()
resources = self.nuageclient.get_resources_to_sync(data)
# Sync all resources
self._sync(resources, fipquota)
except Exception as e:
LOG.error(_LE("Cannot complete the sync between Neutron and VSD "
"because of error:%s"), str(e))
return
LOG.info(_LI("Sync between Neutron and VSD completed successfully"))
def _get_all_data(self):
# Get all net-partitions
net_partition_list = nuagedb.get_all_net_partitions(
self.context.session)
# Get all subnet ids
subnet_id_list = nuagedb.get_subnet_ids(self.context.session)
# Get all router ids
router_id_list = nuagedb.get_router_ids(self.context.session)
# Get all ports
port_list = self.get_ports(self.context)
# Get all routes
route_list = nuagedb.get_all_routes(self.context.session)
# Get all floatingips
fip_list = self.get_floatingips(self.context)
# Get all securitygrp ids
secgrp_id_list = nuagedb.get_secgrp_ids(self.context.session)
# Get all securitygrprules
secgrprule_id_list = self.get_security_group_rules(self.context)
# Get all portbindings
portbinding_list = self._get_port_security_group_bindings(self.context)
data = {
'netpartition': net_partition_list,
'subnet': subnet_id_list,
'router': router_id_list,
'port': port_list,
'route': route_list,
'fip': fip_list,
'secgroup': secgrp_id_list,
'secgrouprule': secgrprule_id_list,
'portbinding': portbinding_list,
}
return data
def _sync(self, resources, fip_quota):
# Sync net-partitions
net_partition_id_dict = self.sync_net_partitions(fip_quota, resources)
# Sync sharednetworks
self.sync_sharednetworks(resources)
# Sync l2domains
self.sync_l2domains(net_partition_id_dict, resources)
# Sync domains
self.sync_domains(net_partition_id_dict, resources)
# Sync domainsubnets
self.sync_domainsubnets(resources)
# Sync routes
self.sync_routes(resources)
# Sync vms
self.sync_vms(resources)
# Sync secgrps
self.sync_secgrps(resources)
# Sync secgrprules
self.sync_secgrp_rules(resources)
# Sync fips
self._sync_fips(resources)
# Delete the old net-partitions
for net_id in net_partition_id_dict:
nuagedb.delete_net_partition_by_id(self.context.session,
net_id)
def sync_net_partitions(self, fip_quota, resources):
net_partition_id_dict = {}
for netpart_id in resources['netpartition']['add']:
with self.context.session.begin(subtransactions=True):
netpart = self._get_netpart_data(netpart_id)
if netpart:
result = self.nuageclient.create_netpart(netpart,
fip_quota)
netpart = result.get(netpart_id)
if netpart:
net_partition_id_dict[netpart_id] = netpart['id']
nuagedb.add_net_partition(
self.context.session,
netpart['id'],
netpart['l3dom_tmplt_id'],
netpart['l2dom_tmplt_id'],
netpart['name'])
return net_partition_id_dict
def sync_sharednetworks(self, resources):
for sharednet_id in resources['sharednetwork']['add']:
with self.context.session.begin(subtransactions=True):
subnet, subl2dom = self._get_subnet_data(
sharednet_id,
get_mapping=False)
if subnet:
self.nuageclient.create_sharednetwork(subnet)
def sync_l2domains(self, net_partition_id_dict, resources):
for l2dom_id in resources['l2domain']['add']:
with self.context.session.begin(subtransactions=True):
subnet, subl2dom = self._get_subnet_data(l2dom_id)
if subnet:
# if subnet exists, subl2dom will exist
netpart_id = subl2dom['net_partition_id']
if netpart_id in net_partition_id_dict.keys():
# Use the id of the newly created net_partition
netpart_id = net_partition_id_dict[netpart_id]
result = self.nuageclient.create_l2domain(netpart_id,
subnet)
if result:
nuagedb.get_update_subnetl2dom_mapping(
self.context.session,
result)
def sync_domains(self, net_partition_id_dict, resources):
for domain_id in resources['domain']['add']:
with self.context.session.begin(subtransactions=True):
router, entrtr = self._get_router_data(domain_id)
if router:
# if router exists, entrtr will exist
netpart_id = entrtr['net_partition_id']
if netpart_id in net_partition_id_dict.keys():
# Use the id of the newly created net_partition
netpart_id = net_partition_id_dict[netpart_id]
netpart = nuagedb.get_net_partition_by_id(
self.context.session,
netpart_id)
result = self.nuageclient.create_domain(netpart, router)
if result:
nuagedb.get_update_entrtr_mapping(self.context.session,
result)
def sync_domainsubnets(self, resources):
for domsubn_id in resources['domainsubnet']['add']:
# This is a dict of subn_id and the router interface port
subn_rtr_intf_port_dict = (
resources['port']['sub_rtr_intf_port_dict'])
port_id = subn_rtr_intf_port_dict[domsubn_id]
port = self._get_port_data(port_id)
if port:
with self.context.session.begin(subtransactions=True):
subnet, subl2dom = self._get_subnet_data(domsubn_id)
if subnet:
result = self.nuageclient.create_domainsubnet(subnet,
port)
if result:
nuagedb.get_update_subnetl2dom_mapping(
self.context.session,
result)
def sync_routes(self, resources):
for rt in resources['route']['add']:
with self.context.session.begin(subtransactions=True):
route = self._get_route_data(rt)
if route:
self.nuageclient.create_route(route)
def sync_vms(self, resources):
for port_id in resources['port']['vm']:
port = self._get_port_data(port_id)
if port:
self.nuageclient.create_vm(port)
def sync_secgrps(self, resources):
secgrp_dict = resources['security']['secgroup']
for secgrp_id, ports in secgrp_dict['l2domain']['add'].iteritems():
with self.context.session.begin(subtransactions=True):
secgrp = self._get_sec_grp_data(secgrp_id)
if secgrp:
self.nuageclient.create_security_group(secgrp, ports)
for secgrp_id, ports in secgrp_dict['domain']['add'].iteritems():
with self.context.session.begin(subtransactions=True):
secgrp = self._get_sec_grp_data(secgrp_id)
if secgrp:
self.nuageclient.create_security_group(secgrp, ports)
def sync_secgrp_rules(self, resources):
secrule_list = resources['security']['secgrouprule']
for secrule_id in secrule_list['l2domain']['add']:
with self.context.session.begin(subtransactions=True):
secgrprule = self._get_sec_grp_rule_data(secrule_id)
if secgrprule:
self.nuageclient.create_security_group_rule(secgrprule)
for secrule_id in secrule_list['domain']['add']:
with self.context.session.begin(subtransactions=True):
secgrprule = self._get_sec_grp_rule_data(secrule_id)
if secgrprule:
self.nuageclient.create_security_group_rule(secgrprule)
def _sync_fips(self, resources):
for fip_id in resources['fip']['add']:
with self.context.session.begin(subtransactions=True):
fip = self._get_fip_data(fip_id)
if fip:
ipalloc = self._get_ipalloc_for_fip(fip)
self.nuageclient.create_fip(fip, ipalloc)
for fip_id in resources['fip']['disassociate']:
with self.context.session.begin(subtransactions=True):
fip = self._get_fip_data(fip_id)
if fip:
self.nuageclient.disassociate_fip(fip)
for fip_id in resources['fip']['associate']:
with self.context.session.begin(subtransactions=True):
fip = self._get_fip_data(fip_id)
if fip:
self.nuageclient.associate_fip(fip)
def _get_subnet_data(self, subnet_id, get_mapping=True):
subnet = None
subl2dom = None
try:
if get_mapping:
subl2dom_db = nuagedb.get_subnet_l2dom_with_lock(
self.context.session,
subnet_id)
subl2dom = nuagedb.make_subnl2dom_dict(subl2dom_db)
subnet_db = nuagedb.get_subnet_with_lock(self.context.session,
subnet_id)
subnet = self._make_subnet_dict(subnet_db)
except db_exc.NoResultFound:
LOG.warning(_LW("Subnet %s not found in neutron for sync"),
subnet_id)
return subnet, subl2dom
def _get_router_data(self, router_id):
router = None
entrtr = None
try:
entrtr_db = nuagedb.get_ent_rtr_mapping_with_lock(
self.context.session,
router_id)
entrtr = nuagedb.make_entrtr_dict(entrtr_db)
router_db = nuagedb.get_router_with_lock(self.context.session,
router_id)
router = self._make_router_dict(router_db)
except db_exc.NoResultFound:
LOG.warning(_LW("Router %s not found in neutron for sync"),
router_id)
return router, entrtr
def _get_route_data(self, rt):
route = None
try:
route = nuagedb.get_route_with_lock(self.context.session,
rt['destination'],
rt['nexthop'])
except db_exc.NoResultFound:
LOG.warning(_LW("Route with destination %(dest)s and nexthop "
"%(hop)s not found in neutron for sync"),
{'dest': rt['destination'],
'hop': rt['nexthop']})
return route
def _get_sec_grp_data(self, secgrp_id):
secgrp = None
try:
secgrp_db = nuagedb.get_secgrp_with_lock(self.context.session,
secgrp_id)
secgrp = self._make_security_group_dict(secgrp_db)
except db_exc.NoResultFound:
LOG.warning(_LW("Security group %s not found in neutron for sync"),
secgrp_id)
return secgrp
def _get_sec_grp_rule_data(self, secgrprule_id):
secgrprule = None
try:
secrule_db = nuagedb.get_secgrprule_with_lock(self.context.session,
secgrprule_id)
secgrprule = self._make_security_group_rule_dict(secrule_db)
except db_exc.NoResultFound:
LOG.warning(_LW("Security group rule %s not found in neutron for "
"sync"), secgrprule_id)
return secgrprule
def _get_fip_data(self, fip_id):
fip = None
try:
fip_db = nuagedb.get_fip_with_lock(self.context.session, fip_id)
fip = self._make_floatingip_dict(fip_db)
except db_exc.NoResultFound:
LOG.warning(_LW("Floating ip %s not found in neutron for sync"),
fip_id)
return fip
def _get_ipalloc_for_fip(self, fip):
ipalloc = None
try:
ipalloc = nuagedb.get_ipalloc_for_fip(self.context.session,
fip['floating_network_id'],
fip['floating_ip_address'],
lock=True)
except db_exc.NoResultFound:
LOG.warning(_LW("IP allocation for floating ip %s not found in "
"neutron for sync"), fip['id'])
return ipalloc
def _get_netpart_data(self, netpart_id):
netpart = None
try:
netpart = nuagedb.get_net_partition_with_lock(
self.context.session,
netpart_id)
except db_exc.NoResultFound:
LOG.warning(_LW("Net-partition %s not found in neutron for sync"),
netpart_id)
return netpart
def _get_port_data(self, port_id):
port = None
try:
port_db = nuagedb.get_port_with_lock(self.context.session, port_id)
port = self._make_port_dict(port_db)
except db_exc.NoResultFound:
LOG.warning(_LW("VM port %s not found in neutron for sync"),
port_id)
return port
def main():
cfg.CONF(default_config_files=(
[NUAGE_CONFIG_FILE]))
config.nuage_register_cfg_opts()
server = cfg.CONF.RESTPROXY.server
serverauth = cfg.CONF.RESTPROXY.serverauth
serverssl = cfg.CONF.RESTPROXY.serverssl
base_uri = cfg.CONF.RESTPROXY.base_uri
auth_resource = cfg.CONF.RESTPROXY.auth_resource
organization = cfg.CONF.RESTPROXY.organization
fipquota = str(cfg.CONF.RESTPROXY.default_floatingip_quota)
logging = importutils.import_module('logging')
nuageclientinst = importutils.import_module('nuagenetlib.nuageclient')
nuageclient = nuageclientinst.NuageClient(server, base_uri,
serverssl, serverauth,
auth_resource,
organization)
logging.basicConfig(level=logging.DEBUG)
SyncManager(nuageclient).synchronize(fipquota)
if __name__ == '__main__':
main()