From 35eff21016c320a06ceefeb74e7ca647eb35169f Mon Sep 17 00:00:00 2001 From: ashoksingh Date: Wed, 23 Nov 2016 20:05:51 +0530 Subject: [PATCH] Open Agent's REST API port after agent initialization is done In vrouter-port-control add the following checks for DPDK mode --Wait for agent's REST API port to be opened before sending port adds with a timeout of 120 seconds --Wait for DPDK vrouter to open netlink tcp port before sending port adds with a timeout of 120 seconds Also return different error codes for each failure to identify the point of failure in the script Closes-Bug: #1614616 (cherry picked from commit 5bcca7956f374c43096d4d255ef12646968deab6) Change-Id: I647bc42b55b9c7c7c095302447788bc8465bcc49 --- .../agent/contrail/contrail_agent_init.cc | 5 +++ src/vnsw/agent/port_ipc/rest_server.cc | 3 ++ src/vnsw/agent/port_ipc/rest_server.h | 1 + src/vnsw/agent/port_ipc/vrouter-port-control | 43 +++++++++++++++++-- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/vnsw/agent/contrail/contrail_agent_init.cc b/src/vnsw/agent/contrail/contrail_agent_init.cc index 340610870f4..2b29645e777 100644 --- a/src/vnsw/agent/contrail/contrail_agent_init.cc +++ b/src/vnsw/agent/contrail/contrail_agent_init.cc @@ -130,6 +130,11 @@ void ContrailAgentInit::WaitForIdle() { void ContrailAgentInit::InitDone() { ContrailInitCommon::InitDone(); + if (agent()->rest_server()) { + /* Open REST API port for port add/change/deletes */ + agent()->rest_server()->InitDone(); + } + /* Reads and processes port information written by nova-compute */ PortIpcHandler *pih = agent()->port_ipc_handler(); if (pih) { diff --git a/src/vnsw/agent/port_ipc/rest_server.cc b/src/vnsw/agent/port_ipc/rest_server.cc index 36c57252ff0..cde7dd69eb3 100644 --- a/src/vnsw/agent/port_ipc/rest_server.cc +++ b/src/vnsw/agent/port_ipc/rest_server.cc @@ -134,6 +134,9 @@ RESTServer::RESTServer(Agent *agent) : agent_(agent), http_server_(new HttpServer(agent->event_manager())) { http_server_->RegisterHandler(HTTP_WILDCARD_ENTRY, boost::bind(&RESTServer::HandleRequest, this, _1, _2)); +} + +void RESTServer::InitDone() { http_server_->Initialize(ContrailPorts::PortIpcVrouterAgentPort()); } diff --git a/src/vnsw/agent/port_ipc/rest_server.h b/src/vnsw/agent/port_ipc/rest_server.h index e1472f9a642..6fcff62fb7a 100644 --- a/src/vnsw/agent/port_ipc/rest_server.h +++ b/src/vnsw/agent/port_ipc/rest_server.h @@ -17,6 +17,7 @@ class RESTServer { explicit RESTServer(Agent *agent); virtual ~RESTServer(); + void InitDone(); void HandleRequest(HttpSession* session, const HttpRequest* request); void Shutdown(); diff --git a/src/vnsw/agent/port_ipc/vrouter-port-control b/src/vnsw/agent/port_ipc/vrouter-port-control index 6260e6d74b4..75de5c7a5ff 100755 --- a/src/vnsw/agent/port_ipc/vrouter-port-control +++ b/src/vnsw/agent/port_ipc/vrouter-port-control @@ -13,6 +13,7 @@ import errno import datetime import re import time +import socket sys.path.insert(1, sys.path[0]+'/../api-venv/lib/python2.7/site-packages') from vnc_api.vnc_api import * @@ -20,6 +21,8 @@ from requests.exceptions import ConnectionError PORT_PATH="/var/lib/contrail/ports/" PORT_IPC_VROUTER_AGENT_PORT=9091 TIMEOUT_SECS=15 +DPDK_NETLINK_TCP_PORT=20914 +PORT_OPEN_TIMEOUT_SECS=120 class VrouterPortControl(object): def __init__(self, args_str = None): @@ -34,8 +37,13 @@ class VrouterPortControl(object): headers = {'content-type': 'application/json'} base_url = "http://localhost:" + str(PORT_IPC_VROUTER_AGENT_PORT) if self._args.oper == "add": - if self._args.vif_type == "VhostUser" and not self._args.vhostuser_socket: - sys.exit(1) + if self._args.vif_type == "VhostUser": + if not self._args.vhostuser_socket: + sys.exit(1) + if not self.WaitForPortOpen(PORT_IPC_VROUTER_AGENT_PORT): + sys.exit(2) + if not self.WaitForPortOpen(DPDK_NETLINK_TCP_PORT): + sys.exit(3) if self._args.port_type == "NovaVMPort": port_type_value = 0 @@ -62,7 +70,7 @@ class VrouterPortControl(object): r = requests.post(url, data=json_dump, headers=headers) '''Overwrite the ret_code based on agent response ''' if r.status_code != 200: - ret_code = 1 + ret_code = 4 else: ret_code = 0 if ret_code == 0 and self._args.vif_type == "VhostUser": @@ -71,6 +79,11 @@ class VrouterPortControl(object): ret_code = self.WaitForSocketFile() except ConnectionError: + '''In DPDK mode return failure when we are not able to connect + to agent + ''' + if self._args.vif_type == "VhostUser": + ret_code = 5 pass elif self._args.oper == "delete": if not self._args.no_persist: @@ -247,9 +260,31 @@ class VrouterPortControl(object): return 0 #sleep takes time in seconds. Convert usecs to secs. time.sleep(sleep_usecs/1000000.0) - return 1 + return 6 #end WaitForSocketFile + def IsPortOpen(self, port_num): + s = socket.socket() + try: + s.connect(('127.0.0.1', port_num)) + s.shutdown(socket.SHUT_RDWR) + s.close() + return True + except socket.error, e: + return False + #end IsPortOpen + + def WaitForPortOpen(self, port_num): + timeout_usecs = PORT_OPEN_TIMEOUT_SECS * 1000000 + sleep_usecs = 1000000 + for i in range(1,(timeout_usecs/sleep_usecs)): + if self.IsPortOpen(port_num): + return True + #sleep takes time in seconds. Convert usecs to secs. + time.sleep(sleep_usecs/1000000.0) + return False + #end WaitForPortOpen + # end class VrouterPortControl def main(args_str = None):