Skip to content

Commit ce25bb0

Browse files
committed
Manually merge PR137 to rework the handling of storage_protocols and duplicati_protocols with default auto detection and elimination of redundancy for duplicati protocol order. Should wrap up the last bits of logic regarding the proposed workaround for github issue 119 and leave only the actual exposure of the new wwwserver_max_bytes conf option still missing.
git-svn-id: svn+ssh://svn.code.sf.net/p/migrid/code/trunk@6155 b75ad72c-e7d7-11dd-a971-7dbc132099af
1 parent 1da80cc commit ce25bb0

12 files changed

+122
-74
lines changed

mig/install/MiGserver-template.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ mig_server_id = %(server_fqdn)s.0
187187
empty_job_name = no_grid_jobs_in_grid_scheduler
188188
notify_protocols = email
189189
smtp_server = __SMTP_SERVER__
190-
storage_protocols = __STORAGE_PROTOCOLS__
191190
gdp_email_notify = __GDP_EMAIL_NOTIFY__
192191

192+
# Optional space-separated prioritized list of efficient storage access
193+
# protocols to advertize to clients. Leave to AUTO to use the ones actually
194+
# enabled with the corresponding enable_SERVICE options. Default is AUTO and
195+
# other allowed values are one or more of sftp, ftps and davs.
196+
# NOTE: the sftpsubsys service is advertized as just sftp to fit the protocol.
197+
storage_protocols = __STORAGE_PROTOCOLS__
198+
193199
# Optional extra service interfaces with common structure
194200
# * user_X_address is the host address to listen on
195201
# * user_X_port is the host port to listen on

