Skip to content

Commit

Permalink
[VNC API Server] Remove irond dependency
Browse files Browse the repository at this point in the history
That patch remove dependency to the irond IF-MAP server. It implements a
minimalist IF-MAP v2 server run as a part of the contrail API server.
That server is directly populated by the VNC API server (directly access
the python dict that represents the ifmap graph, no HTML serialization).
It keeps a HTML interface for control nodes to poll the graph.

Only request 'newSession', 'subscribe' (root graph only) and
'poll' methods are implemented.

For the moment, the old ifmap client which sets and maintains the ifmap
sessions with irond server is use if no IP and TCP port are set to bind
the self managed ifmap server ('ifmap_listen_ip' and 'ifmap_listen_port').
Anyway, config unit tests were migrated to use that new self managed
ifmap server (some schema-transformer unit tests were skiped due to new
issue appeared. That needs to be investigated and fixed).

=== Results with a db populated with 79440 resources ===
Time elapsed for the vnc api server to sync ifmap db from:
- without patch
    #1: 0:04:00.0272121
    #2: 0:03:51.0994972
    #3: 0:03:49.4030671
- with patch:
    #1: 0:00:39.394018
    #2: 0:00:38.890950
    #3: 0:00:39.109681

Time elapsed for a python script to create a new ifmap session,
subscribe to the root graph and poll it (searchResult):
- without patch
    #1: 0:00:14.655667
    #2: 0:00:13.452200
    #3: 0:00:13.905878
- with patch:
    #1: 0:00:04.591735
    #2: 0:00:04.592040
    #3: 0:00:04.192904

Closes-Bug: #1629268
Change-Id: Ib35b48b20c8d46005bf18e8f9b81064985099ff7
(cherry picked from commit a112b1b)
  • Loading branch information
