Skip to content

Commit bb2f026

Browse files
Merge pull request #154 from tofu-rocketry/release-3.2.0
Release 3.2.0 to master
2 parents b0cc13b + 4bdafb4 commit bb2f026

File tree

10 files changed

+409
-412
lines changed

10 files changed

+409
-412
lines changed

CHANGELOG

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
Changelog for ssm
22
=================
3+
* Thu Mar 18 2021 Adrian Coveney <[email protected]> - 3.2.0-1
4+
- Added logging of what certificate DNs/subjects are being used to facilitate
5+
troubleshooting.
6+
- Added stomp.py as .deb package dependency to avoid broken installations.
7+
- Refactored code to enable simpler external calls and better testing.
8+
39
* Wed Dec 16 2020 Adrian Coveney <[email protected]> - 3.1.1-1
410
- Changed logging to reduce how verbose the logging of a 3rd-party module is.
511

apel-ssm.spec

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
%endif
55

66
Name: apel-ssm
7-
Version: 3.1.1
7+
Version: 3.2.0
88
%define releasenumber 1
99
Release: %{releasenumber}%{?dist}
1010
Summary: Secure stomp messenger
@@ -100,6 +100,12 @@ rm -rf $RPM_BUILD_ROOT
100100
%doc %_defaultdocdir/%{name}
101101

102102
%changelog
103+
* Thu Mar 18 2021 Adrian Coveney <[email protected]> - 3.2.0-1
104+
- Added logging of what certificate DNs/subjects are being used to facilitate
105+
troubleshooting.
106+
- Added stomp.py as .deb package dependency to avoid broken installations.
107+
- Refactored code to enable simpler external calls and better testing.
108+
103109
* Wed Dec 16 2020 Adrian Coveney <[email protected]> - 3.1.1-1
104110
- Changed logging to reduce how verbose the logging of a 3rd-party module is.
105111

bin/receiver.py

Lines changed: 8 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -18,60 +18,19 @@
1818

1919
from __future__ import print_function
2020

21-
from ssm.brokers import StompBrokerGetter, STOMP_SERVICE, STOMP_SSL_SERVICE
22-
from ssm.ssm2 import Ssm2, Ssm2Exception
23-
from ssm import __version__, set_up_logging, LOG_BREAK
21+
import ssm.agents
22+
from ssm import __version__, LOG_BREAK
2423

25-
from stomp.exception import NotConnectedException
26-
try:
27-
from argo_ams_library import AmsConnectionException
28-
except ImportError:
29-
# ImportError is raised when Ssm2 initialised if AMS is requested but lib
30-
# not installed.
31-
AmsConnectionException = None
32-
33-
import time
34-
import logging.config
35-
import ldap
24+
import logging
3625
import os
3726
import sys
3827
from optparse import OptionParser
39-
from daemon import DaemonContext
4028

4129
try:
4230
import ConfigParser
4331
except ImportError:
4432
import configparser as ConfigParser
4533

46-
# How often (in seconds) to read the list of valid DNs.
47-
REFRESH_DNS = 600
48-
log = None
49-
50-
51-
def get_dns(dn_file):
52-
"""Retrieve a list of DNs from a file."""
53-
dns = []
54-
f = None
55-
try:
56-
f = open(dn_file, 'r')
57-
lines = f.readlines()
58-
for line in lines:
59-
if line.isspace() or line.strip().startswith('#'):
60-
continue
61-
elif line.strip().startswith('/'):
62-
dns.append(line.strip())
63-
else:
64-
log.warn('DN in incorrect format: %s', line)
65-
finally:
66-
if f is not None:
67-
f.close()
68-
# If no valid DNs, SSM cannot receive any messages.
69-
if len(dns) == 0:
70-
raise Ssm2Exception('No valid DNs found in %s. SSM will not start' % dn_file)
71-
72-
log.debug('%s DNs found.', len(dns))
73-
return dns
74-
7534