mig/shared/configuration.py

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@
5050
from mig.shared.defaults import CSRF_MINIMAL, CSRF_WARN, CSRF_MEDIUM, \
5151
CSRF_FULL, POLICY_NONE, POLICY_WEAK, POLICY_MEDIUM, POLICY_HIGH, \
5252
POLICY_MODERN, POLICY_CUSTOM, freeze_flavors, cert_field_order, \
53-
duplicati_protocol_choices, default_css_filename, keyword_any, \
54-
cert_valid_days, oid_valid_days, generic_valid_days, keyword_all, \
55-
keyword_file, keyword_env, DEFAULT_USER_ID_FORMAT, \
56-
valid_user_id_formats, valid_filter_methods, default_twofactor_auth_apps
53+
default_css_filename, keyword_any, keyword_auto, keyword_all, \
54+
keyword_file, keyword_env, cert_valid_days, oid_valid_days, \
55+
generic_valid_days, DEFAULT_USER_ID_FORMAT, valid_user_id_formats, \
56+
valid_filter_methods, default_twofactor_auth_apps
5757
from mig.shared.logger import Logger, SYSLOG_GDP
5858
from mig.shared.htmlgen import menu_items, vgrid_items
5959
from mig.shared.fileio import read_file, load_json, write_file
@@ -264,7 +264,6 @@ def fix_missing(config_file, verbose=True):
264264
'user_seafile_auth': ['password'],
265265
'user_seafile_local_instance': False,
266266
'user_seafile_ro_access': False,
267-
'user_duplicati_protocols': [],
268267
'user_cloud_console_access': [],
269268
'user_cloud_ssh_auth': ['publickey'],
270269
'user_cloud_alias': '',
@@ -528,7 +527,7 @@ def fix_missing(config_file, verbose=True):
528527
'user_seafile_alias': '',
529528
'user_seafile_local_instance': False,
530529
'user_seafile_ro_access': False,
531-
'user_duplicati_protocols': [],
530+
'user_duplicati_protocols': keyword_auto,
532531
'user_cloud_console_access': [],
533532
'user_cloud_ssh_auth': ['publickey'],
534533
'user_cloud_alias': '',
@@ -619,7 +618,7 @@ def fix_missing(config_file, verbose=True):
619618
'scriptlanguages': [],
620619
'jobtypes': [],
621620
'lrmstypes': [],
622-
'storage_protocols': [],
621+
'storage_protocols': keyword_auto,
623622
'server_cert': '',
624623
'server_key': '',
625624
'passphrase_file': '',
@@ -1284,6 +1283,17 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
12841283
'user_ftps_alias')
12851284
if config.has_option('GLOBAL', 'user_ftps_log'):
12861285
self.user_ftps_log = config.get('GLOBAL', 'user_ftps_log')
1286+
1287+
# NOTE: prioritized order based on performance and robustness.
1288+
# Needed by duplicati and storage protocols setup below.
1289+
prio_storage_protos = []
1290+
if self.site_enable_sftp_subsys or self.site_enable_sftp:
1291+
prio_storage_protos.append('sftp')
1292+
if self.site_enable_ftps:
1293+
prio_storage_protos.append('ftps')
1294+
if self.site_enable_davs:
1295+
prio_storage_protos.append('davs')
1296+
12871297
if config.has_option('SITE', 'enable_seafile'):
12881298
self.site_enable_seafile = config.getboolean(
12891299
'SITE', 'enable_seafile')
@@ -1321,10 +1331,21 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
13211331
else:
13221332
self.site_enable_duplicati = False
13231333
if config.has_option('GLOBAL', 'user_duplicati_protocols'):
1324-
allowed_protos = [j for (i, j) in duplicati_protocol_choices]
1325-
protos = config.get('GLOBAL', 'user_duplicati_protocols').split()
1334+
allowed_protos = prio_storage_protos
1335+
plain_val = config.get('GLOBAL', 'user_duplicati_protocols')
1336+
protos = [i for i in plain_val.split() if i]
1337+
# Append missing supported protocols for AUTO and filter invalid
1338+
if keyword_auto in protos:
1339+
protos = [i for i in protos if i != keyword_auto] +\
1340+
[i for i in allowed_protos if i not in protos]
13261341
valid_protos = [i for i in protos if i in allowed_protos]
1342+
if protos != valid_protos:
1343+
invalid_protos = [i for i in protos if i not in valid_protos]
1344+
self.logger.warning("invalid duplicati_protocol value(s): %s" %
1345+
', '.join(invalid_protos))
13271346
self.user_duplicati_protocols = valid_protos
1347+
else:
1348+
self.user_duplicati_protocols = prio_storage_protos
13281349
if config.has_option('SITE', 'enable_cloud'):
13291350
self.site_enable_cloud = config.getboolean(
13301351
'SITE', 'enable_cloud')
@@ -1589,8 +1610,22 @@ def reload_config(self, verbose, skip_log=False, disable_auth_log=False,
15891610
else:
15901611
self.notify_protocols = []
15911612
if config.has_option('GLOBAL', 'storage_protocols'):
1592-
self.storage_protocols = config.get(
1593-
'GLOBAL', 'storage_protocols').split()
1613+
allowed_protos = prio_storage_protos
1614+
plain_val = config.get('GLOBAL', 'storage_protocols')
1615+
protos = [i for i in plain_val.split() if i]
1616+
# Append missing supported protocols for AUTO and filter invalid
1617+
if keyword_auto in protos:
1618+
protos = [i for i in protos if i != keyword_auto] +\
1619+
[i for i in allowed_protos if i not in protos]
1620+
valid_protos = [i for i in protos if i in allowed_protos]
1621+
if protos != valid_protos:
1622+
invalid_protos = [i for i in protos if i not in valid_protos]
1623+
self.logger.warning("invalid storage_protocols value(s): %s" %
1624+
', '.join(invalid_protos))
1625+
self.storage_protocols = valid_protos
1626+
else:
1627+
self.storage_protocols = prio_storage_protos
1628+
15941629
if config.has_option('SITE', 'enable_jupyter'):
15951630
self.site_enable_jupyter = config.getboolean(
15961631
'SITE', 'enable_jupyter')

mig/shared/defaults.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,6 @@
424424
'rsyncssh': 'RSYNC over SSH', 'rsyncd': 'RSYNC daemon',
425425
'oid': 'OpenID 2.0', 'openid': 'OpenID 2.0',
426426
'oidc': 'OpenID Connect', 'openidc': 'OpenID Connect'}
427-
# Prioritized protocol choices for duplicati - order matters!
428-
duplicati_protocol_choices = [(protocol_aliases[i], i) for i in
429-
['sftp', 'ftps', 'davs']]
430427
# Prioritized schedule backup frequency choices and json values
431428
duplicati_schedule_choices = [('Daily', '1D'), ('Weekly', '1W'),
432429
('Monthly', '1M'), ('Never', '')]

