Add shutdown option for zuul_console
This should look for the process holding open the port, and then delete
all of the remaining files.
Co-Authored-By: Clark Boylan <clark.boylan@gmail.com>
Change-Id: Iba3eda63e84c4357a121a1782b97a12232e1b8ce
diff --git a/zuul/ansible/library/zuul_console.py b/zuul/ansible/library/zuul_console.py
index 7f8a1b6..42f41f0 100644
--- a/zuul/ansible/library/zuul_console.py
+++ b/zuul/ansible/library/zuul_console.py
@@ -15,10 +15,12 @@
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
+import glob
import os
import sys
import select
import socket
+import subprocess
import threading
import time
@@ -196,6 +198,53 @@
pass
+def get_inode(port_number=19885):
+ for netfile in ('/proc/net/tcp6', '/proc/net/tcp'):
+ if not os.path.exists(netfile):
+ continue
+ with open(netfile) as f:
+ # discard header line
+ f.readline()
+ for line in f:
+ # sl local_address rem_address st tx_queue:rx_queue tr:tm->when
+ # retrnsmt uid timeout inode
+ fields = line.split()
+ # Format is localaddr:localport in hex
+ port = int(fields[1].split(':')[1], base=16)
+ if port == port_number:
+ return fields[9]
+
+
+def get_pid_from_inode(inode):
+ my_euid = os.geteuid()
+ exceptions = []
+ for d in os.listdir('/proc'):
+ try:
+ try:
+ int(d)
+ except Exception as e:
+ continue
+ d_abs_path = os.path.join('/proc', d)
+ if os.stat(d_abs_path).st_uid != my_euid:
+ continue
+ fd_dir = os.path.join(d_abs_path, 'fd')
+ if os.path.exists(fd_dir):
+ if os.stat(fd_dir).st_uid != my_euid:
+ continue
+ for fd in os.listdir(fd_dir):
+ try:
+ fd_path = os.path.join(fd_dir, fd)
+ if os.path.islink(fd_path):
+ target = os.readlink(fd_path)
+ if '[' + inode + ']' in target:
+ return d, exceptions
+ except Exception as e:
+ exceptions.append(e)
+ except Exception as e:
+ exceptions.append(e)
+ return None, exceptions
+
+
def test():
s = Server(LOG_STREAM_FILE, LOG_STREAM_PORT)
s.run()
@@ -206,19 +255,54 @@
argument_spec=dict(
path=dict(default=LOG_STREAM_FILE),
port=dict(default=LOG_STREAM_PORT, type='int'),
+ state=dict(default='present', choices=['absent', 'present']),
)
)
p = module.params
path = p['path']
port = p['port']
+ state = p['state']
- if daemonize():
+ if state == 'present':
+ if daemonize():
+ module.exit_json()
+
+ s = Server(path, port)
+ s.run()
+ else:
+ pid = None
+ exceptions = []
+ inode = get_inode()
+ if not inode:
+ module.fail_json(
+ "Could not find inode for port",
+ exceptions=[])
+
+ pid, exceptions = get_pid_from_inode(inode)
+ if not pid:
+ except_strings = [str(e) for e in exceptions]
+ module.fail_json(
+ msg="Could not find zuul_console process for inode",
+ exceptions=except_strings)
+
+ try:
+ subprocess.check_output(['kill', pid])
+ except subprocess.CalledProcessError as e:
+ module.fail_json(
+ msg="Could not kill zuul_console pid",
+ exceptions=[str(e)])
+
+ for fn in glob.glob(LOG_STREAM_FILE.format(log_uuid='*')):
+ try:
+ os.unlink(fn)
+ except Exception as e:
+ module.fail_json(
+ msg="Could not remove logfile {fn}".format(fn=fn),
+ exceptions=[str(e)])
+
module.exit_json()
- s = Server(path, port)
- s.run()
-
from ansible.module_utils.basic import * # noqa
from ansible.module_utils.basic import AnsibleModule