synapse 2.185.0__py311-none-any.whl → 2.187.0__py311-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.
Potentially problematic release.
This version of synapse might be problematic. Click here for more details.
- synapse/cortex.py +5 -4
- synapse/exc.py +2 -0
- synapse/lib/ast.py +1 -1
- synapse/lib/cell.py +65 -2
- synapse/lib/drive.py +45 -10
- synapse/lib/hive.py +1 -1
- synapse/lib/modelrev.py +771 -11
- synapse/lib/snap.py +0 -6
- synapse/lib/spooled.py +26 -3
- synapse/lib/storm.py +7 -0
- synapse/lib/stormlib/model.py +320 -250
- synapse/lib/stormtypes.py +36 -10
- synapse/lib/types.py +6 -0
- synapse/lib/version.py +2 -2
- synapse/models/infotech.py +49 -22
- synapse/models/risk.py +3 -0
- synapse/tests/test_cortex.py +10 -5
- synapse/tests/test_lib_base.py +2 -2
- synapse/tests/test_lib_cell.py +16 -4
- synapse/tests/test_lib_modelrev.py +918 -379
- synapse/tests/test_lib_spooled.py +34 -0
- synapse/tests/test_lib_stormlib_model.py +0 -270
- synapse/tests/test_lib_stormtypes.py +11 -0
- synapse/tests/test_model_infotech.py +14 -11
- synapse/tests/test_model_risk.py +2 -0
- synapse/tests/test_tools_snapshot.py +47 -0
- synapse/tools/aha/clone.py +3 -1
- synapse/tools/aha/easycert.py +1 -1
- synapse/tools/aha/enroll.py +3 -1
- synapse/tools/aha/provision/service.py +3 -1
- synapse/tools/aha/provision/user.py +3 -1
- synapse/tools/changelog.py +11 -3
- synapse/tools/livebackup.py +3 -1
- synapse/tools/promote.py +9 -3
- synapse/tools/snapshot.py +69 -0
- {synapse-2.185.0.dist-info → synapse-2.187.0.dist-info}/METADATA +1 -1
- {synapse-2.185.0.dist-info → synapse-2.187.0.dist-info}/RECORD +40 -41
- {synapse-2.185.0.dist-info → synapse-2.187.0.dist-info}/WHEEL +1 -1
- synapse/assets/__init__.py +0 -35
- synapse/assets/storm/migrations/model-0.2.28.storm +0 -355
- synapse/tests/test_assets.py +0 -25
- {synapse-2.185.0.dist-info → synapse-2.187.0.dist-info}/LICENSE +0 -0
- {synapse-2.185.0.dist-info → synapse-2.187.0.dist-info}/top_level.txt +0 -0
synapse/cortex.py
CHANGED
|
@@ -1938,12 +1938,12 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
1938
1938
|
return
|
|
1939
1939
|
|
|
1940
1940
|
async def coreQueuePuts(self, name, items):
|
|
1941
|
-
await self._push('queue:puts', name, items)
|
|
1941
|
+
return await self._push('queue:puts', name, items)
|
|
1942
1942
|
|
|
1943
1943
|
@s_nexus.Pusher.onPush('queue:puts', passitem=True)
|
|
1944
1944
|
async def _coreQueuePuts(self, name, items, nexsitem):
|
|
1945
1945
|
nexsoff, nexsmesg = nexsitem
|
|
1946
|
-
await self.multiqueue.puts(name, items, reqid=nexsoff)
|
|
1946
|
+
return await self.multiqueue.puts(name, items, reqid=nexsoff)
|
|
1947
1947
|
|
|
1948
1948
|
@s_nexus.Pusher.onPushAuto('queue:cull')
|
|
1949
1949
|
async def coreQueueCull(self, name, offs):
|
|
@@ -2056,9 +2056,10 @@ class Cortex(s_oauth.OAuthMixin, s_cell.Cell): # type: ignore
|
|
|
2056
2056
|
continue
|
|
2057
2057
|
|
|
2058
2058
|
if not regex.fullmatch(regx[i], parts[i]):
|
|
2059
|
-
|
|
2059
|
+
mesg = f'Tag part ({parts[i]}) of tag ({tagname}) does not match the tag model regex: [{regx[i]}]'
|
|
2060
|
+
return (False, mesg)
|
|
2060
2061
|
|
|
2061
|
-
return True
|
|
2062
|
+
return (True, None)
|
|
2062
2063
|
|
|
2063
2064
|
async def getTagPrune(self, tagname):
|
|
2064
2065
|
return self.tagprune.get(tagname)
|
synapse/exc.py
CHANGED
synapse/lib/ast.py
CHANGED
|
@@ -4579,7 +4579,7 @@ class EditTagAdd(Edit):
|
|
|
4579
4579
|
else:
|
|
4580
4580
|
oper_offset = 0
|
|
4581
4581
|
|
|
4582
|
-
excignore = (s_exc.BadTypeValu,
|
|
4582
|
+
excignore = (s_exc.BadTypeValu,) if oper_offset == 1 else ()
|
|
4583
4583
|
|
|
4584
4584
|
hasval = len(self.kids) > 2 + oper_offset
|
|
4585
4585
|
|
synapse/lib/cell.py
CHANGED
|
@@ -35,6 +35,7 @@ import synapse.lib.boss as s_boss
|
|
|
35
35
|
import synapse.lib.coro as s_coro
|
|
36
36
|
import synapse.lib.hive as s_hive
|
|
37
37
|
import synapse.lib.link as s_link
|
|
38
|
+
import synapse.lib.task as s_task
|
|
38
39
|
import synapse.lib.cache as s_cache
|
|
39
40
|
import synapse.lib.const as s_const
|
|
40
41
|
import synapse.lib.drive as s_drive
|
|
@@ -206,6 +207,14 @@ class CellApi(s_base.Base):
|
|
|
206
207
|
async def initCellApi(self):
|
|
207
208
|
pass
|
|
208
209
|
|
|
210
|
+
@adminapi(log=True)
|
|
211
|
+
async def freeze(self, timeout=30):
|
|
212
|
+
return await self.cell.freeze(timeout=timeout)
|
|
213
|
+
|
|
214
|
+
@adminapi(log=True)
|
|
215
|
+
async def resume(self):
|
|
216
|
+
return await self.cell.resume()
|
|
217
|
+
|
|
209
218
|
async def allowed(self, perm, default=None):
|
|
210
219
|
'''
|
|
211
220
|
Check if the user has the requested permission.
|
|
@@ -1102,6 +1111,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1102
1111
|
self.auth = None
|
|
1103
1112
|
self.cellparent = parent
|
|
1104
1113
|
self.sessions = {}
|
|
1114
|
+
self.paused = False
|
|
1105
1115
|
self.isactive = False
|
|
1106
1116
|
self.activebase = None
|
|
1107
1117
|
self.inaugural = False
|
|
@@ -1767,8 +1777,11 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1767
1777
|
|
|
1768
1778
|
return await self.drive.addItemInfo(info, path=path, reldir=reldir)
|
|
1769
1779
|
|
|
1770
|
-
async def getDriveInfo(self, iden):
|
|
1771
|
-
return self.drive.getItemInfo(iden)
|
|
1780
|
+
async def getDriveInfo(self, iden, typename=None):
|
|
1781
|
+
return self.drive.getItemInfo(iden, typename=typename)
|
|
1782
|
+
|
|
1783
|
+
def reqDriveInfo(self, iden, typename=None):
|
|
1784
|
+
return self.drive.reqItemInfo(iden, typename=typename)
|
|
1772
1785
|
|
|
1773
1786
|
async def getDrivePath(self, path, reldir=s_drive.rootdir):
|
|
1774
1787
|
'''
|
|
@@ -4461,6 +4474,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4461
4474
|
'run': await self.getCellRunId(),
|
|
4462
4475
|
'type': self.getCellType(),
|
|
4463
4476
|
'iden': self.getCellIden(),
|
|
4477
|
+
'paused': self.paused,
|
|
4464
4478
|
'active': self.isactive,
|
|
4465
4479
|
'started': self.startms,
|
|
4466
4480
|
'ready': self.nexsroot.ready.is_set(),
|
|
@@ -4932,3 +4946,52 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4932
4946
|
|
|
4933
4947
|
key = tuple(sorted(opts.items()))
|
|
4934
4948
|
return self._sslctx_cache.get(key)
|
|
4949
|
+
|
|
4950
|
+
async def freeze(self, timeout=30):
|
|
4951
|
+
|
|
4952
|
+
if self.paused:
|
|
4953
|
+
mesg = 'The service is already frozen.'
|
|
4954
|
+
raise s_exc.BadState(mesg=mesg)
|
|
4955
|
+
|
|
4956
|
+
logger.warning(f'Freezing service for volume snapshot.')
|
|
4957
|
+
|
|
4958
|
+
logger.warning('...acquiring nexus lock to prevent edits.')
|
|
4959
|
+
|
|
4960
|
+
try:
|
|
4961
|
+
await asyncio.wait_for(self.nexslock.acquire(), timeout=timeout)
|
|
4962
|
+
|
|
4963
|
+
except asyncio.TimeoutError:
|
|
4964
|
+
logger.warning('...nexus lock acquire timed out!')
|
|
4965
|
+
logger.warning('Aborting freeze and resuming normal operation.')
|
|
4966
|
+
|
|
4967
|
+
mesg = 'Nexus lock acquire timed out.'
|
|
4968
|
+
raise s_exc.TimeOut(mesg=mesg)
|
|
4969
|
+
|
|
4970
|
+
self.paused = True
|
|
4971
|
+
|
|
4972
|
+
try:
|
|
4973
|
+
|
|
4974
|
+
logger.warning('...committing pending transactions.')
|
|
4975
|
+
await self.slab.syncLoopOnce()
|
|
4976
|
+
|
|
4977
|
+
logger.warning('...flushing dirty buffers to disk.')
|
|
4978
|
+
await s_task.executor(os.sync)
|
|
4979
|
+
|
|
4980
|
+
logger.warning('...done!')
|
|
4981
|
+
|
|
4982
|
+
except Exception:
|
|
4983
|
+
self.paused = False
|
|
4984
|
+
self.nexslock.release()
|
|
4985
|
+
logger.exception('Failed to freeze. Resuming normal operation.')
|
|
4986
|
+
raise
|
|
4987
|
+
|
|
4988
|
+
async def resume(self):
|
|
4989
|
+
|
|
4990
|
+
if not self.paused:
|
|
4991
|
+
mesg = 'The service is not frozen.'
|
|
4992
|
+
raise s_exc.BadState(mesg=mesg)
|
|
4993
|
+
|
|
4994
|
+
logger.warning('Resuming normal operations from a freeze.')
|
|
4995
|
+
|
|
4996
|
+
self.paused = False
|
|
4997
|
+
self.nexslock.release()
|
synapse/lib/drive.py
CHANGED
|
@@ -22,6 +22,7 @@ LKEY_INFO = b'\x02' # <bidn> = <info>
|
|
|
22
22
|
LKEY_DATA = b'\x03' # <bidn> <vers> = <data>
|
|
23
23
|
LKEY_VERS = b'\x04' # <bidn> <vers> = <versinfo>
|
|
24
24
|
LKEY_INFO_BYTYPE = b'\x05' # <type> 00 <bidn> = 01
|
|
25
|
+
LKEY_TYPE_VERS = b'\x06' # <type> = <uint64>
|
|
25
26
|
|
|
26
27
|
rootdir = '00000000000000000000000000000000'
|
|
27
28
|
|
|
@@ -60,24 +61,36 @@ class Drive(s_base.Base):
|
|
|
60
61
|
|
|
61
62
|
return [reqValidName(p.strip().lower()) for p in path]
|
|
62
63
|
|
|
63
|
-
def
|
|
64
|
-
|
|
64
|
+
def _reqInfoType(self, info, typename):
|
|
65
|
+
infotype = info.get('type')
|
|
66
|
+
if infotype != typename:
|
|
67
|
+
mesg = f'Drive item has the wrong type. Expected: {typename} got {infotype}.'
|
|
68
|
+
raise s_exc.TypeMismatch(mesg=mesg, expected=typename, got=infotype)
|
|
69
|
+
|
|
70
|
+
def getItemInfo(self, iden, typename=None):
|
|
71
|
+
info = self._getItemInfo(s_common.uhex(iden))
|
|
72
|
+
if typename is not None:
|
|
73
|
+
self._reqInfoType(info, typename)
|
|
74
|
+
return info
|
|
65
75
|
|
|
66
76
|
def _getItemInfo(self, bidn):
|
|
67
77
|
byts = self.slab.get(LKEY_INFO + bidn, db=self.dbname)
|
|
68
78
|
if byts is not None:
|
|
69
79
|
return s_msgpack.un(byts)
|
|
70
80
|
|
|
71
|
-
def reqItemInfo(self, iden):
|
|
72
|
-
return self._reqItemInfo(s_common.uhex(iden))
|
|
81
|
+
def reqItemInfo(self, iden, typename=None):
|
|
82
|
+
return self._reqItemInfo(s_common.uhex(iden), typename=typename)
|
|
73
83
|
|
|
74
|
-
def _reqItemInfo(self, bidn):
|
|
84
|
+
def _reqItemInfo(self, bidn, typename=None):
|
|
75
85
|
info = self._getItemInfo(bidn)
|
|
76
|
-
if info is
|
|
77
|
-
|
|
86
|
+
if info is None:
|
|
87
|
+
mesg = f'No drive item with ID {s_common.ehex(bidn)}.'
|
|
88
|
+
raise s_exc.NoSuchIden(mesg=mesg)
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
if typename is not None:
|
|
91
|
+
self._reqInfoType(info, typename)
|
|
92
|
+
|
|
93
|
+
return info
|
|
81
94
|
|
|
82
95
|
async def setItemPath(self, iden, path):
|
|
83
96
|
'''
|
|
@@ -494,10 +507,27 @@ class Drive(s_base.Base):
|
|
|
494
507
|
if byts is not None:
|
|
495
508
|
return s_msgpack.un(byts)
|
|
496
509
|
|
|
497
|
-
|
|
510
|
+
def getTypeSchemaVersion(self, typename):
|
|
511
|
+
verskey = LKEY_TYPE_VERS + typename.encode()
|
|
512
|
+
byts = self.slab.get(verskey, db=self.dbname)
|
|
513
|
+
if byts is not None:
|
|
514
|
+
return s_msgpack.un(byts)
|
|
515
|
+
|
|
516
|
+
async def setTypeSchema(self, typename, schema, callback=None, vers=None):
|
|
498
517
|
|
|
499
518
|
reqValidName(typename)
|
|
500
519
|
|
|
520
|
+
if vers is not None:
|
|
521
|
+
vers = int(vers)
|
|
522
|
+
curv = self.getTypeSchemaVersion(typename)
|
|
523
|
+
if curv is not None:
|
|
524
|
+
if vers == curv:
|
|
525
|
+
return False
|
|
526
|
+
|
|
527
|
+
if vers < curv:
|
|
528
|
+
mesg = f'Cannot downgrade drive schema version for type {typename}.'
|
|
529
|
+
raise s_exc.BadVersion(mesg=mesg)
|
|
530
|
+
|
|
501
531
|
vtor = s_config.getJsValidator(schema)
|
|
502
532
|
|
|
503
533
|
self.validators[typename] = vtor
|
|
@@ -506,6 +536,10 @@ class Drive(s_base.Base):
|
|
|
506
536
|
|
|
507
537
|
self.slab.put(lkey, s_msgpack.en(schema), db=self.dbname)
|
|
508
538
|
|
|
539
|
+
if vers is not None:
|
|
540
|
+
verskey = LKEY_TYPE_VERS + typename.encode()
|
|
541
|
+
self.slab.put(verskey, s_msgpack.en(vers), db=self.dbname)
|
|
542
|
+
|
|
509
543
|
if callback is not None:
|
|
510
544
|
async for info in self.getItemsByType(typename):
|
|
511
545
|
bidn = s_common.uhex(info.get('iden'))
|
|
@@ -516,6 +550,7 @@ class Drive(s_base.Base):
|
|
|
516
550
|
vtor(data)
|
|
517
551
|
self.slab.put(LKEY_DATA + bidn + versindx, s_msgpack.en(data), db=self.dbname)
|
|
518
552
|
await asyncio.sleep(0)
|
|
553
|
+
return True
|
|
519
554
|
|
|
520
555
|
async def getItemsByType(self, typename):
|
|
521
556
|
tkey = typename.encode() + b'\x00'
|
synapse/lib/hive.py
CHANGED
|
@@ -351,7 +351,7 @@ class Hive(s_nexus.Pusher, s_telepath.Aware):
|
|
|
351
351
|
await self.cell.auth._hndlsetUserProfileValu(iden, name, valu)
|
|
352
352
|
|
|
353
353
|
elif full[0] == 'cellvers':
|
|
354
|
-
self.cell.setCellVers(full[-1], valu, nexs=False)
|
|
354
|
+
await self.cell.setCellVers(full[-1], valu, nexs=False)
|
|
355
355
|
|
|
356
356
|
node = await self._getHiveNode(full)
|
|
357
357
|
|