blob: eef8182aba4c51689d1cf4b68e01dc42af19149f [file] [log] [blame]
azvyagintseve5c4e832018-01-25 20:02:46 +02001#!/usr/bin/env python
2"""
3Management of debmirror
4=======================
5
6Create debian mirrors, using debmirror
7--------------------------------------
8
9.. code-block:: yaml
10 debmirror_test1_present:
11 debmirror.mirror_present:
12 - name: test1
13
14"""
15import logging
16import os
17from functools import wraps
18from salt.exceptions import CommandExecutionError, SaltInvocationError
19log = logging.getLogger(__name__)
20
21def __virtual__():
22 '''
23 Only load this module if debmirror is installed with deps.
24 '''
25 return 'debmirror'
26
27def _test_call(method):
28 (resource, functionality) = method.func_name.split('_')
29 if functionality == 'present':
30 functionality = 'updated'
31 else:
32 functionality = 'removed'
33
34 @wraps(method)
35 def check_for_testing(name, *args, **kwargs):
36 if __opts__.get('test', None):
37 return _no_change(name, resource, test=functionality)
38 return method(name, *args, **kwargs)
39 return check_for_testing
40
41def _created(name, resource, resource_definition={}):
42 changes_dict = {'name': name,
43 'changes': resource_definition,
44 'result': True,
45 'comment': '{0} {1} created'.format(resource, name)}
46 return changes_dict
47
48def _failed(name, resource, resource_definition={}):
49 changes_dict = {'name': name,
50 'changes': resource_definition,
51 'result': False,
52 'comment': '{0} {1} failed to create'.format(resource, name)}
53 return changes_dict
54
55def _no_change(name, resource, test=False):
56 changes_dict = {'name': name,
57 'changes': {},
58 'result': True}
59 if test:
60 changes_dict['comment'] = \
61 '{0} {1} will be {2}'.format(resource, name, test)
62 else:
63 changes_dict['comment'] = \
64 '{0} {1} is in correct state'.format(resource, name)
65 return changes_dict
66
67def _check_state(name, tgt):
68 lock_file = _get_target_path(name,tgt)['lock_file']
69 if os.path.isfile(lock_file) and not tgt.get('force', False) :
azvyagintsevb80d6222018-02-19 15:53:40 +020070 return _no_change(name, '{} exist=>repo locked.'.format(lock_file))
azvyagintseve5c4e832018-01-25 20:02:46 +020071 return False
72
73def _get_target_path(name,tgt):
74 if not tgt.get('target_dir',False):
75 raise SaltInvocationError('Argument "target_dir" is mandatory! ')
76 return {'target_dir': tgt.get('target_dir'),
77 'lock_file': tgt.get('lock_file', os.path.join(tgt.get('target_dir'), '.lockmirror')),
78 'log_file': tgt.get('log_file', '/var/log/debmirror_'.join(name)) }
79
80def _get_cmdline(name,tgt):
81 cmdline = " debmirror "
82 if tgt.get('extra_flags'):
83 cmdline += ' '.join(tgt['extra_flags'])
84 if tgt.get('dist'):
85 cmdline += ' --dist=' + ",".join(tgt['dist'])
86 if tgt.get('section'):
87 cmdline += ' --section=' + ",".join(tgt['section'])
88 if tgt.get('method'):
89 cmdline += ' --method=' + tgt.get('method')
90 if tgt.get('mirror_host'):
91 cmdline += ' --host="{}"'.format(tgt.get('mirror_host'))
92 if tgt.get('mirror_root'):
93 cmdline += ' --root="{}"'.format(tgt.get('mirror_root'))
94 if tgt.get('arch', 'amd64'):
95 cmdline += ' --arch=' + ','.join(tgt.get('arch'))
azvyagintsev6e410f92018-03-07 23:35:05 +020096 if tgt.get('exclude_deb_section'):
97 for section in tgt['exclude_deb_section']:
98 cmdline += " --exclude-deb-section='" + section + "'"
azvyagintseve5c4e832018-01-25 20:02:46 +020099 if tgt.get('filter'):
100 for key, value in enumerate(sorted(tgt['filter'])):
101 cmdline += " " + tgt['filter'][value]
102 if tgt.get('target_dir',False):
103 cmdline += ' ' + _get_target_path(name,tgt)['target_dir']
104 return cmdline
105
106def _update_mirror(name,tgt):
107 # Remove old lock file, is was.
108 lock_file = _get_target_path(name,tgt)['lock_file']
109 if os.path.isfile(lock_file):
110 log.debug("Removing lockfile:{} for mirror{}".format(lock_file,name))
111 __states__['file.absent'](lock_file)
112 cmdline = _get_cmdline(name,tgt)
113 # init file logger
114 l_dir = os.path.dirname(tgt['log_file'])
115 if not os.path.isdir(l_dir):
azvyagintsevf5fc6532018-02-21 22:17:02 +0200116 __salt__['file.makedirs'](l_dir + '/')
azvyagintseve5c4e832018-01-25 20:02:46 +0200117 fh = logging.FileHandler("{0}".format(_get_target_path(name,tgt)['log_file']))
118 fh.setLevel(logging.DEBUG)
119 fh_format = logging.Formatter('%(asctime)s - %(lineno)d - %(levelname)-8s - %(message)s')
120 fh.setFormatter(fh_format)
121 log2file = logging.getLogger("debmirror")
122 log2file.addHandler(fh)
123 result = __salt__['cmd.run_all'](cmdline, redirect_stderr=True)
124 log2file.debug(result['stdout'])
125 # destroy file logger
126 for i in list(log2file.handlers):
127 log2file.removeHandler(i)
128 i.flush()
129 i.close()
130 if result['retcode'] != 0:
131 #raise CommandExecutionError(result['stderr'])
132 return _failed(name, "debmirror failed.Reason {0}".format(result['stderr']))
133 if tgt.get('lock_target',None):
134 __states__['file.touch'](lock_file)
135 return _created(name, "Mirror {0} created.".format(name) )
136
137@_test_call
138def mirror_present(name, **kwargs):
139 '''
140
141 :param name: mirror key name
142 '''
143 try:
144 tgt = __salt__['config.get']('debmirror')['client']['mirrors'][name]
145 except KeyError:
146 comment ='Mirror "{0}" not exist in configurathion,skipping..'.format(name)
147 return _no_change(name, comment)
148
149 current_state = _check_state(name,tgt)
150 if not current_state:
151 return _update_mirror(name,tgt)
152 return current_state