From e19ce060d8d1bb20f29cb196f360fe25f30fd14b Mon Sep 17 00:00:00 2001 From: Tobias Kurze Date: Thu, 14 Nov 2019 14:15:36 +0100 Subject: [PATCH] exception decorator and mail send for errors and changes to rec state checker --- Pipfile | 2 + Pipfile.lock | 244 +++++++++++++--------- backend/__init__.py | 30 ++- backend/config.py | Bin 4073 -> 4256 bytes backend/recorder_adapters/__init__.py | 3 + backend/recorder_adapters/epiphan_base.py | 11 +- backend/recorder_adapters/extron_smp.py | 8 +- backend/serve_frontend.py | 1 + backend/tools/exception_decorator.py | 13 ++ backend/tools/send_mail.py | 45 ++++ backend/tools/simple_state_checker.py | 84 +++++--- logs/app.log.2019-11-13 | 0 12 files changed, 305 insertions(+), 136 deletions(-) create mode 100644 backend/tools/exception_decorator.py create mode 100644 backend/tools/send_mail.py create mode 100644 logs/app.log.2019-11-13 diff --git a/Pipfile b/Pipfile index 9cb0957..e892b73 100644 --- a/Pipfile +++ b/Pipfile @@ -27,6 +27,8 @@ html5lib = "*" beautifulsoup4 = "*" flask-socketio = "*" eventlet = "*" +ics = "*" +coloredlogs = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 2ee09d7..462e236 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "1eb275e98d59f5fec7c926d01669aafaa57050844b8a5f35aebf396bcbdaeaa5" + "sha256": "f202c24683975df8c5539037b48a09753cfdfcab4669da6c6d35ffef97a4eb63" }, "pipfile-spec": 6, "requires": { @@ -25,9 +25,9 @@ }, "alembic": { "hashes": [ - "sha256:9f907d7e8b286a1cfb22db9084f9ce4fde7ad7956bb496dc7c952e10ac90e36a" + "sha256:e6c6a4243e89c8d3e2342a1562b2388f3b524c9cac2fccc4d2c461a1320cc1c1" ], - "version": "==1.2.1" + "version": "==1.3.0" }, "aniso8601": { "hashes": [ @@ -38,10 +38,17 @@ }, "apispec": { "hashes": [ - "sha256:5fdaa1173b32515cc83f9d413a49a6c37fafc2b87f6b40e95923d3e85f0942c5", - "sha256:9e88c51517a6515612e818459f61c1bc06c00f2313e5187828bdbabaa7461473" + "sha256:cf8e1f3b56949710f8cf23797b7f40215e9dae8bac583789a3f2c13dc56349fa", + "sha256:fe5cf5fc89b1c4a73acd5af3a10ede02b31ec116f215ed02271cb905d3172367" ], - "version": "==3.0.0" + "version": "==3.1.0" + }, + "arrow": { + "hashes": [ + "sha256:4bfacea734ead51495dc47df00421ecfd4ca1f2c0fbe58b9a26eaeddedc31caf", + "sha256:67f8be7c0cf420424bc62d8d7dc40b44e4bb2f7b515f9cc2954fb36e35797656" + ], + "version": "==0.14.7" }, "attrs": { "hashes": [ @@ -74,38 +81,41 @@ }, "cffi": { "hashes": [ - "sha256:00d890313797d9fe4420506613384b43099ad7d2b905c0752dbcc3a6f14d80fa", - "sha256:0cf9e550ac6c5e57b713437e2f4ac2d7fd0cd10336525a27224f5fc1ec2ee59a", - "sha256:0ea23c9c0cdd6778146a50d867d6405693ac3b80a68829966c98dd5e1bbae400", - "sha256:193697c2918ecdb3865acf6557cddf5076bb39f1f654975e087b67efdff83365", - "sha256:1ae14b542bf3b35e5229439c35653d2ef7d8316c1fffb980f9b7647e544baa98", - "sha256:1e389e069450609c6ffa37f21f40cce36f9be7643bbe5051ab1de99d5a779526", - "sha256:263242b6ace7f9cd4ea401428d2d45066b49a700852334fd55311bde36dcda14", - "sha256:33142ae9807665fa6511cfa9857132b2c3ee6ddffb012b3f0933fc11e1e830d5", - "sha256:364f8404034ae1b232335d8c7f7b57deac566f148f7222cef78cf8ae28ef764e", - "sha256:47368f69fe6529f8f49a5d146ddee713fc9057e31d61e8b6dc86a6a5e38cecc1", - "sha256:4895640844f17bec32943995dc8c96989226974dfeb9dd121cc45d36e0d0c434", - "sha256:558b3afef987cf4b17abd849e7bedf64ee12b28175d564d05b628a0f9355599b", - "sha256:5ba86e1d80d458b338bda676fd9f9d68cb4e7a03819632969cf6d46b01a26730", - "sha256:63424daa6955e6b4c70dc2755897f5be1d719eabe71b2625948b222775ed5c43", - "sha256:6381a7d8b1ebd0bc27c3bc85bc1bfadbb6e6f756b4d4db0aa1425c3719ba26b4", - "sha256:6381ab708158c4e1639da1f2a7679a9bbe3e5a776fc6d1fd808076f0e3145331", - "sha256:6fd58366747debfa5e6163ada468a90788411f10c92597d3b0a912d07e580c36", - "sha256:728ec653964655d65408949b07f9b2219df78badd601d6c49e28d604efe40599", - "sha256:7cfcfda59ef1f95b9f729c56fe8a4041899f96b72685d36ef16a3440a0f85da8", - "sha256:819f8d5197c2684524637f940445c06e003c4a541f9983fd30d6deaa2a5487d8", - "sha256:825ecffd9574557590e3225560a8a9d751f6ffe4a49e3c40918c9969b93395fa", - "sha256:9009e917d8f5ef780c2626e29b6bc126f4cb2a4d43ca67aa2b40f2a5d6385e78", - "sha256:9c77564a51d4d914ed5af096cd9843d90c45b784b511723bd46a8a9d09cf16fc", - "sha256:a19089fa74ed19c4fe96502a291cfdb89223a9705b1d73b3005df4256976142e", - "sha256:a40ed527bffa2b7ebe07acc5a3f782da072e262ca994b4f2085100b5a444bbb2", - "sha256:bb75ba21d5716abc41af16eac1145ab2e471deedde1f22c6f99bd9f995504df0", - "sha256:e22a00c0c81ffcecaf07c2bfb3672fa372c50e2bd1024ffee0da191c1b27fc71", - "sha256:e55b5a746fb77f10c83e8af081979351722f6ea48facea79d470b3731c7b2891", - "sha256:ec2fa3ee81707a5232bf2dfbd6623fdb278e070d596effc7e2d788f2ada71a05", - "sha256:fd82eb4694be712fcae03c717ca2e0fc720657ac226b80bbb597e971fc6928c2" + "sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42", + "sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04", + "sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5", + "sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54", + "sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba", + "sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57", + "sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396", + "sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12", + "sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97", + "sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43", + "sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db", + "sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3", + "sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b", + "sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579", + "sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346", + "sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159", + "sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652", + "sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e", + "sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a", + "sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506", + "sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f", + "sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d", + "sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c", + "sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20", + "sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858", + "sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc", + "sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a", + "sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3", + "sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e", + "sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410", + "sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25", + "sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b", + "sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d" ], - "version": "==1.13.1" + "version": "==1.13.2" }, "chardet": { "hashes": [ @@ -121,6 +131,22 @@ ], "version": "==7.0" }, + "colorama": { + "hashes": [ + "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", + "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48" + ], + "markers": "sys_platform == 'win32'", + "version": "==0.4.1" + }, + "coloredlogs": { + "hashes": [ + "sha256:34fad2e342d5a559c31b6c889e8d14f97cb62c47d9a2ae7b5ed14ea10a79eff8", + "sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36" + ], + "index": "pypi", + "version": "==10.0" + }, "coverage": { "hashes": [ "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", @@ -187,10 +213,10 @@ }, "decorator": { "hashes": [ - "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", - "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6" + "sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce", + "sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d" ], - "version": "==4.4.0" + "version": "==4.4.1" }, "dnspython": { "hashes": [ @@ -201,10 +227,10 @@ }, "ecdsa": { "hashes": [ - "sha256:163c80b064a763ea733870feb96f9dd9b92216cfcacd374837af18e4e8ec3d4d", - "sha256:9814e700890991abeceeb2242586024d4758c8fc18445b194a49bd62d85861db" + "sha256:64c613005f13efec6541bb0a33290d0d03c27abab5f15fbab20fb0ee162bdd8e", + "sha256:e108a5fe92c67639abae3260e43561af914e7fd0d27bae6d2ec1312ae7934dfe" ], - "version": "==0.13.3" + "version": "==0.14.1" }, "eventlet": { "hashes": [ @@ -320,9 +346,9 @@ }, "future": { "hashes": [ - "sha256:858e38522e8fd0d3ce8f0c1feaf0603358e366d5403209674c7b617fa0c24093" + "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d" ], - "version": "==0.18.1" + "version": "==0.18.2" }, "greenlet": { "hashes": [ @@ -356,6 +382,20 @@ "index": "pypi", "version": "==1.0.1" }, + "humanfriendly": { + "hashes": [ + "sha256:23057b10ad6f782e7bc3a20e3cb6768ab919f619bbdc0dd75691121bbde5591d", + "sha256:33ee8ceb63f1db61cce8b5c800c531e1a61023ac5488ccde2ba574a85be00a85" + ], + "version": "==4.18" + }, + "ics": { + "hashes": [ + "sha256:12cf34aed0dafa1bf99d79ca58e99949d6721511b856386e118015fe5f5d6e3a" + ], + "index": "pypi", + "version": "==0.6" + }, "idna": { "hashes": [ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", @@ -432,10 +472,10 @@ }, "marshmallow": { "hashes": [ - "sha256:077b4612f5d3b9333b736fdc6b963d2b46d409070f44ff3e6c4109645c673e83", - "sha256:9a2f3e8ea5f530a9664e882d7d04b58650f46190178b2264c72b7d20399d28f0" + "sha256:1a358beb89c2b4d5555272065a9533591a3eb02f1b854f3c4002d88d8f2a1ddb", + "sha256:eb97c42c5928b5720812c9268865fe863d4807bc1a8b48ddd7d5c9e1779a6af0" ], - "version": "==3.2.1" + "version": "==3.2.2" }, "monotonic": { "hashes": [ @@ -487,36 +527,40 @@ }, "pycryptodomex": { "hashes": [ - "sha256:020928b2831b2047288c9143f41c6690eb669d60761c7ca8c5ca743a2c51517c", - "sha256:0ce1950ba6544eca4d6fd7386e2502d4bd871fcbd5e5b977604f48ea37b29fc6", - "sha256:0d5b1159a24a56fd3359b7b1aa1e4331c394033eababb2972bb923d6767968db", - "sha256:11453e8628cdccbcb08e04405298d659c0c0458cf9bf23eaaa3c201f8d635389", - "sha256:22e050089f60e70b97909fe62612ee9589f0be1c928c2aa637f2534eddf61632", - "sha256:27317f1e8e496a2f208b1c40da425d5fe760b494f95c847bb7c3074c95a8edcb", - "sha256:32e2fe1d0c5fada45b22b647f88367b210dfea40a5cc849b142b4e9fa497c488", - "sha256:3a998b390a80fd0d22c7d9fbaf49a9a11772ef90495a8baecdea2e6d09929937", - "sha256:46dda35fbed5426794ab64d483d6257dc43f52e78ba934563492df7cb89f7de6", - "sha256:4846ca0f2363bdb934c556667b056331d4aabd48f20924b0c5583a49d764d3fc", - "sha256:550f5e6f07b091f986023f871fa8a2bde9875ccae51d4bd07b31fa9855fe994f", - "sha256:561905b459de41c3ad19912cdcd88c8e24295d01e97b7b2a63d4188c8e4e0dbc", - "sha256:5745ca86a4e88a775b7cace28b947a86661d5cc09ecc1c8d97293a7d20c1bb79", - "sha256:5c2a3bb28dde992f97d856937e973dda0462bf3acb7d0009308a81159a35323b", - "sha256:73a8acc8ff7f09d482e481757d92a250f803e66e0f248019df90a69e61840180", - "sha256:8601613ebc329b853e466f581ad1156638989926e0dcdf52952542a89883836c", - "sha256:8b604f4fa1de456d6d19771b01c2823675a75a2c60e51a6b738f71fdfe865370", - "sha256:96f8622cb8061f4aca95e52cc835659f024bc2e237ee6a9d01117873b7490b98", - "sha256:a01c99532c5f7ab96274b5c9f3e135315b79b55ba5c8233fc4d029e0369e94df", - "sha256:c63040e0313e27b62b0f4295f41adecf96cde7ff4d49f653b81b1958cb1180bf", - "sha256:c812cb9f3af63da8eaa251e7e48f8b38c4e40974d2bdae2f0ca7a7a12549727a", - "sha256:cb9e8ef672b7a961f90e0a497718e0f052f76324f216840a4ec30248e4d19f20", - "sha256:ce8edda46374c344de87089f9887ad4dd317bb4a22f91f1844202eaf14b08de0", - "sha256:de58de0d5f2fb9253707ee718e1378f2194fdd394cdbed1b6464ab44642f5217", - "sha256:e0100f9b93d0119d846a33e6cb5001ee208519b81c6acf76da614b71de75885b", - "sha256:e530b77bdff5c2bf3065e6a088e1602ad193b43e285bac196d4b8820308ec6bb", - "sha256:f048069aa7b530f1c5e84d55c2b28ca7a7272bb3b8d28829d454a94bec6529a8", - "sha256:f6a9271c842e93c349b6007676a62d03dca712c9f4dff66c3270d50504ca9014" + "sha256:0ab2251a386c065331115c408c23274e8aea7ddf5452f2e92120b88fa09aba23", + "sha256:0da48ccd0944a952cbaac623bf0e1139969078551a213c019ca885ed66771539", + "sha256:1d98214b7bc6f9ceb68eb5cdbd4237f23485b4b746e7e582990be492b6c4797b", + "sha256:275e8f0f7fd03ec4b9f7fecfeac3dad8e5a1fe389369efda1e365e8c5795c1ac", + "sha256:30975ac3ee7c632eb34a05d2aa0e9933cab9a0746b77d44612a3b61c56ecfa3c", + "sha256:37f84bef86e935e10a2ccb22f6cd2cebac274dff8867f16f7c2d5da9aa27665d", + "sha256:3b80f06556552a515ff9f1052ea41895e34745558a5ddbab46e300ba43384a35", + "sha256:3b9f81fd0c897c493ff8367cca41b9b93f6c9277990c8c4c2756538ed1aa4a99", + "sha256:6d58f13c8ca6bac3bf0d64e7474725ff55c2d6db60ed03d5b98b81c757bf1f4c", + "sha256:6f86a6d668d4f918b21452fcf8bb24dc9c135b6564cbd4ff7b954b1d35fe7527", + "sha256:7c462632ff441203fc30f11cab9cf12e2eb00417b4a1ea3c5208e875d81cb160", + "sha256:87d278909c7fabd303d87268eeda7350641f094792ecd023965f960ae6d2d3da", + "sha256:87d3f7357789171a0f05e3b1bac782989619043693e4200518c678245856ca7c", + "sha256:8913f185eccb2f270030a0347161d2cd47ef691f12a4b9af9772319e5a6a717b", + "sha256:8ac49b6ad1e57a0914d8d5e0267e4df5fbdf4e62abdf982bd5493d634cd3a686", + "sha256:8d8b071a159e9b46734cbb802282719a0d0d0e40523c8648fab0b6739f98a882", + "sha256:a06a1f927d02c1fea1f7656e32bf36149d0f6cab750313a03a085e43632163e8", + "sha256:adb6ca0aee7fd2807628d1cb77fc9be8a82f493240e2349da06419221b1f6b19", + "sha256:b3503841cb5185b210876d7ff8f541e2c2ea0915c83f6330be6d7026a34828ca", + "sha256:b90ecc35567d77e7dc9f70817826f077c9dbb37abdd16e2c2d57887c21053e53", + "sha256:ba18a7dfef6d89605ca76f077d033143fab8f2d6948620d09337567402f1c0c4", + "sha256:be635b1f9ee9615243dc706c11047015d22312e7425c9009dd6447c229370e1a", + "sha256:d1db857b0ac6bac6d4d4758250d548d7146d63cb36c6c50b7481837f02d38ef7", + "sha256:d9537841af488a4b83977aeebfd4aebe011b7d1d19e9d45ad32a1f8dfca7eec8", + "sha256:e413457859d3c3e4a4263ef24ccaefe4107b3e3e219c4fb87215cfc34ff8dba0", + "sha256:e87c272263559d657ab3b990be8174c0d492cbc2f4f8d0bddfaef82dfe05d54c", + "sha256:eb5aef32e65d7802e04c78074af1ba8e7a5b4c0482d3a110f236082fadac6859", + "sha256:ee03dc6124287e27738e5f1d1150031d706f7fb96f1770859cb3cebe64c191ea", + "sha256:f792b5deca98bee676912d27bc1aba96b614986a9a89df7cf15e95d7bd480768", + "sha256:f84e6e66af8805703b5f4d1243747accf519cba0223d598b58e85edbec8583d7", + "sha256:fbd9e3ba9437b087b16481d1e34ec4f495ffabb4bee7e2c150b50d28ebe00e44", + "sha256:fbfaf65e610089f37c46e2cb2ff2dbf9a04bbcecd3a2beaa85494094e9987aff" ], - "version": "==3.9.0" + "version": "==3.9.3" }, "pyjwkest": { "hashes": [ @@ -539,18 +583,25 @@ ], "version": "==19.0.0" }, + "pyreadline": { + "hashes": [ + "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1" + ], + "markers": "sys_platform == 'win32'", + "version": "==2.1" + }, "pyrsistent": { "hashes": [ - "sha256:34b47fa169d6006b32e99d4b3c4031f155e6e68ebcc107d6454852e8e0ee6533" + "sha256:eb6545dbeb1aa69ab1fb4809bfbf5a8705e44d92ef8fc7c2361682a47c46c778" ], - "version": "==0.15.4" + "version": "==0.15.5" }, "python-dateutil": { "hashes": [ - "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", - "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" ], - "version": "==2.8.0" + "version": "==2.8.1" }, "python-editor": { "hashes": [ @@ -605,24 +656,24 @@ }, "six": { "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", + "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66" ], - "version": "==1.12.0" + "version": "==1.13.0" }, "soupsieve": { "hashes": [ - "sha256:605f89ad5fdbfefe30cdc293303665eff2d188865d4dbe4eb510bba1edfbfce3", - "sha256:b91d676b330a0ebd5b21719cb6e9b57c57d433671f65b9c28dd3461d9a1ed0b6" + "sha256:bdb0d917b03a1369ce964056fc195cfdff8819c40de04695a80bc813c3cfa1f5", + "sha256:e2c1c5dee4a1c36bcb790e0fabd5492d874b8ebd4617622c4f6a731701060dda" ], - "version": "==1.9.4" + "version": "==1.9.5" }, "sqlalchemy": { "hashes": [ - "sha256:0f0768b5db594517e1f5e1572c73d14cf295140756431270d89496dc13d5e46c" + "sha256:afa5541e9dea8ad0014251bc9d56171ca3d8b130c9627c6cb3681cff30be3f8a" ], "index": "pypi", - "version": "==1.3.10" + "version": "==1.3.11" }, "sqlalchemy-migrate": { "hashes": [ @@ -672,6 +723,13 @@ ], "version": "==1.1.0" }, + "tatsu": { + "hashes": [ + "sha256:80713413473a009f2081148d0f494884cabaf9d6866b71f2a68a92b6442f343d", + "sha256:c9211eeee9a2d4c90f69879ec0b518b1aa0d9450249cb0dd181f5f5b18be0a92" + ], + "version": "==4.4.0" + }, "tempita": { "hashes": [ "sha256:cacecf0baa674d356641f1d406b8bff1d756d739c46b869a54de515d08e6fc9c" @@ -687,10 +745,10 @@ }, "urllib3": { "hashes": [ - "sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398", - "sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86" + "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293", + "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745" ], - "version": "==1.25.6" + "version": "==1.25.7" }, "webargs": { "hashes": [ diff --git a/backend/__init__.py b/backend/__init__.py index 217b2b3..cca5aac 100644 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -3,7 +3,10 @@ Backend base module """ import logging +from io import StringIO from logging.config import dictConfig +from typing import Union + import coloredlogs as coloredlogs import jwt import requests @@ -25,7 +28,6 @@ __email__ = "it@t-kurze.de" # __status__ = "Production" __status__ = "Development" - dictConfig({ 'version': 1, 'formatters': { @@ -66,7 +68,7 @@ dictConfig({ }, }, 'loggers': { - 'mal': { + 'lrc': { 'level': Config.LOG_LEVEL, 'handlers': ['wsgi', 'file', 'errors_file'] } @@ -78,18 +80,34 @@ dictConfig({ }) main_logger = logging.getLogger("lrc") + +# following might be dangerous, as buffer might be filled without a mechanism to empty it +# error_log_stream = StringIO() +# error_log_stream_handler = logging.StreamHandler(stream=error_log_stream) +# error_log_stream_handler.setLevel(logging.ERROR) +# main_logger.addHandler(error_log_stream_handler) + coloredlogs.install(level='DEBUG', logger=main_logger) class LrcException(Exception): - def __init__(self, message: str, html_code: int = None): - super().__init__(message) + def __init__(self, message_or_exception: Union[str, Exception], html_code: int = None): + if isinstance(message_or_exception, str): + super().__init__(message_or_exception) + self.type = None + else: + super().__init__(str(message_or_exception)) + self.type = type(message_or_exception) self.html_code = html_code def __repr__(self): + if self.type is None: + msg = "LRC Exception: \"{}\"".format(', '.join(super().args)) + else: + msg = "LRC Exception: (original Exception: {}) \"{}\"".format(self.type, ', '.join(super().args)) if self.html_code is not None: - return "LRC Exception: \"{}\" (HTML Code: {})".format(', '.join(super().args), self.html_code) - return ', '.join(super().args) + msg += " (HTML Code: {})".format(self.html_code) + return msg def __str__(self): return self.__repr__() diff --git a/backend/config.py b/backend/config.py index a2c60e70816267ed9cdcc499f8a86ff07e89be9f..ae96269255a588eb65f34abf20dd3eed58369593 100644 GIT binary patch literal 4256 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 bmU9b;PE7EJ!M{44{4rJnGl>X9eRMq9gjef6 diff --git a/backend/recorder_adapters/__init__.py b/backend/recorder_adapters/__init__.py index 57a029d..b911227 100644 --- a/backend/recorder_adapters/__init__.py +++ b/backend/recorder_adapters/__init__.py @@ -104,6 +104,9 @@ class RecorderAdapter: def is_recording(self) -> bool: pass + def get_recording_status(self) -> str: + pass + def get_defined_recorder_adapters(): models = [] diff --git a/backend/recorder_adapters/epiphan_base.py b/backend/recorder_adapters/epiphan_base.py index 8d90515..d98f834 100644 --- a/backend/recorder_adapters/epiphan_base.py +++ b/backend/recorder_adapters/epiphan_base.py @@ -6,11 +6,14 @@ from pprint import pprint import requests from requests.auth import HTTPBasicAuth +from requests.exceptions import ConnectionError from backend import LrcException from backend.recorder_adapters import RecorderAdapter # HOST = "localhost" +from backend.tools.exception_decorator import exception_decorator + BASE_URL = "http://172.23.8.102" # Audimax SMP 351 USER = "admin" @@ -34,12 +37,14 @@ class EpiphanV1(RecorderAdapter): def _get_version(self): pass - def get_status(self) -> dict: + @exception_decorator(ConnectionError) + def get_recording_status(self) -> dict: res = self.session.get(self.url + "/admin/ajax/recorder_status.cgi") if res.ok: return res.json() raise LrcException(res.text, res.status_code) + @exception_decorator(ConnectionError) def get_sysinfo(self) -> dict: res = self.session.get(self.url + "/ajax/sysinfo.cgi") if res.ok: @@ -47,7 +52,7 @@ class EpiphanV1(RecorderAdapter): raise LrcException(res.text, res.status_code) def is_recording(self) -> bool: - state = self.get_status().get('state', None) + state = self.get_recording_status().get('state', None) return state == "up" def get_recording_time(self): @@ -55,7 +60,7 @@ class EpiphanV1(RecorderAdapter): Returns recording time in seconds. Also returns 0 if not recording. :return: """ - return self.get_status().get('seconds', None) + return self.get_recording_status().get('seconds', None) def start_recording(self): res = self.session.get(self.url + "/admin/ajax/start_recorder.cgi") diff --git a/backend/recorder_adapters/extron_smp.py b/backend/recorder_adapters/extron_smp.py index ec87e89..a434bf8 100644 --- a/backend/recorder_adapters/extron_smp.py +++ b/backend/recorder_adapters/extron_smp.py @@ -2,8 +2,9 @@ import logging from backend import LrcException from backend.recorder_adapters import telnetlib, TelnetAdapter, RecorderAdapter +from backend.tools.exception_decorator import exception_decorator -logger = logging.getLogger() +logger = logging.getLogger("lrc.recorder_adapters.extron_smp") RECORDER_MODEL_NAME = "SMP 351 / 352" VERSION = "0.9.0" @@ -28,11 +29,13 @@ class SMP(TelnetAdapter, RecorderAdapter): self._login() def _login(self): - print("Connecting to {} ...".format(self.address)) + logger.info("Connecting to {} ...".format(self.address)) try: self.tn = telnetlib.Telnet(self.address) except TimeoutError as e: raise LrcException(str(e)) + except ConnectionRefusedError as e: + raise LrcException(str(e)) self.tn.read_until("\r\nPassword:") # password = getpass.getpass() password = self.admin_pw @@ -371,6 +374,7 @@ class SMP(TelnetAdapter, RecorderAdapter): self.tn.write("{}Y2RCDR\n".format(self.esc_char)) return TelnetAdapter._get_response_str(self.tn.read_until_non_empty_line()) + @exception_decorator(ConnectionError) def get_recording_status(self): """ Status may be one of: diff --git a/backend/serve_frontend.py b/backend/serve_frontend.py index 3226b97..59e1b25 100644 --- a/backend/serve_frontend.py +++ b/backend/serve_frontend.py @@ -16,6 +16,7 @@ if not os.path.exists(fe_path) or not os.path.exists(os.path.join(fe_path, "inde app.logger.critical( "Frontend path and/or index.html does not exist! Please build frontend before continuing! " "You might want to go to ../frontend and continue from there.") + print("FATAL: Frontend path wrong or index.html missing -> EXITING!") exit() fe_bp = Blueprint('frontend', __name__, url_prefix='/', template_folder=os.path.join(fe_path, "")) diff --git a/backend/tools/exception_decorator.py b/backend/tools/exception_decorator.py new file mode 100644 index 0000000..3d4fa08 --- /dev/null +++ b/backend/tools/exception_decorator.py @@ -0,0 +1,13 @@ +from backend import LrcException + + +def exception_decorator(*exceptions): + def decorator(func): + def new_func(*args, **kwargs): + try: + ret = func(*args, **kwargs) + return ret + except exceptions as e: + raise LrcException(e) + return new_func + return decorator \ No newline at end of file diff --git a/backend/tools/send_mail.py b/backend/tools/send_mail.py new file mode 100644 index 0000000..a2d9b77 --- /dev/null +++ b/backend/tools/send_mail.py @@ -0,0 +1,45 @@ +import smtplib +import traceback +from email.message import EmailMessage +from typing import List, Union + +from backend import main_logger, Config + + +def send_mail(subject: str, msg_body: str, to_mail: List, from_mail: str = Config.FROM_MAIL): + subject = subject.strip().replace("\r", "").split("\n")[0] # remove breaks resp. cut after line break + try: + msg = EmailMessage() + msg.set_content(msg_body) + msg["Subject"] = subject + msg["From"] = from_mail + msg["To"] = to_mail + s = smtplib.SMTP(Config.SMTP_SERVER) + s.send_message(msg) + s.quit() + except Exception as e: + main_logger.error( + "Could not send E-Mail (Exception: {})".format(str(e))) + + +def send_error_mail(message_or_exception: Union[str, Exception], subject: str = None, + subject_prefix: str = "[LRC] Error: ", + receiver_mail_addresses=Config.ERROR_E_MAIL_TO): + if isinstance(message_or_exception, Exception): + if subject is None: + subject = subject_prefix + str(type(message_or_exception)) + else: + subject = subject_prefix + subject + msg_body = str(type(message_or_exception)) + ": " + str(message_or_exception) + "\n\n" + traceback.format_exc() + else: + if subject is None: + subject = str(message_or_exception) + else: + subject = subject_prefix + subject + msg_body = str(message_or_exception) + + send_mail(subject, msg_body, receiver_mail_addresses) + + +def send_warning_mail(): + pass diff --git a/backend/tools/simple_state_checker.py b/backend/tools/simple_state_checker.py index 222449a..290266f 100644 --- a/backend/tools/simple_state_checker.py +++ b/backend/tools/simple_state_checker.py @@ -1,23 +1,31 @@ import json import os import logging +from io import StringIO + +import requests +from requests.auth import HTTPBasicAuth from multiprocessing.pool import ThreadPool from pprint import pprint -import requests -from requests.auth import HTTPBasicAuth from ics import Calendar +from backend import LrcException from backend.config import Config +from backend.recorder_adapters import RecorderAdapter + from backend.recorder_adapters.epiphan_base import EpiphanV1 from backend.recorder_adapters.extron_smp import SMP +from backend.tools.send_mail import send_error_mail -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) -stream_handler = logging.StreamHandler() -stream_handler.setLevel(logging.DEBUG) -logger.addHandler(stream_handler) +logger = logging.getLogger("lrc.tools.simple_state_checker") + +rec_err_state_log_stream = StringIO() +rec_err_state_log_stream_handler = logging.StreamHandler(stream=rec_err_state_log_stream) +rec_err_state_log_stream_handler.setLevel(logging.ERROR) + +logger.addHandler(rec_err_state_log_stream_handler) base_url = "https://opencast.bibliothek.kit.edu" @@ -46,7 +54,6 @@ def get_service_url(service_type: str): def get_calender(rec_id): params = {'agentid': rec_id} url = get_service_url('org.opencastproject.scheduler') + "/calendars" - print(url) res = session.get(url, params=params) if res.ok: return Calendar(res.text) @@ -80,41 +87,49 @@ def notify_users_of_problem(msg: str): pass +def get_recorder_adapter(recorder_info:dict) -> RecorderAdapter: + if "SMP" in recorder_info["type"]: + rec = SMP(recorder_info['ip'], recorder_info['password']) + else: + rec = EpiphanV1(recorder_info['ip'], recorder_info["username"], recorder_info["password"]) + return rec + + def check_capture_agent_state(a: dict): logger.debug("Checking Agent {}".format(a['name'])) c = get_calender(a['name']) is_recording_in_calendar = len(list(c.timeline.now())) >= 1 if is_recording_in_calendar: + logger.info("{} has entry in Calender and should therfor be recording... checking now!".format(a['name'])) if a['state'] == "capturing": - print( + logger.info( "{} is in capturing state, so there should be an entry in the calendar of the recorder, right? -> {}".format( a['name'], is_recording_in_calendar )) - rec = get_recorder_by_name(a['name']) - print(rec) - if "SMP" in rec["type"]: - print("using SMP adapter") - rec = SMP(rec['ip'], rec['password']) - else: - rec = EpiphanV1(rec['ip'], rec["username"], rec["password"]) - if rec.is_recording(): - print("OK – recorder is recording :)") - else: - logger.info(rec.get_recording_status()) - logger.error("FATAL - recorder {} must be recording!!!!".format(a['name'])) + recorder_info = get_recorder_by_name(a['name']) + try: + rec = get_recorder_adapter(recorder_info) + if rec.is_recording(): + logger.info("OK – recorder {} is recording :)".format(a['name'])) + else: + logger.info(rec.get_recording_status()) + logger.error("FATAL - recorder {} must be recording but is not!!!!".format(a['name'])) + except LrcException as e: + logger.fatal("Exception occurred: {}".format(str(e))) + logger.error("Could not check state of recorder {}, Address: {}".format(a['name'], recorder_info['ip'])) else: - print("FATAL: {} is not in capturing state...but should be!!".format(a['name'])) + logger.error("FATAL: {} is not in capturing state...but should be!!".format(a['name'])) else: - rec = get_recorder_by_name(a['name']) - if "SMP" in rec["type"]: - logger.debug("using SMP adapter") - rec = SMP(rec['ip'], rec['password']) - else: - rec = EpiphanV1(rec['ip'], rec["username"], rec["password"]) - if rec.is_recording(): - logger.error("FATAL - recorder must not be recording!!!!") - else: - logger.info("OK – recorder is not recording :)") + recorder_info = get_recorder_by_name(a['name']) + try: + rec = get_recorder_adapter(recorder_info) + if rec.is_recording(): + logger.error("FATAL - recorder must not be recording!!!!") + else: + logger.info("OK – recorder is not recording :)") + except LrcException as e: + logger.fatal("Exception occurred: {}".format(str(e))) + logger.error("Could not check state of recorder {}, Address: {}".format(a['name'], recorder_info['ip'])) agents = get_capture_agents() @@ -123,6 +138,11 @@ logger.info("Got {} capture agents that will be checked...".format(len(agents))) pool = ThreadPool(5) pool.map(check_capture_agent_state, agents) +pool.close() +pool.join() +logged_events = rec_err_state_log_stream.getvalue() +if len(logged_events) > 0: + send_error_mail(logged_events, "Errors have been detected while checking recorder states!") exit() c = get_calender('CS 30.46 Chemie Neuer Hoersaal') diff --git a/logs/app.log.2019-11-13 b/logs/app.log.2019-11-13 new file mode 100644 index 0000000..e69de29