Édouard Thuleau committed Feb 14, 2017
1 parent 5e6c3f7 commit 584680b
Show file tree
Hide file tree
Showing 28 changed files with 1,929 additions and 1,914 deletions.
4 changes: 3 additions & 1 deletion src/config/api-server/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ for file in setup_sources:
local_sources = [
'__init__.py',
'vnc_cfg_api_server.py',
'vnc_cfg_ifmap.py',
'vnc_ifmap.py',
'vnc_ifmap_client.py',
'vnc_db.py',
'vnc_cfg_types.py',
'vnc_auth.py',
'vnc_auth_keystone.py',
Expand Down
2 changes: 1 addition & 1 deletion src/config/api-server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* vnc_cfg_api_server
* gen.resource_common
* gen.resource_xsd
* vnc_cfg_ifmap
* vnc_db
* vnc_addr_mgmt
* vnc_cfg_types
"""
15 changes: 13 additions & 2 deletions src/config/api-server/contrail-api.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
log_file = /var/log/contrail/contrail-api.log
log_level = SYS_NOTICE
log_local = 1
ifmap_username = api-server
ifmap_password = api-server
# ifmap_username = api-server
# ifmap_password = api-server
cassandra_server_list = 127.0.0.1:9160
disc_server_ip = 127.0.0.1
disc_server_port = 5998
Expand All @@ -21,3 +21,14 @@ disc_server_port = 5998
# Enable optimizations to list resources. Be careful, resources created on
# release under R1.05 does not support that optimization (especially for port)
# list_optimization_enabled = False

[IFMAP_SERVER]
# # IF-MAP server configuration
# # Listen IP and port
# ifmap_listen_ip = 0.0.0.0
# ifmap_listen_port = 8443
# # Key ans certificate files path. If not set automatically create
# ifmap_key_path = /var/lib/contrail/api-server/ifmap-cert/key
# ifmap_cert_path = /var/lib/contrail/api-server/ifmap-cert/cert
# # Credentials: user:passwd[,user:passwd]
# ifmap_credentials = control:secret
98 changes: 38 additions & 60 deletions src/config/api-server/db_manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
from cfgm_common.ifmap.request import NewSessionRequest
from cfgm_common.ifmap.response import newSessionResult
from cfgm_common.imid import ifmap_read, parse_search_result
from cfgm_common.vnc_cassandra import VncCassandraClient
import pycassa
import utils

import vnc_cfg_ifmap
from vnc_db import VncServerCassandraClient
import schema_transformer.db
import discovery.disc_cassdb

Expand Down Expand Up @@ -78,7 +79,7 @@ class DatabaseManager(object):
BASE_SG_ID_ZK_PATH = '/id/security-groups/id'
BASE_SUBNET_ZK_PATH = '/api-server/subnets'
AUTO_RTGT_START = 8000000
def __init__(self, args_str):
def __init__(self, args_str=''):
self._parse_args(args_str)

self._logger = utils.ColorLog(logging.getLogger(__name__))
Expand All @@ -96,7 +97,7 @@ def __init__(self, args_str):

# cassandra connection
self._cassandra_servers = self._api_args.cassandra_server_list
db_info = vnc_cfg_ifmap.VncServerCassandraClient.get_db_info()
db_info = VncServerCassandraClient.get_db_info()
rd_consistency = pycassa.cassandra.ttypes.ConsistencyLevel.QUORUM
self._cf_dict = {}
cred = None
Expand Down Expand Up @@ -134,12 +135,11 @@ def _parse_args(self, args_str):
"--debug", help="Run in debug mode, default False",
action='store_true', default=False)
parser.add_argument(
"--ifmap-servers",
"--ifmap-servers", nargs='*',
help="List of ifmap-ip:ifmap-port, default from api-conf")
parser.add_argument(
"--ifmap-credentials",
help="<username>:<password> for read-only user",
required=True)
help="<username>:<password> for read-only user")
parser.add_argument("--cassandra-user")
parser.add_argument("--cassandra-password")

Expand Down Expand Up @@ -218,7 +218,7 @@ def audit_route_targets_id(self):
base_path = self.BASE_RTGT_ID_ZK_PATH
logger.debug("Doing recursive zookeeper read from %s", base_path)
zk_all_rtgts = {}
num_bad_rtgts = 0
num_bad_rtgts = 0
for rtgt_id in self._zk_client.get_children(base_path) or []:
rtgt_fq_name_str = self._zk_client.get(base_path+'/'+rtgt_id)[0]
zk_all_rtgts[int(rtgt_id)] = rtgt_fq_name_str
Expand All @@ -242,7 +242,7 @@ def audit_route_targets_id(self):
rtgt_row = []
rtgt_uuids = [x.split(':')[-1] for x in rtgt_row]
cassandra_all_rtgts = {}
num_bad_rtgts = 0
num_bad_rtgts = 0
for rtgt_uuid in rtgt_uuids:
rtgt_cols = obj_uuid_table.get(rtgt_uuid,
columns=['fq_name'],
Expand All @@ -258,7 +258,7 @@ def audit_route_targets_id(self):
logger.debug("Got %d route-targets with id in cassandra %d from wrong range",
len(cassandra_all_rtgts), num_bad_rtgts)
zk_set = set([(id, fqns) for id, fqns in zk_all_rtgts.items()])
cassandra_set = set([(id-self.AUTO_RTGT_START, fqns)
cassandra_set = set([(id-self.AUTO_RTGT_START, fqns)
for id, fqns in cassandra_all_rtgts.items()
if id >= self.AUTO_RTGT_START])

Expand All @@ -280,7 +280,7 @@ def audit_security_groups_id(self):
if sg_val != '__reserved__':
ret_errors.append(SG0UnreservedError(''))
continue

sg_fq_name_str = self._zk_client.get(base_path+'/'+sg_id)[0]
zk_all_sgs[int(sg_id)] = sg_fq_name_str

Expand Down Expand Up @@ -453,7 +453,7 @@ def check_cassandra_keyspace_replication(self):
'password':self._args.cassandra_password}
for server in self._cassandra_servers:
sys_mgr = pycassa.SystemManager(server, credentials=cred)
db_info = vnc_cfg_ifmap.VncCassandraClient.get_db_info() + \
db_info = VncCassandraClient.get_db_info() + \
schema_transformer.db.SchemaTransformerDB.get_db_info() + \
discovery.disc_cassdb.DiscoveryCassandraClient.get_db_info()
for ks_name, _ in db_info:
Expand Down Expand Up @@ -485,6 +485,8 @@ def check_fq_name_uuid_ifmap_match(self):
ret_errors = []
logger = self._logger

self._connect_to_ifmap_servers()

obj_fq_name_table = self._cf_dict['obj_fq_name_table']
obj_uuid_table = self._cf_dict['obj_uuid_table']
fq_name_table_all = []
Expand Down Expand Up @@ -535,19 +537,16 @@ def check_fq_name_uuid_ifmap_match(self):
'Extra object %s %s %s in obj_uuid_table'
%(obj_type, fq_name_str, obj_uuid)))

if self._args.ifmap_servers:
ifmap_ips_ports = [(ip_port.split(':'))
for ip_port in self._args.ifmap_servers]
else:
ifmap_ips_ports = [(self._api_args.ifmap_server_ip,
self._api_args.ifmap_server_port)]
ifmap_user, ifmap_passwd = self._args.ifmap_credentials.split(':')
for ifmap_ip, ifmap_port in ifmap_ips_ports:
for mapclient in self._mapclients:
all_ifmap_idents = []
search_results = parse_search_result(
ifmap_read(self._get_mapclient(ifmap_ip, ifmap_port,
ifmap_user, ifmap_passwd), 'contrail:config-root:root',
srch_meta=None, result_meta='contrail:id-perms'))
ifmap_read(
mapclient,
'contrail:config-root:root',
srch_meta=None,
result_meta='contrail:id-perms'
)
)
# search_results is in form of
# [ ({'config-root': 'root'}, <Element metadata at 0x1e19b48>)
# ({'config-root': 'root',
Expand All @@ -565,21 +564,21 @@ def check_fq_name_uuid_ifmap_match(self):
all_ifmap_idents = set(all_ifmap_idents)
all_cassandra_idents = set([item[1] for item in uuid_table_all])
logger.debug("Got %d idents from %s server",
len(all_ifmap_idents), ifmap_ip)
len(all_ifmap_idents), mapclient._client__url[0])

extra = all_ifmap_idents - all_cassandra_idents
if (len(extra) == 1) and (extra == set(['root'])):
pass # good
else:
ret_errors.append(IfmapExtraIdentifiersError(
'Extra identifiers %s in ifmap %s vs obj_uuid_table'
%(extra, ifmap_ip)))
%(extra, mapclient._client__url[0])))

extra = all_cassandra_idents - all_ifmap_idents
if extra:
ret_errors.append(IfmapMissingIdentifiersError(
'Missing identifiers %s in ifmap %s vs obj_uuid_table.\n' \
%(extra, ifmap_ip)))
%(extra, mapclient._client__url[0])))


return ret_errors
Expand Down Expand Up @@ -698,7 +697,7 @@ def check_subnet_addr_alloc(self):

num_addrs += len(fip_uuids)

logger.debug("Got %d networks %d addresses",
logger.debug("Got %d networks %d addresses",
len(cassandra_all_vns), num_addrs)

# check for differences in networks
Expand Down Expand Up @@ -925,7 +924,7 @@ def set_reserved_addrs_in_cassandra(vn_id, fq_name_str):
except pycassa.NotFoundException:
logger.debug('VN %s (%s) has no ipam refs',
vn_id, fq_name_str)
return
return

cassandra_all_vns[fq_name_str] = {}
for ipam in ipam_refs:
Expand Down Expand Up @@ -1021,28 +1020,30 @@ def set_reserved_addrs_in_cassandra(vn_id, fq_name_str):

def _connect_to_ifmap_servers(self):
self._mapclients = []
mapclients = []
NAMESPACES = {
'env': "http://www.w3.org/2003/05/soap-envelope",
'ifmap': "http://www.trustedcomputinggroup.org/2010/IFMAP/2",
'meta':
"http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2",
'contrail': "http://www.contrailsystems.com/vnc_cfg.xsd"
}
ifmap_user, ifmap_passwd = self._args.ifmap_credentials.split(':')
# pick ifmap servers from args to this utility and if absent
# pick it from contrail-api conf file
if self._args.ifmap_servers:
ifmap_ips_ports = [(ip_port.split(':'))
for ip_port in self._args.ifmap_servers]
else:
ifmap_ips_ports = [(self._api_args.ifmap_server_ip,
self._api_args.ifmap_server_port)]
ifmap_ips_ports = [(self._api_args.ifmap_listen_ip,
str(self._api_args.ifmap_listen_port))]
if self._args.ifmap_credentials:
ifmap_user, ifmap_passwd = self._args.ifmap_credentials.split(':')
else:
ifmap_user, ifmap_passwd = self._api_args.ifmap_credentials[0]

for ifmap_ip, ifmap_port in ifmap_ips_ports:
mapclient = client((ifmap_ip, ifmap_port),
ifmap_user, ifmap_passwd,
NAMESPACES)
self._mapclients.append(mapclient)
connected = False
while not connected:
try:
Expand All @@ -1053,31 +1054,8 @@ def _connect_to_ifmap_servers(self):

mapclient.set_session_id(newSessionResult(result).get_session_id())
mapclient.set_publisher_id(newSessionResult(result).get_publisher_id())

self._mapclients.append(mapclient)
# end _connect_to_ifmap_servers

def _get_mapclient(self, ifmap_ip, ifmap_port, ifmap_user, ifmap_password):
NAMESPACES = {
'env': "http://www.w3.org/2003/05/soap-envelope",
'ifmap': "http://www.trustedcomputinggroup.org/2010/IFMAP/2",
'meta':
"http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2",
'contrail': "http://www.contrailsystems.com/vnc_cfg.xsd"
}
mapclient = client((ifmap_ip, ifmap_port), ifmap_user, ifmap_password,
NAMESPACES)
connected = False
while not connected:
try:
result = mapclient.call('newSession', NewSessionRequest())
connected = True
except socket.error as e:
time.sleep(3)

mapclient.set_session_id(newSessionResult(result).get_session_id())
mapclient.set_publisher_id(newSessionResult(result).get_publisher_id())
return mapclient
# end _get_mapclient
# end class DatabaseChecker


Expand Down Expand Up @@ -1451,7 +1429,7 @@ def heal_security_groups_id(self):
# end heal_security_groups_id
# end class DatabaseCleaner

def db_check(args_str):
def db_check(args_str=''):
vnc_cgitb.enable(format='text')

db_checker = DatabaseChecker(args_str)
Expand All @@ -1468,7 +1446,7 @@ def db_check(args_str):
db_checker.check_schema_db_mismatch()
# end db_check

def db_clean(args_str):
def db_clean(args_str=''):
vnc_cgitb.enable(format='text')

db_cleaner = DatabaseCleaner(args_str)
Expand All @@ -1483,7 +1461,7 @@ def db_clean(args_str):
db_cleaner.clean_stale_security_groups_id()
# end db_clean

def db_heal(args_str):
def db_heal(args_str=''):
vnc_cgitb.enable(format='text')

db_healer = DatabaseHealer(args_str)
Expand All @@ -1496,7 +1474,7 @@ def db_heal(args_str):
db_healer.heal_security_groups_id()
# end db_heal

def db_touch_latest(args_str):
def db_touch_latest(args_str=''):
vnc_cgitb.enable(format='text')

db_mgr = DatabaseManager(args_str)
Expand Down
1 change: 1 addition & 0 deletions src/config/api-server/test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ webtest
pyaml
keystonemiddleware
junitxml
pyOpenSSL

0 comments on commit 584680b

Please sign in to comment.