synapse 2.184.0__py311-none-any.whl → 2.186.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 +4 -3
- synapse/datamodel.py +41 -6
- synapse/exc.py +2 -0
- synapse/lib/ast.py +83 -22
- synapse/lib/auth.py +13 -0
- synapse/lib/cell.py +78 -2
- synapse/lib/drive.py +45 -10
- synapse/lib/modules.py +1 -0
- synapse/lib/parser.py +1 -0
- synapse/lib/snap.py +1 -6
- synapse/lib/storm.lark +12 -6
- synapse/lib/storm.py +45 -9
- synapse/lib/storm_format.py +1 -0
- synapse/lib/stormlib/stix.py +14 -5
- synapse/lib/stormtypes.py +64 -36
- synapse/lib/types.py +6 -0
- synapse/lib/version.py +2 -2
- synapse/models/doc.py +93 -0
- synapse/models/infotech.py +2 -1
- synapse/models/media.py +0 -1
- synapse/models/orgs.py +26 -3
- synapse/models/proj.py +56 -36
- synapse/models/risk.py +3 -0
- synapse/models/syn.py +64 -6
- synapse/tests/test_cortex.py +49 -6
- synapse/tests/test_lib_base.py +2 -2
- synapse/tests/test_lib_cell.py +59 -5
- synapse/tests/test_lib_grammar.py +2 -0
- synapse/tests/test_lib_storm.py +54 -1
- synapse/tests/test_lib_stormlib_stix.py +3 -2
- synapse/tests/test_model_doc.py +51 -0
- synapse/tests/test_model_orgs.py +41 -0
- synapse/tests/test_model_risk.py +2 -0
- synapse/tests/test_model_syn.py +43 -0
- synapse/tests/test_tools_promote.py +67 -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/livebackup.py +3 -1
- synapse/tools/promote.py +23 -4
- synapse/tools/snapshot.py +69 -0
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/METADATA +5 -10
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/RECORD +49 -44
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/WHEEL +1 -1
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/LICENSE +0 -0
- {synapse-2.184.0.dist-info → synapse-2.186.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_model_orgs.py
CHANGED
|
@@ -701,6 +701,47 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
701
701
|
self.len(1, await core.nodes('ou:asset :owner -> ps:contact +:name=foo '))
|
|
702
702
|
self.len(1, await core.nodes('ou:asset :operator -> ps:contact +:name=bar '))
|
|
703
703
|
|
|
704
|
+
visi = await core.auth.addUser('visi')
|
|
705
|
+
|
|
706
|
+
nodes = await core.nodes('''
|
|
707
|
+
[ ou:enacted=*
|
|
708
|
+
:id=V-99
|
|
709
|
+
:project={[ proj:project=* ]}
|
|
710
|
+
:status=10
|
|
711
|
+
:priority=highest
|
|
712
|
+
:created=20241018
|
|
713
|
+
:updated=20241018
|
|
714
|
+
:due=20241018
|
|
715
|
+
:completed=20241018
|
|
716
|
+
:creator=root
|
|
717
|
+
:assignee=visi
|
|
718
|
+
:scope=(ou:team, *)
|
|
719
|
+
:ext:creator={[ ps:contact=* :name=root ]}
|
|
720
|
+
:ext:assignee={[ ps:contact=* :name=visi ]}
|
|
721
|
+
]
|
|
722
|
+
''')
|
|
723
|
+
self.len(1, nodes)
|
|
724
|
+
self.eq('V-99', nodes[0].get('id'))
|
|
725
|
+
self.eq(10, nodes[0].get('status'))
|
|
726
|
+
self.eq(50, nodes[0].get('priority'))
|
|
727
|
+
|
|
728
|
+
self.eq(1729209600000, nodes[0].get('due'))
|
|
729
|
+
self.eq(1729209600000, nodes[0].get('created'))
|
|
730
|
+
self.eq(1729209600000, nodes[0].get('updated'))
|
|
731
|
+
self.eq(1729209600000, nodes[0].get('completed'))
|
|
732
|
+
|
|
733
|
+
self.eq(visi.iden, nodes[0].get('assignee'))
|
|
734
|
+
self.eq(core.auth.rootuser.iden, nodes[0].get('creator'))
|
|
735
|
+
|
|
736
|
+
self.nn(nodes[0].get('scope'))
|
|
737
|
+
self.nn(nodes[0].get('ext:creator'))
|
|
738
|
+
self.nn(nodes[0].get('ext:assignee'))
|
|
739
|
+
|
|
740
|
+
self.len(1, await core.nodes('ou:enacted -> proj:project'))
|
|
741
|
+
self.len(1, await core.nodes('ou:enacted :scope -> ou:team'))
|
|
742
|
+
self.len(1, await core.nodes('ou:enacted :ext:creator -> ps:contact +:name=root'))
|
|
743
|
+
self.len(1, await core.nodes('ou:enacted :ext:assignee -> ps:contact +:name=visi'))
|
|
744
|
+
|
|
704
745
|
async def test_ou_code_prefixes(self):
|
|
705
746
|
guid0 = s_common.guid()
|
|
706
747
|
guid1 = s_common.guid()
|
synapse/tests/test_model_risk.py
CHANGED
|
@@ -577,6 +577,7 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
577
577
|
:techniques=(*,)
|
|
578
578
|
:tag=cno.mal.cobaltstrike
|
|
579
579
|
:mitre:attack:software=S0001
|
|
580
|
+
:id=" AAAbbb123 "
|
|
580
581
|
|
|
581
582
|
:sophistication=high
|
|
582
583
|
:availability=public
|
|
@@ -593,6 +594,7 @@ class RiskModelTest(s_t_utils.SynTest):
|
|
|
593
594
|
self.eq(1643673600000, nodes[0].get('reporter:discovered'))
|
|
594
595
|
self.eq(1675209600000, nodes[0].get('reporter:published'))
|
|
595
596
|
self.eq('S0001', nodes[0].get('mitre:attack:software'))
|
|
597
|
+
self.eq('AAAbbb123', nodes[0].get('id'))
|
|
596
598
|
|
|
597
599
|
self.eq('cobaltstrike', nodes[0].get('soft:name'))
|
|
598
600
|
self.eq(('beacon',), nodes[0].get('soft:names'))
|
synapse/tests/test_model_syn.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import synapse.exc as s_exc
|
|
2
|
+
import synapse.common as s_common
|
|
2
3
|
import synapse.cortex as s_cortex
|
|
4
|
+
import synapse.datamodel as s_datamodel
|
|
3
5
|
|
|
4
6
|
import synapse.lib.stormsvc as s_stormsvc
|
|
5
7
|
|
|
@@ -46,6 +48,47 @@ class TestService(s_stormsvc.StormSvc):
|
|
|
46
48
|
|
|
47
49
|
class SynModelTest(s_t_utils.SynTest):
|
|
48
50
|
|
|
51
|
+
async def test_syn_userrole(self):
|
|
52
|
+
|
|
53
|
+
async with self.getTestCore() as core:
|
|
54
|
+
|
|
55
|
+
(ok, iden) = await core.callStorm('return($lib.trycast(syn:user, root))')
|
|
56
|
+
self.true(ok)
|
|
57
|
+
self.eq(iden, core.auth.rootuser.iden)
|
|
58
|
+
|
|
59
|
+
# coverage for iden taking precedence
|
|
60
|
+
(ok, iden) = await core.callStorm(f'return($lib.trycast(syn:user, {iden}))')
|
|
61
|
+
self.true(ok)
|
|
62
|
+
self.eq(iden, core.auth.rootuser.iden)
|
|
63
|
+
|
|
64
|
+
self.eq('root', await core.callStorm(f'return($lib.repr(syn:user, {iden}))'))
|
|
65
|
+
|
|
66
|
+
(ok, iden) = await core.callStorm('return($lib.trycast(syn:role, all))')
|
|
67
|
+
self.true(ok)
|
|
68
|
+
self.eq(iden, core.auth.allrole.iden)
|
|
69
|
+
|
|
70
|
+
# coverage for iden taking precedence
|
|
71
|
+
(ok, iden) = await core.callStorm(f'return($lib.trycast(syn:role, {iden}))')
|
|
72
|
+
self.true(ok)
|
|
73
|
+
self.eq(iden, core.auth.allrole.iden)
|
|
74
|
+
|
|
75
|
+
self.eq('all', await core.callStorm(f'return($lib.repr(syn:role, {iden}))'))
|
|
76
|
+
|
|
77
|
+
# coverage for DataModel without a cortex reference
|
|
78
|
+
iden = s_common.guid()
|
|
79
|
+
|
|
80
|
+
model = core.model
|
|
81
|
+
model.core = None
|
|
82
|
+
|
|
83
|
+
synuser = model.type('syn:user')
|
|
84
|
+
synrole = model.type('syn:user')
|
|
85
|
+
|
|
86
|
+
self.eq(iden, synuser.repr(iden))
|
|
87
|
+
self.eq(iden, synrole.repr(iden))
|
|
88
|
+
|
|
89
|
+
self.eq(iden, synuser.norm(iden)[0])
|
|
90
|
+
self.eq(iden, synrole.norm(iden)[0])
|
|
91
|
+
|
|
49
92
|
async def test_syn_tag(self):
|
|
50
93
|
|
|
51
94
|
async with self.getTestCore() as core:
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import synapse.common as s_common
|
|
2
|
+
|
|
3
|
+
import synapse.lib.base as s_base
|
|
4
|
+
import synapse.lib.cell as s_cell
|
|
5
|
+
|
|
6
|
+
import synapse.tools.promote as s_tools_promote
|
|
7
|
+
|
|
8
|
+
import synapse.tests.utils as s_t_utils
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PromoteToolTest(s_t_utils.SynTest):
|
|
12
|
+
|
|
13
|
+
async def test_tool_promote_simple(self):
|
|
14
|
+
async with self.getTestAha() as aha:
|
|
15
|
+
async with await s_base.Base.anit() as base:
|
|
16
|
+
with self.getTestDir() as dirn:
|
|
17
|
+
dirn00 = s_common.genpath(dirn, '00.cell')
|
|
18
|
+
dirn01 = s_common.genpath(dirn, '01.cell')
|
|
19
|
+
|
|
20
|
+
cell00 = await base.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
|
|
21
|
+
cell01 = await base.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
|
|
22
|
+
provinfo={'mirror': 'cell'}))
|
|
23
|
+
self.true(cell00.isactive)
|
|
24
|
+
self.false(cell01.isactive)
|
|
25
|
+
await cell01.sync()
|
|
26
|
+
|
|
27
|
+
outp = self.getTestOutp()
|
|
28
|
+
argv = ['--svcurl', cell00.getLocalUrl()]
|
|
29
|
+
ret = await s_tools_promote.main(argv, outp=outp)
|
|
30
|
+
self.eq(1, ret)
|
|
31
|
+
outp.expect('Failed to promote service')
|
|
32
|
+
outp.expect('promote() called on non-mirror')
|
|
33
|
+
|
|
34
|
+
outp.clear()
|
|
35
|
+
argv = ['--svcurl', cell01.getLocalUrl()]
|
|
36
|
+
ret = await s_tools_promote.main(argv, outp=outp)
|
|
37
|
+
self.eq(0, ret)
|
|
38
|
+
self.false(cell00.isactive)
|
|
39
|
+
self.true(cell01.isactive)
|
|
40
|
+
await cell00.sync()
|
|
41
|
+
|
|
42
|
+
async def test_tool_promote_schism(self):
|
|
43
|
+
# Create a mirror of mirrors and try promoting the end mirror.
|
|
44
|
+
async with self.getTestAha() as aha:
|
|
45
|
+
async with await s_base.Base.anit() as base:
|
|
46
|
+
with self.getTestDir() as dirn:
|
|
47
|
+
dirn00 = s_common.genpath(dirn, '00.cell')
|
|
48
|
+
dirn01 = s_common.genpath(dirn, '01.cell')
|
|
49
|
+
dirn02 = s_common.genpath(dirn, '02.cell')
|
|
50
|
+
|
|
51
|
+
cell00 = await base.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
|
|
52
|
+
cell01 = await base.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
|
|
53
|
+
provinfo={'mirror': '00.cell'}))
|
|
54
|
+
cell02 = await base.enter_context(self.addSvcToAha(aha, '02.cell', s_cell.Cell, dirn=dirn02,
|
|
55
|
+
provinfo={'mirror': '01.cell'}))
|
|
56
|
+
self.true(cell00.isactive)
|
|
57
|
+
self.false(cell01.isactive)
|
|
58
|
+
self.false(cell02.isactive)
|
|
59
|
+
await cell02.sync()
|
|
60
|
+
|
|
61
|
+
outp = self.getTestOutp()
|
|
62
|
+
argv = ['--svcurl', cell02.getLocalUrl()]
|
|
63
|
+
ret = await s_tools_promote.main(argv, outp=outp)
|
|
64
|
+
self.eq(1, ret)
|
|
65
|
+
outp.expect('Failed to promote service')
|
|
66
|
+
# Note: The following message may change when SYN-7659 is addressed
|
|
67
|
+
outp.expect('ahaname=01.cell is not the current leader and cannot handoff leadership to aha://02.cell.synapse')
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from unittest import mock
|
|
2
|
+
|
|
3
|
+
import synapse.lib.output as s_output
|
|
4
|
+
import synapse.tools.snapshot as s_tools_snapshot
|
|
5
|
+
|
|
6
|
+
import synapse.tests.utils as s_t_utils
|
|
7
|
+
|
|
8
|
+
class PromoteToolTest(s_t_utils.SynTest):
|
|
9
|
+
|
|
10
|
+
async def test_tool_snapshot(self):
|
|
11
|
+
|
|
12
|
+
async with self.getTestCore() as core:
|
|
13
|
+
|
|
14
|
+
lurl = core.getLocalUrl()
|
|
15
|
+
|
|
16
|
+
self.eq(0, await s_tools_snapshot.main(('freeze', '--svcurl', lurl)))
|
|
17
|
+
self.true(core.paused)
|
|
18
|
+
|
|
19
|
+
outp = s_output.OutPutStr()
|
|
20
|
+
self.eq(1, await s_tools_snapshot.main(('freeze', '--svcurl', lurl), outp=outp))
|
|
21
|
+
self.isin('ERROR BadState', str(outp))
|
|
22
|
+
|
|
23
|
+
self.eq(0, await s_tools_snapshot.main(('resume', '--svcurl', lurl)))
|
|
24
|
+
self.false(core.paused)
|
|
25
|
+
|
|
26
|
+
outp = s_output.OutPutStr()
|
|
27
|
+
self.eq(1, await s_tools_snapshot.main(('resume', '--svcurl', lurl), outp=outp))
|
|
28
|
+
self.isin('ERROR BadState', str(outp))
|
|
29
|
+
|
|
30
|
+
outp = s_output.OutPutStr()
|
|
31
|
+
async with core.nexslock:
|
|
32
|
+
argv = ('freeze', '--svcurl', lurl, '--timeout', '1')
|
|
33
|
+
self.eq(1, await s_tools_snapshot.main(argv, outp=outp))
|
|
34
|
+
self.isin('ERROR TimeOut', str(outp))
|
|
35
|
+
|
|
36
|
+
def boom():
|
|
37
|
+
raise Exception('boom')
|
|
38
|
+
|
|
39
|
+
outp = s_output.OutPutStr()
|
|
40
|
+
with mock.patch('os.sync', boom):
|
|
41
|
+
self.eq(1, await s_tools_snapshot.main(('freeze', '--svcurl', lurl), outp=outp))
|
|
42
|
+
self.false(core.paused)
|
|
43
|
+
self.isin('ERROR SynErr: boom', str(outp))
|
|
44
|
+
|
|
45
|
+
outp = s_output.OutPutStr()
|
|
46
|
+
self.eq(1, await s_tools_snapshot.main(('freeze', '--svcurl', 'newp://newp'), outp=outp))
|
|
47
|
+
self.isin('ERROR BadUrl', str(outp))
|
synapse/tools/aha/clone.py
CHANGED
|
@@ -18,7 +18,9 @@ Examples:
|
|
|
18
18
|
|
|
19
19
|
async def main(argv, outp=s_output.stdout):
|
|
20
20
|
|
|
21
|
-
pars = argparse.ArgumentParser(prog='synapse.tools.aha.clone', description=descr
|
|
21
|
+
pars = argparse.ArgumentParser(prog='synapse.tools.aha.clone', description=descr,
|
|
22
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
23
|
+
|
|
22
24
|
pars.add_argument('dnsname', help='The DNS name of the new AHA server.')
|
|
23
25
|
pars.add_argument('--port', type=int, default=27492, help='The port that the new AHA server should listen on.')
|
|
24
26
|
pars.add_argument('--url', default='cell:///vertex/storage', help='The telepath URL to connect to the AHA service.')
|
synapse/tools/aha/easycert.py
CHANGED
|
@@ -51,7 +51,7 @@ async def _main(argv, outp):
|
|
|
51
51
|
|
|
52
52
|
def getArgParser():
|
|
53
53
|
desc = 'CLI tool to generate simple x509 certificates from an Aha server.'
|
|
54
|
-
pars = argparse.ArgumentParser(prog='aha.easycert', description=desc)
|
|
54
|
+
pars = argparse.ArgumentParser(prog='synapse.tools.aha.easycert', description=desc)
|
|
55
55
|
|
|
56
56
|
pars.add_argument('-a', '--aha', required=True, # type=str,
|
|
57
57
|
help='Aha server to connect too.')
|
synapse/tools/aha/enroll.py
CHANGED
|
@@ -21,7 +21,9 @@ Examples:
|
|
|
21
21
|
|
|
22
22
|
async def main(argv, outp=s_output.stdout):
|
|
23
23
|
|
|
24
|
-
pars = argparse.ArgumentParser(prog='
|
|
24
|
+
pars = argparse.ArgumentParser(prog='synapse.tools.aha.enroll', description=descr,
|
|
25
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
26
|
+
|
|
25
27
|
pars.add_argument('onceurl', help='The one-time use AHA user enrollment URL.')
|
|
26
28
|
opts = pars.parse_args(argv)
|
|
27
29
|
|
|
@@ -23,7 +23,9 @@ Examples:
|
|
|
23
23
|
|
|
24
24
|
async def main(argv, outp=s_output.stdout):
|
|
25
25
|
|
|
26
|
-
pars = argparse.ArgumentParser(prog='synapse.tools.aha.provision.service', description=descr
|
|
26
|
+
pars = argparse.ArgumentParser(prog='synapse.tools.aha.provision.service', description=descr,
|
|
27
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
28
|
+
|
|
27
29
|
pars.add_argument('--url', default='cell:///vertex/storage', help='The telepath URL to connect to the AHA service.')
|
|
28
30
|
pars.add_argument('--user', help='Provision the new service with the username.')
|
|
29
31
|
pars.add_argument('--cellyaml', help='Specify the path to a YAML file containing config options for the service.')
|
|
@@ -22,7 +22,9 @@ Examples:
|
|
|
22
22
|
|
|
23
23
|
async def main(argv, outp=s_output.stdout):
|
|
24
24
|
|
|
25
|
-
pars = argparse.ArgumentParser(prog='synapse.tools.aha.provision.user', description=descr
|
|
25
|
+
pars = argparse.ArgumentParser(prog='synapse.tools.aha.provision.user', description=descr,
|
|
26
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
27
|
+
|
|
26
28
|
pars.add_argument('--url', default='cell:///vertex/storage', help='The telepath URL to connect to the AHA service.')
|
|
27
29
|
pars.add_argument('--again', default=False, action='store_true', help='Generate a new enroll URL for an existing user.')
|
|
28
30
|
pars.add_argument('--only-url', help='Only output the URL upon successful execution',
|
synapse/tools/livebackup.py
CHANGED
|
@@ -20,7 +20,9 @@ Examples:
|
|
|
20
20
|
|
|
21
21
|
async def main(argv, outp=s_output.stdout):
|
|
22
22
|
|
|
23
|
-
pars = argparse.ArgumentParser(prog='livebackup', description=descr
|
|
23
|
+
pars = argparse.ArgumentParser(prog='synapse.tools.livebackup', description=descr,
|
|
24
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
25
|
+
|
|
24
26
|
pars.add_argument('--url', default='cell:///vertex/storage', help='The telepath URL of the Synapse service.')
|
|
25
27
|
pars.add_argument('--name', default=None, help='Specify a name for the backup. Defaults to an automatically generated timestamp.')
|
|
26
28
|
|
synapse/tools/promote.py
CHANGED
|
@@ -2,9 +2,12 @@ import sys
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import argparse
|
|
4
4
|
|
|
5
|
+
import synapse.exc as s_exc
|
|
6
|
+
|
|
5
7
|
import synapse.telepath as s_telepath
|
|
6
8
|
|
|
7
9
|
import synapse.lib.output as s_output
|
|
10
|
+
import synapse.lib.urlhelp as s_urlhelp
|
|
8
11
|
|
|
9
12
|
descr = '''
|
|
10
13
|
Promote a mirror to the leader.
|
|
@@ -15,9 +18,15 @@ Example (being run from a Cortex mirror docker container):
|
|
|
15
18
|
|
|
16
19
|
async def main(argv, outp=s_output.stdout):
|
|
17
20
|
|
|
18
|
-
pars = argparse.ArgumentParser(prog='
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
pars = argparse.ArgumentParser(prog='synapse.tools.promote', description=descr,
|
|
22
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
23
|
+
|
|
24
|
+
pars.add_argument('--svcurl', default='cell:///vertex/storage',
|
|
25
|
+
help='The telepath URL of the Synapse service.')
|
|
26
|
+
|
|
27
|
+
pars.add_argument('--failure', default=False, action='store_true',
|
|
28
|
+
help='Promotion is due to leader being offline. Graceful handoff is not possible.')
|
|
29
|
+
|
|
21
30
|
# TODO pars.add_argument('--timeout', type=float, default=30.0, help='The maximum timeout to wait for the mirror to catch up.')
|
|
22
31
|
|
|
23
32
|
opts = pars.parse_args(argv)
|
|
@@ -29,7 +38,17 @@ async def main(argv, outp=s_output.stdout):
|
|
|
29
38
|
graceful = not opts.failure
|
|
30
39
|
|
|
31
40
|
outp.printf(f'Promoting to leader: {opts.svcurl}')
|
|
32
|
-
|
|
41
|
+
try:
|
|
42
|
+
await cell.promote(graceful=graceful)
|
|
43
|
+
except s_exc.BadState as e:
|
|
44
|
+
mesg = f'Failed to promote service to being a leader; {e.get("mesg")}'
|
|
45
|
+
outp.printf(mesg)
|
|
46
|
+
return 1
|
|
47
|
+
except s_exc.SynErr as e:
|
|
48
|
+
outp.printf(f'Failed to promote service {s_urlhelp.sanitizeUrl(opts.svcurl)}: {e}')
|
|
49
|
+
return 1
|
|
50
|
+
|
|
51
|
+
return 0
|
|
33
52
|
|
|
34
53
|
if __name__ == '__main__': # pragma: no cover
|
|
35
54
|
sys.exit(asyncio.run(main(sys.argv[1:])))
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import asyncio
|
|
3
|
+
import logging
|
|
4
|
+
import argparse
|
|
5
|
+
|
|
6
|
+
import synapse.exc as s_exc
|
|
7
|
+
import synapse.telepath as s_telepath
|
|
8
|
+
|
|
9
|
+
import synapse.lib.output as s_output
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
desc = '''
|
|
14
|
+
Command line tool to freeze/resume service operations to allow
|
|
15
|
+
system admins to generate a transactionally consistent volume
|
|
16
|
+
snapshot using 3rd party tools.
|
|
17
|
+
|
|
18
|
+
The use pattern should be::
|
|
19
|
+
|
|
20
|
+
python -m synapse.tools.snapshot freeze
|
|
21
|
+
|
|
22
|
+
<generate volume snapshot using 3rd party tools>
|
|
23
|
+
|
|
24
|
+
python -m synapse.tools.snapshot resume
|
|
25
|
+
|
|
26
|
+
The tool will set the process exit code to 0 on success.
|
|
27
|
+
'''
|
|
28
|
+
|
|
29
|
+
async def main(argv, outp=s_output.stdout):
|
|
30
|
+
|
|
31
|
+
pars = argparse.ArgumentParser('synapse.tools.snapshot',
|
|
32
|
+
description=desc,
|
|
33
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
34
|
+
|
|
35
|
+
subs = pars.add_subparsers(required=True, title='commands', dest='cmd')
|
|
36
|
+
|
|
37
|
+
freeze = subs.add_parser('freeze', help='Suspend edits and sync changes to disk.')
|
|
38
|
+
freeze.add_argument('--timeout', type=int, default=120,
|
|
39
|
+
help='Maximum time to wait for the nexus lock.')
|
|
40
|
+
|
|
41
|
+
freeze.add_argument('--svcurl', default='cell:///vertex/storage',
|
|
42
|
+
help='The telepath URL of the Synapse service.')
|
|
43
|
+
|
|
44
|
+
resume = subs.add_parser('resume', help='Resume edits and continue normal operation.')
|
|
45
|
+
resume.add_argument('--svcurl', default='cell:///vertex/storage',
|
|
46
|
+
help='The telepath URL of the Synapse service.')
|
|
47
|
+
|
|
48
|
+
opts = pars.parse_args(argv)
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
async with s_telepath.withTeleEnv():
|
|
52
|
+
|
|
53
|
+
async with await s_telepath.openurl(opts.svcurl) as proxy:
|
|
54
|
+
|
|
55
|
+
if opts.cmd == 'freeze':
|
|
56
|
+
await proxy.freeze(timeout=opts.timeout)
|
|
57
|
+
return 0
|
|
58
|
+
|
|
59
|
+
if opts.cmd == 'resume':
|
|
60
|
+
await proxy.resume()
|
|
61
|
+
return 0
|
|
62
|
+
|
|
63
|
+
except s_exc.SynErr as e:
|
|
64
|
+
mesg = e.errinfo.get('mesg')
|
|
65
|
+
outp.printf(f'ERROR {e.__class__.__name__}: {mesg}')
|
|
66
|
+
return 1
|
|
67
|
+
|
|
68
|
+
if __name__ == '__main__': # pragma: no cover
|
|
69
|
+
sys.exit(asyncio.run(main(sys.argv[1:])))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: synapse
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.186.0
|
|
4
4
|
Summary: Synapse Intelligence Analysis Framework
|
|
5
5
|
Author-email: The Vertex Project LLC <root@vertex.link>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -59,15 +59,10 @@ Requires-Dist: bump2version<1.1.0,>=1.0.1; extra == "dev"
|
|
|
59
59
|
Requires-Dist: pytest-xdist<4.0.0,>=3.0.2; extra == "dev"
|
|
60
60
|
Requires-Dist: coverage<8.0.0,>=7.0.0; extra == "dev"
|
|
61
61
|
Provides-Extra: docs
|
|
62
|
-
Requires-Dist:
|
|
63
|
-
Requires-Dist:
|
|
64
|
-
Requires-Dist:
|
|
65
|
-
Requires-Dist:
|
|
66
|
-
Requires-Dist: nbstripout<1.0.0,>=0.3.3; extra == "docs"
|
|
67
|
-
Requires-Dist: sphinx<7.0.0,>=6.2.0; extra == "docs"
|
|
68
|
-
Requires-Dist: sphinx-rtd-theme<2.0.0,>=1.0.0; extra == "docs"
|
|
69
|
-
Requires-Dist: sphinx-notfound-page==0.8.3; extra == "docs"
|
|
70
|
-
Requires-Dist: jinja2<3.1.0; extra == "docs"
|
|
62
|
+
Requires-Dist: sphinx<9.0.0,>=8.0.0; extra == "docs"
|
|
63
|
+
Requires-Dist: sphinx-rtd-theme<4.0.0,>=3.0.0; extra == "docs"
|
|
64
|
+
Requires-Dist: sphinx-notfound-page<2.0.0,>=1.0.4; extra == "docs"
|
|
65
|
+
Requires-Dist: jinja2<4.0.0,>=3.1.4; extra == "docs"
|
|
71
66
|
|
|
72
67
|
Synapse
|
|
73
68
|
=======
|