2
# -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5
# Copyright (C) 2010 Patrick Crews
8
code for dealing with the various tasks
9
around handing out and managing server ports
10
that we need to run tests
19
""" class for doing the work of handing out and tracking ports """
20
def __init__(self, system_manager, debug = 0):
21
# This is a file that can be read into a dictionary
22
# it is in port:owner format
23
self.skip_keys = [ 'port_file_delimiter'
26
self.port_catalog = "/tmp/drizzle_test_port_catalog.dat"
27
self.port_file_delimiter = ':' # what we use to separate port:owner
29
self.logging = system_manager.logging
30
self.system_manager = system_manager
32
self.logging.debug_class(self)
35
def get_port_block(self, requester, base_port, block_size):
36
""" Try to return a block of ports of size
37
block_size, starting with base_port
39
We take a target port and increment it
40
until we find an unused port. We make
41
no guarantee of continuous ports, only
42
that we will try to return block_size
45
We can probably get fancier / smarter in the future
46
but this should work for now :-/
50
current_port = base_port
51
while len(assigned_ports) != block_size:
52
new_port = (self.get_port(requester, current_port))
53
assigned_ports.append(new_port)
54
current_port = new_port+1
57
def get_port(self, requester, desired_port):
58
""" Try to lock in the desired_port
59
if not, we increment the value until
60
we find an unused port.
61
We take max / min port values from test-run.pl
62
This is a bit bobo, but will work for now...
66
searching_for_port = 1
68
max_port_value = 32767
70
while searching_for_port and attempts_remain:
71
# Check if the port is used
72
if self.check_port_status(desired_port):
74
self.assign_port(requester, desired_port)
76
else: # increment the port and try again
77
desired_port = desired_port + 1
78
if desired_port >= max_port_value:
79
desired_port = min_port_value
80
attempts_remain = attempts_remain - 1
81
self.logging.error("Failed to assign a port in %d attempts")
84
def check_port_status(self, port):
85
""" Check if a port is in use, via the catalog file
86
which all copies of test-run.py should use
88
Not *really* sure how well this works with multiple
89
test-run.py instances...we'll see if we even need it
93
# read the catalog file
94
port_catalog = self.process_port_catalog()
95
if port not in port_catalog and not self.is_port_used(port):
100
def is_port_used(self, port):
101
""" See if a given port is used on the system """
102
retcode, output = self.system_manager.execute_cmd("netstat -lant")
104
entry_list = output.split("\n")
106
for entry in entry_list:
107
if entry.startswith('Proto'):
110
used_port = int(entry.split()[3].split(':')[-1].strip())
111
if port == used_port:
112
if entry.split()[-1] != "TIME_WAIT":
116
def process_port_catalog(self):
117
""" Read in the catalog file so that we can see
118
if the port is in use or not
123
if os.path.exists(self.port_catalog):
125
port_file = open(self.port_catalog,'r')
126
for line in port_file:
128
port, owner = line.split(self.port_file_delimiter)
129
port_catalog[port] = owner
132
self.logging.error("Problem opening port catalog file: %s" %(self.port_catalog))
133
self.logging.error("%s" %e)
137
def assign_port(self, owner, port):
138
"""Assigns a port - logs it in the port_catalog file"""
140
data_string = "%d:%s\n" %(port, owner)
142
port_file = open(self.port_catalog,'a')
143
port_file.write(data_string)
146
self.logging.error("Problem opening port catalog file: %s" %(self.port_catalog))
147
self.logging.error("%s" %e)
150
def free_ports(self, portlist):
151
""" Clean up our port catalog """
152
for port in portlist:
155
def free_port(self, port):
156
""" Free a single port from the catalog """
158
self.logging.debug("Freeing port %d" %(port))
159
port_catalog = self.process_port_catalog()
160
port_catalog.pop(str(port),None)
161
self.write_port_catalog(port_catalog)
163
def write_port_catalog(self, port_catalog):
164
port_file = open(self.port_catalog, 'w')
165
for key, value in port_catalog.items():
166
port_file.write(("%s:%s\n" %(key, value)))