Skip to content

Commit

Permalink
Taking the haproxy process id from config.pid file
Browse files Browse the repository at this point in the history
The haproxy config is updated by providing the new configuration file
and old haproxy process id. This starts a new haproxy process letting
the old haproxy process to handle the old sessions. New haproxy handles
the new sessions. If a new configuration update comes while both old and
new haproxy processes are runnning, another haproxy process needs to be started
by providing the latest running haproxy process id.

In the existing update code, the haproxy process id is found by "ps"
output. This is resulating in not getting the latest haproxy process id,
but an older process id. This is leading to second haproxy process never
getting killed leaving two haproxies running for ever.

The latest haproxy process that is handling the new session is always
updated in a file by haproxy itself. As a fix, this process id used to
start a new haproxy rather taking the pid from "ps". When the
loadbalancer VIP is deleted, Agent deletes the directory where haproxy
config file, stats file and pid file are stored. This can result in
vrouter_netns.py script failing as pid is not found to stop the haproxy.
To overcome this, the config file, pid file and sock file are stored not
in an explicit directory corresponding to the pool. Only config fike and
sock file are deleted by Agent and pid file is deleted by vrouter_netns
script.

Change-Id: Iebc6230e0eef73c4e18b18e4fc0ca65b8af6b4e4
closes-bug: #1495702
  • Loading branch information
divakardhar committed Feb 29, 2016
1 parent f14892a commit 04f36c5
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 27 deletions.
12 changes: 6 additions & 6 deletions src/vnsw/agent/oper/instance_manager.cc
Expand Up @@ -100,16 +100,16 @@ class InstanceManager::NamespaceStaleCleaner {
//If Loadbalncer, delete the config files as well
if (prop.service_type == ServiceInstance::LoadBalancer) {

std::stringstream cfg_dir_path;
cfg_dir_path <<
//Delete the complete directory
std::stringstream cfg_path;
cfg_path <<
manager_->loadbalancer_config_path_ << prop.pool_id;

boost::system::error_code error;
if (fs::exists(cfg_dir_path.str())) {
fs::remove_all(cfg_dir_path.str(), error);
if (fs::exists(cfg_path.str())) {
fs::remove_all(cfg_path.str(), error);
if (error) {
LOG(ERROR, "Stale loadbalancer cfg fle delete error"
<< error.message());
LOG(ERROR, "Stale loadbalancer cfg directory delete error ");
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/vnsw/agent/oper/test/instance_manager_test.cc
Expand Up @@ -575,7 +575,6 @@ TEST_F(InstanceManagerTest, LoadbalancerConfig) {

stringstream pathgen;
pathgen << loadbalancer_config_path() << lbid << "/conf.json";

boost::filesystem::path config(pathgen.str());
std::time_t old_time =
boost::filesystem::last_write_time(pathgen.str());
Expand Down
Expand Up @@ -6,16 +6,32 @@

SUPERVISOR_BASE_DIR = '/etc/contrail/supervisord_vrouter_files/lbaas-haproxy-'

def get_pid_file_from_conf_file(conf_file):
dir_name = os.path.dirname(conf_file)
sout = os.path.split(dir_name)
pid_file = sout[0] + "/" + sout[1] + ".haproxy.pid"
return pid_file

def delete_haproxy_pid_file(conf_file):
pid_file = get_pid_file_from_conf_file(conf_file)
if os.path.isfile(pid_file):
cmd = "rm " + pid_file
cmd_list = shlex.split(cmd)
subprocess.Popen(cmd_list)

def stop_haproxy(conf_file, daemon_mode=False):
pool_id = os.path.split(os.path.dirname(conf_file))[1]
try:
if daemon_mode:
_stop_haproxy_daemon(pool_id)
_stop_haproxy_daemon(conf_file)
else:
pool_id = os.path.split(os.path.dirname(conf_file))[1]
_stop_supervisor_haproxy(pool_id)
except Exception as e:
pass

delete_haproxy_pid_file(conf_file)


def start_update_haproxy(conf_file, netns, daemon_mode=False,
keystone_auth_conf_file=None):
pool_id = os.path.split(os.path.dirname(conf_file))[1]
Expand All @@ -29,34 +45,32 @@ def start_update_haproxy(conf_file, netns, daemon_mode=False,
except Exception as e:
pass

def _get_lbaas_pid(pool_id):
cmd_list = shlex.split('ps aux')
p1 = subprocess.Popen(cmd_list, stdout=subprocess.PIPE)
cmd_list = shlex.split('grep haproxy')
p2 = subprocess.Popen(cmd_list, stdin=p1.stdout, stdout=subprocess.PIPE)
cmd_list = shlex.split('grep ' + pool_id)
p = subprocess.Popen(cmd_list, stdin=p2.stdout, stdout=subprocess.PIPE)
out, err = p.communicate()
try:
pid = out.split()[1]
except Exception:
pid = None
def _get_lbaas_pid(conf_file):
pid_file = get_pid_file_from_conf_file(conf_file)
if not os.path.isfile(pid_file):
return None
cmd = 'cat %s' % pid_file
cmd_list = shlex.split(cmd)
p = subprocess.Popen(cmd_list, stdout=subprocess.PIPE)
pid, err = p.communicate()
if err:
return None
return pid

def _stop_haproxy_daemon(pool_id):
last_pid = _get_lbaas_pid(pool_id)
def _stop_haproxy_daemon(conf_file):
last_pid = _get_lbaas_pid(conf_file)
if last_pid:
cmd_list = shlex.split('kill -9 ' + last_pid)
subprocess.Popen(cmd_list)

def _start_haproxy_daemon(pool_id, netns, conf_file):
last_pid = _get_lbaas_pid(pool_id)
last_pid = _get_lbaas_pid(conf_file)
if last_pid:
sf_opt = '-sf ' + last_pid
else:
sf_opt = ''
conf_dir = os.path.dirname(conf_file)
pid_file = conf_dir + '/haproxy.pid'

pid_file = get_pid_file_from_conf_file(conf_file)

cmd = 'ip netns exec %s haproxy -f %s -p %s %s' % \
(netns, conf_file, pid_file, sf_opt)
Expand Down
Expand Up @@ -32,6 +32,7 @@
import subprocess
import requests
import json
import os

from linux import ip_lib
import haproxy_process
Expand Down Expand Up @@ -150,7 +151,6 @@ def release_lbaas(self):
'relasing lbaas')

haproxy_process.stop_haproxy(self.cfg_file, True)

try:
self.ip_ns.netns.execute(['route', 'del', 'default'])
except RuntimeError:
Expand Down

0 comments on commit 04f36c5

Please sign in to comment.