synapse 2.176.0__py311-none-any.whl → 2.178.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/axon.py +24 -9
- synapse/cortex.py +337 -172
- synapse/cryotank.py +46 -37
- synapse/datamodel.py +17 -4
- synapse/exc.py +19 -0
- synapse/lib/agenda.py +7 -13
- synapse/lib/aha.py +361 -88
- synapse/lib/auth.py +1520 -0
- synapse/lib/base.py +27 -9
- synapse/lib/cell.py +422 -163
- synapse/lib/config.py +15 -11
- synapse/lib/coro.py +13 -0
- synapse/lib/grammar.py +5 -0
- synapse/lib/hive.py +24 -3
- synapse/lib/hiveauth.py +6 -32
- synapse/lib/layer.py +7 -9
- synapse/lib/link.py +22 -18
- synapse/lib/lmdbslab.py +152 -3
- synapse/lib/modelrev.py +1 -1
- synapse/lib/nexus.py +24 -12
- synapse/lib/schemas.py +136 -0
- synapse/lib/storm.py +61 -29
- synapse/lib/stormlib/aha.py +1 -1
- synapse/lib/stormlib/auth.py +185 -10
- synapse/lib/stormlib/cortex.py +16 -5
- synapse/lib/stormlib/gen.py +80 -0
- synapse/lib/stormlib/imap.py +6 -2
- synapse/lib/stormlib/model.py +55 -0
- synapse/lib/stormlib/modelext.py +60 -0
- synapse/lib/stormlib/smtp.py +12 -2
- synapse/lib/stormlib/tabular.py +212 -0
- synapse/lib/stormtypes.py +14 -1
- synapse/lib/trigger.py +1 -1
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +55 -28
- synapse/models/base.py +7 -0
- synapse/models/biz.py +4 -0
- synapse/models/files.py +8 -1
- synapse/models/inet.py +8 -0
- synapse/telepath.py +32 -17
- synapse/tests/files/aha/certs/cas/synapse.crt +28 -0
- synapse/tests/files/aha/certs/cas/synapse.key +51 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.crt +30 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.key +51 -0
- synapse/tests/files/aha/certs/users/root@synapse.crt +29 -0
- synapse/tests/files/aha/certs/users/root@synapse.key +51 -0
- synapse/tests/files/changelog/model_2.176.0_16ee721a6b7221344eaf946c3ab4602dda546b1a.yaml.gz +0 -0
- synapse/tests/files/changelog/model_2.176.0_2a25c58bbd344716cd7cbc3f4304d8925b0f4ef2.yaml.gz +0 -0
- synapse/tests/files/rstorm/testsvc.py +1 -1
- synapse/tests/test_axon.py +8 -5
- synapse/tests/test_cortex.py +149 -141
- synapse/tests/test_cryotank.py +4 -4
- synapse/tests/test_datamodel.py +7 -0
- synapse/tests/test_lib_agenda.py +10 -3
- synapse/tests/test_lib_aha.py +336 -490
- synapse/tests/{test_lib_hiveauth.py → test_lib_auth.py} +314 -11
- synapse/tests/test_lib_base.py +20 -0
- synapse/tests/test_lib_cell.py +210 -30
- synapse/tests/test_lib_config.py +4 -3
- synapse/tests/test_lib_httpapi.py +18 -14
- synapse/tests/test_lib_layer.py +33 -33
- synapse/tests/test_lib_link.py +42 -1
- synapse/tests/test_lib_lmdbslab.py +68 -0
- synapse/tests/test_lib_nexus.py +12 -4
- synapse/tests/test_lib_node.py +0 -7
- synapse/tests/test_lib_storm.py +45 -0
- synapse/tests/test_lib_stormlib_aha.py +35 -36
- synapse/tests/test_lib_stormlib_auth.py +21 -0
- synapse/tests/test_lib_stormlib_cell.py +4 -15
- synapse/tests/test_lib_stormlib_cortex.py +12 -12
- synapse/tests/test_lib_stormlib_gen.py +99 -0
- synapse/tests/test_lib_stormlib_imap.py +14 -3
- synapse/tests/test_lib_stormlib_model.py +108 -0
- synapse/tests/test_lib_stormlib_modelext.py +64 -0
- synapse/tests/test_lib_stormlib_smtp.py +51 -0
- synapse/tests/test_lib_stormlib_tabular.py +226 -0
- synapse/tests/test_lib_stormsvc.py +4 -1
- synapse/tests/test_lib_stormtypes.py +10 -0
- synapse/tests/test_model_base.py +3 -0
- synapse/tests/test_model_biz.py +3 -0
- synapse/tests/test_model_files.py +12 -2
- synapse/tests/test_model_inet.py +24 -0
- synapse/tests/test_tools_aha.py +78 -101
- synapse/tests/test_tools_changelog.py +196 -0
- synapse/tests/test_tools_healthcheck.py +4 -3
- synapse/tests/utils.py +87 -121
- synapse/tools/aha/clone.py +50 -0
- synapse/tools/aha/enroll.py +2 -1
- synapse/tools/backup.py +2 -2
- synapse/tools/changelog.py +776 -15
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/METADATA +48 -48
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/RECORD +95 -82
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/WHEEL +1 -1
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/LICENSE +0 -0
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/top_level.txt +0 -0
synapse/lib/cell.py
CHANGED
|
@@ -29,6 +29,7 @@ import synapse.common as s_common
|
|
|
29
29
|
import synapse.daemon as s_daemon
|
|
30
30
|
import synapse.telepath as s_telepath
|
|
31
31
|
|
|
32
|
+
import synapse.lib.auth as s_auth
|
|
32
33
|
import synapse.lib.base as s_base
|
|
33
34
|
import synapse.lib.boss as s_boss
|
|
34
35
|
import synapse.lib.coro as s_coro
|
|
@@ -50,7 +51,6 @@ import synapse.lib.schemas as s_schemas
|
|
|
50
51
|
import synapse.lib.spooled as s_spooled
|
|
51
52
|
import synapse.lib.urlhelp as s_urlhelp
|
|
52
53
|
import synapse.lib.version as s_version
|
|
53
|
-
import synapse.lib.hiveauth as s_hiveauth
|
|
54
54
|
import synapse.lib.lmdbslab as s_lmdbslab
|
|
55
55
|
import synapse.lib.thisplat as s_thisplat
|
|
56
56
|
|
|
@@ -60,6 +60,8 @@ import synapse.tools.backup as s_t_backup
|
|
|
60
60
|
|
|
61
61
|
logger = logging.getLogger(__name__)
|
|
62
62
|
|
|
63
|
+
NEXUS_VERSION = (2, 177)
|
|
64
|
+
|
|
63
65
|
SLAB_MAP_SIZE = 128 * s_const.mebibyte
|
|
64
66
|
SSLCTX_CACHE_SIZE = 64
|
|
65
67
|
|
|
@@ -891,6 +893,10 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
891
893
|
'type': 'object',
|
|
892
894
|
'hideconf': True,
|
|
893
895
|
},
|
|
896
|
+
'auth:passwd:policy': {
|
|
897
|
+
'description': 'Specify password policy/complexity requirements.',
|
|
898
|
+
'type': 'object',
|
|
899
|
+
},
|
|
894
900
|
'max:users': {
|
|
895
901
|
'default': 0,
|
|
896
902
|
'description': 'Maximum number of users allowed on system, not including root or locked/archived users (0 is no limit).',
|
|
@@ -904,7 +910,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
904
910
|
},
|
|
905
911
|
'nexslog:async': {
|
|
906
912
|
'default': True,
|
|
907
|
-
'description': '
|
|
913
|
+
'description': 'Deprecated. This option ignored.',
|
|
908
914
|
'type': 'boolean',
|
|
909
915
|
'hidedocs': True,
|
|
910
916
|
'hidecmdl': True,
|
|
@@ -961,7 +967,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
961
967
|
'type': 'string',
|
|
962
968
|
},
|
|
963
969
|
'aha:network': {
|
|
964
|
-
'description': 'The AHA service network.
|
|
970
|
+
'description': 'The AHA service network.',
|
|
965
971
|
'type': 'string',
|
|
966
972
|
},
|
|
967
973
|
'aha:registry': {
|
|
@@ -1105,6 +1111,9 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1105
1111
|
self._checkspace = s_coro.Event()
|
|
1106
1112
|
self._reloadfuncs = {} # name -> func
|
|
1107
1113
|
|
|
1114
|
+
self.nexslock = asyncio.Lock()
|
|
1115
|
+
self.netready = asyncio.Event()
|
|
1116
|
+
|
|
1108
1117
|
self.conf = self._initCellConf(conf)
|
|
1109
1118
|
|
|
1110
1119
|
self.minfree = self.conf.get('limit:disk:free')
|
|
@@ -1175,23 +1184,32 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1175
1184
|
self.backlastexc = None # err, errmsg, errtrace of last backup
|
|
1176
1185
|
|
|
1177
1186
|
if self.conf.get('mirror') and not self.conf.get('nexslog:en'):
|
|
1178
|
-
|
|
1179
|
-
raise s_exc.BadConfValu(mesg=mesg)
|
|
1187
|
+
self.modCellConf({'nexslog:en': True})
|
|
1180
1188
|
|
|
1181
|
-
# construct our nexsroot instance ( but do not start it )
|
|
1182
1189
|
await s_nexus.Pusher.__anit__(self, self.iden)
|
|
1183
1190
|
|
|
1184
1191
|
self._initCertDir()
|
|
1185
1192
|
|
|
1186
|
-
|
|
1193
|
+
await self.enter_context(s_telepath.loadTeleCell(self.dirn))
|
|
1194
|
+
|
|
1195
|
+
await self._initCellSlab(readonly=readonly)
|
|
1196
|
+
|
|
1197
|
+
# initialize network daemons (but do not listen yet)
|
|
1198
|
+
# to allow registration of callbacks and shared objects
|
|
1199
|
+
await self._initCellHttp()
|
|
1200
|
+
await self._initCellDmon()
|
|
1201
|
+
|
|
1202
|
+
await self.initServiceEarly()
|
|
1187
1203
|
|
|
1188
|
-
|
|
1189
|
-
self.onfini(root.fini)
|
|
1190
|
-
root.onfini(self.fini)
|
|
1204
|
+
nexsroot = await self._ctorNexsRoot()
|
|
1191
1205
|
|
|
1192
|
-
self.setNexsRoot(
|
|
1206
|
+
self.setNexsRoot(nexsroot)
|
|
1207
|
+
|
|
1208
|
+
async def fini():
|
|
1209
|
+
await self.nexsroot.fini()
|
|
1210
|
+
|
|
1211
|
+
self.onfini(fini)
|
|
1193
1212
|
|
|
1194
|
-
await self._initCellSlab(readonly=readonly)
|
|
1195
1213
|
self.apikeydb = self.slab.initdb('user:apikeys') # apikey -> useriden
|
|
1196
1214
|
self.usermetadb = self.slab.initdb('user:meta') # useriden + <valu> -> dict valu
|
|
1197
1215
|
self.rolemetadb = self.slab.initdb('role:meta') # roleiden + <valu> -> dict valu
|
|
@@ -1203,10 +1221,15 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1203
1221
|
|
|
1204
1222
|
self.hive = await self._initCellHive()
|
|
1205
1223
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
self.
|
|
1224
|
+
self.cellinfo = self.slab.getSafeKeyVal('cell:info')
|
|
1225
|
+
self.cellvers = self.slab.getSafeKeyVal('cell:vers')
|
|
1226
|
+
|
|
1227
|
+
await self._bumpCellVers('cell:storage', (
|
|
1228
|
+
(1, self._storCellHiveMigration),
|
|
1229
|
+
), nexs=False)
|
|
1230
|
+
|
|
1231
|
+
if self.inaugural:
|
|
1232
|
+
self.cellinfo.set('nexus:version', NEXUS_VERSION)
|
|
1210
1233
|
|
|
1211
1234
|
# Check the cell version didn't regress
|
|
1212
1235
|
if (lastver := self.cellinfo.get('cell:version')) is not None and self.VERSION < lastver:
|
|
@@ -1214,7 +1237,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1214
1237
|
logger.error(mesg)
|
|
1215
1238
|
raise s_exc.BadVersion(mesg=mesg, currver=self.VERSION, lastver=lastver)
|
|
1216
1239
|
|
|
1217
|
-
|
|
1240
|
+
self.cellinfo.set('cell:version', self.VERSION)
|
|
1218
1241
|
|
|
1219
1242
|
# Check the synapse version didn't regress
|
|
1220
1243
|
if (lastver := self.cellinfo.get('synapse:version')) is not None and s_version.version < lastver:
|
|
@@ -1222,10 +1245,14 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1222
1245
|
logger.error(mesg)
|
|
1223
1246
|
raise s_exc.BadVersion(mesg=mesg, currver=s_version.version, lastver=lastver)
|
|
1224
1247
|
|
|
1225
|
-
|
|
1248
|
+
self.cellinfo.set('synapse:version', s_version.version)
|
|
1226
1249
|
|
|
1227
|
-
|
|
1228
|
-
self.
|
|
1250
|
+
self.nexsvers = self.cellinfo.get('nexus:version', (0, 0))
|
|
1251
|
+
self.nexspatches = ()
|
|
1252
|
+
|
|
1253
|
+
await self._bumpCellVers('cell:storage', (
|
|
1254
|
+
(2, self._storCellAuthMigration),
|
|
1255
|
+
), nexs=False)
|
|
1229
1256
|
|
|
1230
1257
|
self.auth = await self._initCellAuth()
|
|
1231
1258
|
|
|
@@ -1233,8 +1260,8 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1233
1260
|
if auth_passwd is not None:
|
|
1234
1261
|
user = await self.auth.getUserByName('root')
|
|
1235
1262
|
|
|
1236
|
-
if not await user.tryPasswd(auth_passwd, nexs=False):
|
|
1237
|
-
await user.setPasswd(auth_passwd, nexs=False)
|
|
1263
|
+
if not await user.tryPasswd(auth_passwd, nexs=False, enforce_policy=False):
|
|
1264
|
+
await user.setPasswd(auth_passwd, nexs=False, enforce_policy=False)
|
|
1238
1265
|
|
|
1239
1266
|
self.boss = await s_boss.Boss.anit()
|
|
1240
1267
|
self.onfini(self.boss)
|
|
@@ -1244,11 +1271,6 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1244
1271
|
'cell': self
|
|
1245
1272
|
}
|
|
1246
1273
|
|
|
1247
|
-
# a tuple of (vers, func) tuples
|
|
1248
|
-
# it is expected that this is set by
|
|
1249
|
-
# initServiceStorage
|
|
1250
|
-
self.cellupdaters = ()
|
|
1251
|
-
|
|
1252
1274
|
self.permdefs = None
|
|
1253
1275
|
self.permlook = None
|
|
1254
1276
|
|
|
@@ -1262,17 +1284,13 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1262
1284
|
# initialize network backend infrastructure
|
|
1263
1285
|
await self._initAhaRegistry()
|
|
1264
1286
|
|
|
1265
|
-
# initialize network daemons (but do not listen yet)
|
|
1266
|
-
# to allow registration of callbacks and shared objects
|
|
1267
|
-
# within phase 2/4.
|
|
1268
|
-
await self._initCellHttp()
|
|
1269
|
-
await self._initCellDmon()
|
|
1270
|
-
|
|
1271
1287
|
# phase 2 - service storage
|
|
1272
1288
|
await self.initServiceStorage()
|
|
1273
1289
|
# phase 3 - nexus subsystem
|
|
1274
1290
|
await self.initNexusSubsystem()
|
|
1275
1291
|
|
|
1292
|
+
await self.configNexsVers()
|
|
1293
|
+
|
|
1276
1294
|
# We can now do nexus-safe operations
|
|
1277
1295
|
await self._initInauguralConfig()
|
|
1278
1296
|
|
|
@@ -1281,6 +1299,128 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1281
1299
|
# phase 5 - service networking
|
|
1282
1300
|
await self.initServiceNetwork()
|
|
1283
1301
|
|
|
1302
|
+
async def _storCellHiveMigration(self):
|
|
1303
|
+
logger.warning(f'migrating Cell ({self.getCellType()}) info out of hive')
|
|
1304
|
+
|
|
1305
|
+
async with await self.hive.open(('cellvers',)) as versnode:
|
|
1306
|
+
versdict = await versnode.dict()
|
|
1307
|
+
for key, valu in versdict.items():
|
|
1308
|
+
self.cellvers.set(key, valu)
|
|
1309
|
+
|
|
1310
|
+
async with await self.hive.open(('cellinfo',)) as infonode:
|
|
1311
|
+
infodict = await infonode.dict()
|
|
1312
|
+
for key, valu in infodict.items():
|
|
1313
|
+
self.cellinfo.set(key, valu)
|
|
1314
|
+
|
|
1315
|
+
logger.warning(f'...Cell ({self.getCellType()}) info migration complete!')
|
|
1316
|
+
|
|
1317
|
+
async def _storCellAuthMigration(self):
|
|
1318
|
+
if self.conf.get('auth:ctor') is not None:
|
|
1319
|
+
return
|
|
1320
|
+
|
|
1321
|
+
logger.warning(f'migrating Cell ({self.getCellType()}) auth out of hive')
|
|
1322
|
+
|
|
1323
|
+
authkv = self.slab.getSafeKeyVal('auth')
|
|
1324
|
+
|
|
1325
|
+
async with await self.hive.open(('auth',)) as rootnode:
|
|
1326
|
+
|
|
1327
|
+
rolekv = authkv.getSubKeyVal('role:info:')
|
|
1328
|
+
rolenamekv = authkv.getSubKeyVal('role:name:')
|
|
1329
|
+
|
|
1330
|
+
async with await rootnode.open(('roles',)) as roles:
|
|
1331
|
+
for iden, node in roles:
|
|
1332
|
+
roledict = await node.dict()
|
|
1333
|
+
roleinfo = roledict.pack()
|
|
1334
|
+
|
|
1335
|
+
roleinfo['iden'] = iden
|
|
1336
|
+
roleinfo['name'] = node.valu
|
|
1337
|
+
roleinfo['authgates'] = {}
|
|
1338
|
+
roleinfo.setdefault('admin', False)
|
|
1339
|
+
roleinfo.setdefault('rules', ())
|
|
1340
|
+
|
|
1341
|
+
rolekv.set(iden, roleinfo)
|
|
1342
|
+
rolenamekv.set(node.valu, iden)
|
|
1343
|
+
|
|
1344
|
+
userkv = authkv.getSubKeyVal('user:info:')
|
|
1345
|
+
usernamekv = authkv.getSubKeyVal('user:name:')
|
|
1346
|
+
|
|
1347
|
+
async with await rootnode.open(('users',)) as users:
|
|
1348
|
+
for iden, node in users:
|
|
1349
|
+
userdict = await node.dict()
|
|
1350
|
+
userinfo = userdict.pack()
|
|
1351
|
+
|
|
1352
|
+
userinfo['iden'] = iden
|
|
1353
|
+
userinfo['name'] = node.valu
|
|
1354
|
+
userinfo['authgates'] = {}
|
|
1355
|
+
userinfo.setdefault('admin', False)
|
|
1356
|
+
userinfo.setdefault('rules', ())
|
|
1357
|
+
userinfo.setdefault('locked', False)
|
|
1358
|
+
userinfo.setdefault('passwd', None)
|
|
1359
|
+
userinfo.setdefault('archived', False)
|
|
1360
|
+
|
|
1361
|
+
realroles = []
|
|
1362
|
+
for userrole in userinfo.get('roles', ()):
|
|
1363
|
+
if rolekv.get(userrole) is None:
|
|
1364
|
+
mesg = f'Unknown role {userrole} on user {iden} during migration, ignoring.'
|
|
1365
|
+
logger.warning(mesg)
|
|
1366
|
+
continue
|
|
1367
|
+
|
|
1368
|
+
realroles.append(userrole)
|
|
1369
|
+
|
|
1370
|
+
userinfo['roles'] = tuple(realroles)
|
|
1371
|
+
|
|
1372
|
+
userkv.set(iden, userinfo)
|
|
1373
|
+
usernamekv.set(node.valu, iden)
|
|
1374
|
+
|
|
1375
|
+
varskv = authkv.getSubKeyVal(f'user:{iden}:vars:')
|
|
1376
|
+
async with await node.open(('vars',)) as varnodes:
|
|
1377
|
+
for name, varnode in varnodes:
|
|
1378
|
+
varskv.set(name, varnode.valu)
|
|
1379
|
+
|
|
1380
|
+
profkv = authkv.getSubKeyVal(f'user:{iden}:profile:')
|
|
1381
|
+
async with await node.open(('profile',)) as profnodes:
|
|
1382
|
+
for name, profnode in profnodes:
|
|
1383
|
+
profkv.set(name, profnode.valu)
|
|
1384
|
+
|
|
1385
|
+
gatekv = authkv.getSubKeyVal('gate:info:')
|
|
1386
|
+
async with await rootnode.open(('authgates',)) as authgates:
|
|
1387
|
+
for gateiden, node in authgates:
|
|
1388
|
+
gateinfo = {
|
|
1389
|
+
'iden': gateiden,
|
|
1390
|
+
'type': node.valu
|
|
1391
|
+
}
|
|
1392
|
+
gatekv.set(gateiden, gateinfo)
|
|
1393
|
+
|
|
1394
|
+
async with await node.open(('users',)) as usernodes:
|
|
1395
|
+
for useriden, usernode in usernodes:
|
|
1396
|
+
if (user := userkv.get(useriden)) is None:
|
|
1397
|
+
mesg = f'Unknown user {useriden} on gate {gateiden} during migration, ignoring.'
|
|
1398
|
+
logger.warning(mesg)
|
|
1399
|
+
continue
|
|
1400
|
+
|
|
1401
|
+
userinfo = await usernode.dict()
|
|
1402
|
+
userdict = userinfo.pack()
|
|
1403
|
+
authkv.set(f'gate:{gateiden}:user:{useriden}', userdict)
|
|
1404
|
+
|
|
1405
|
+
user['authgates'][gateiden] = userdict
|
|
1406
|
+
userkv.set(useriden, user)
|
|
1407
|
+
|
|
1408
|
+
async with await node.open(('roles',)) as rolenodes:
|
|
1409
|
+
for roleiden, rolenode in rolenodes:
|
|
1410
|
+
if (role := rolekv.get(roleiden)) is None:
|
|
1411
|
+
mesg = f'Unknown role {roleiden} on gate {gateiden} during migration, ignoring.'
|
|
1412
|
+
logger.warning(mesg)
|
|
1413
|
+
continue
|
|
1414
|
+
|
|
1415
|
+
roleinfo = await rolenode.dict()
|
|
1416
|
+
roledict = roleinfo.pack()
|
|
1417
|
+
authkv.set(f'gate:{gateiden}:role:{roleiden}', roledict)
|
|
1418
|
+
|
|
1419
|
+
role['authgates'][gateiden] = roledict
|
|
1420
|
+
rolekv.set(roleiden, role)
|
|
1421
|
+
|
|
1422
|
+
logger.warning(f'...Cell ({self.getCellType()}) auth migration complete!')
|
|
1423
|
+
|
|
1284
1424
|
def getPermDef(self, perm):
|
|
1285
1425
|
perm = tuple(perm)
|
|
1286
1426
|
if self.permlook is None:
|
|
@@ -1412,10 +1552,52 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1412
1552
|
# ( and do so using _bumpCellVers )
|
|
1413
1553
|
pass
|
|
1414
1554
|
|
|
1555
|
+
async def setNexsVers(self, vers):
|
|
1556
|
+
if self.nexsvers < NEXUS_VERSION:
|
|
1557
|
+
await self._push('nexs:vers:set', NEXUS_VERSION)
|
|
1558
|
+
|
|
1559
|
+
@s_nexus.Pusher.onPush('nexs:vers:set')
|
|
1560
|
+
async def _setNexsVers(self, vers):
|
|
1561
|
+
if vers > self.nexsvers:
|
|
1562
|
+
self.cellvers.set('nexus:version', vers)
|
|
1563
|
+
self.nexsvers = vers
|
|
1564
|
+
await self.configNexsVers()
|
|
1565
|
+
|
|
1566
|
+
async def configNexsVers(self):
|
|
1567
|
+
for meth, orig in self.nexspatches:
|
|
1568
|
+
setattr(self, meth, orig)
|
|
1569
|
+
|
|
1570
|
+
if self.nexsvers == NEXUS_VERSION:
|
|
1571
|
+
return
|
|
1572
|
+
|
|
1573
|
+
patches = []
|
|
1574
|
+
if self.nexsvers < (2, 177):
|
|
1575
|
+
patches.extend([
|
|
1576
|
+
('popUserVarValu', self._popUserVarValuV0),
|
|
1577
|
+
('setUserVarValu', self._setUserVarValuV0),
|
|
1578
|
+
('popUserProfInfo', self._popUserProfInfoV0),
|
|
1579
|
+
('setUserProfInfo', self._setUserProfInfoV0),
|
|
1580
|
+
])
|
|
1581
|
+
|
|
1582
|
+
self.nexspatches = []
|
|
1583
|
+
for meth, repl in patches:
|
|
1584
|
+
self.nexspatches.append((meth, getattr(self, meth)))
|
|
1585
|
+
setattr(self, meth, repl)
|
|
1586
|
+
|
|
1587
|
+
async def setCellVers(self, name, vers, nexs=True):
|
|
1588
|
+
if nexs:
|
|
1589
|
+
await self._push('cell:vers:set', name, vers)
|
|
1590
|
+
else:
|
|
1591
|
+
await self._setCellVers(name, vers)
|
|
1592
|
+
|
|
1593
|
+
@s_nexus.Pusher.onPush('cell:vers:set')
|
|
1594
|
+
async def _setCellVers(self, name, vers):
|
|
1595
|
+
self.cellvers.set(name, vers)
|
|
1596
|
+
|
|
1415
1597
|
async def _bumpCellVers(self, name, updates, nexs=True):
|
|
1416
1598
|
|
|
1417
1599
|
if self.inaugural:
|
|
1418
|
-
await self.
|
|
1600
|
+
await self.setCellVers(name, updates[-1][0], nexs=nexs)
|
|
1419
1601
|
return
|
|
1420
1602
|
|
|
1421
1603
|
curv = self.cellvers.get(name, 0)
|
|
@@ -1427,7 +1609,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1427
1609
|
|
|
1428
1610
|
await callback()
|
|
1429
1611
|
|
|
1430
|
-
await self.
|
|
1612
|
+
await self.setCellVers(name, vers, nexs=nexs)
|
|
1431
1613
|
|
|
1432
1614
|
curv = vers
|
|
1433
1615
|
|
|
@@ -1436,10 +1618,10 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1436
1618
|
|
|
1437
1619
|
async def _runFreeSpaceLoop(self):
|
|
1438
1620
|
|
|
1439
|
-
nexsroot = self.getCellNexsRoot()
|
|
1440
|
-
|
|
1441
1621
|
while not self.isfini:
|
|
1442
1622
|
|
|
1623
|
+
nexsroot = self.getCellNexsRoot()
|
|
1624
|
+
|
|
1443
1625
|
self._checkspace.clear()
|
|
1444
1626
|
|
|
1445
1627
|
disk = shutil.disk_usage(self.dirn)
|
|
@@ -1486,37 +1668,61 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1486
1668
|
|
|
1487
1669
|
await self.waitfini(self.SYSCTL_CHECK_FREQ)
|
|
1488
1670
|
|
|
1489
|
-
def _getAhaAdmin(self):
|
|
1490
|
-
name = self.conf.get('aha:admin')
|
|
1491
|
-
if name is not None:
|
|
1492
|
-
return name
|
|
1493
|
-
|
|
1494
1671
|
async def _initAhaRegistry(self):
|
|
1495
1672
|
|
|
1496
|
-
|
|
1497
|
-
if
|
|
1673
|
+
ahaurls = self.conf.get('aha:registry')
|
|
1674
|
+
if ahaurls is not None:
|
|
1675
|
+
|
|
1676
|
+
await s_telepath.addAhaUrl(ahaurls)
|
|
1677
|
+
if self.ahaclient is not None:
|
|
1678
|
+
await self.ahaclient.fini()
|
|
1679
|
+
|
|
1680
|
+
async def onlink(proxy):
|
|
1681
|
+
ahauser = self.conf.get('aha:user', 'root')
|
|
1682
|
+
newurls = await proxy.getAhaUrls(user=ahauser)
|
|
1683
|
+
oldurls = self.conf.get('aha:registry')
|
|
1684
|
+
if isinstance(oldurls, str):
|
|
1685
|
+
oldurls = (oldurls,)
|
|
1686
|
+
elif isinstance(oldurls, list):
|
|
1687
|
+
oldurls = tuple(oldurls)
|
|
1688
|
+
if newurls and newurls != oldurls:
|
|
1689
|
+
if oldurls[0].startswith('tcp://'):
|
|
1690
|
+
s_common.deprecated('aha:registry: tcp:// client values.')
|
|
1691
|
+
logger.warning('tcp:// based aha:registry options are deprecated and will be removed in Synapse v3.0.0')
|
|
1692
|
+
return
|
|
1498
1693
|
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
self.ahaclient = await s_telepath.Client.anit(info.get('url'))
|
|
1502
|
-
self.ahaclient._fini_atexit = True
|
|
1503
|
-
self.onfini(self.ahaclient)
|
|
1694
|
+
self.modCellConf({'aha:registry': newurls})
|
|
1695
|
+
self.ahaclient.setBootUrls(newurls)
|
|
1504
1696
|
|
|
1505
|
-
|
|
1506
|
-
|
|
1697
|
+
self.ahaclient = await s_telepath.Client.anit(ahaurls, onlink=onlink)
|
|
1698
|
+
self.onfini(self.ahaclient)
|
|
1507
1699
|
|
|
1508
|
-
|
|
1700
|
+
async def fini():
|
|
1701
|
+
await s_telepath.delAhaUrl(ahaurls)
|
|
1509
1702
|
|
|
1703
|
+
self.ahaclient.onfini(fini)
|
|
1704
|
+
|
|
1705
|
+
ahaadmin = self.conf.get('aha:admin')
|
|
1510
1706
|
ahauser = self.conf.get('aha:user')
|
|
1511
|
-
ahanetw = self.conf.get('aha:network')
|
|
1512
1707
|
|
|
1513
|
-
ahaadmin = self._getAhaAdmin()
|
|
1514
1708
|
if ahaadmin is not None:
|
|
1515
1709
|
await self._addAdminUser(ahaadmin)
|
|
1516
1710
|
|
|
1517
1711
|
if ahauser is not None:
|
|
1518
1712
|
await self._addAdminUser(ahauser)
|
|
1519
1713
|
|
|
1714
|
+
def _getDmonListen(self):
|
|
1715
|
+
|
|
1716
|
+
lisn = self.conf.get('dmon:listen', s_common.novalu)
|
|
1717
|
+
if lisn is not s_common.novalu:
|
|
1718
|
+
return lisn
|
|
1719
|
+
|
|
1720
|
+
ahaname = self.conf.get('aha:name')
|
|
1721
|
+
ahanetw = self.conf.get('aha:network')
|
|
1722
|
+
if ahaname is not None and ahanetw is not None:
|
|
1723
|
+
hostname = f'{ahaname}.{ahanetw}'
|
|
1724
|
+
return f'ssl://0.0.0.0:0?hostname={hostname}&ca={ahanetw}'
|
|
1725
|
+
|
|
1520
1726
|
async def _addAdminUser(self, username):
|
|
1521
1727
|
# add the user in a pre-nexus compatible way
|
|
1522
1728
|
user = await self.auth.getUserByName(username)
|
|
@@ -1532,6 +1738,9 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1532
1738
|
if user.isLocked():
|
|
1533
1739
|
await user.setLocked(False, logged=False)
|
|
1534
1740
|
|
|
1741
|
+
async def initServiceEarly(self):
|
|
1742
|
+
pass
|
|
1743
|
+
|
|
1535
1744
|
async def initServiceStorage(self):
|
|
1536
1745
|
pass
|
|
1537
1746
|
|
|
@@ -1544,7 +1753,11 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1544
1753
|
if self.minfree is not None:
|
|
1545
1754
|
self.schedCoro(self._runFreeSpaceLoop())
|
|
1546
1755
|
|
|
1547
|
-
async def
|
|
1756
|
+
async def _bindDmonListen(self):
|
|
1757
|
+
|
|
1758
|
+
# functionalized so downstream code can bind early.
|
|
1759
|
+
if self.sockaddr is not None:
|
|
1760
|
+
return
|
|
1548
1761
|
|
|
1549
1762
|
# start a unix local socket daemon listener
|
|
1550
1763
|
sockpath = os.path.join(self.dirn, 'sock')
|
|
@@ -1552,24 +1765,25 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1552
1765
|
|
|
1553
1766
|
try:
|
|
1554
1767
|
await self.dmon.listen(sockurl)
|
|
1555
|
-
except asyncio.CancelledError: # pragma: no cover TODO: remove once >= py 3.8 only
|
|
1556
|
-
raise
|
|
1557
1768
|
except OSError as e:
|
|
1558
1769
|
logger.error(f'Failed to listen on unix socket at: [{sockpath}][{e}]')
|
|
1559
1770
|
logger.error('LOCAL UNIX SOCKET WILL BE UNAVAILABLE')
|
|
1560
1771
|
except Exception: # pragma: no cover
|
|
1561
1772
|
logging.exception('Unknown dmon listen error.')
|
|
1562
|
-
raise
|
|
1563
1773
|
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
turl = self.conf.get('dmon:listen')
|
|
1774
|
+
turl = self._getDmonListen()
|
|
1567
1775
|
if turl is not None:
|
|
1568
|
-
self.sockaddr = await self.dmon.listen(turl)
|
|
1569
1776
|
logger.info(f'dmon listening: {turl}')
|
|
1777
|
+
self.sockaddr = await self.dmon.listen(turl)
|
|
1778
|
+
|
|
1779
|
+
async def initServiceNetwork(self):
|
|
1780
|
+
|
|
1781
|
+
await self._bindDmonListen()
|
|
1570
1782
|
|
|
1571
1783
|
await self._initAhaService()
|
|
1572
1784
|
|
|
1785
|
+
self.netready.set()
|
|
1786
|
+
|
|
1573
1787
|
port = self.conf.get('https:port')
|
|
1574
1788
|
if port is not None:
|
|
1575
1789
|
await self.addHttpsPort(port)
|
|
@@ -1628,27 +1842,34 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1628
1842
|
if ahaname is None:
|
|
1629
1843
|
return
|
|
1630
1844
|
|
|
1631
|
-
ahalead = self.conf.get('aha:leader')
|
|
1632
1845
|
ahanetw = self.conf.get('aha:network')
|
|
1846
|
+
if ahanetw is None:
|
|
1847
|
+
return
|
|
1633
1848
|
|
|
1634
1849
|
ahainfo = await self.getAhaInfo()
|
|
1635
1850
|
if ahainfo is None:
|
|
1636
1851
|
return
|
|
1637
1852
|
|
|
1853
|
+
ahalead = self.conf.get('aha:leader')
|
|
1854
|
+
|
|
1638
1855
|
self.ahasvcname = f'{ahaname}.{ahanetw}'
|
|
1639
1856
|
|
|
1640
1857
|
async def _runAhaRegLoop():
|
|
1641
1858
|
|
|
1642
1859
|
while not self.isfini:
|
|
1860
|
+
|
|
1643
1861
|
try:
|
|
1644
1862
|
proxy = await self.ahaclient.proxy()
|
|
1863
|
+
|
|
1645
1864
|
info = await self.getAhaInfo()
|
|
1646
1865
|
await proxy.addAhaSvc(ahaname, info, network=ahanetw)
|
|
1647
1866
|
if self.isactive and ahalead is not None:
|
|
1648
1867
|
await proxy.addAhaSvc(ahalead, info, network=ahanetw)
|
|
1868
|
+
|
|
1649
1869
|
except Exception as e:
|
|
1650
1870
|
logger.exception(f'Error registering service {self.ahasvcname} with AHA: {e}')
|
|
1651
1871
|
await self.waitfini(1)
|
|
1872
|
+
|
|
1652
1873
|
else:
|
|
1653
1874
|
await proxy.waitfini()
|
|
1654
1875
|
|
|
@@ -1729,6 +1950,11 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1729
1950
|
async def setNexsIndx(self, indx):
|
|
1730
1951
|
return await self.nexsroot.setindex(indx)
|
|
1731
1952
|
|
|
1953
|
+
def getMyUrl(self, user='root'):
|
|
1954
|
+
host = self.conf.req('aha:name')
|
|
1955
|
+
network = self.conf.req('aha:network')
|
|
1956
|
+
return f'aha://{host}.{network}'
|
|
1957
|
+
|
|
1732
1958
|
async def promote(self, graceful=False):
|
|
1733
1959
|
'''
|
|
1734
1960
|
Transform this cell from a passive follower to
|
|
@@ -1739,48 +1965,39 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1739
1965
|
mesg = 'promote() called on non-mirror'
|
|
1740
1966
|
raise s_exc.BadConfValu(mesg=mesg)
|
|
1741
1967
|
|
|
1742
|
-
|
|
1743
|
-
logger.warning(f'PROMOTION: Performing leadership promotion graceful={graceful}
|
|
1968
|
+
_dispname = f' ahaname={self.conf.get("aha:name")}' if self.conf.get('aha:name') else ''
|
|
1969
|
+
logger.warning(f'PROMOTION: Performing leadership promotion graceful={graceful}{_dispname}.')
|
|
1744
1970
|
|
|
1745
1971
|
if graceful:
|
|
1746
1972
|
|
|
1747
|
-
|
|
1748
|
-
mesg = 'Cannot gracefully promote without aha:name configured.'
|
|
1749
|
-
raise s_exc.BadArg(mesg=mesg)
|
|
1750
|
-
|
|
1751
|
-
ahanetw = self.conf.get('aha:network')
|
|
1752
|
-
if ahanetw is None: # pragma: no cover
|
|
1753
|
-
mesg = 'Cannot gracefully promote without aha:network configured.'
|
|
1754
|
-
raise s_exc.BadArg(mesg=mesg)
|
|
1973
|
+
myurl = self.getMyUrl()
|
|
1755
1974
|
|
|
1756
|
-
|
|
1757
|
-
logger.debug(f'PROMOTION: Connecting to {mirurl} to request leadership handoff to ahaname={ahaname}')
|
|
1975
|
+
logger.debug(f'PROMOTION: Connecting to {mirurl} to request leadership handoff{_dispname}.')
|
|
1758
1976
|
async with await s_telepath.openurl(mirurl) as lead:
|
|
1759
|
-
logger.debug(f'PROMOTION: Requesting leadership handoff to ahaname={ahaname}')
|
|
1760
1977
|
await lead.handoff(myurl)
|
|
1761
|
-
logger.warning(f'PROMOTION: Completed leadership handoff to
|
|
1978
|
+
logger.warning(f'PROMOTION: Completed leadership handoff to {myurl}{_dispname}')
|
|
1762
1979
|
return
|
|
1763
1980
|
|
|
1764
|
-
logger.debug(f'PROMOTION: Clearing mirror configuration
|
|
1981
|
+
logger.debug(f'PROMOTION: Clearing mirror configuration{_dispname}.')
|
|
1765
1982
|
self.modCellConf({'mirror': None})
|
|
1766
1983
|
|
|
1767
|
-
logger.debug(f'PROMOTION: Promoting the nexus root
|
|
1984
|
+
logger.debug(f'PROMOTION: Promoting the nexus root{_dispname}.')
|
|
1768
1985
|
await self.nexsroot.promote()
|
|
1769
1986
|
|
|
1770
|
-
logger.debug(f'PROMOTION: Setting the cell as active
|
|
1987
|
+
logger.debug(f'PROMOTION: Setting the cell as active{_dispname}.')
|
|
1771
1988
|
await self.setCellActive(True)
|
|
1772
1989
|
|
|
1773
|
-
logger.warning(f'PROMOTION: Finished leadership promotion
|
|
1990
|
+
logger.warning(f'PROMOTION: Finished leadership promotion{_dispname}.')
|
|
1774
1991
|
|
|
1775
1992
|
async def handoff(self, turl, timeout=30):
|
|
1776
1993
|
'''
|
|
1777
1994
|
Hand off leadership to a mirror in a transactional fashion.
|
|
1778
1995
|
'''
|
|
1779
|
-
|
|
1780
|
-
logger.warning(f'HANDOFF: Performing leadership handoff to {s_urlhelp.sanitizeUrl(turl)}
|
|
1996
|
+
_dispname = f' ahaname={self.conf.get("aha:name")}' if self.conf.get('aha:name') else ''
|
|
1997
|
+
logger.warning(f'HANDOFF: Performing leadership handoff to {s_urlhelp.sanitizeUrl(turl)}{_dispname}.')
|
|
1781
1998
|
async with await s_telepath.openurl(turl) as cell:
|
|
1782
1999
|
|
|
1783
|
-
logger.debug(f'HANDOFF: Connected to {s_urlhelp.sanitizeUrl(turl)}
|
|
2000
|
+
logger.debug(f'HANDOFF: Connected to {s_urlhelp.sanitizeUrl(turl)}{_dispname}.')
|
|
1784
2001
|
|
|
1785
2002
|
if self.iden != await cell.getCellIden(): # pragma: no cover
|
|
1786
2003
|
mesg = 'Mirror handoff remote cell iden does not match!'
|
|
@@ -1790,33 +2007,34 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1790
2007
|
mesg = 'Cannot handoff mirror leadership to myself!'
|
|
1791
2008
|
raise s_exc.BadArg(mesg=mesg)
|
|
1792
2009
|
|
|
1793
|
-
logger.debug(f'HANDOFF: Obtaining nexus
|
|
2010
|
+
logger.debug(f'HANDOFF: Obtaining nexus lock{_dispname}.')
|
|
1794
2011
|
|
|
1795
|
-
async with self.
|
|
2012
|
+
async with self.nexslock:
|
|
1796
2013
|
|
|
1797
|
-
logger.debug(f'HANDOFF: Obtained nexus
|
|
2014
|
+
logger.debug(f'HANDOFF: Obtained nexus lock{_dispname}.')
|
|
1798
2015
|
indx = await self.getNexsIndx()
|
|
1799
2016
|
|
|
1800
|
-
logger.debug(f'HANDOFF: Waiting {timeout} seconds for mirror to reach {indx=}
|
|
2017
|
+
logger.debug(f'HANDOFF: Waiting {timeout} seconds for mirror to reach {indx=}{_dispname}.')
|
|
1801
2018
|
if not await cell.waitNexsOffs(indx - 1, timeout=timeout): # pragma: no cover
|
|
1802
2019
|
mndx = await cell.getNexsIndx()
|
|
1803
2020
|
mesg = f'Remote mirror did not catch up in time: {mndx}/{indx}.'
|
|
1804
2021
|
raise s_exc.NotReady(mesg=mesg)
|
|
1805
2022
|
|
|
1806
|
-
logger.debug(f'HANDOFF: Mirror has caught up to the current leader, performing promotion
|
|
2023
|
+
logger.debug(f'HANDOFF: Mirror has caught up to the current leader, performing promotion{_dispname}.')
|
|
1807
2024
|
await cell.promote()
|
|
1808
2025
|
|
|
1809
|
-
logger.debug(f'HANDOFF: Setting the service as inactive
|
|
2026
|
+
logger.debug(f'HANDOFF: Setting the service as inactive{_dispname}.')
|
|
1810
2027
|
await self.setCellActive(False)
|
|
1811
2028
|
|
|
1812
|
-
logger.debug(f'HANDOFF: Configuring service to
|
|
2029
|
+
logger.debug(f'HANDOFF: Configuring service to sync from new leader{_dispname}.')
|
|
1813
2030
|
self.modCellConf({'mirror': turl})
|
|
1814
2031
|
|
|
1815
|
-
logger.debug(f'HANDOFF: Restarting the nexus
|
|
2032
|
+
logger.debug(f'HANDOFF: Restarting the nexus{_dispname}.')
|
|
1816
2033
|
await self.nexsroot.startup()
|
|
1817
2034
|
|
|
1818
|
-
logger.debug(f'HANDOFF: Released nexus
|
|
1819
|
-
|
|
2035
|
+
logger.debug(f'HANDOFF: Released nexus lock{_dispname}.')
|
|
2036
|
+
|
|
2037
|
+
logger.warning(f'HANDOFF: Done performing the leadership handoff with {s_urlhelp.sanitizeUrl(turl)}{_dispname}.')
|
|
1820
2038
|
|
|
1821
2039
|
async def reqAhaProxy(self, timeout=None):
|
|
1822
2040
|
if self.ahaclient is None:
|
|
@@ -1849,7 +2067,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1849
2067
|
await proxy.fini()
|
|
1850
2068
|
return
|
|
1851
2069
|
|
|
1852
|
-
ahanetw = self.conf.
|
|
2070
|
+
ahanetw = self.conf.req('aha:network')
|
|
1853
2071
|
try:
|
|
1854
2072
|
await proxy.addAhaSvc(ahalead, ahainfo, network=ahanetw)
|
|
1855
2073
|
except asyncio.CancelledError: # pragma: no cover
|
|
@@ -1959,6 +2177,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
1959
2177
|
self.onfini(self.activebase)
|
|
1960
2178
|
self._fireActiveCoros()
|
|
1961
2179
|
await self._execCellUpdates()
|
|
2180
|
+
await self.setNexsVers(NEXUS_VERSION)
|
|
1962
2181
|
await self.initServiceActive()
|
|
1963
2182
|
else:
|
|
1964
2183
|
await self._killActiveCoros()
|
|
@@ -2115,7 +2334,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2115
2334
|
|
|
2116
2335
|
try:
|
|
2117
2336
|
|
|
2118
|
-
async with self.
|
|
2337
|
+
async with self.nexslock:
|
|
2119
2338
|
|
|
2120
2339
|
logger.debug('Syncing LMDB Slabs')
|
|
2121
2340
|
|
|
@@ -2361,7 +2580,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2361
2580
|
self.backupstreaming = False
|
|
2362
2581
|
|
|
2363
2582
|
async def isUserAllowed(self, iden, perm, gateiden=None, default=False):
|
|
2364
|
-
user = self.auth.user(iden) # type:
|
|
2583
|
+
user = self.auth.user(iden) # type: s_auth.User
|
|
2365
2584
|
if user is None:
|
|
2366
2585
|
return False
|
|
2367
2586
|
|
|
@@ -2386,36 +2605,59 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2386
2605
|
|
|
2387
2606
|
async def getUserProfile(self, iden):
|
|
2388
2607
|
user = await self.auth.reqUser(iden)
|
|
2389
|
-
return user.profile.
|
|
2608
|
+
return dict(user.profile.items())
|
|
2390
2609
|
|
|
2391
|
-
async def getUserProfInfo(self, iden, name):
|
|
2610
|
+
async def getUserProfInfo(self, iden, name, default=None):
|
|
2392
2611
|
user = await self.auth.reqUser(iden)
|
|
2393
|
-
return user.profile.get(name)
|
|
2612
|
+
return user.profile.get(name, defv=default)
|
|
2613
|
+
|
|
2614
|
+
async def _setUserProfInfoV0(self, iden, name, valu):
|
|
2615
|
+
path = ('auth', 'users', iden, 'profile', name)
|
|
2616
|
+
return await self.hive._push('hive:set', path, valu)
|
|
2394
2617
|
|
|
2395
2618
|
async def setUserProfInfo(self, iden, name, valu):
|
|
2396
2619
|
user = await self.auth.reqUser(iden)
|
|
2397
|
-
return await user.
|
|
2620
|
+
return await user.setProfileValu(name, valu)
|
|
2621
|
+
|
|
2622
|
+
async def _popUserProfInfoV0(self, iden, name, default=None):
|
|
2623
|
+
path = ('auth', 'users', iden, 'profile', name)
|
|
2624
|
+
return await self.hive._push('hive:pop', path)
|
|
2398
2625
|
|
|
2399
2626
|
async def popUserProfInfo(self, iden, name, default=None):
|
|
2400
2627
|
user = await self.auth.reqUser(iden)
|
|
2401
|
-
return await user.
|
|
2628
|
+
return await user.popProfileValu(name, default=default)
|
|
2402
2629
|
|
|
2403
2630
|
async def iterUserVars(self, iden):
|
|
2404
2631
|
user = await self.auth.reqUser(iden)
|
|
2405
2632
|
for item in user.vars.items():
|
|
2406
2633
|
yield item
|
|
2634
|
+
await asyncio.sleep(0)
|
|
2407
2635
|
|
|
2408
|
-
async def
|
|
2636
|
+
async def iterUserProfInfo(self, iden):
|
|
2409
2637
|
user = await self.auth.reqUser(iden)
|
|
2410
|
-
|
|
2638
|
+
for item in user.profile.items():
|
|
2639
|
+
yield item
|
|
2640
|
+
await asyncio.sleep(0)
|
|
2641
|
+
|
|
2642
|
+
async def getUserVarValu(self, iden, name, default=None):
|
|
2643
|
+
user = await self.auth.reqUser(iden)
|
|
2644
|
+
return user.vars.get(name, defv=default)
|
|
2645
|
+
|
|
2646
|
+
async def _setUserVarValuV0(self, iden, name, valu):
|
|
2647
|
+
path = ('auth', 'users', iden, 'vars', name)
|
|
2648
|
+
return await self.hive._push('hive:set', path, valu)
|
|
2411
2649
|
|
|
2412
2650
|
async def setUserVarValu(self, iden, name, valu):
|
|
2413
2651
|
user = await self.auth.reqUser(iden)
|
|
2414
|
-
return await user.
|
|
2652
|
+
return await user.setVarValu(name, valu)
|
|
2653
|
+
|
|
2654
|
+
async def _popUserVarValuV0(self, iden, name, default=None):
|
|
2655
|
+
path = ('auth', 'users', iden, 'vars', name)
|
|
2656
|
+
return await self.hive._push('hive:pop', path)
|
|
2415
2657
|
|
|
2416
2658
|
async def popUserVarValu(self, iden, name, default=None):
|
|
2417
2659
|
user = await self.auth.reqUser(iden)
|
|
2418
|
-
return await user.
|
|
2660
|
+
return await user.popVarValu(name, default=default)
|
|
2419
2661
|
|
|
2420
2662
|
async def addUserRule(self, iden, rule, indx=None, gateiden=None):
|
|
2421
2663
|
user = await self.auth.reqUser(iden)
|
|
@@ -2807,7 +3049,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2807
3049
|
sslctx = self.initSslCtx(certpath, pkeypath)
|
|
2808
3050
|
|
|
2809
3051
|
kwargs = {
|
|
2810
|
-
'xheaders': self.conf.
|
|
3052
|
+
'xheaders': self.conf.req('https:parse:proxy:remoteip')
|
|
2811
3053
|
}
|
|
2812
3054
|
serv = self.wapp.listen(port, address=addr, ssl_options=sslctx, **kwargs)
|
|
2813
3055
|
self.httpds.append(serv)
|
|
@@ -2958,9 +3200,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2958
3200
|
|
|
2959
3201
|
async def _initCellDmon(self):
|
|
2960
3202
|
|
|
2961
|
-
ahainfo = {
|
|
2962
|
-
'name': self.ahasvcname
|
|
2963
|
-
}
|
|
3203
|
+
ahainfo = {'name': self.ahasvcname}
|
|
2964
3204
|
|
|
2965
3205
|
self.dmon = await s_daemon.Daemon.anit(ahainfo=ahainfo)
|
|
2966
3206
|
self.dmon.share('*', self)
|
|
@@ -2969,11 +3209,17 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2969
3209
|
|
|
2970
3210
|
async def _initCellHive(self):
|
|
2971
3211
|
db = self.slab.initdb('hive')
|
|
2972
|
-
hive = await s_hive.SlabHive.anit(self.slab, db=db, nexsroot=self.getCellNexsRoot())
|
|
3212
|
+
hive = await s_hive.SlabHive.anit(self.slab, db=db, nexsroot=self.getCellNexsRoot(), cell=self)
|
|
2973
3213
|
self.onfini(hive)
|
|
2974
3214
|
|
|
2975
3215
|
return hive
|
|
2976
3216
|
|
|
3217
|
+
async def _initSlabFile(self, path, readonly=False):
|
|
3218
|
+
slab = await s_lmdbslab.Slab.anit(path, map_size=SLAB_MAP_SIZE, readonly=readonly)
|
|
3219
|
+
slab.addResizeCallback(self.checkFreeSpace)
|
|
3220
|
+
self.onfini(slab)
|
|
3221
|
+
return slab
|
|
3222
|
+
|
|
2977
3223
|
async def _initCellSlab(self, readonly=False):
|
|
2978
3224
|
|
|
2979
3225
|
s_common.gendir(self.dirn, 'slabs')
|
|
@@ -2985,44 +3231,31 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
2985
3231
|
_slab.initdb('hive')
|
|
2986
3232
|
await _slab.fini()
|
|
2987
3233
|
|
|
2988
|
-
self.slab = await
|
|
2989
|
-
self.slab.addResizeCallback(self.checkFreeSpace)
|
|
2990
|
-
|
|
2991
|
-
self.onfini(self.slab.fini)
|
|
3234
|
+
self.slab = await self._initSlabFile(path)
|
|
2992
3235
|
|
|
2993
3236
|
async def _initCellAuth(self):
|
|
2994
3237
|
|
|
3238
|
+
# Add callbacks
|
|
3239
|
+
self.on('user:del', self._onUserDelEvnt)
|
|
3240
|
+
|
|
2995
3241
|
authctor = self.conf.get('auth:ctor')
|
|
2996
3242
|
if authctor is not None:
|
|
2997
3243
|
s_common.deprecated('auth:ctor cell config option', curv='2.157.0')
|
|
2998
3244
|
ctor = s_dyndeps.getDynLocal(authctor)
|
|
2999
|
-
|
|
3000
|
-
else:
|
|
3001
|
-
auth = await self._initCellHiveAuth()
|
|
3002
|
-
|
|
3003
|
-
# Add callbacks
|
|
3004
|
-
self.on('user:del', self._onUserDelEvnt)
|
|
3005
|
-
|
|
3006
|
-
return auth
|
|
3007
|
-
|
|
3008
|
-
def getCellNexsRoot(self):
|
|
3009
|
-
# the "cell scope" nexusroot only exists if we are *not* embedded
|
|
3010
|
-
# (aka we dont have a self.cellparent)
|
|
3011
|
-
if self.cellparent is None:
|
|
3012
|
-
return self.nexsroot
|
|
3013
|
-
|
|
3014
|
-
async def _initCellHiveAuth(self):
|
|
3245
|
+
return await ctor(self)
|
|
3015
3246
|
|
|
3016
3247
|
maxusers = self.conf.get('max:users')
|
|
3248
|
+
policy = self.conf.get('auth:passwd:policy')
|
|
3017
3249
|
|
|
3018
3250
|
seed = s_common.guid((self.iden, 'hive', 'auth'))
|
|
3019
3251
|
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3252
|
+
auth = await s_auth.Auth.anit(
|
|
3253
|
+
self.slab,
|
|
3254
|
+
'auth',
|
|
3023
3255
|
seed=seed,
|
|
3024
3256
|
nexsroot=self.getCellNexsRoot(),
|
|
3025
|
-
maxusers=maxusers
|
|
3257
|
+
maxusers=maxusers,
|
|
3258
|
+
policy=policy
|
|
3026
3259
|
)
|
|
3027
3260
|
|
|
3028
3261
|
auth.link(self.dist)
|
|
@@ -3035,6 +3268,12 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3035
3268
|
self.onfini(auth.fini)
|
|
3036
3269
|
return auth
|
|
3037
3270
|
|
|
3271
|
+
def getCellNexsRoot(self):
|
|
3272
|
+
# the "cell scope" nexusroot only exists if we are *not* embedded
|
|
3273
|
+
# (aka we dont have a self.cellparent)
|
|
3274
|
+
if self.cellparent is None:
|
|
3275
|
+
return self.nexsroot
|
|
3276
|
+
|
|
3038
3277
|
async def _initInauguralConfig(self):
|
|
3039
3278
|
if self.inaugural:
|
|
3040
3279
|
icfg = self.conf.get('inaugural')
|
|
@@ -3044,7 +3283,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3044
3283
|
name = rnfo.get('name')
|
|
3045
3284
|
logger.debug(f'Adding inaugural role {name}')
|
|
3046
3285
|
iden = s_common.guid((self.iden, 'auth', 'role', name))
|
|
3047
|
-
role = await self.auth.addRole(name, iden) # type:
|
|
3286
|
+
role = await self.auth.addRole(name, iden) # type: s_auth.Role
|
|
3048
3287
|
|
|
3049
3288
|
for rule in rnfo.get('rules', ()):
|
|
3050
3289
|
await role.addRule(rule)
|
|
@@ -3054,7 +3293,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3054
3293
|
email = unfo.get('email')
|
|
3055
3294
|
iden = s_common.guid((self.iden, 'auth', 'user', name))
|
|
3056
3295
|
logger.debug(f'Adding inaugural user {name}')
|
|
3057
|
-
user = await self.auth.addUser(name, email=email, iden=iden) # type:
|
|
3296
|
+
user = await self.auth.addUser(name, email=email, iden=iden) # type: s_auth.User
|
|
3058
3297
|
|
|
3059
3298
|
if unfo.get('admin'):
|
|
3060
3299
|
await user.setAdmin(True)
|
|
@@ -3221,7 +3460,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3221
3460
|
|
|
3222
3461
|
Args:
|
|
3223
3462
|
link (s_link.Link): The link object.
|
|
3224
|
-
user (
|
|
3463
|
+
user (s_auth.User): The heavy user object.
|
|
3225
3464
|
path (str): The path requested.
|
|
3226
3465
|
|
|
3227
3466
|
Notes:
|
|
@@ -3245,7 +3484,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3245
3484
|
'''
|
|
3246
3485
|
extra = {**kwargs}
|
|
3247
3486
|
sess = s_scope.get('sess') # type: s_daemon.Sess
|
|
3248
|
-
user = s_scope.get('user') # type:
|
|
3487
|
+
user = s_scope.get('user') # type: s_auth.User
|
|
3249
3488
|
if user:
|
|
3250
3489
|
extra['user'] = user.iden
|
|
3251
3490
|
extra['username'] = user.name
|
|
@@ -3402,13 +3641,24 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3402
3641
|
return pars
|
|
3403
3642
|
|
|
3404
3643
|
async def _initCellBoot(self):
|
|
3644
|
+
# NOTE: best hook point for custom provisioning
|
|
3405
3645
|
|
|
3406
|
-
pnfo = await self._bootCellProv()
|
|
3646
|
+
isok, pnfo = await self._bootCellProv()
|
|
3407
3647
|
|
|
3408
3648
|
# check this before we setup loadTeleCell()
|
|
3409
3649
|
if not self._mustBootMirror():
|
|
3410
3650
|
return
|
|
3411
3651
|
|
|
3652
|
+
if not isok:
|
|
3653
|
+
# The way that we get to this requires the following states to be true:
|
|
3654
|
+
# 1. self.dirn/cell.guid file is NOT present in the service directory.
|
|
3655
|
+
# 2. mirror config is present.
|
|
3656
|
+
# 3. aha:provision config is not set OR the aha:provision guid matches the self.dirn/prov.done file.
|
|
3657
|
+
mesg = 'Service has been configured to boot from an upstream mirror, but has entered into an invalid ' \
|
|
3658
|
+
'state. This may have been caused by manipulation of the service storage or an error during a ' \
|
|
3659
|
+
f'backup / restore operation. {pnfo.get("mesg")}'
|
|
3660
|
+
raise s_exc.FatalErr(mesg=mesg)
|
|
3661
|
+
|
|
3412
3662
|
async with s_telepath.loadTeleCell(self.dirn):
|
|
3413
3663
|
await self._bootCellMirror(pnfo)
|
|
3414
3664
|
|
|
@@ -3540,7 +3790,8 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3540
3790
|
|
|
3541
3791
|
provurl = self.conf.get('aha:provision')
|
|
3542
3792
|
if provurl is None:
|
|
3543
|
-
return
|
|
3793
|
+
return False, {'mesg': 'No aha:provision configuration has been provided to allow the service to '
|
|
3794
|
+
'bootstrap via AHA.'}
|
|
3544
3795
|
|
|
3545
3796
|
doneiden = None
|
|
3546
3797
|
|
|
@@ -3553,7 +3804,8 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3553
3804
|
providen = urlinfo.get('path').strip('/')
|
|
3554
3805
|
|
|
3555
3806
|
if doneiden == providen:
|
|
3556
|
-
return
|
|
3807
|
+
return False, {'mesg': f'The aha:provision URL guid matches the service prov.done guid, '
|
|
3808
|
+
f'aha:provision={provurl}'}
|
|
3557
3809
|
|
|
3558
3810
|
logger.info(f'Provisioning {self.getCellType()} from AHA service.')
|
|
3559
3811
|
|
|
@@ -3613,7 +3865,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3613
3865
|
|
|
3614
3866
|
logger.info(f'Done provisioning {self.getCellType()} AHA service.')
|
|
3615
3867
|
|
|
3616
|
-
return provconf, providen
|
|
3868
|
+
return True, {'conf': provconf, 'iden': providen}
|
|
3617
3869
|
|
|
3618
3870
|
async def _bootProvConf(self, provconf):
|
|
3619
3871
|
'''
|
|
@@ -3695,23 +3947,14 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3695
3947
|
await self.nexsroot.enNexsLog()
|
|
3696
3948
|
await self.sync()
|
|
3697
3949
|
|
|
3698
|
-
async def
|
|
3699
|
-
# this function must assume almost nothing is initialized
|
|
3700
|
-
# but that's ok since it will only run rarely.
|
|
3701
|
-
# It assumes it has a tuple of (provisioning configuration, provisioning iden) available
|
|
3702
|
-
murl = self.conf.reqConfValu('mirror')
|
|
3703
|
-
provconf, providen = pnfo
|
|
3704
|
-
|
|
3705
|
-
logger.warning(f'Bootstrap mirror from: {murl} (this could take a while!)')
|
|
3950
|
+
async def _initCloneCell(self, proxy):
|
|
3706
3951
|
|
|
3707
3952
|
tarpath = s_common.genpath(self.dirn, 'tmp', 'bootstrap.tgz')
|
|
3708
|
-
|
|
3709
3953
|
try:
|
|
3710
3954
|
|
|
3711
|
-
|
|
3712
|
-
await cell.readyToMirror()
|
|
3955
|
+
await proxy.readyToMirror()
|
|
3713
3956
|
with s_common.genfile(tarpath) as fd:
|
|
3714
|
-
async for byts in
|
|
3957
|
+
async for byts in proxy.iterNewBackupArchive(remove=True):
|
|
3715
3958
|
fd.write(byts)
|
|
3716
3959
|
|
|
3717
3960
|
with tarfile.open(tarpath) as tgz:
|
|
@@ -3726,6 +3969,18 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3726
3969
|
if os.path.isfile(tarpath):
|
|
3727
3970
|
os.unlink(tarpath)
|
|
3728
3971
|
|
|
3972
|
+
async def _bootCellMirror(self, pnfo):
|
|
3973
|
+
# this function must assume almost nothing is initialized
|
|
3974
|
+
# but that's ok since it will only run rarely.
|
|
3975
|
+
# It assumes it has a tuple of (provisioning configuration, provisioning iden) available
|
|
3976
|
+
murl = self.conf.req('mirror')
|
|
3977
|
+
provconf, providen = pnfo.get('conf'), pnfo.get('iden')
|
|
3978
|
+
|
|
3979
|
+
logger.warning(f'Bootstrap mirror from: {murl} (this could take a while!)')
|
|
3980
|
+
|
|
3981
|
+
async with await s_telepath.openurl(murl) as proxy:
|
|
3982
|
+
await self._initCloneCell(proxy)
|
|
3983
|
+
|
|
3729
3984
|
# Remove aha:provision from cell.yaml if it exists and the iden differs.
|
|
3730
3985
|
mnfo = s_common.yamlload(self.dirn, 'cell.yaml')
|
|
3731
3986
|
if mnfo:
|
|
@@ -3821,15 +4076,12 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3821
4076
|
|
|
3822
4077
|
try:
|
|
3823
4078
|
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
lisn = cell.conf.get('dmon:listen')
|
|
3829
|
-
if lisn is None:
|
|
3830
|
-
lisn = cell.getLocalUrl()
|
|
4079
|
+
turl = cell._getDmonListen()
|
|
4080
|
+
if turl is None:
|
|
4081
|
+
turl = opts.telepath
|
|
4082
|
+
await cell.dmon.listen(turl)
|
|
3831
4083
|
|
|
3832
|
-
|
|
4084
|
+
logger.info(f'...{cell.getCellType()} API (telepath): {turl}')
|
|
3833
4085
|
|
|
3834
4086
|
if 'https:port' not in cell.conf:
|
|
3835
4087
|
await cell.addHttpsPort(opts.https)
|
|
@@ -3997,6 +4249,12 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
3997
4249
|
async def _onLoadHiveTree(self, tree, path, trim):
|
|
3998
4250
|
return await self.hive.loadHiveTree(tree, path=path, trim=trim)
|
|
3999
4251
|
|
|
4252
|
+
async def iterSlabData(self, name, prefix=''):
|
|
4253
|
+
slabkv = self.slab.getSafeKeyVal(name, prefix=prefix, create=False)
|
|
4254
|
+
for key, valu in slabkv.items():
|
|
4255
|
+
yield key, valu
|
|
4256
|
+
await asyncio.sleep(0)
|
|
4257
|
+
|
|
4000
4258
|
@s_nexus.Pusher.onPushAuto('sync')
|
|
4001
4259
|
async def sync(self):
|
|
4002
4260
|
'''
|
|
@@ -4065,6 +4323,7 @@ class Cell(s_nexus.Pusher, s_telepath.Aware):
|
|
|
4065
4323
|
'type': self.getCellType(),
|
|
4066
4324
|
'iden': self.getCellIden(),
|
|
4067
4325
|
'active': self.isactive,
|
|
4326
|
+
'started': self.startms,
|
|
4068
4327
|
'ready': self.nexsroot.ready.is_set(),
|
|
4069
4328
|
'commit': self.COMMIT,
|
|
4070
4329
|
'version': self.VERSION,
|