opensipscli 0.3.1__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.
- opensipscli/__init__.py +20 -0
- opensipscli/args.py +56 -0
- opensipscli/cli.py +472 -0
- opensipscli/comm.py +57 -0
- opensipscli/config.py +162 -0
- opensipscli/db.py +989 -0
- opensipscli/defaults.py +91 -0
- opensipscli/libs/__init__.py +20 -0
- opensipscli/libs/sqlalchemy_utils.py +244 -0
- opensipscli/logger.py +85 -0
- opensipscli/main.py +86 -0
- opensipscli/module.py +69 -0
- opensipscli/modules/__init__.py +24 -0
- opensipscli/modules/database.py +1062 -0
- opensipscli/modules/diagnose.py +1089 -0
- opensipscli/modules/instance.py +53 -0
- opensipscli/modules/mi.py +200 -0
- opensipscli/modules/tls.py +354 -0
- opensipscli/modules/trace.py +292 -0
- opensipscli/modules/trap.py +138 -0
- opensipscli/modules/user.py +281 -0
- opensipscli/version.py +22 -0
- opensipscli-0.3.1.data/scripts/opensips-cli +9 -0
- opensipscli-0.3.1.dist-info/LICENSE +674 -0
- opensipscli-0.3.1.dist-info/METADATA +225 -0
- opensipscli-0.3.1.dist-info/RECORD +28 -0
- opensipscli-0.3.1.dist-info/WHEEL +5 -0
- opensipscli-0.3.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1062 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
##
|
|
3
|
+
## This file is part of OpenSIPS CLI
|
|
4
|
+
## (see https://github.com/OpenSIPS/opensips-cli).
|
|
5
|
+
##
|
|
6
|
+
## This program is free software: you can redistribute it and/or modify
|
|
7
|
+
## it under the terms of the GNU General Public License as published by
|
|
8
|
+
## the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
## (at your option) any later version.
|
|
10
|
+
##
|
|
11
|
+
## This program is distributed in the hope that it will be useful,
|
|
12
|
+
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
## GNU General Public License for more details.
|
|
15
|
+
##
|
|
16
|
+
## You should have received a copy of the GNU General Public License
|
|
17
|
+
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
##
|
|
19
|
+
|
|
20
|
+
from opensipscli.module import Module
|
|
21
|
+
from opensipscli.logger import logger
|
|
22
|
+
from opensipscli.config import cfg
|
|
23
|
+
from opensipscli.db import (
|
|
24
|
+
osdb, osdbError, osdbConnectError,
|
|
25
|
+
osdbArgumentError, osdbNoSuchModuleError,
|
|
26
|
+
osdbModuleAlreadyExistsError, osdbAccessDeniedError,
|
|
27
|
+
SUPPORTED_BACKENDS,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
import os, re
|
|
31
|
+
from getpass import getpass, getuser
|
|
32
|
+
from collections import OrderedDict
|
|
33
|
+
|
|
34
|
+
DEFAULT_DB_TEMPLATE = "template1"
|
|
35
|
+
OPENSIPS_SCHEMA_SRC_PATH = "/usr/local/share/opensips"
|
|
36
|
+
|
|
37
|
+
STANDARD_DB_MODULES = [
|
|
38
|
+
"acc",
|
|
39
|
+
"alias_db",
|
|
40
|
+
"auth_db",
|
|
41
|
+
"avpops",
|
|
42
|
+
"clusterer",
|
|
43
|
+
"dialog",
|
|
44
|
+
"dialplan",
|
|
45
|
+
"dispatcher",
|
|
46
|
+
"domain",
|
|
47
|
+
"drouting",
|
|
48
|
+
"group",
|
|
49
|
+
"load_balancer",
|
|
50
|
+
"msilo",
|
|
51
|
+
"permissions",
|
|
52
|
+
"rtpproxy",
|
|
53
|
+
"rtpengine",
|
|
54
|
+
"speeddial",
|
|
55
|
+
"tls_mgm",
|
|
56
|
+
"usrloc"
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
EXTRA_DB_MODULES = [
|
|
60
|
+
"b2b",
|
|
61
|
+
"b2b_sca",
|
|
62
|
+
"call_center",
|
|
63
|
+
"carrierroute",
|
|
64
|
+
"closeddial",
|
|
65
|
+
"domainpolicy",
|
|
66
|
+
"emergency",
|
|
67
|
+
"fraud_detection",
|
|
68
|
+
"freeswitch_scripting",
|
|
69
|
+
"imc",
|
|
70
|
+
"presence",
|
|
71
|
+
"registrant",
|
|
72
|
+
"rls",
|
|
73
|
+
"smpp",
|
|
74
|
+
"tracer",
|
|
75
|
+
"userblacklist"
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
DB_MIGRATIONS = {
|
|
79
|
+
'3.4_to_3.5': [
|
|
80
|
+
'acc',
|
|
81
|
+
'active_watchers',
|
|
82
|
+
'address',
|
|
83
|
+
'b2b_entities',
|
|
84
|
+
'b2b_logic',
|
|
85
|
+
'b2b_sca',
|
|
86
|
+
'cachedb',
|
|
87
|
+
'carrierfailureroute',
|
|
88
|
+
'carrierroute',
|
|
89
|
+
'cc_agents',
|
|
90
|
+
'cc_calls',
|
|
91
|
+
'cc_cdrs',
|
|
92
|
+
'cc_flows',
|
|
93
|
+
'closeddial',
|
|
94
|
+
'clusterer',
|
|
95
|
+
'cpl',
|
|
96
|
+
'dbaliases',
|
|
97
|
+
'dialog',
|
|
98
|
+
'dialplan',
|
|
99
|
+
'dispatcher',
|
|
100
|
+
'domain',
|
|
101
|
+
'domainpolicy',
|
|
102
|
+
'dr_carriers',
|
|
103
|
+
'dr_gateways',
|
|
104
|
+
'dr_groups',
|
|
105
|
+
'dr_partitions',
|
|
106
|
+
'dr_rules',
|
|
107
|
+
'emergency_report',
|
|
108
|
+
'emergency_routing',
|
|
109
|
+
'emergency_service_provider',
|
|
110
|
+
'fraud_detection',
|
|
111
|
+
'freeswitch',
|
|
112
|
+
'globalblacklist',
|
|
113
|
+
'grp',
|
|
114
|
+
'imc_members',
|
|
115
|
+
'imc_rooms',
|
|
116
|
+
'jwt_profiles',
|
|
117
|
+
'jwt_secrets',
|
|
118
|
+
'load_balancer',
|
|
119
|
+
'location',
|
|
120
|
+
'missed_calls',
|
|
121
|
+
'presentity',
|
|
122
|
+
'pua',
|
|
123
|
+
'qr_profiles',
|
|
124
|
+
'rc_clients',
|
|
125
|
+
'rc_demo_ratesheet',
|
|
126
|
+
'rc_ratesheets',
|
|
127
|
+
'rc_vendors',
|
|
128
|
+
're_grp',
|
|
129
|
+
'registrant',
|
|
130
|
+
'rls_presentity',
|
|
131
|
+
'rls_watchers',
|
|
132
|
+
'route_tree',
|
|
133
|
+
'rtpengine',
|
|
134
|
+
'rtpproxy_sockets',
|
|
135
|
+
'silo',
|
|
136
|
+
'sip_trace',
|
|
137
|
+
'smpp',
|
|
138
|
+
'speed_dial',
|
|
139
|
+
'subscriber',
|
|
140
|
+
'tcp_mgm',
|
|
141
|
+
'tls_mgm',
|
|
142
|
+
'uri',
|
|
143
|
+
'userblacklist',
|
|
144
|
+
'usr_preferences',
|
|
145
|
+
'watchers',
|
|
146
|
+
'xcap',
|
|
147
|
+
],
|
|
148
|
+
|
|
149
|
+
'3.3_to_3.4': [
|
|
150
|
+
'dispatcher', # changed in 3.4
|
|
151
|
+
'cc_agents',
|
|
152
|
+
'acc',
|
|
153
|
+
'active_watchers',
|
|
154
|
+
'address',
|
|
155
|
+
'b2b_entities',
|
|
156
|
+
'b2b_logic',
|
|
157
|
+
'b2b_sca',
|
|
158
|
+
'cachedb',
|
|
159
|
+
'carrierfailureroute',
|
|
160
|
+
'carrierroute',
|
|
161
|
+
'cc_agents',
|
|
162
|
+
'cc_calls',
|
|
163
|
+
'cc_cdrs',
|
|
164
|
+
'cc_flows',
|
|
165
|
+
'closeddial',
|
|
166
|
+
'clusterer',
|
|
167
|
+
'cpl',
|
|
168
|
+
'dbaliases',
|
|
169
|
+
'dialog',
|
|
170
|
+
'dialplan',
|
|
171
|
+
'domain',
|
|
172
|
+
'domainpolicy',
|
|
173
|
+
'dr_carriers',
|
|
174
|
+
'dr_gateways',
|
|
175
|
+
'dr_groups',
|
|
176
|
+
'dr_partitions',
|
|
177
|
+
'dr_rules',
|
|
178
|
+
'emergency_report',
|
|
179
|
+
'emergency_routing',
|
|
180
|
+
'emergency_service_provider',
|
|
181
|
+
'fraud_detection',
|
|
182
|
+
'freeswitch',
|
|
183
|
+
'globalblacklist',
|
|
184
|
+
'grp',
|
|
185
|
+
'imc_members',
|
|
186
|
+
'imc_rooms',
|
|
187
|
+
'jwt_profiles',
|
|
188
|
+
'jwt_secrets',
|
|
189
|
+
'load_balancer',
|
|
190
|
+
'location',
|
|
191
|
+
'missed_calls',
|
|
192
|
+
'presentity',
|
|
193
|
+
'pua',
|
|
194
|
+
'qr_profiles',
|
|
195
|
+
'rc_clients',
|
|
196
|
+
'rc_demo_ratesheet',
|
|
197
|
+
'rc_ratesheets',
|
|
198
|
+
'rc_vendors',
|
|
199
|
+
're_grp',
|
|
200
|
+
'registrant',
|
|
201
|
+
'rls_presentity',
|
|
202
|
+
'rls_watchers',
|
|
203
|
+
'route_tree',
|
|
204
|
+
'rtpengine',
|
|
205
|
+
'rtpproxy_sockets',
|
|
206
|
+
'silo',
|
|
207
|
+
'sip_trace',
|
|
208
|
+
'smpp',
|
|
209
|
+
'speed_dial',
|
|
210
|
+
'subscriber',
|
|
211
|
+
'tcp_mgm',
|
|
212
|
+
'tls_mgm',
|
|
213
|
+
'uri',
|
|
214
|
+
'userblacklist',
|
|
215
|
+
'usr_preferences',
|
|
216
|
+
'watchers',
|
|
217
|
+
'xcap',
|
|
218
|
+
],
|
|
219
|
+
|
|
220
|
+
'3.2_to_3.3': [
|
|
221
|
+
'cc_agents', # changed in 3.3
|
|
222
|
+
'cc_calls' # changed in 3.3
|
|
223
|
+
'cc_cdrs', # changed in 3.3
|
|
224
|
+
'tcp_mgm', # new in 3.3
|
|
225
|
+
'acc',
|
|
226
|
+
'active_watchers',
|
|
227
|
+
'address',
|
|
228
|
+
'b2b_entities',
|
|
229
|
+
'b2b_logic',
|
|
230
|
+
'b2b_sca',
|
|
231
|
+
'cachedb',
|
|
232
|
+
'carrierfailureroute',
|
|
233
|
+
'carrierroute',
|
|
234
|
+
'cc_flows',
|
|
235
|
+
'closeddial',
|
|
236
|
+
'clusterer',
|
|
237
|
+
'cpl',
|
|
238
|
+
'dbaliases',
|
|
239
|
+
'dialog',
|
|
240
|
+
'dialplan',
|
|
241
|
+
'dispatcher',
|
|
242
|
+
'domain',
|
|
243
|
+
'domainpolicy',
|
|
244
|
+
'dr_carriers',
|
|
245
|
+
'dr_gateways',
|
|
246
|
+
'dr_groups',
|
|
247
|
+
'dr_partitions',
|
|
248
|
+
'dr_rules',
|
|
249
|
+
'emergency_report',
|
|
250
|
+
'emergency_routing',
|
|
251
|
+
'emergency_service_provider',
|
|
252
|
+
'fraud_detection',
|
|
253
|
+
'freeswitch',
|
|
254
|
+
'globalblacklist',
|
|
255
|
+
'grp',
|
|
256
|
+
'imc_members',
|
|
257
|
+
'imc_rooms',
|
|
258
|
+
'jwt_profiles',
|
|
259
|
+
'jwt_secrets',
|
|
260
|
+
'load_balancer',
|
|
261
|
+
'location',
|
|
262
|
+
'missed_calls',
|
|
263
|
+
'presentity',
|
|
264
|
+
'pua',
|
|
265
|
+
'qr_profiles',
|
|
266
|
+
'rc_clients',
|
|
267
|
+
'rc_demo_ratesheet',
|
|
268
|
+
'rc_ratesheets',
|
|
269
|
+
'rc_vendors',
|
|
270
|
+
're_grp',
|
|
271
|
+
'registrant',
|
|
272
|
+
'rls_presentity',
|
|
273
|
+
'rls_watchers',
|
|
274
|
+
'route_tree',
|
|
275
|
+
'rtpengine',
|
|
276
|
+
'rtpproxy_sockets',
|
|
277
|
+
'silo',
|
|
278
|
+
'sip_trace',
|
|
279
|
+
'smpp',
|
|
280
|
+
'speed_dial',
|
|
281
|
+
'subscriber',
|
|
282
|
+
'tls_mgm',
|
|
283
|
+
'uri',
|
|
284
|
+
'userblacklist',
|
|
285
|
+
'usr_preferences',
|
|
286
|
+
'watchers',
|
|
287
|
+
'xcap',
|
|
288
|
+
],
|
|
289
|
+
|
|
290
|
+
'3.1_to_3.2': [
|
|
291
|
+
'b2b_logic', # changed in 3.2
|
|
292
|
+
'pua', # changed in 3.2
|
|
293
|
+
'registrant', # changed in 3.2
|
|
294
|
+
'subscriber', # changed in 3.2
|
|
295
|
+
'jwt_profiles', # new in 3.1
|
|
296
|
+
'jwt_secrets', # new in 3.1
|
|
297
|
+
'qr_profiles', # new in 3.1
|
|
298
|
+
'rc_clients', # new in 3.1
|
|
299
|
+
'rc_vendors', # new in 3.1
|
|
300
|
+
'rc_ratesheets', # new in 3.1
|
|
301
|
+
'rc_demo_ratesheet', # new in 3.1
|
|
302
|
+
'acc',
|
|
303
|
+
'active_watchers',
|
|
304
|
+
'address',
|
|
305
|
+
'b2b_entities',
|
|
306
|
+
'b2b_sca',
|
|
307
|
+
'cachedb',
|
|
308
|
+
'carrierfailureroute',
|
|
309
|
+
'carrierroute',
|
|
310
|
+
'cc_agents',
|
|
311
|
+
'cc_calls',
|
|
312
|
+
'cc_cdrs',
|
|
313
|
+
'cc_flows',
|
|
314
|
+
'closeddial',
|
|
315
|
+
'clusterer',
|
|
316
|
+
'cpl',
|
|
317
|
+
'dbaliases',
|
|
318
|
+
'dialog',
|
|
319
|
+
'dialplan',
|
|
320
|
+
'dispatcher',
|
|
321
|
+
'domain',
|
|
322
|
+
'domainpolicy',
|
|
323
|
+
'dr_carriers',
|
|
324
|
+
'dr_gateways',
|
|
325
|
+
'dr_groups',
|
|
326
|
+
'dr_partitions',
|
|
327
|
+
'dr_rules',
|
|
328
|
+
'emergency_report',
|
|
329
|
+
'emergency_routing',
|
|
330
|
+
'emergency_service_provider',
|
|
331
|
+
'fraud_detection',
|
|
332
|
+
'freeswitch',
|
|
333
|
+
'globalblacklist',
|
|
334
|
+
'grp',
|
|
335
|
+
'imc_members',
|
|
336
|
+
'imc_rooms',
|
|
337
|
+
'load_balancer',
|
|
338
|
+
'location',
|
|
339
|
+
'missed_calls',
|
|
340
|
+
'presentity',
|
|
341
|
+
're_grp',
|
|
342
|
+
'rls_presentity',
|
|
343
|
+
'rls_watchers',
|
|
344
|
+
'route_tree',
|
|
345
|
+
'rtpengine',
|
|
346
|
+
'rtpproxy_sockets',
|
|
347
|
+
'silo',
|
|
348
|
+
'sip_trace',
|
|
349
|
+
'smpp',
|
|
350
|
+
'speed_dial',
|
|
351
|
+
'tls_mgm',
|
|
352
|
+
'uri',
|
|
353
|
+
'userblacklist',
|
|
354
|
+
'usr_preferences',
|
|
355
|
+
'watchers',
|
|
356
|
+
'xcap',
|
|
357
|
+
],
|
|
358
|
+
|
|
359
|
+
'3.0_to_3.1': [
|
|
360
|
+
'smpp', # new in 3.0
|
|
361
|
+
'cc_agents', # changed in 3.1
|
|
362
|
+
'cc_calls', # changed in 3.1
|
|
363
|
+
'cc_flows', # changed in 3.1
|
|
364
|
+
'dialog', # changed in 3.1
|
|
365
|
+
'dr_carriers', # changed in 3.1
|
|
366
|
+
'dr_rules', # changed in 3.1
|
|
367
|
+
'load_balancer', # changed in 3.1
|
|
368
|
+
'acc',
|
|
369
|
+
'active_watchers',
|
|
370
|
+
'address',
|
|
371
|
+
'b2b_entities',
|
|
372
|
+
'b2b_logic',
|
|
373
|
+
'b2b_sca',
|
|
374
|
+
'cachedb',
|
|
375
|
+
'carrierfailureroute',
|
|
376
|
+
'carrierroute',
|
|
377
|
+
'cc_cdrs',
|
|
378
|
+
'closeddial',
|
|
379
|
+
'clusterer',
|
|
380
|
+
'cpl',
|
|
381
|
+
'dbaliases',
|
|
382
|
+
'dialplan',
|
|
383
|
+
'dispatcher',
|
|
384
|
+
'domain',
|
|
385
|
+
'domainpolicy',
|
|
386
|
+
'dr_gateways',
|
|
387
|
+
'dr_groups',
|
|
388
|
+
'dr_partitions',
|
|
389
|
+
'emergency_report',
|
|
390
|
+
'emergency_routing',
|
|
391
|
+
'emergency_service_provider',
|
|
392
|
+
'fraud_detection',
|
|
393
|
+
'freeswitch',
|
|
394
|
+
'globalblacklist',
|
|
395
|
+
'grp',
|
|
396
|
+
'imc_members',
|
|
397
|
+
'imc_rooms',
|
|
398
|
+
'location',
|
|
399
|
+
'missed_calls',
|
|
400
|
+
'presentity',
|
|
401
|
+
'pua',
|
|
402
|
+
're_grp',
|
|
403
|
+
'registrant',
|
|
404
|
+
'rls_presentity',
|
|
405
|
+
'rls_watchers',
|
|
406
|
+
'route_tree',
|
|
407
|
+
'rtpengine',
|
|
408
|
+
'rtpproxy_sockets',
|
|
409
|
+
'silo',
|
|
410
|
+
'sip_trace',
|
|
411
|
+
'speed_dial',
|
|
412
|
+
'subscriber',
|
|
413
|
+
'tls_mgm',
|
|
414
|
+
'uri',
|
|
415
|
+
'userblacklist',
|
|
416
|
+
'usr_preferences',
|
|
417
|
+
'watchers',
|
|
418
|
+
'xcap',
|
|
419
|
+
],
|
|
420
|
+
|
|
421
|
+
'2.4_to_3.0': [
|
|
422
|
+
'registrant', # changed in 3.0
|
|
423
|
+
'tls_mgm', # changed in 3.0
|
|
424
|
+
'acc',
|
|
425
|
+
'active_watchers',
|
|
426
|
+
'address',
|
|
427
|
+
'b2b_entities',
|
|
428
|
+
'b2b_logic',
|
|
429
|
+
'b2b_sca',
|
|
430
|
+
'cachedb',
|
|
431
|
+
'carrierfailureroute',
|
|
432
|
+
'carrierroute',
|
|
433
|
+
'cc_agents',
|
|
434
|
+
'cc_calls',
|
|
435
|
+
'cc_cdrs',
|
|
436
|
+
'cc_flows',
|
|
437
|
+
'closeddial',
|
|
438
|
+
'clusterer',
|
|
439
|
+
'cpl',
|
|
440
|
+
'dbaliases',
|
|
441
|
+
'dialog',
|
|
442
|
+
'dialplan',
|
|
443
|
+
'dispatcher',
|
|
444
|
+
'domain',
|
|
445
|
+
'domainpolicy',
|
|
446
|
+
'dr_carriers',
|
|
447
|
+
'dr_gateways',
|
|
448
|
+
'dr_groups',
|
|
449
|
+
'dr_partitions',
|
|
450
|
+
'dr_rules',
|
|
451
|
+
'emergency_report',
|
|
452
|
+
'emergency_routing',
|
|
453
|
+
'emergency_service_provider',
|
|
454
|
+
'fraud_detection',
|
|
455
|
+
'freeswitch',
|
|
456
|
+
'globalblacklist',
|
|
457
|
+
'grp',
|
|
458
|
+
'imc_members',
|
|
459
|
+
'imc_rooms',
|
|
460
|
+
'load_balancer',
|
|
461
|
+
'location',
|
|
462
|
+
'missed_calls',
|
|
463
|
+
'presentity',
|
|
464
|
+
'pua',
|
|
465
|
+
're_grp',
|
|
466
|
+
'rls_presentity',
|
|
467
|
+
'rls_watchers',
|
|
468
|
+
'route_tree',
|
|
469
|
+
'rtpengine',
|
|
470
|
+
'rtpproxy_sockets',
|
|
471
|
+
'silo',
|
|
472
|
+
'sip_trace',
|
|
473
|
+
'speed_dial',
|
|
474
|
+
'subscriber',
|
|
475
|
+
'uri',
|
|
476
|
+
'userblacklist',
|
|
477
|
+
'usr_preferences',
|
|
478
|
+
'watchers',
|
|
479
|
+
'xcap',
|
|
480
|
+
],
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
class database(Module):
|
|
485
|
+
"""
|
|
486
|
+
Class: database modules
|
|
487
|
+
"""
|
|
488
|
+
def __init__(self, *args, **kwargs):
|
|
489
|
+
"""
|
|
490
|
+
Constructor
|
|
491
|
+
"""
|
|
492
|
+
super().__init__(*args, **kwargs)
|
|
493
|
+
self.db_path = None
|
|
494
|
+
|
|
495
|
+
def __complete__(self, command, text, line, begidx, endidx):
|
|
496
|
+
"""
|
|
497
|
+
helper for autocompletion in interactive mode
|
|
498
|
+
"""
|
|
499
|
+
|
|
500
|
+
if command == 'create':
|
|
501
|
+
db_name = ['opensips', 'opensips_test']
|
|
502
|
+
if not text:
|
|
503
|
+
return db_name
|
|
504
|
+
ret = [t for t in db_name if t.startswith(text)]
|
|
505
|
+
elif command == 'add':
|
|
506
|
+
modules = STANDARD_DB_MODULES + EXTRA_DB_MODULES
|
|
507
|
+
if not text:
|
|
508
|
+
return modules
|
|
509
|
+
|
|
510
|
+
ret = [t for t in modules if t.startswith(text)]
|
|
511
|
+
elif command == 'migrate':
|
|
512
|
+
arg = len(line.split())
|
|
513
|
+
if arg == 2 or (arg == 3 and line[-1] != ' '):
|
|
514
|
+
mig_flavours = [f + ' ' for f in DB_MIGRATIONS]
|
|
515
|
+
if not text:
|
|
516
|
+
return mig_flavours
|
|
517
|
+
ret = [t for t in mig_flavours if t.startswith(text)]
|
|
518
|
+
|
|
519
|
+
elif arg == 3 or (arg == 4 and line[-1] != ' '):
|
|
520
|
+
db_source = ['opensips ']
|
|
521
|
+
if not text:
|
|
522
|
+
return db_source
|
|
523
|
+
ret = [t for t in db_source if t.startswith(text)]
|
|
524
|
+
|
|
525
|
+
elif arg == 4 or (arg == 5 and line[-1] != ' '):
|
|
526
|
+
db_dest = ['opensips_new ']
|
|
527
|
+
if not text:
|
|
528
|
+
return db_dest
|
|
529
|
+
ret = [t for t in db_dest if t.startswith(text)]
|
|
530
|
+
|
|
531
|
+
return ret or ['']
|
|
532
|
+
|
|
533
|
+
def __exclude__(self):
|
|
534
|
+
"""
|
|
535
|
+
method exlusion list
|
|
536
|
+
"""
|
|
537
|
+
if cfg.exists("database_url"):
|
|
538
|
+
db_url = cfg.get("database_url")
|
|
539
|
+
return (not osdb.has_dialect(osdb.get_dialect(db_url)), None)
|
|
540
|
+
else:
|
|
541
|
+
return (not osdb.has_sqlalchemy(), None)
|
|
542
|
+
|
|
543
|
+
def __get_methods__(self):
|
|
544
|
+
"""
|
|
545
|
+
methods available for autocompletion
|
|
546
|
+
"""
|
|
547
|
+
return [
|
|
548
|
+
'create',
|
|
549
|
+
'drop',
|
|
550
|
+
'add',
|
|
551
|
+
'migrate',
|
|
552
|
+
]
|
|
553
|
+
|
|
554
|
+
def get_db_url(self, db_name=cfg.get('database_name')):
|
|
555
|
+
engine = osdb.get_db_engine()
|
|
556
|
+
if not engine:
|
|
557
|
+
return None
|
|
558
|
+
|
|
559
|
+
# make sure to inherit the 'database_admin_url' engine + host
|
|
560
|
+
db_url = osdb.set_url_driver(cfg.get("database_url"), engine)
|
|
561
|
+
db_url = osdb.set_url_host(db_url, osdb.get_db_host())
|
|
562
|
+
|
|
563
|
+
logger.debug("DB URL: '{}'".format(db_url))
|
|
564
|
+
return db_url
|
|
565
|
+
|
|
566
|
+
def get_admin_db_url(self, db_name):
|
|
567
|
+
engine = osdb.get_db_engine()
|
|
568
|
+
if not engine:
|
|
569
|
+
return None
|
|
570
|
+
|
|
571
|
+
if cfg.exists('database_admin_url'):
|
|
572
|
+
admin_url = cfg.get("database_admin_url")
|
|
573
|
+
if engine == "postgresql":
|
|
574
|
+
admin_url = osdb.set_url_db(admin_url, 'postgres')
|
|
575
|
+
else:
|
|
576
|
+
admin_url = osdb.set_url_db(admin_url, None)
|
|
577
|
+
else:
|
|
578
|
+
if engine == 'postgresql':
|
|
579
|
+
if getuser() != "postgres":
|
|
580
|
+
logger.error("Command must be run as 'postgres' user: "
|
|
581
|
+
"sudo -u postgres opensips-cli ...")
|
|
582
|
+
return None
|
|
583
|
+
|
|
584
|
+
"""
|
|
585
|
+
For PG, do the initial setup using 'postgres' as role + DB
|
|
586
|
+
"""
|
|
587
|
+
admin_url = "postgresql://postgres@localhost/postgres"
|
|
588
|
+
else:
|
|
589
|
+
admin_url = "{}://root@localhost".format(engine)
|
|
590
|
+
|
|
591
|
+
if osdb.get_url_pswd(admin_url) is None:
|
|
592
|
+
pswd = getpass("Password for admin {} user ({}): ".format(
|
|
593
|
+
osdb.get_url_driver(admin_url, capitalize=True),
|
|
594
|
+
osdb.get_url_user(admin_url)))
|
|
595
|
+
logger.debug("read password: '%s'", pswd)
|
|
596
|
+
admin_url = osdb.set_url_password(admin_url, pswd)
|
|
597
|
+
|
|
598
|
+
logger.debug("admin DB URL: '{}'".format(admin_url))
|
|
599
|
+
return admin_url
|
|
600
|
+
|
|
601
|
+
def do_add(self, params, modifiers=None):
|
|
602
|
+
"""
|
|
603
|
+
add a given table to the database (connection via URL)
|
|
604
|
+
"""
|
|
605
|
+
if len(params) < 1:
|
|
606
|
+
logger.error("Please specify a module to add (e.g. dialog)")
|
|
607
|
+
return -1
|
|
608
|
+
module = params[0]
|
|
609
|
+
|
|
610
|
+
if len(params) < 2:
|
|
611
|
+
db_name = cfg.read_param("database_name",
|
|
612
|
+
"Please provide the database to add the module to")
|
|
613
|
+
else:
|
|
614
|
+
db_name = params[1]
|
|
615
|
+
|
|
616
|
+
db_url = self.get_db_url(db_name)
|
|
617
|
+
if not db_url:
|
|
618
|
+
logger.error("no DB URL specified: aborting!")
|
|
619
|
+
return -1
|
|
620
|
+
|
|
621
|
+
engine = osdb.get_db_engine()
|
|
622
|
+
if not engine:
|
|
623
|
+
return -1
|
|
624
|
+
|
|
625
|
+
if engine != 'sqlite':
|
|
626
|
+
admin_url = self.get_admin_db_url(db_name)
|
|
627
|
+
if not admin_url:
|
|
628
|
+
return -1
|
|
629
|
+
|
|
630
|
+
db = self.get_db(admin_url if engine != 'sqlite' else db_url, db_name)
|
|
631
|
+
if not db:
|
|
632
|
+
return -1
|
|
633
|
+
|
|
634
|
+
if engine == 'sqlite' and not db.exists(db_name):
|
|
635
|
+
logger.error("database '%s' does not exist!", db_name)
|
|
636
|
+
return -1
|
|
637
|
+
|
|
638
|
+
ret = self.create_tables(db_name, db_url, db, tables=[module],
|
|
639
|
+
create_std=False)
|
|
640
|
+
|
|
641
|
+
db.destroy()
|
|
642
|
+
return ret
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def do_create(self, params=None, modifiers=None):
|
|
646
|
+
"""
|
|
647
|
+
create database with role-assigment and tables
|
|
648
|
+
"""
|
|
649
|
+
if len(params) >= 1:
|
|
650
|
+
db_name = params[0]
|
|
651
|
+
else:
|
|
652
|
+
db_name = cfg.read_param("database_name",
|
|
653
|
+
"Please provide the database to create")
|
|
654
|
+
logger.debug("db_name: '%s'", db_name)
|
|
655
|
+
|
|
656
|
+
engine = osdb.get_db_engine()
|
|
657
|
+
if not engine:
|
|
658
|
+
return -1
|
|
659
|
+
|
|
660
|
+
if engine != 'sqlite':
|
|
661
|
+
admin_url = self.get_admin_db_url(db_name)
|
|
662
|
+
if not admin_url:
|
|
663
|
+
return -1
|
|
664
|
+
|
|
665
|
+
db_url = self.get_db_url(db_name)
|
|
666
|
+
if not db_url:
|
|
667
|
+
return -1
|
|
668
|
+
|
|
669
|
+
db = self.get_db(admin_url if engine != 'sqlite' else db_url, db_name)
|
|
670
|
+
if not db:
|
|
671
|
+
return -1
|
|
672
|
+
|
|
673
|
+
if self.create_db(db_name, \
|
|
674
|
+
admin_url if engine != 'sqlite' else db_url, db) < 0:
|
|
675
|
+
return -1
|
|
676
|
+
|
|
677
|
+
if self.ensure_user(db_url, db_name, db) < 0:
|
|
678
|
+
return -1
|
|
679
|
+
|
|
680
|
+
if self.create_tables(db_name, db_url, db) < 0:
|
|
681
|
+
return -1
|
|
682
|
+
|
|
683
|
+
db.destroy()
|
|
684
|
+
return 0
|
|
685
|
+
|
|
686
|
+
def create_db(self, db_name, admin_url, db=None):
|
|
687
|
+
# 1) create an object store database instance
|
|
688
|
+
# -> use it to create the database itself
|
|
689
|
+
if not db:
|
|
690
|
+
db = self.get_db(admin_url, db_name)
|
|
691
|
+
if not db:
|
|
692
|
+
return -1
|
|
693
|
+
destroy = True
|
|
694
|
+
else:
|
|
695
|
+
destroy = False
|
|
696
|
+
|
|
697
|
+
# check to see if the database has already been created
|
|
698
|
+
if db.exists(db_name):
|
|
699
|
+
logger.warn("database '%s' already exists!", db_name)
|
|
700
|
+
return -2
|
|
701
|
+
|
|
702
|
+
# create the db instance
|
|
703
|
+
if not db.create(db_name):
|
|
704
|
+
return -1
|
|
705
|
+
|
|
706
|
+
if destroy:
|
|
707
|
+
db.destroy()
|
|
708
|
+
return 0
|
|
709
|
+
|
|
710
|
+
def create_tables(self, db_name, db_url, admin_db, tables=[],
|
|
711
|
+
create_std=True):
|
|
712
|
+
"""
|
|
713
|
+
create database tables
|
|
714
|
+
"""
|
|
715
|
+
if admin_db.dialect != "sqlite":
|
|
716
|
+
db_url = osdb.set_url_db(db_url, db_name)
|
|
717
|
+
else:
|
|
718
|
+
db_url = 'sqlite:///' + db_name
|
|
719
|
+
|
|
720
|
+
# 2) prepare new object store database instance
|
|
721
|
+
# use it to connect to the created database
|
|
722
|
+
db = self.get_db(db_url, db_name)
|
|
723
|
+
if db is None:
|
|
724
|
+
return -1
|
|
725
|
+
|
|
726
|
+
if admin_db.dialect != "sqlite" and not db.exists():
|
|
727
|
+
logger.warning("database '{}' does not exist!".format(db_name))
|
|
728
|
+
return -1
|
|
729
|
+
|
|
730
|
+
schema_path = self.get_schema_path(db.dialect)
|
|
731
|
+
if schema_path is None:
|
|
732
|
+
return -1
|
|
733
|
+
|
|
734
|
+
table_files = OrderedDict()
|
|
735
|
+
|
|
736
|
+
if create_std:
|
|
737
|
+
standard_file_path = os.path.join(schema_path, "standard-create.sql")
|
|
738
|
+
if not os.path.isfile(standard_file_path):
|
|
739
|
+
logger.error("cannot find stardard OpenSIPS DB file: '{}'!".
|
|
740
|
+
format(standard_file_path))
|
|
741
|
+
return -1
|
|
742
|
+
table_files['standard'] = standard_file_path
|
|
743
|
+
|
|
744
|
+
# check to see what tables we shall deploy
|
|
745
|
+
if tables:
|
|
746
|
+
pass
|
|
747
|
+
elif cfg.exists("database_modules"):
|
|
748
|
+
# we know exactly what modules we want to instsall
|
|
749
|
+
tables_line = cfg.get("database_modules").strip().lower()
|
|
750
|
+
if tables_line == "all":
|
|
751
|
+
logger.debug("Creating all tables")
|
|
752
|
+
tables = [ f.replace('-create.sql', '') \
|
|
753
|
+
for f in os.listdir(schema_path) \
|
|
754
|
+
if os.path.isfile(os.path.join(schema_path, f)) and \
|
|
755
|
+
f.endswith('-create.sql') ]
|
|
756
|
+
else:
|
|
757
|
+
logger.debug("Creating custom tables")
|
|
758
|
+
tables = tables_line.split(" ")
|
|
759
|
+
else:
|
|
760
|
+
logger.debug("Creating standard tables")
|
|
761
|
+
tables = STANDARD_DB_MODULES
|
|
762
|
+
|
|
763
|
+
# check for corresponding SQL schemas files in system path
|
|
764
|
+
logger.debug("checking tables: {}".format(" ".join(tables)))
|
|
765
|
+
|
|
766
|
+
for table in tables:
|
|
767
|
+
if table == "standard":
|
|
768
|
+
# already checked for it
|
|
769
|
+
continue
|
|
770
|
+
table_file_path = os.path.join(schema_path,
|
|
771
|
+
"{}-create.sql".format(table))
|
|
772
|
+
if not os.path.isfile(table_file_path):
|
|
773
|
+
logger.warn("cannot find SQL file for module {}: {}".
|
|
774
|
+
format(table, table_file_path))
|
|
775
|
+
else:
|
|
776
|
+
table_files[table] = table_file_path
|
|
777
|
+
|
|
778
|
+
username = osdb.get_url_user(db_url)
|
|
779
|
+
admin_db.connect(db_name)
|
|
780
|
+
|
|
781
|
+
if db.dialect == "postgresql":
|
|
782
|
+
self.pg_grant_schema(username, admin_db)
|
|
783
|
+
|
|
784
|
+
# create tables from SQL schemas
|
|
785
|
+
for module, table_file in table_files.items():
|
|
786
|
+
logger.info("Running {}...".format(os.path.basename(table_file)))
|
|
787
|
+
try:
|
|
788
|
+
db.create_module(table_file)
|
|
789
|
+
if db.dialect == "postgresql":
|
|
790
|
+
self.pg_grant_table_access(table_file, username, admin_db)
|
|
791
|
+
except osdbModuleAlreadyExistsError:
|
|
792
|
+
logger.error("{} table(s) are already created!".format(module))
|
|
793
|
+
except osdbError as ex:
|
|
794
|
+
logger.error("cannot import: {}".format(ex))
|
|
795
|
+
|
|
796
|
+
# terminate active database connection
|
|
797
|
+
db.destroy()
|
|
798
|
+
return 0
|
|
799
|
+
|
|
800
|
+
def ensure_user(self, db_url, db_name, admin_db):
|
|
801
|
+
"""
|
|
802
|
+
Ensures that the user/password in @db_url can connect to @db_name.
|
|
803
|
+
It assumes @db_name has been created beforehand. If the user doesn't
|
|
804
|
+
exist or has insufficient permissions, this will be fixed using the
|
|
805
|
+
@admin_db connection.
|
|
806
|
+
"""
|
|
807
|
+
if admin_db.dialect != "sqlite":
|
|
808
|
+
db_url = osdb.set_url_db(db_url, db_name)
|
|
809
|
+
else:
|
|
810
|
+
db_url = 'sqlite:///' + db_name
|
|
811
|
+
|
|
812
|
+
try:
|
|
813
|
+
db = self.get_db(db_url, db_name, check_access=True)
|
|
814
|
+
logger.info("connected to DB, '%s' user is already created",
|
|
815
|
+
osdb.get_url_user(db_url))
|
|
816
|
+
except osdbAccessDeniedError:
|
|
817
|
+
logger.info("creating access user for {} ...".format(db_name))
|
|
818
|
+
if not admin_db.ensure_user(db_url):
|
|
819
|
+
logger.error("failed to create user on {} DB".format(db_name))
|
|
820
|
+
return -1
|
|
821
|
+
|
|
822
|
+
db = self.get_db(db_url, db_name, cfg_url_param='database_url')
|
|
823
|
+
if db is None:
|
|
824
|
+
return -1
|
|
825
|
+
|
|
826
|
+
db.destroy()
|
|
827
|
+
return 0
|
|
828
|
+
|
|
829
|
+
def do_drop(self, params=None, modifiers=None):
|
|
830
|
+
"""
|
|
831
|
+
drop a given database object (connection via URL)
|
|
832
|
+
For PostgreSQL, perform this operation using 'postgres' as role + DB
|
|
833
|
+
"""
|
|
834
|
+
if params and len(params) > 0:
|
|
835
|
+
db_name = params[0]
|
|
836
|
+
else:
|
|
837
|
+
db_name = cfg.read_param("database_name",
|
|
838
|
+
"Please provide the database to drop")
|
|
839
|
+
|
|
840
|
+
engine = osdb.get_db_engine()
|
|
841
|
+
if not engine:
|
|
842
|
+
return -1
|
|
843
|
+
|
|
844
|
+
if engine != 'sqlite':
|
|
845
|
+
db_url = self.get_admin_db_url(db_name)
|
|
846
|
+
if db_url is None:
|
|
847
|
+
return -1
|
|
848
|
+
|
|
849
|
+
if db_url.lower().startswith("postgresql"):
|
|
850
|
+
db_url = osdb.set_url_db(db_url, 'postgres')
|
|
851
|
+
else:
|
|
852
|
+
db_url = self.get_db_url(db_name)
|
|
853
|
+
if not db_url:
|
|
854
|
+
return -1
|
|
855
|
+
|
|
856
|
+
# create an object store database instance
|
|
857
|
+
db = self.get_db(db_url, db_name)
|
|
858
|
+
if db is None:
|
|
859
|
+
return -1
|
|
860
|
+
|
|
861
|
+
# check to see if the database has already been created
|
|
862
|
+
if db.exists():
|
|
863
|
+
if cfg.read_param("database_force_drop",
|
|
864
|
+
"Do you really want to drop the '{}' database".
|
|
865
|
+
format(db_name),
|
|
866
|
+
False, True, isbool=True):
|
|
867
|
+
|
|
868
|
+
if db.drop():
|
|
869
|
+
logger.info("database '%s' dropped!", db_name)
|
|
870
|
+
else:
|
|
871
|
+
logger.info("database '%s' not dropped!", db_name)
|
|
872
|
+
else:
|
|
873
|
+
logger.info("database '{}' not dropped!".format(db_name))
|
|
874
|
+
else:
|
|
875
|
+
logger.warning("database '{}' does not exist!".format(db_name))
|
|
876
|
+
db.destroy()
|
|
877
|
+
return -1
|
|
878
|
+
|
|
879
|
+
db.destroy()
|
|
880
|
+
return 0
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
def do_migrate(self, params, modifiers=None):
|
|
884
|
+
if len(params) < 3:
|
|
885
|
+
print("Usage: database migrate <flavour> <old-database> <new-database>")
|
|
886
|
+
return 0
|
|
887
|
+
|
|
888
|
+
flavour = params[0].lower()
|
|
889
|
+
old_db = params[1]
|
|
890
|
+
new_db = params[2]
|
|
891
|
+
|
|
892
|
+
if flavour not in DB_MIGRATIONS:
|
|
893
|
+
logger.error("unsupported migration flavour: {}".format(flavour))
|
|
894
|
+
return -1
|
|
895
|
+
|
|
896
|
+
admin_url = self.get_admin_db_url(new_db)
|
|
897
|
+
if not admin_url:
|
|
898
|
+
return -1
|
|
899
|
+
|
|
900
|
+
db = self.get_db(admin_url, new_db)
|
|
901
|
+
if not db:
|
|
902
|
+
return -1
|
|
903
|
+
|
|
904
|
+
if db.dialect != "mysql":
|
|
905
|
+
logger.error("'migrate' is only available for MySQL right now! :(")
|
|
906
|
+
return -1
|
|
907
|
+
|
|
908
|
+
if not db.exists(old_db):
|
|
909
|
+
logger.error("the source database ({}) does not exist!".format(old_db))
|
|
910
|
+
return -2
|
|
911
|
+
|
|
912
|
+
print("Creating database {}...".format(new_db))
|
|
913
|
+
if self.create_db(new_db, admin_url, db) < 0:
|
|
914
|
+
return -1
|
|
915
|
+
if self.create_tables(new_db, admin_url, db) < 0:
|
|
916
|
+
return -1
|
|
917
|
+
|
|
918
|
+
backend = osdb.get_url_driver(admin_url)
|
|
919
|
+
|
|
920
|
+
# obtain the DB schema files for the in-use backend
|
|
921
|
+
schema_path = self.get_schema_path(backend)
|
|
922
|
+
if schema_path is None:
|
|
923
|
+
return -1
|
|
924
|
+
|
|
925
|
+
migrate_scripts = self.get_migrate_scripts_path(backend)
|
|
926
|
+
if migrate_scripts is None:
|
|
927
|
+
logger.debug("migration scripts for %s not found", backend)
|
|
928
|
+
return -1
|
|
929
|
+
else:
|
|
930
|
+
logger.debug("found migration scripts for %s", backend)
|
|
931
|
+
|
|
932
|
+
logger.info("Migrating all matching OpenSIPS tables...")
|
|
933
|
+
db.migrate(flavour.replace('.', '_').upper(),
|
|
934
|
+
migrate_scripts, old_db, new_db, DB_MIGRATIONS[flavour])
|
|
935
|
+
|
|
936
|
+
db.destroy()
|
|
937
|
+
return True
|
|
938
|
+
|
|
939
|
+
def get_db(self, db_url, db_name, cfg_url_param="database_admin_url",
|
|
940
|
+
check_access=False):
|
|
941
|
+
"""
|
|
942
|
+
helper function: check database url and its dialect
|
|
943
|
+
"""
|
|
944
|
+
try:
|
|
945
|
+
return osdb(db_url, db_name)
|
|
946
|
+
except osdbAccessDeniedError:
|
|
947
|
+
if check_access:
|
|
948
|
+
raise
|
|
949
|
+
logger.error("failed to connect to DB as %s, please provide or " +
|
|
950
|
+
"fix the '%s'", osdb.get_url_user(db_url), cfg_url_param)
|
|
951
|
+
except osdbArgumentError:
|
|
952
|
+
logger.error("Bad URL, it should resemble: {}".format(
|
|
953
|
+
"backend://user:pass@hostname" if not \
|
|
954
|
+
db_url.startswith('sqlite:') else "sqlite:////path/to/db"))
|
|
955
|
+
except osdbConnectError:
|
|
956
|
+
logger.error("Failed to connect to database!")
|
|
957
|
+
except osdbNoSuchModuleError:
|
|
958
|
+
logger.error("This database backend is not supported! " \
|
|
959
|
+
"Supported: {}".format(', '.join(SUPPORTED_BACKENDS)))
|
|
960
|
+
|
|
961
|
+
def get_migrate_scripts_path(self, backend="mysql"):
|
|
962
|
+
"""
|
|
963
|
+
helper function: migrate database schema
|
|
964
|
+
"""
|
|
965
|
+
if '+' in backend:
|
|
966
|
+
backend = backend[0:backend.index('+')]
|
|
967
|
+
|
|
968
|
+
if self.db_path is not None:
|
|
969
|
+
scripts = [
|
|
970
|
+
os.path.join(self.db_path, backend, 'table-migrate.sql'),
|
|
971
|
+
os.path.join(self.db_path, backend, 'db-migrate.sql'),
|
|
972
|
+
]
|
|
973
|
+
|
|
974
|
+
for s in scripts:
|
|
975
|
+
if not os.path.isfile(s):
|
|
976
|
+
logger.error("Missing migration script ({}), please pull" \
|
|
977
|
+
" the latest OpenSIPS {} module package!".format(
|
|
978
|
+
s, backend))
|
|
979
|
+
return None
|
|
980
|
+
|
|
981
|
+
return scripts
|
|
982
|
+
|
|
983
|
+
def get_schema_path(self, backend="mysql"):
|
|
984
|
+
"""
|
|
985
|
+
helper function: get the path defining the root path holding sql schema template
|
|
986
|
+
"""
|
|
987
|
+
if '+' in backend:
|
|
988
|
+
backend = backend[0:backend.index('+')]
|
|
989
|
+
|
|
990
|
+
if self.db_path is not None:
|
|
991
|
+
return os.path.join(self.db_path, backend)
|
|
992
|
+
|
|
993
|
+
db_path = os.path.expanduser(cfg.get("database_schema_path"))
|
|
994
|
+
|
|
995
|
+
if db_path.endswith('/'):
|
|
996
|
+
db_path = db_path[:-1]
|
|
997
|
+
if os.path.basename(db_path) == backend:
|
|
998
|
+
db_path = os.path.dirname(db_path)
|
|
999
|
+
|
|
1000
|
+
if not os.path.exists(db_path):
|
|
1001
|
+
if not os.path.exists(OPENSIPS_SCHEMA_SRC_PATH):
|
|
1002
|
+
logger.error("path '{}' to OpenSIPS DB scripts does not exist!".
|
|
1003
|
+
format(db_path))
|
|
1004
|
+
return None
|
|
1005
|
+
|
|
1006
|
+
logger.info("schema path '{}' not found, using '{}' instead (detected on system)".
|
|
1007
|
+
format(db_path, OPENSIPS_SCHEMA_SRC_PATH))
|
|
1008
|
+
db_path = OPENSIPS_SCHEMA_SRC_PATH
|
|
1009
|
+
|
|
1010
|
+
if not os.path.isdir(db_path):
|
|
1011
|
+
logger.error("path '{}' to OpenSIPS DB scripts is not a directory!".
|
|
1012
|
+
format(db_path))
|
|
1013
|
+
return None
|
|
1014
|
+
|
|
1015
|
+
def build_schema_path(db_path, backend):
|
|
1016
|
+
"""
|
|
1017
|
+
Replaces schema path of postgresql to old postgre schema path if exists.
|
|
1018
|
+
Should be deleted after opensips main repo refactors folder name to the new backend name.
|
|
1019
|
+
"""
|
|
1020
|
+
if backend == "postgresql":
|
|
1021
|
+
old_postgre_path = os.path.join(db_path, "postgres")
|
|
1022
|
+
if os.path.isdir(old_postgre_path):
|
|
1023
|
+
return old_postgre_path
|
|
1024
|
+
schema_path = os.path.join(db_path, backend)
|
|
1025
|
+
return schema_path
|
|
1026
|
+
|
|
1027
|
+
schema_path = build_schema_path(db_path, backend)
|
|
1028
|
+
if not os.path.isdir(schema_path):
|
|
1029
|
+
logger.error("invalid OpenSIPS DB scripts dir: '{}'!".
|
|
1030
|
+
format(schema_path))
|
|
1031
|
+
return None
|
|
1032
|
+
|
|
1033
|
+
std_tables = os.path.join(schema_path, 'standard-create.sql')
|
|
1034
|
+
if not os.path.isfile(std_tables):
|
|
1035
|
+
logger.error("standard tables file not found ({})".format(std_tables))
|
|
1036
|
+
return None
|
|
1037
|
+
|
|
1038
|
+
self.db_path = db_path
|
|
1039
|
+
return schema_path
|
|
1040
|
+
|
|
1041
|
+
def pg_grant_table_access(self, sql_file, username, admin_db):
|
|
1042
|
+
"""
|
|
1043
|
+
Grant access to all tables and sequence IDs of a DB module
|
|
1044
|
+
"""
|
|
1045
|
+
with open(sql_file, "r") as f:
|
|
1046
|
+
for line in f.readlines():
|
|
1047
|
+
res = re.search('CREATE TABLE (.*) ', line, re.IGNORECASE)
|
|
1048
|
+
if res:
|
|
1049
|
+
table = res.group(1)
|
|
1050
|
+
admin_db.grant_table_options(username, table)
|
|
1051
|
+
|
|
1052
|
+
res = re.search('ALTER SEQUENCE (.*) MAXVALUE', line,
|
|
1053
|
+
re.IGNORECASE)
|
|
1054
|
+
if res:
|
|
1055
|
+
seq = res.group(1)
|
|
1056
|
+
admin_db.grant_table_options(username, seq)
|
|
1057
|
+
|
|
1058
|
+
def pg_grant_schema(self, username, admin_db):
|
|
1059
|
+
"""
|
|
1060
|
+
Grant access to public schema of DB
|
|
1061
|
+
"""
|
|
1062
|
+
admin_db.grant_public_schema(username)
|