7635
def main():
7736
"""Set up connection, and listen for messages."""
@@ -97,192 +56,21 @@ def main():
9756
print('Cannot start SSM. Pidfile %s already exists.' % pidfile)
9857
sys.exit(1)
9958

100-
# set up logging
101-
try:
102-
if os.path.exists(options.log_config):
103-
logging.config.fileConfig(options.log_config)
104-
else:
105-
set_up_logging(cp.get('logging', 'logfile'),
106-
cp.get('logging', 'level'),
107-
cp.getboolean('logging', 'console'))
108-
except (ConfigParser.Error, ValueError, IOError) as err:
109-
print('Error configuring logging: %s' % err)
110-
print('SSM will exit.')
111-
sys.exit(1)
59+
ssm.agents.logging_helper(cp, options.log_config)
11260

113-
global log
11461
log = logging.getLogger('ssmreceive')
11562

11663
log.info(LOG_BREAK)
11764
log.info('Starting receiving SSM version %s.%s.%s.', *__version__)
11865

119-
# Determine the protocol for the SSM to use.
120-
try:
121-
protocol = cp.get('receiver', 'protocol')
122-
123-
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
124-
# If the newer configuration setting 'protocol' is not set, use 'STOMP'
125-
# for backwards compatability.
126-
protocol = Ssm2.STOMP_MESSAGING
127-
log.debug("No option set for 'protocol'. Defaulting to %s.", protocol)
66+
protocol = ssm.agents.get_protocol(cp, log)
12867

12968
log.info('Setting up SSM with protocol: %s', protocol)
13069

131-
if protocol == Ssm2.STOMP_MESSAGING:
132-
# Set defaults for AMS variables that Ssm2 constructor requires below.
133-
project = None
134-
token = ''
135-
136-
use_ssl = cp.getboolean('broker', 'use_ssl')
137-
if use_ssl:
138-
service = STOMP_SSL_SERVICE
139-
else:
140-
service = STOMP_SERVICE
141-
142-
# If we can't get a broker to connect to, we have to give up.
143-
try:
144-
bg = StompBrokerGetter(cp.get('broker', 'bdii'))
145-
brokers = bg.get_broker_hosts_and_ports(service, cp.get('broker',
146-
'network'))
147-
except ConfigParser.NoOptionError as e:
148-
try:
149-
host = cp.get('broker', 'host')
150-
port = cp.get('broker', 'port')
151-
brokers = [(host, int(port))]
152-
except ConfigParser.NoOptionError:
153-
log.error('Options incorrectly supplied for either single '
154-
'broker or broker network. '
155-
'Please check configuration')
156-
log.error('System will exit.')
157-
log.info(LOG_BREAK)
158-
sys.exit(1)
159-
except ldap.SERVER_DOWN as e:
160-
log.error('Could not connect to LDAP server: %s', e)
161-
log.error('System will exit.')
162-
log.info(LOG_BREAK)
163-
sys.exit(1)
164-
165-
elif protocol == Ssm2.AMS_MESSAGING:
166-
# Then we are setting up an SSM to connect to a AMS.
167-
168-
# 'use_ssl' isn't checked when using AMS (SSL is always used), but it
169-
# is needed for the call to the Ssm2 constructor below.
170-
use_ssl = None
171-
try:
172-
# We only need a hostname, not a port
173-
host = cp.get('broker', 'host')
174-
# Use brokers variable so subsequent code is not dependant on
175-
# the exact destination type.
176-
brokers = [host]
177-
178-
except ConfigParser.NoOptionError:
179-
log.error('The host must be specified when connecting to AMS, '
180-
'please check your configuration')
181-
log.error('System will exit.')
182-
log.info(LOG_BREAK)
183-
print('SSM failed to start. See log file for details.')
184-
sys.exit(1)
185-
186-
# Attempt to configure AMS specific variables.
187-
try:
188-
token = cp.get('messaging', 'token')
189-
project = cp.get('messaging', 'ams_project')
190-
191-
except (ConfigParser.Error, ValueError, IOError) as err:
192-
# A token and project are needed to successfully receive from an
193-
# AMS instance, so log and then exit on an error.
194-
log.error('Error configuring AMS values: %s', err)
195-
log.error('SSM will exit.')
196-
print('SSM failed to start. See log file for details.')
197-
sys.exit(1)
70+
brokers, project, token = ssm.agents.get_ssm_args(protocol, cp, log)
19871