mig/shared/duplicatikeywords.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# duplicatikeywords - keywords used in the duplicati settings file
7-
# Copyright (C) 2003-2021 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
88
#
99
# This file is part of MiG.
1010
#
@@ -29,8 +29,7 @@
2929

3030
from __future__ import absolute_import
3131

32-
from mig.shared.defaults import duplicati_protocol_choices, \
33-
duplicati_schedule_choices
32+
from mig.shared.defaults import protocol_aliases, duplicati_schedule_choices
3433
from mig.shared.url import urlencode
3534

3635

@@ -54,17 +53,31 @@
5453
}'''
5554
}
5655

57-
protocol_map = dict(duplicati_protocol_choices)
5856
schedule_map = dict(duplicati_schedule_choices)
5957

60-
# TODO: this function should probably move to shared.settings or something
58+
59+
def get_duplicati_protocol_map(configuration, reverse=False):
60+
"""Simple helper to extract supported storage protocols from conf and map
61+
them to user-friendly aliases. If the optional reverse argument is set the
62+
map is reversed to map from aliases to protocols instead of vice-versa.
63+
"""
64+
if reverse:
65+
return {protocol_aliases[i]: i for i in configuration.storage_protocols}
66+
else:
67+
return {i: protocol_aliases[i] for i in configuration.storage_protocols}
6168

6269

70+
# TODO: this function should probably move to shared.settings or something
71+
6372
def extract_duplicati_helper(configuration, client_id, duplicati_dict):
6473
"""Fill helper dictionary with values used in duplicati_conf_templates"""
6574
# lookup fqdn, username, etc for specified protocol
66-
default_protocol = duplicati_protocol_choices[0][0]
67-
protocol_alias = duplicati_dict.get('PROTOCOL', default_protocol)
75+
rev_proto_map = get_duplicati_protocol_map(configuration, reverse=True)
76+
if configuration.storage_protocols:
77+
default_alias = protocol_aliases[configuration.storage_protocols[0]]
78+
else:
79+
default_alias = ''
80+
protocol_alias = duplicati_dict.get('PROTOCOL', default_alias)
6881
username = duplicati_dict.get('USERNAME')
6982
password = duplicati_dict.get('PASSWORD', '')
7083
credentials = [('auth-username', username)]
@@ -82,7 +95,7 @@ def extract_duplicati_helper(configuration, client_id, duplicati_dict):
8295
# cert renew will change the hash and thus break existing confs.
8396
schedule_alias = duplicati_dict.get('SCHEDULE', '')
8497
schedule_freq = schedule_map.get(schedule_alias, '')
85-
protocol = protocol_map[protocol_alias]
98+
protocol = rev_proto_map[protocol_alias]
8699
if protocol in ('webdavs', 'davs'):
87100
# Duplicati client requires webdavs://BLA
88101
protocol = 'webdavs'

mig/shared/functionality/settings.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# settings - back end for the settings page
7-
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
88
#
99
# This file is part of MiG.
1010
#
@@ -41,8 +41,9 @@
4141
from mig.shared.defaults import default_mrsl_filename, \
4242
default_css_filename, profile_img_max_kb, profile_img_extensions, \
4343
seafile_ro_dirname, duplicati_conf_dir, csrf_field, \
44-
duplicati_protocol_choices, duplicati_schedule_choices
45-
from mig.shared.duplicatikeywords import get_duplicati_specs
44+
duplicati_schedule_choices
45+
from mig.shared.duplicatikeywords import get_duplicati_specs, \
46+
get_duplicati_protocol_map
4647
from mig.shared.editing import cm_css, cm_javascript, cm_options, wrap_edit_area
4748
from mig.shared.functional import validate_input_and_cert
4849
from mig.shared.handlers import get_csrf_limit, make_csrf_token
@@ -1675,9 +1676,8 @@ def main(client_id, user_arguments_dict):
16751676
if configuration.user_duplicati_protocols:
16761677
protocol_order = configuration.user_duplicati_protocols
16771678
else:
1678-
protocol_order = [j for (i, j) in duplicati_protocol_choices]
1679-
reverse_proto_map = dict([(j, i) for (i, j) in
1680-
duplicati_protocol_choices])
1679+
protocol_order = configuration.storage_protocols
1680+
proto_map = get_duplicati_protocol_map(configuration)
16811681

16821682
enabled_map = {
16831683
'davs': configuration.site_enable_davs,
@@ -1691,7 +1691,7 @@ def main(client_id, user_arguments_dict):
16911691
'ftps': extract_field(client_id, configuration.user_ftps_alias)
16921692
}
16931693
for proto in protocol_order:
1694-
pretty_proto = reverse_proto_map[proto]
1694+
pretty_proto = proto_map[proto]
16951695
if not enabled_map[proto]:
16961696
continue
16971697
if not pretty_proto in configuration.protocol:

mig/shared/functionality/setup.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# --- BEGIN_HEADER ---
55
#
66
# setup - back end for the client access setup page
7-
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
7+
# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
88
#
99
# This file is part of MiG.
1010
#
@@ -38,9 +38,10 @@
3838
from mig.shared.base import client_alias, client_id_dir, extract_field, get_xgi_bin, \
3939
get_short_id, requested_url_base, requested_backend
4040
from mig.shared.defaults import seafile_ro_dirname, duplicati_conf_dir, csrf_field, \
41-
duplicati_protocol_choices, duplicati_schedule_choices, keyword_all, \
42-
AUTH_MIG_OID, AUTH_EXT_OID, AUTH_MIG_OIDC, AUTH_EXT_OIDC
43-
from mig.shared.duplicatikeywords import get_duplicati_specs
41+
duplicati_schedule_choices, keyword_all, AUTH_MIG_OID, AUTH_EXT_OID, \
42+
AUTH_MIG_OIDC, AUTH_EXT_OIDC
43+
from mig.shared.duplicatikeywords import get_duplicati_specs, \
44+
get_duplicati_protocol_map
4445
from mig.shared.editing import cm_css, cm_javascript, cm_options, wrap_edit_area
4546
from mig.shared.functional import validate_input_and_cert
4647
from mig.shared.handlers import get_csrf_limit, make_csrf_token
@@ -1377,9 +1378,8 @@ def main(client_id, user_arguments_dict, target_op='settingsaction'):
13771378
if configuration.user_duplicati_protocols:
13781379
protocol_order = configuration.user_duplicati_protocols
13791380
else:
1380-
protocol_order = [j for (i, j) in duplicati_protocol_choices]
1381-
reverse_proto_map = dict([(j, i) for (i, j) in
1382-
duplicati_protocol_choices])
1381+
protocol_order = configuration.storage_protocols
1382+
proto_map = get_duplicati_protocol_map(configuration)
13831383

13841384
enabled_map = {
13851385
'davs': configuration.site_enable_davs,
@@ -1393,7 +1393,7 @@ def main(client_id, user_arguments_dict, target_op='settingsaction'):
13931393
'ftps': extract_field(client_id, configuration.user_ftps_alias)
13941394
}
13951395
for proto in protocol_order:
1396-
pretty_proto = reverse_proto_map[proto]
1396+
pretty_proto = proto_map[proto]
13971397
if not enabled_map[proto]:
13981398
continue
13991399
if not pretty_proto in configuration.protocol:

mig/shared/install.py

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,8 @@ def _generate_confs_prepare(
10541054
user_dict['__PERMANENT_FREEZE__'] = permanent_freeze
10551055
user_dict['__FREEZE_TO_TAPE__'] = freeze_to_tape
10561056
user_dict['__STATUS_SYSTEM_MATCH__'] = status_system_match
1057+
user_dict['__STORAGE_PROTOCOLS__'] = storage_protocols
1058+
user_dict['__DUPLICATI_PROTOCOLS__'] = duplicati_protocols
10571059
user_dict['__IMNOTIFY_ADDRESS__'] = imnotify_address
10581060
user_dict['__IMNOTIFY_CHANNEL__'] = imnotify_channel
10591061
user_dict['__IMNOTIFY_USERNAME__'] = imnotify_username
@@ -1330,29 +1332,6 @@ def _generate_confs_prepare(
13301332
if davs_show_port:
13311333
fail2ban_daemon_ports.append(davs_show_port)
13321334

1333-
# NOTE: prioritized order based on performance and robustness
1334-
best_storage_svc = []
1335-
if enable_sftp_subsys or enable_sftp:
1336-
best_storage_svc.append('sftp')
1337-
if enable_ftps:
1338-
best_storage_svc.append('ftps')
1339-
if enable_davs:
1340-
best_storage_svc.append('davs')
1341-
1342-
if storage_protocols != keyword_auto:
1343-
storage_protocols = [i for i in storage_protocols.split() if i in
1344-
best_storage_svc]
1345-
else:
1346-
storage_protocols = best_storage_svc
1347-
user_dict['__STORAGE_PROTOCOLS__'] = ' '.join(storage_protocols)
1348-
1349-
if duplicati_protocols != keyword_auto:
1350-
prio_duplicati_protocols = [i for i in duplicati_protocols.split() if i
1351-
in best_storage_svc]
1352-
else:
1353-
prio_duplicati_protocols = best_storage_svc
1354-
user_dict['__DUPLICATI_PROTOCOLS__'] = ' '.join(prio_duplicati_protocols)
1355-
13561335
user_dict['__SEAFILE_TIMEZONE__'] = options['timezone']
13571336

13581337
if seafile_secret == keyword_auto:

tests/data/MiGserver--storage_protocols.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ mig_server_id = %(server_fqdn)s.0
187187
empty_job_name = no_grid_jobs_in_grid_scheduler
188188
notify_protocols = email
189189
smtp_server = localhost
190-
storage_protocols = xxx yyy zzz
191190
gdp_email_notify = False
192191

192+
# Optional space-separated prioritized list of efficient storage access
193+
# protocols to advertize to clients. Leave to AUTO to use the ones actually
194+
# enabled with the corresponding enable_SERVICE options. Default is AUTO and
195+
# other allowed values are one or more of sftp, ftps and davs.
196+
# NOTE: the sftpsubsys service is advertized as just sftp to fit the protocol.
197+
storage_protocols = sftp
198+
193199
# Optional extra service interfaces with common structure
194200
# * user_X_address is the host address to listen on
195201
# * user_X_port is the host port to listen on

tests/fixture/confs-stdlocal/MiGserver.conf

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ mig_server_id = %(server_fqdn)s.0
187187
empty_job_name = no_grid_jobs_in_grid_scheduler
188188
notify_protocols = email
189189
smtp_server = localhost
190-
storage_protocols =
191190
gdp_email_notify = False
192191

192+
# Optional space-separated prioritized list of efficient storage access
193+
# protocols to advertize to clients. Leave to AUTO to use the ones actually
194+
# enabled with the corresponding enable_SERVICE options. Default is AUTO and
195+
# other allowed values are one or more of sftp, ftps and davs.
196+
# NOTE: the sftpsubsys service is advertized as just sftp to fit the protocol.
197+
storage_protocols = AUTO
198+
193199
# Optional extra service interfaces with common structure
194200
# * user_X_address is the host address to listen on
195201
# * user_X_port is the host port to listen on
@@ -290,7 +296,7 @@ user_seafile_local_instance = False
290296
# if local read-only mount is available for user home integration (default: False)
291297
user_seafile_ro_access = True
292298
# Priority list of protocols allowed in Duplicati backups (sftp, ftps, davs)
293-
user_duplicati_protocols =
299+
user_duplicati_protocols = AUTO
294300
# Cloud settings for remote access - more in individual service sections
295301
# space separated list of cloud user authentication methods
296302
# (default: publickey)

tests/fixture/mig_shared_configuration--new.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@
207207
"smtp_server": "",
208208
"sss_home": "",
209209
"state_path": "/some/place/state",
210-
"storage_protocols": [],
210+
"storage_protocols": "AUTO",
211211
"submitui": [
212212
"fields",
213213
"textarea",
@@ -242,7 +242,7 @@
242242
"user_davs_show_address": "",
243243
"user_davs_show_port": 4443,
244244
"user_db_home": "",
245-
"user_duplicati_protocols": [],
245+
"user_duplicati_protocols": "AUTO",
246246
"user_events_log": "events.log",
247247
"user_ext_cert_title": "",
248248
"user_ext_oid_provider": "",

0 commit comments

Comments
 (0)