pyreposync 0.2.6__py3-none-any.whl → 0.2.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyreposync/__init__.py +13 -0
- pyreposync/downloader.py +32 -12
- pyreposync/sync_deb822.py +72 -13
- pyreposync/sync_generic.py +8 -1
- pyreposync/sync_rpm.py +7 -2
- {pyreposync-0.2.6.dist-info → pyreposync-0.2.8.dist-info}/METADATA +1 -1
- pyreposync-0.2.8.dist-info/RECORD +11 -0
- pyreposync-0.2.6.dist-info/RECORD +0 -11
- {pyreposync-0.2.6.dist-info → pyreposync-0.2.8.dist-info}/WHEEL +0 -0
- {pyreposync-0.2.6.dist-info → pyreposync-0.2.8.dist-info}/entry_points.txt +0 -0
- {pyreposync-0.2.6.dist-info → pyreposync-0.2.8.dist-info}/licenses/LICENSE.txt +0 -0
pyreposync/__init__.py
CHANGED
@@ -269,6 +269,12 @@ class PyRepoSync:
|
|
269
269
|
section, "allow_missing_packages", fallback=False
|
270
270
|
),
|
271
271
|
treeinfo=self.config.get(section, "treeinfo", fallback=".treeinfo"),
|
272
|
+
basic_auth_user=self.config.get(
|
273
|
+
section, "basic_auth_user", fallback=None
|
274
|
+
),
|
275
|
+
basic_auth_pass=self.config.get(
|
276
|
+
section, "basic_auth_pass", fallback=None
|
277
|
+
),
|
272
278
|
proxy=self.config.get("main", "proxy", fallback=None),
|
273
279
|
client_cert=self.config.get(section, "sslclientcert", fallback=None),
|
274
280
|
client_key=self.config.get(section, "sslclientkey", fallback=None),
|
@@ -283,6 +289,12 @@ class PyRepoSync:
|
|
283
289
|
allow_missing_packages=self.config.getboolean(
|
284
290
|
section, "allow_missing_packages", fallback=False
|
285
291
|
),
|
292
|
+
basic_auth_user=self.config.get(
|
293
|
+
section, "basic_auth_user", fallback=None
|
294
|
+
),
|
295
|
+
basic_auth_pass=self.config.get(
|
296
|
+
section, "basic_auth_pass", fallback=None
|
297
|
+
),
|
286
298
|
proxy=self.config.get(section, "proxy", fallback=None),
|
287
299
|
client_cert=self.config.get(section, "sslclientcert", fallback=None),
|
288
300
|
client_key=self.config.get(section, "sslclientkey", fallback=None),
|
@@ -291,6 +303,7 @@ class PyRepoSync:
|
|
291
303
|
components=self.config.get(section, "components").split(),
|
292
304
|
binary_archs=self.config.get(section, "binary_archs").split(),
|
293
305
|
)
|
306
|
+
return None
|
294
307
|
|
295
308
|
def get_sections(self):
|
296
309
|
sections = set()
|
pyreposync/downloader.py
CHANGED
@@ -2,6 +2,7 @@ import hashlib
|
|
2
2
|
import logging
|
3
3
|
import os
|
4
4
|
import requests
|
5
|
+
import requests.auth
|
5
6
|
import requests.exceptions
|
6
7
|
import shutil
|
7
8
|
import tempfile
|
@@ -11,8 +12,20 @@ from pyreposync.exceptions import OSRepoSyncDownLoadError, OSRepoSyncHashError
|
|
11
12
|
|
12
13
|
|
13
14
|
class Downloader(object):
|
14
|
-
def __init__(
|
15
|
+
def __init__(
|
16
|
+
self,
|
17
|
+
basic_auth_user=None,
|
18
|
+
basic_auth_pass=None,
|
19
|
+
proxy=None,
|
20
|
+
client_cert=None,
|
21
|
+
client_key=None,
|
22
|
+
ca_cert=None,
|
23
|
+
):
|
15
24
|
self.log = logging.getLogger("application")
|
25
|
+
if basic_auth_user and basic_auth_pass:
|
26
|
+
self._basic_auth = (basic_auth_user, basic_auth_pass)
|
27
|
+
else:
|
28
|
+
self._basic_auth = None
|
16
29
|
if proxy:
|
17
30
|
self._proxy = {"http": proxy, "https": proxy}
|
18
31
|
else:
|
@@ -26,6 +39,10 @@ class Downloader(object):
|
|
26
39
|
else:
|
27
40
|
self._ca_cert = True
|
28
41
|
|
42
|
+
@property
|
43
|
+
def basic_auth(self):
|
44
|
+
return self._basic_auth
|
45
|
+
|
29
46
|
@property
|
30
47
|
def ca_cert(self):
|
31
48
|
return self._ca_cert
|
@@ -54,13 +71,11 @@ class Downloader(object):
|
|
54
71
|
|
55
72
|
with open(destination, "rb") as dest:
|
56
73
|
hasher.update(dest.read())
|
57
|
-
self.log.debug(f"expected hash: {hasher.hexdigest()}")
|
58
|
-
self.log.debug(f"actual hash: {checksum}")
|
59
74
|
if hasher.hexdigest() == checksum:
|
60
|
-
self.log.debug(f"download valid: {destination}")
|
75
|
+
self.log.debug(f"download valid: {destination}, expected hash: {hasher.hexdigest()}, actual hash: {checksum}")
|
61
76
|
else:
|
62
|
-
self.log.error(f"download invalid: {destination}")
|
63
|
-
raise OSRepoSyncHashError(f"download invalid: {destination}")
|
77
|
+
self.log.error(f"download invalid: {destination} expected hash: {hasher.hexdigest()}, actual hash: {checksum}")
|
78
|
+
raise OSRepoSyncHashError(f"download invalid: {destination} expected hash: {hasher.hexdigest()}, actual hash: {checksum}")
|
64
79
|
|
65
80
|
def get(
|
66
81
|
self,
|
@@ -71,11 +86,11 @@ class Downloader(object):
|
|
71
86
|
replace=False,
|
72
87
|
not_found_ok=False,
|
73
88
|
):
|
74
|
-
self.log.info(f"downloading: {url}")
|
75
89
|
if not replace:
|
76
90
|
if os.path.isfile(destination):
|
77
|
-
self.log.
|
91
|
+
self.log.debug(f"{url} already there, not downloading")
|
78
92
|
return
|
93
|
+
self.log.info(f"{url} downloading")
|
79
94
|
retries = 10
|
80
95
|
while retries >= 0:
|
81
96
|
try:
|
@@ -90,7 +105,7 @@ class Downloader(object):
|
|
90
105
|
pass
|
91
106
|
else:
|
92
107
|
raise
|
93
|
-
self.log.info(f"
|
108
|
+
self.log.info(f"{url} download done")
|
94
109
|
return
|
95
110
|
except requests.exceptions.ConnectionError:
|
96
111
|
self.log.error("could not fetch resource, retry in 10 seconds")
|
@@ -102,8 +117,8 @@ class Downloader(object):
|
|
102
117
|
time.sleep(10)
|
103
118
|
except OSRepoSyncDownLoadError:
|
104
119
|
break
|
105
|
-
self.log.error(f"could not download
|
106
|
-
raise OSRepoSyncDownLoadError(f"could not download
|
120
|
+
self.log.error(f"{url} could not download")
|
121
|
+
raise OSRepoSyncDownLoadError(f"{url} could not download")
|
107
122
|
|
108
123
|
def create_dir(self, destination):
|
109
124
|
if not os.path.isdir(os.path.dirname(destination)):
|
@@ -123,7 +138,12 @@ class Downloader(object):
|
|
123
138
|
):
|
124
139
|
self.create_dir(destination)
|
125
140
|
r = requests.get(
|
126
|
-
url,
|
141
|
+
url,
|
142
|
+
auth=self.basic_auth,
|
143
|
+
stream=True,
|
144
|
+
proxies=self.proxy,
|
145
|
+
cert=self.cert,
|
146
|
+
verify=self.ca_cert,
|
127
147
|
)
|
128
148
|
if r.status_code == 200:
|
129
149
|
with open(destination, "wb", 0) as dst:
|
pyreposync/sync_deb822.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
from shutil import copyfile
|
2
|
+
import threading
|
2
3
|
|
3
4
|
import gzip
|
5
|
+
import lzma
|
4
6
|
import os
|
5
7
|
|
8
|
+
from pyreposync import OSRepoSyncException
|
6
9
|
from pyreposync.sync_generic import SyncGeneric
|
7
10
|
|
8
11
|
|
@@ -17,6 +20,8 @@ class SyncDeb822(SyncGeneric):
|
|
17
20
|
components,
|
18
21
|
binary_archs,
|
19
22
|
allow_missing_packages,
|
23
|
+
basic_auth_user=None,
|
24
|
+
basic_auth_pass=None,
|
20
25
|
proxy=None,
|
21
26
|
client_cert=None,
|
22
27
|
client_key=None,
|
@@ -28,6 +33,8 @@ class SyncDeb822(SyncGeneric):
|
|
28
33
|
reponame=reponame,
|
29
34
|
date=date,
|
30
35
|
allow_missing_packages=allow_missing_packages,
|
36
|
+
basic_auth_user=basic_auth_user,
|
37
|
+
basic_auth_pass=basic_auth_pass,
|
31
38
|
proxy=proxy,
|
32
39
|
client_cert=client_cert,
|
33
40
|
client_key=client_key,
|
@@ -51,15 +58,34 @@ class SyncDeb822(SyncGeneric):
|
|
51
58
|
return self._components
|
52
59
|
|
53
60
|
def _snap(self):
|
61
|
+
jobs = []
|
54
62
|
for suite in self.suites:
|
55
|
-
|
63
|
+
job = threading.Thread(
|
64
|
+
name=f"{threading.current_thread().name}_{suite}",
|
65
|
+
target=self.snap_suites,
|
66
|
+
kwargs={"suite": suite},
|
67
|
+
)
|
68
|
+
job.start()
|
69
|
+
jobs.append(job)
|
70
|
+
for job in jobs:
|
71
|
+
job.join()
|
56
72
|
|
57
73
|
def snap_suites(self, suite):
|
58
74
|
self.log.info(f"creating snapshot for suite {suite}")
|
59
75
|
self.snap_release(suite=suite)
|
60
76
|
self.snap_release_files(suite=suite)
|
61
|
-
|
62
|
-
|
77
|
+
jobs = []
|
78
|
+
for component in self.components:
|
79
|
+
for arch in self.binary_archs:
|
80
|
+
job = threading.Thread(
|
81
|
+
name=f"{threading.current_thread().name}_{component}_{arch}",
|
82
|
+
target=self.snap_package_binary_files,
|
83
|
+
kwargs={"suite": suite, "component": component, "arch": arch},
|
84
|
+
)
|
85
|
+
job.start()
|
86
|
+
jobs.append(job)
|
87
|
+
for job in jobs:
|
88
|
+
job.join()
|
63
89
|
self.log.info(f"creating snapshot for suite {suite}, done")
|
64
90
|
|
65
91
|
def snap_release(self, suite):
|
@@ -95,11 +121,11 @@ class SyncDeb822(SyncGeneric):
|
|
95
121
|
pass
|
96
122
|
self.log.info(f"creating snapshot for suite {suite} release files, done")
|
97
123
|
|
98
|
-
def snap_package_binary_files(self, suite, arch):
|
124
|
+
def snap_package_binary_files(self, suite, component, arch):
|
99
125
|
self.log.info(
|
100
|
-
f"creating snapshot for suite {suite} arch {arch} package binary files"
|
126
|
+
f"creating snapshot for suite {suite} component {component} arch {arch} package binary files"
|
101
127
|
)
|
102
|
-
packages = self.binary_files_sha256(suite=suite, component=
|
128
|
+
packages = self.binary_files_sha256(suite=suite, component=component, arch=arch)
|
103
129
|
src_path = f"{self.destination}/sync/{self.reponame}"
|
104
130
|
dst_path = f"{self.destination}/snap/{self.reponame}/{self.date}"
|
105
131
|
for filename, sha256_dict in packages.items():
|
@@ -116,16 +142,35 @@ class SyncDeb822(SyncGeneric):
|
|
116
142
|
|
117
143
|
def sync(self):
|
118
144
|
self.log.info("starting thread")
|
145
|
+
jobs = []
|
119
146
|
for suite in self.suites:
|
120
|
-
|
147
|
+
job = threading.Thread(
|
148
|
+
name=f"{threading.current_thread().name}_{suite}",
|
149
|
+
target=self.sync_suites,
|
150
|
+
kwargs={"suite": suite},
|
151
|
+
)
|
152
|
+
job.start()
|
153
|
+
jobs.append(job)
|
154
|
+
for job in jobs:
|
155
|
+
job.join()
|
121
156
|
self.log.info("shutdown thread complete")
|
122
157
|
|
123
158
|
def sync_suites(self, suite):
|
124
159
|
self.log.info(f"syncing suite {suite}")
|
125
160
|
self.sync_release(suite=suite)
|
126
161
|
self.sync_release_files(suite=suite)
|
127
|
-
|
128
|
-
|
162
|
+
jobs = []
|
163
|
+
for component in self.components:
|
164
|
+
for arch in self.binary_archs:
|
165
|
+
job = threading.Thread(
|
166
|
+
name=f"{threading.current_thread().name}_{component}_{arch}",
|
167
|
+
target=self.sync_package_binary_files,
|
168
|
+
kwargs={"suite": suite, "component": component, "arch": arch},
|
169
|
+
)
|
170
|
+
job.start()
|
171
|
+
jobs.append(job)
|
172
|
+
for job in jobs:
|
173
|
+
job.join()
|
129
174
|
self.log.info(f"syncing suite {suite}, done")
|
130
175
|
|
131
176
|
def sync_release(self, suite):
|
@@ -142,9 +187,9 @@ class SyncDeb822(SyncGeneric):
|
|
142
187
|
)
|
143
188
|
self.log.info(f"syncing suite {suite} release files, done")
|
144
189
|
|
145
|
-
def sync_package_binary_files(self, suite, arch):
|
190
|
+
def sync_package_binary_files(self, suite, component, arch):
|
146
191
|
self.log.info(f"syncing suite {suite} arch {arch} package binary files")
|
147
|
-
packages = self.binary_files_sha256(suite=suite, component=
|
192
|
+
packages = self.binary_files_sha256(suite=suite, component=component, arch=arch)
|
148
193
|
base_path = f"{self.destination}/sync/{self.reponame}"
|
149
194
|
base_url = f"{self.base_url}"
|
150
195
|
for filename, sha256_dict in packages.items():
|
@@ -158,12 +203,26 @@ class SyncDeb822(SyncGeneric):
|
|
158
203
|
self.log.info(f"syncing suite {suite} arch {arch} package binary files, done")
|
159
204
|
|
160
205
|
def binary_files_sha256(self, suite, component, arch):
|
161
|
-
|
206
|
+
packages_file = f"{self.destination}/sync/{self.reponame}/dists/{suite}/{component}/binary-{arch}/Packages."
|
207
|
+
if os.path.isfile(f"{packages_file}gz"):
|
208
|
+
comp = gzip
|
209
|
+
packages_file += "gz"
|
210
|
+
elif os.path.isfile(f"{packages_file}xz"):
|
211
|
+
comp = lzma
|
212
|
+
packages_file += "xz"
|
213
|
+
else:
|
214
|
+
self.log.error(
|
215
|
+
f"no Packages.gz or Packages.xz file found for suite {suite}, component {component}, arch {arch}"
|
216
|
+
)
|
217
|
+
raise OSRepoSyncException(
|
218
|
+
f"no Packages.gz or Packages.xz file found for suite {suite}, component {component}, arch {arch}"
|
219
|
+
)
|
220
|
+
|
162
221
|
packages = dict()
|
163
222
|
sha256 = None
|
164
223
|
filename = None
|
165
224
|
size = None
|
166
|
-
with
|
225
|
+
with comp.open(packages_file, "rb") as source:
|
167
226
|
for line in source:
|
168
227
|
line = line.decode("utf-8")
|
169
228
|
if line.startswith("SHA256: "):
|
pyreposync/sync_generic.py
CHANGED
@@ -14,6 +14,8 @@ class SyncGeneric:
|
|
14
14
|
reponame,
|
15
15
|
date,
|
16
16
|
allow_missing_packages,
|
17
|
+
basic_auth_user=None,
|
18
|
+
basic_auth_pass=None,
|
17
19
|
proxy=None,
|
18
20
|
client_cert=None,
|
19
21
|
client_key=None,
|
@@ -25,7 +27,12 @@ class SyncGeneric:
|
|
25
27
|
self._destination = destination
|
26
28
|
self._reponame = reponame
|
27
29
|
self.downloader = Downloader(
|
28
|
-
|
30
|
+
basic_auth_user=basic_auth_user,
|
31
|
+
basic_auth_pass=basic_auth_pass,
|
32
|
+
proxy=proxy,
|
33
|
+
client_cert=client_cert,
|
34
|
+
client_key=client_key,
|
35
|
+
ca_cert=ca_cert,
|
29
36
|
)
|
30
37
|
self.log = logging.getLogger("application")
|
31
38
|
|
pyreposync/sync_rpm.py
CHANGED
@@ -24,6 +24,8 @@ class SyncRPM(SyncGeneric):
|
|
24
24
|
date,
|
25
25
|
treeinfo,
|
26
26
|
allow_missing_packages,
|
27
|
+
basic_auth_user=None,
|
28
|
+
basic_auth_pass=None,
|
27
29
|
proxy=None,
|
28
30
|
client_cert=None,
|
29
31
|
client_key=None,
|
@@ -35,6 +37,8 @@ class SyncRPM(SyncGeneric):
|
|
35
37
|
reponame=reponame,
|
36
38
|
date=date,
|
37
39
|
allow_missing_packages=allow_missing_packages,
|
40
|
+
basic_auth_user=basic_auth_user,
|
41
|
+
basic_auth_pass=basic_auth_pass,
|
38
42
|
proxy=proxy,
|
39
43
|
client_cert=client_cert,
|
40
44
|
client_key=client_key,
|
@@ -248,14 +252,15 @@ class SyncRPM(SyncGeneric):
|
|
248
252
|
def snap_treeinfo(self):
|
249
253
|
self.log.info("copy treeinfo")
|
250
254
|
try:
|
251
|
-
dst = f"{self.destination}/snap/{self.reponame}/{self.
|
255
|
+
dst = f"{self.destination}/snap/{self.reponame}/{self.date}/{self.treeinfo}"
|
252
256
|
src = f"{self.destination}/sync/{self.reponame}/{self.treeinfo}"
|
253
257
|
copyfile(src, dst)
|
254
258
|
except (OSError, FileNotFoundError) as err:
|
255
259
|
self.log.error(f"could not copy {self.treeinfo}: {err}")
|
260
|
+
self.log.error(dst)
|
256
261
|
for location, hash_algo, hash_sum in self.treeinfo_files():
|
257
262
|
dst = (
|
258
|
-
f"{self.destination}/snap/{self.reponame}/{self.
|
263
|
+
f"{self.destination}/snap/{self.reponame}/{self.date}/{location}"
|
259
264
|
)
|
260
265
|
src = f"{self.destination}/sync/{self.reponame}/{location}"
|
261
266
|
try:
|
@@ -0,0 +1,11 @@
|
|
1
|
+
pyreposync/__init__.py,sha256=fHirsBBkEk806RJwVKQZHgujQZRk13YnokX-8rp_QJE,17117
|
2
|
+
pyreposync/downloader.py,sha256=rEv9lOg2X1VwCtADO63-yceZAZCeSJOBIGbyRsEnKQU,5275
|
3
|
+
pyreposync/exceptions.py,sha256=IlnvhNaffQQ6geOgrjCciNFVbFpNcycH4ijSuMTbrGA,169
|
4
|
+
pyreposync/sync_deb822.py,sha256=7Cuzg-1pC8WDiFTxw-qH26VsfzOEY9IxfZztGfLkdKg,10513
|
5
|
+
pyreposync/sync_generic.py,sha256=qe-ERp8O2kCnhOuToSZWhdQzGY7aYb7G7nUxuKD3lxY,5880
|
6
|
+
pyreposync/sync_rpm.py,sha256=bl1mVX8LZt5AF33o-oVsmaNwzC9teLN-quQMkQrwyUk,11781
|
7
|
+
pyreposync-0.2.8.dist-info/METADATA,sha256=4ZJYmZtU02e0YaE1-awb39qUPIwAqKwl2fdhiyGfimY,1591
|
8
|
+
pyreposync-0.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
+
pyreposync-0.2.8.dist-info/entry_points.txt,sha256=9LsBDWOF3O6_3ONP3Lc-4v1MTt5ay0Xv-TMcFbOIt2s,47
|
10
|
+
pyreposync-0.2.8.dist-info/licenses/LICENSE.txt,sha256=lwnJoIo7uwc0h6y6gC_RYqJkvjplViV3Ad6u7pQM4Bw,1084
|
11
|
+
pyreposync-0.2.8.dist-info/RECORD,,
|
@@ -1,11 +0,0 @@
|
|
1
|
-
pyreposync/__init__.py,sha256=hhsb3ZqssxKAcSZ_rEiG_2XjgbRK1SveMtL_sI9pMnI,16577
|
2
|
-
pyreposync/downloader.py,sha256=828bIMCctd1X6I1w91-XHytQ1M5fmxkEw0YDKd5nvAY,4764
|
3
|
-
pyreposync/exceptions.py,sha256=IlnvhNaffQQ6geOgrjCciNFVbFpNcycH4ijSuMTbrGA,169
|
4
|
-
pyreposync/sync_deb822.py,sha256=XkIZfYfgshYFwdk1oL8TsysUge2_6iPiz5zOmKNaZRk,8367
|
5
|
-
pyreposync/sync_generic.py,sha256=wN5hPcIacvQiMQoajcf7WSbiBGqxI86CYwfVnq1fR38,5693
|
6
|
-
pyreposync/sync_rpm.py,sha256=1yf2-lQShKyY3CI_FW1i0tyWQ0sg69iBUn-4iWfoevk,11613
|
7
|
-
pyreposync-0.2.6.dist-info/METADATA,sha256=_iKcUStZxLy2goNOQgaIMgRE3CzmG34iDz-nXKN51Jw,1591
|
8
|
-
pyreposync-0.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
-
pyreposync-0.2.6.dist-info/entry_points.txt,sha256=9LsBDWOF3O6_3ONP3Lc-4v1MTt5ay0Xv-TMcFbOIt2s,47
|
10
|
-
pyreposync-0.2.6.dist-info/licenses/LICENSE.txt,sha256=lwnJoIo7uwc0h6y6gC_RYqJkvjplViV3Ad6u7pQM4Bw,1084
|
11
|
-
pyreposync-0.2.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|