199-
if len(brokers) == 0:
200-
log.error('No brokers available.')
201-
log.error('System will exit.')
202-
log.info(LOG_BREAK)
203-
sys.exit(1)
204-
205-
log.info('The SSM will run as a daemon.')
206-
207-
# We need to preserve the file descriptor for any log files.
208-
rootlog = logging.getLogger()
209-
log_files = [x.stream for x in rootlog.handlers]
210-
dc = DaemonContext(files_preserve=log_files)
211-
212-
try:
213-
ssm = Ssm2(brokers,
214-
cp.get('messaging', 'path'),
215-
cert=cp.get('certificates', 'certificate'),
216-
key=cp.get('certificates', 'key'),
217-
listen=cp.get('messaging', 'destination'),
218-
use_ssl=use_ssl,
219-
capath=cp.get('certificates', 'capath'),
220-
check_crls=cp.getboolean('certificates', 'check_crls'),
221-
pidfile=pidfile,
222-
protocol=protocol,
223-
project=project,
224-
token=token)
225-
226-
log.info('Fetching valid DNs.')
227-
dns = get_dns(options.dn_file)
228-
ssm.set_dns(dns)
229-
230-
except Exception as e:
231-
log.fatal('Failed to initialise SSM: %s', e)
232-
log.info(LOG_BREAK)
233-
sys.exit(1)
234-
235-
try:
236-
# Note: because we need to be compatible with python 2.4, we can't use
237-
# with dc:
238-
# here - we need to call the open() and close() methods
239-
# manually.
240-
dc.open()
241-
ssm.startup()
242-
i = 0
243-
# The message listening loop.
244-
while True:
245-
try:
246-
time.sleep(0.1)
247-
if protocol == Ssm2.AMS_MESSAGING:
248-
# We need to pull down messages as part of
249-
# this loop when using AMS.
250-
ssm.pull_msg_ams()
251-
252-
if i % (REFRESH_DNS * 10) == 0:
253-
log.info('Refreshing valid DNs and then sending ping.')
254-
dns = get_dns(options.dn_file)
255-
ssm.set_dns(dns)
256-
257-
if protocol == Ssm2.STOMP_MESSAGING:
258-
ssm.send_ping()
259-
260-
except (NotConnectedException, AmsConnectionException) as error:
261-
log.warn('Connection lost.')
262-
log.debug(error)
263-
ssm.shutdown()
264-
dc.close()
265-
log.info("Waiting for 10 minutes before restarting...")
266-
time.sleep(10 * 60)
267-
log.info('Restarting SSM.')
268-
dc.open()
269-
ssm.startup()
270-
271-
i += 1
272-
273-
except SystemExit as e:
274-
log.info('Received the shutdown signal: %s', e)
275-
ssm.shutdown()
276-
dc.close()
277-
except Exception as e:
278-
log.error('Unexpected exception: %s', e)
279-
log.error('Exception type: %s', e.__class__)
280-
log.error('The SSM will exit.')
281-
ssm.shutdown()
282-
dc.close()
283-
284-
log.info('Receiving SSM has shut down.')
285-
log.info(LOG_BREAK)
72+
ssm.agents.run_receiver(protocol, brokers, project, token,
73+
cp, log, options.dn_file)
28674

28775

28876
if __name__ == '__main__':

0 commit comments

Comments
 (0)