Request mechanism rolled out, migration mechanism incorporated, Code style now inclined toward EAFP, DeleteVM now working, resume/suspend functionality removed
This commit is contained in:
		
					parent
					
						
							
								70ec3f832b
							
						
					
				
			
			
				commit
				
					
						945b34d76c
					
				
			
		
					 4 changed files with 407 additions and 10840 deletions
				
			
		
							
								
								
									
										1
									
								
								Pipfile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Pipfile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -12,6 +12,7 @@ python-decouple = "*"
 | 
			
		|||
cython = "*"
 | 
			
		||||
pylint = "*"
 | 
			
		||||
python-etcd3 = {editable = true,git = "https://github.com/kragniz/python-etcd3"}
 | 
			
		||||
sshtunnel = "*"
 | 
			
		||||
 | 
			
		||||
[requires]
 | 
			
		||||
python_version = "3.7"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										179
									
								
								Pipfile.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										179
									
								
								Pipfile.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
{
 | 
			
		||||
    "_meta": {
 | 
			
		||||
        "hash": {
 | 
			
		||||
            "sha256": "6f0726e9d014ad330ab36d11b44a15c59316234e343697e46ea2a10ab0997a90"
 | 
			
		||||
            "sha256": "8f820ace244a315a831e3330707a6ec24895ed73f8fa1646ce6889915aec0db4"
 | 
			
		||||
        },
 | 
			
		||||
        "pipfile-spec": 6,
 | 
			
		||||
        "requires": {
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +16,13 @@
 | 
			
		|||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    "default": {
 | 
			
		||||
        "asn1crypto": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87",
 | 
			
		||||
                "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==0.24.0"
 | 
			
		||||
        },
 | 
			
		||||
        "astroid": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4",
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +30,81 @@
 | 
			
		|||
            ],
 | 
			
		||||
            "version": "==2.2.5"
 | 
			
		||||
        },
 | 
			
		||||
        "bcrypt": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:0258f143f3de96b7c14f762c770f5fc56ccd72f8a1857a451c1cd9a655d9ac89",
 | 
			
		||||
                "sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42",
 | 
			
		||||
                "sha256:19a4b72a6ae5bb467fea018b825f0a7d917789bcfe893e53f15c92805d187294",
 | 
			
		||||
                "sha256:5432dd7b34107ae8ed6c10a71b4397f1c853bd39a4d6ffa7e35f40584cffd161",
 | 
			
		||||
                "sha256:69361315039878c0680be456640f8705d76cb4a3a3fe1e057e0f261b74be4b31",
 | 
			
		||||
                "sha256:6fe49a60b25b584e2f4ef175b29d3a83ba63b3a4df1b4c0605b826668d1b6be5",
 | 
			
		||||
                "sha256:74a015102e877d0ccd02cdeaa18b32aa7273746914a6c5d0456dd442cb65b99c",
 | 
			
		||||
                "sha256:763669a367869786bb4c8fcf731f4175775a5b43f070f50f46f0b59da45375d0",
 | 
			
		||||
                "sha256:8b10acde4e1919d6015e1df86d4c217d3b5b01bb7744c36113ea43d529e1c3de",
 | 
			
		||||
                "sha256:9fe92406c857409b70a38729dbdf6578caf9228de0aef5bc44f859ffe971a39e",
 | 
			
		||||
                "sha256:a190f2a5dbbdbff4b74e3103cef44344bc30e61255beb27310e2aec407766052",
 | 
			
		||||
                "sha256:a595c12c618119255c90deb4b046e1ca3bcfad64667c43d1166f2b04bc72db09",
 | 
			
		||||
                "sha256:c9457fa5c121e94a58d6505cadca8bed1c64444b83b3204928a866ca2e599105",
 | 
			
		||||
                "sha256:cb93f6b2ab0f6853550b74e051d297c27a638719753eb9ff66d1e4072be67133",
 | 
			
		||||
                "sha256:d7bdc26475679dd073ba0ed2766445bb5b20ca4793ca0db32b399dccc6bc84b7",
 | 
			
		||||
                "sha256:ff032765bb8716d9387fd5376d987a937254b0619eff0972779515b5c98820bc"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==3.1.7"
 | 
			
		||||
        },
 | 
			
		||||
        "cffi": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
 | 
			
		||||
                "sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
 | 
			
		||||
                "sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
 | 
			
		||||
                "sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
 | 
			
		||||
                "sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
 | 
			
		||||
                "sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
 | 
			
		||||
                "sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
 | 
			
		||||
                "sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
 | 
			
		||||
                "sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
 | 
			
		||||
                "sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
 | 
			
		||||
                "sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
 | 
			
		||||
                "sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
 | 
			
		||||
                "sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
 | 
			
		||||
                "sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
 | 
			
		||||
                "sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
 | 
			
		||||
                "sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
 | 
			
		||||
                "sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
 | 
			
		||||
                "sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
 | 
			
		||||
                "sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
 | 
			
		||||
                "sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
 | 
			
		||||
                "sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
 | 
			
		||||
                "sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
 | 
			
		||||
                "sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
 | 
			
		||||
                "sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
 | 
			
		||||
                "sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
 | 
			
		||||
                "sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
 | 
			
		||||
                "sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
 | 
			
		||||
                "sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==1.12.3"
 | 
			
		||||
        },
 | 
			
		||||
        "cryptography": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c",
 | 
			
		||||
                "sha256:25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643",
 | 
			
		||||
                "sha256:3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216",
 | 
			
		||||
                "sha256:41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799",
 | 
			
		||||
                "sha256:5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a",
 | 
			
		||||
                "sha256:5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9",
 | 
			
		||||
                "sha256:72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc",
 | 
			
		||||
                "sha256:7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8",
 | 
			
		||||
                "sha256:961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53",
 | 
			
		||||
                "sha256:96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1",
 | 
			
		||||
                "sha256:ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609",
 | 
			
		||||
                "sha256:b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292",
 | 
			
		||||
                "sha256:cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e",
 | 
			
		||||
                "sha256:e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6",
 | 
			
		||||
                "sha256:f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed",
 | 
			
		||||
                "sha256:f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==2.7"
 | 
			
		||||
        },
 | 
			
		||||
        "cython": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:07efba7b32c082c519b75e3b03821c2f32848e2b3e9986c784bbd8ffaf0666d7",
 | 
			
		||||
| 
						 | 
				
			
			@ -131,6 +213,13 @@
 | 
			
		|||
            ],
 | 
			
		||||
            "version": "==0.6.1"
 | 
			
		||||
        },
 | 
			
		||||
        "paramiko": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:99f0179bdc176281d21961a003ffdb2ec369daac1a1007241f53374e376576cf",
 | 
			
		||||
                "sha256:f4b2edfa0d226b70bd4ca31ea7e389325990283da23465d572ed1f70a7583041"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==2.6.0"
 | 
			
		||||
        },
 | 
			
		||||
        "protobuf": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:05c36022fef3c7d3562ac22402965c0c2b9fe8421f459bb377323598996e407f",
 | 
			
		||||
| 
						 | 
				
			
			@ -154,6 +243,12 @@
 | 
			
		|||
            ],
 | 
			
		||||
            "version": "==3.9.0"
 | 
			
		||||
        },
 | 
			
		||||
        "pycparser": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==2.19"
 | 
			
		||||
        },
 | 
			
		||||
        "pylint": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:5d77031694a5fb97ea95e828c8d10fc770a1df6eb3906067aaed42201a8a6a09",
 | 
			
		||||
| 
						 | 
				
			
			@ -162,6 +257,30 @@
 | 
			
		|||
            "index": "pypi",
 | 
			
		||||
            "version": "==2.3.1"
 | 
			
		||||
        },
 | 
			
		||||
        "pynacl": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255",
 | 
			
		||||
                "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c",
 | 
			
		||||
                "sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e",
 | 
			
		||||
                "sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae",
 | 
			
		||||
                "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621",
 | 
			
		||||
                "sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56",
 | 
			
		||||
                "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39",
 | 
			
		||||
                "sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310",
 | 
			
		||||
                "sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1",
 | 
			
		||||
                "sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a",
 | 
			
		||||
                "sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786",
 | 
			
		||||
                "sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b",
 | 
			
		||||
                "sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b",
 | 
			
		||||
                "sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f",
 | 
			
		||||
                "sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20",
 | 
			
		||||
                "sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415",
 | 
			
		||||
                "sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715",
 | 
			
		||||
                "sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1",
 | 
			
		||||
                "sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==1.3.0"
 | 
			
		||||
        },
 | 
			
		||||
        "python-decouple": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:1317df14b43efee4337a4aa02914bf004f010cd56d6c4bd894e6474ec8c4fe2d"
 | 
			
		||||
| 
						 | 
				
			
			@ -181,6 +300,13 @@
 | 
			
		|||
            ],
 | 
			
		||||
            "version": "==1.12.0"
 | 
			
		||||
        },
 | 
			
		||||
        "sshtunnel": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:c813fdcda8e81c3936ffeac47cb69cfb2d1f5e77ad0de656c6dab56aeebd9249"
 | 
			
		||||
            ],
 | 
			
		||||
            "index": "pypi",
 | 
			
		||||
            "version": "==0.1.5"
 | 
			
		||||
        },
 | 
			
		||||
        "tenacity": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:a0c3c5f7ae0c33f5556c775ca059c12d6fd8ab7121613a713e8b7d649908571b",
 | 
			
		||||
| 
						 | 
				
			
			@ -225,19 +351,6 @@
 | 
			
		|||
            "index": "pypi",
 | 
			
		||||
            "version": "==1.6.2"
 | 
			
		||||
        },
 | 
			
		||||
        "ddt": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:474546b4020ce8a2f9550ba8899c28aa2c284c7bbf175bddede98be949d1ca7c",
 | 
			
		||||
                "sha256:d13e6af8f36238e89d00f4ebccf2bda4f6d1878be560a6600689e42077e164e3"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==1.2.1"
 | 
			
		||||
        },
 | 
			
		||||
        "gitdb": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:a3ebbc27be035a2e874ed904df516e35f4a29a778a764385de09de9e0f139658"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==0.6.4"
 | 
			
		||||
        },
 | 
			
		||||
        "gitdb2": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:83361131a1836661a155172932a13c08bda2db3674e4caa32368aa6eb02f38c2",
 | 
			
		||||
| 
						 | 
				
			
			@ -247,10 +360,10 @@
 | 
			
		|||
        },
 | 
			
		||||
        "gitpython": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:7428f1cc5e72d53e65c3259d5cebc22fb2b07f973c49d95b3c3d26c64890a3c3",
 | 
			
		||||
                "sha256:a0f744a4941eac5d99033eb0adcbec83bf443ee173fda4292d92a906aedce952"
 | 
			
		||||
                "sha256:c15c55ff890cd3a6a8330059e80885410a328f645551b55a91d858bfb3eb2573",
 | 
			
		||||
                "sha256:df752b6b6f06f11213e91c4925aea7eaf9e37e88fb71c8a7a1aa0a5c10852120"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==2.1.12"
 | 
			
		||||
            "version": "==2.1.13"
 | 
			
		||||
        },
 | 
			
		||||
        "mccabe": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
| 
						 | 
				
			
			@ -296,19 +409,21 @@
 | 
			
		|||
        },
 | 
			
		||||
        "pyyaml": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3",
 | 
			
		||||
                "sha256:588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043",
 | 
			
		||||
                "sha256:68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7",
 | 
			
		||||
                "sha256:70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265",
 | 
			
		||||
                "sha256:86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391",
 | 
			
		||||
                "sha256:a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778",
 | 
			
		||||
                "sha256:a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225",
 | 
			
		||||
                "sha256:b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955",
 | 
			
		||||
                "sha256:cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e",
 | 
			
		||||
                "sha256:ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190",
 | 
			
		||||
                "sha256:fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"
 | 
			
		||||
                "sha256:0113bc0ec2ad727182326b61326afa3d1d8280ae1122493553fd6f4397f33df9",
 | 
			
		||||
                "sha256:01adf0b6c6f61bd11af6e10ca52b7d4057dd0be0343eb9283c878cf3af56aee4",
 | 
			
		||||
                "sha256:5124373960b0b3f4aa7df1707e63e9f109b5263eca5976c66e08b1c552d4eaf8",
 | 
			
		||||
                "sha256:5ca4f10adbddae56d824b2c09668e91219bb178a1eee1faa56af6f99f11bf696",
 | 
			
		||||
                "sha256:7907be34ffa3c5a32b60b95f4d95ea25361c951383a894fec31be7252b2b6f34",
 | 
			
		||||
                "sha256:7ec9b2a4ed5cad025c2278a1e6a19c011c80a3caaac804fd2d329e9cc2c287c9",
 | 
			
		||||
                "sha256:87ae4c829bb25b9fe99cf71fbb2140c448f534e24c998cc60f39ae4f94396a73",
 | 
			
		||||
                "sha256:9de9919becc9cc2ff03637872a440195ac4241c80536632fffeb6a1e25a74299",
 | 
			
		||||
                "sha256:a5a85b10e450c66b49f98846937e8cfca1db3127a9d5d1e31ca45c3d0bef4c5b",
 | 
			
		||||
                "sha256:b0997827b4f6a7c286c01c5f60384d218dca4ed7d9efa945c3e1aa623d5709ae",
 | 
			
		||||
                "sha256:b631ef96d3222e62861443cc89d6563ba3eeb816eeb96b2629345ab795e53681",
 | 
			
		||||
                "sha256:bf47c0607522fdbca6c9e817a6e81b08491de50f3766a7a0e6a5be7905961b41",
 | 
			
		||||
                "sha256:f81025eddd0327c7d4cfe9b62cf33190e1e736cc6e97502b3ec425f574b3e7a8"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==5.1.1"
 | 
			
		||||
            "version": "==5.1.2"
 | 
			
		||||
        },
 | 
			
		||||
        "six": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
| 
						 | 
				
			
			@ -317,12 +432,6 @@
 | 
			
		|||
            ],
 | 
			
		||||
            "version": "==1.12.0"
 | 
			
		||||
        },
 | 
			
		||||
        "smmap": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:0e2b62b497bd5f0afebc002eda4d90df9d209c30ef257e8673c90a6b5c119d62"
 | 
			
		||||
            ],
 | 
			
		||||
            "version": "==0.9.0"
 | 
			
		||||
        },
 | 
			
		||||
        "smmap2": {
 | 
			
		||||
            "hashes": [
 | 
			
		||||
                "sha256:0555a7bf4df71d1ef4218e4807bbf9b201f910174e6e08af2e138d4e517b4dde",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										423
									
								
								main.py
									
										
									
									
									
								
							
							
						
						
									
										423
									
								
								main.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -12,21 +12,29 @@ import logging
 | 
			
		|||
import subprocess
 | 
			
		||||
import threading
 | 
			
		||||
import time
 | 
			
		||||
import traceback
 | 
			
		||||
import sshtunnel
 | 
			
		||||
import errno
 | 
			
		||||
 | 
			
		||||
from etcd3_wrapper import Etcd3Wrapper
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
from typing import Union
 | 
			
		||||
from functools import wraps
 | 
			
		||||
from string import Template
 | 
			
		||||
from os.path import join
 | 
			
		||||
 | 
			
		||||
from ucloud_common.rbd import RBD
 | 
			
		||||
from ucloud_common.vm import VmPool, VMEntry, VMStatus
 | 
			
		||||
from etcd3_wrapper import Etcd3Wrapper
 | 
			
		||||
from ucloud_common.vm import VmPool, VMStatus, VMEntry
 | 
			
		||||
from ucloud_common.host import HostPool, HostEntry
 | 
			
		||||
from ucloud_common.request import RequestEntry, RequestPool, RequestType
 | 
			
		||||
from ucloud_common.helpers import get_ipv4_address
 | 
			
		||||
 | 
			
		||||
running_vms = []
 | 
			
		||||
vnc_port_pool = list(range(0, 100))
 | 
			
		||||
 | 
			
		||||
client = Etcd3Wrapper()
 | 
			
		||||
VM_POOL = None
 | 
			
		||||
HOST_POOL = None
 | 
			
		||||
vm_pool = None
 | 
			
		||||
host_pool = None
 | 
			
		||||
request_pool = None
 | 
			
		||||
 | 
			
		||||
logging.basicConfig(
 | 
			
		||||
    level=logging.DEBUG,
 | 
			
		||||
| 
						 | 
				
			
			@ -37,16 +45,37 @@ logging.basicConfig(
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_start_command_args(image_path, vnc_port, migration=False, migration_port=4444):
 | 
			
		||||
    _args = ("-drive file=$image_path,format=raw,if=virtio,cache=none"
 | 
			
		||||
             " -m 1024 -device virtio-rng-pci -enable-kvm -vnc :$vnc_port")
 | 
			
		||||
 | 
			
		||||
    if migration:
 | 
			
		||||
        _args = _args + " -incoming tcp:0:$migration_port"
 | 
			
		||||
 | 
			
		||||
    args_template = Template(_args)
 | 
			
		||||
 | 
			
		||||
    if migration:
 | 
			
		||||
        args = args_template.substitute(image_path=image_path, vnc_port=vnc_port,
 | 
			
		||||
                                        migration_port=migration_port)
 | 
			
		||||
    else:
 | 
			
		||||
        args = args_template.substitute(image_path=image_path, vnc_port=vnc_port)
 | 
			
		||||
 | 
			
		||||
    return args.split(" ")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class VM:
 | 
			
		||||
    key: str
 | 
			
		||||
    vm: qmp.QEMUMachine
 | 
			
		||||
    handle: qmp.QEMUMachine
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return f"VM({self.key})"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def update_heartbeat(host: HostEntry):
 | 
			
		||||
    while True:
 | 
			
		||||
        host.update_heartbeat()
 | 
			
		||||
        HOST_POOL.put(host)
 | 
			
		||||
        host_pool.put(host)
 | 
			
		||||
        time.sleep(10)
 | 
			
		||||
 | 
			
		||||
        logging.info(f"Updated last heartbeat time {host.last_heartbeat}")
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +87,7 @@ def need_running_vm(func):
 | 
			
		|||
        vm = get_vm(running_vms, e.key)
 | 
			
		||||
        if vm:
 | 
			
		||||
            try:
 | 
			
		||||
                status = vm.vm.command("query-status")
 | 
			
		||||
                status = vm.handle.command("query-status")
 | 
			
		||||
                logging.debug(f"VM Status Check - {status}")
 | 
			
		||||
            except OSError:
 | 
			
		||||
                logging.info(
 | 
			
		||||
| 
						 | 
				
			
			@ -75,119 +104,79 @@ def need_running_vm(func):
 | 
			
		|||
    return wrapper
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_vm(vm):
 | 
			
		||||
    image = client.get(f"/v1/image/{vm.value['image_uuid']}", value_in_json=True)
 | 
			
		||||
    if image:
 | 
			
		||||
        logging.debug(image)
 | 
			
		||||
        logging.info("Creating New VM...")
 | 
			
		||||
 | 
			
		||||
        _command_to_create = f"rbd clone images/{vm.image_uuid}@protected uservms/{vm.uuid}"
 | 
			
		||||
        try:
 | 
			
		||||
            subprocess.call(_command_to_create.split(" "))
 | 
			
		||||
            vm.status = VMStatus.requested_start
 | 
			
		||||
            VM_POOL.put(vm)
 | 
			
		||||
        except:
 | 
			
		||||
            logging.exception("Can't clone image")
 | 
			
		||||
    else:
 | 
			
		||||
        logging.info(f"Image not found for {vm.image_uuid}")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def start_vm(e):
 | 
			
		||||
    vm_path = f"rbd:uservms/{e.uuid}"
 | 
			
		||||
 | 
			
		||||
def create_vm(vm_entry: VMEntry):
 | 
			
		||||
    _command_to_create = f"rbd clone images/{vm_entry.image_uuid}@protected uservms/{vm_entry.uuid}"
 | 
			
		||||
    try:
 | 
			
		||||
        user_vms = RBD.ls("uservms")
 | 
			
		||||
    except:
 | 
			
		||||
        logging.info("Can't access uservms pool")
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if e.uuid not in user_vms:
 | 
			
		||||
        logging.info(f"Image file of vm {e.key} does not exists")
 | 
			
		||||
        logging.info(f"Deleting vm {e.key}")
 | 
			
		||||
        client.client.delete(e.key)
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    _vm = get_vm(running_vms, e.key)
 | 
			
		||||
    if _vm:
 | 
			
		||||
        logging.info(f"{e.key} already running")
 | 
			
		||||
        e.status = VMStatus.running
 | 
			
		||||
        VM_POOL.put(e)
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # FIXME: There should be better vnc port allocation scheme
 | 
			
		||||
    vm = qmp.QEMUMachine(
 | 
			
		||||
        "/usr/bin/qemu-system-x86_64",
 | 
			
		||||
        test_dir="vm_socklog",
 | 
			
		||||
        args=[
 | 
			
		||||
            vm_path,
 | 
			
		||||
            "-boot",
 | 
			
		||||
            "c",  # First Boot Hard drive
 | 
			
		||||
            "-m",
 | 
			
		||||
            "1024",  # RAM limit
 | 
			
		||||
            # Ever growing port number
 | 
			
		||||
            "-vnc",
 | 
			
		||||
            f":{vnc_port_pool.pop(0)}",  # Allow VNC
 | 
			
		||||
        ],
 | 
			
		||||
    )
 | 
			
		||||
    try:
 | 
			
		||||
        logging.info(f"Starting {e.key}")
 | 
			
		||||
        vm.launch()
 | 
			
		||||
        if vm.is_running():
 | 
			
		||||
            running_vms.append(VM(e.key, vm))
 | 
			
		||||
            e.status = VMStatus.running
 | 
			
		||||
            VM_POOL.put(e)
 | 
			
		||||
        else:
 | 
			
		||||
            e.declare_killed()
 | 
			
		||||
            VM_POOL.put(e)
 | 
			
		||||
        subprocess.check_call(_command_to_create.split(" "))
 | 
			
		||||
    except subprocess.CalledProcessError as e:
 | 
			
		||||
        if e.returncode == errno.EEXIST:
 | 
			
		||||
            logging.debug(f"Image for vm {vm_entry.uuid} exists")
 | 
			
		||||
            # File Already exists. No Problem Continue
 | 
			
		||||
            return
 | 
			
		||||
    except (qmp.QEMUMachineError, TypeError):
 | 
			
		||||
        logging.exception(f"Machine Error Occurred on {e.key}")
 | 
			
		||||
        e.declare_killed()
 | 
			
		||||
        VM_POOL.put(e)
 | 
			
		||||
        else:
 | 
			
		||||
            # This exception catches all other exceptions
 | 
			
		||||
            # i.e FileNotFound (BaseImage), pool Does Not Exists etc.
 | 
			
		||||
            logging.exception(f"Can't clone image - {e}")
 | 
			
		||||
    else:
 | 
			
		||||
        logging.info(f"Started Successfully {e.key}")
 | 
			
		||||
        logging.info("New VM Created")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def start_vm(vm_entry: VMEntry):
 | 
			
		||||
    _vm = get_vm(running_vms, vm_entry.key)
 | 
			
		||||
 | 
			
		||||
    # VM already running. No need to proceed further.
 | 
			
		||||
    if _vm:
 | 
			
		||||
        logging.info(f"VM {vm_entry.uuid} already running")
 | 
			
		||||
        return
 | 
			
		||||
    else:
 | 
			
		||||
        create_vm(vm_entry)
 | 
			
		||||
 | 
			
		||||
        logging.info(f"Starting {vm_entry.key}")
 | 
			
		||||
 | 
			
		||||
        # FIXME: There should be better vnc port allocation scheme
 | 
			
		||||
        vm = qmp.QEMUMachine(
 | 
			
		||||
            "/usr/bin/qemu-system-x86_64",
 | 
			
		||||
            args=get_start_command_args(vm_entry.path, vnc_port_pool.pop(0)),
 | 
			
		||||
        )
 | 
			
		||||
        try:
 | 
			
		||||
            vm.launch()
 | 
			
		||||
        except (qmp.QEMUMachineError, TypeError, Exception):
 | 
			
		||||
            vm_entry.declare_killed()
 | 
			
		||||
            vm_entry.add_log(f"Machine Error occurred - {traceback.format_exc()}")
 | 
			
		||||
            vm_pool.put(vm_entry)
 | 
			
		||||
        else:
 | 
			
		||||
            running_vms.append(VM(vm_entry.key, vm))
 | 
			
		||||
            vm_entry.status = VMStatus.running
 | 
			
		||||
            vm_entry.add_log("Started successfully")
 | 
			
		||||
            vm_pool.put(vm_entry)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@need_running_vm
 | 
			
		||||
def suspend_vm(e):
 | 
			
		||||
    vm = get_vm(running_vms, e.key)
 | 
			
		||||
    vm.vm.command("stop")
 | 
			
		||||
    if vm.vm.command("query-status")["status"] == "paused":
 | 
			
		||||
        e.status = VMStatus.suspended
 | 
			
		||||
        VM_POOL.put(e)
 | 
			
		||||
        logging.info(f"Successfully suspended VM {e.key}")
 | 
			
		||||
    else:
 | 
			
		||||
        logging.info(f"Suspending VM {e.key} failed")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@need_running_vm
 | 
			
		||||
def resume_vm(e):
 | 
			
		||||
    vm = get_vm(running_vms, e.key)
 | 
			
		||||
    vm.vm.command("cont")
 | 
			
		||||
    if vm.vm.command("query-status")["status"] == "running":
 | 
			
		||||
        e.status = VMStatus.running
 | 
			
		||||
        VM_POOL.put(e)
 | 
			
		||||
        logging.info(f"Successfully resumed VM {e.key}")
 | 
			
		||||
    else:
 | 
			
		||||
        logging.info(f"Resuming VM {e.key} failed")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@need_running_vm
 | 
			
		||||
def shutdown_vm(e):
 | 
			
		||||
    vm = get_vm(running_vms, e.key)
 | 
			
		||||
    vm.vm.shutdown()
 | 
			
		||||
    if not vm.vm.is_running():
 | 
			
		||||
        logging.info(f"VM {e.key} shutdown successfully")
 | 
			
		||||
        e.status = VMStatus.stopped
 | 
			
		||||
        VM_POOL.put(e)
 | 
			
		||||
def stop_vm(vm_entry):
 | 
			
		||||
    vm = get_vm(running_vms, vm_entry.key)
 | 
			
		||||
    vm.handle.shutdown()
 | 
			
		||||
    if not vm.handle.is_running():
 | 
			
		||||
        vm_entry.add_log("Shutdown successfully")
 | 
			
		||||
        vm_entry.declare_stopped()
 | 
			
		||||
        vm_pool.put(vm_entry)
 | 
			
		||||
        running_vms.remove(vm)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def delete_vm(e):
 | 
			
		||||
    # TODO: Delete VM Image From CEPH
 | 
			
		||||
    logging.info(f"Deleting VM {e.key}")
 | 
			
		||||
    shutdown_vm(e)
 | 
			
		||||
    client.client.delete(e.key)
 | 
			
		||||
def delete_vm(vm_entry):
 | 
			
		||||
    logging.info(f"Deleting VM {vm_entry}")
 | 
			
		||||
    stop_vm(vm_entry)
 | 
			
		||||
    path_without_protocol = vm_entry.path[vm_entry.path.find(":") + 1:]
 | 
			
		||||
    try:
 | 
			
		||||
        rc = subprocess.call(f"rbd rm {path_without_protocol}".split(" "))
 | 
			
		||||
    except FileNotFoundError as e:
 | 
			
		||||
        logging.exception(e)
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        logging.exception(f"Unknown error occurred - {e}")
 | 
			
		||||
    else:
 | 
			
		||||
        if rc == 0:
 | 
			
		||||
            client.client.delete(vm_entry.key)
 | 
			
		||||
        else:
 | 
			
		||||
            logging.info("Some unknown problem occur while deleting vm file")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_vm(vm_list: list, vm_key) -> Union[VM, None]:
 | 
			
		||||
| 
						 | 
				
			
			@ -195,87 +184,199 @@ def get_vm(vm_list: list, vm_key) -> Union[VM, None]:
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def maintenance(host):
 | 
			
		||||
    _vms = VM_POOL.by_host(host.key)
 | 
			
		||||
    alleged_running_vms = VM_POOL.by_status("RUNNING", _vms)
 | 
			
		||||
    # To capture vm running according to running_vms list
 | 
			
		||||
 | 
			
		||||
    for vm in alleged_running_vms:
 | 
			
		||||
        _vm = get_vm(running_vms, vm.key)
 | 
			
		||||
        if (_vm and not _vm.vm.is_running()) or _vm is None:
 | 
			
		||||
            logging.debug(f"{_vm} {vm.key}")
 | 
			
		||||
            logging.info(
 | 
			
		||||
                f"{vm.key} is not running but is said to be running"
 | 
			
		||||
            )
 | 
			
		||||
            logging.info(f"Updating {vm.key} status to KILLED")
 | 
			
		||||
            vm.declare_killed()
 | 
			
		||||
            VM_POOL.put(vm)
 | 
			
		||||
            running_vms.remove(vm)
 | 
			
		||||
    # This is to capture successful migration of a VM.
 | 
			
		||||
    # Suppose, this host is running "vm1" and user initiated
 | 
			
		||||
    # request to migrate this "vm1" to some other host. On,
 | 
			
		||||
    # successful migration the destination host would set
 | 
			
		||||
    # the vm hostname to itself. Thus, we are checking
 | 
			
		||||
    # whether this host vm is successfully migrated. If yes
 | 
			
		||||
    # then we shutdown "vm1" on this host.
 | 
			
		||||
 | 
			
		||||
    for vm in running_vms:
 | 
			
		||||
        with vm_pool.get_put(vm.key) as vm_entry:
 | 
			
		||||
            if vm_entry.hostname != host.key and not vm_entry.in_migration:
 | 
			
		||||
                vm.handle.shutdown()
 | 
			
		||||
                vm_entry.add_log("VM on source host shutdown.")
 | 
			
		||||
    # To check vm running according to etcd entries
 | 
			
		||||
    alleged_running_vms = vm_pool.by_status("RUNNING", vm_pool.by_host(host.key))
 | 
			
		||||
 | 
			
		||||
    for vm_entry in alleged_running_vms:
 | 
			
		||||
        _vm = get_vm(running_vms, vm_entry.key)
 | 
			
		||||
 | 
			
		||||
        # Whether, the allegedly running vm is in our
 | 
			
		||||
        # running_vms list or not if it is said to be
 | 
			
		||||
        # running on this host but it is not then we
 | 
			
		||||
        # need to shut it down
 | 
			
		||||
 | 
			
		||||
        # This is to capture poweroff/shutdown of a VM
 | 
			
		||||
        # initiated by user inside VM. OR crash of VM by some
 | 
			
		||||
        # user running process
 | 
			
		||||
        if (_vm and not _vm.handle.is_running())\
 | 
			
		||||
                or not _vm:
 | 
			
		||||
            vm_entry.add_log(f"{vm_entry.key} is not running but is said to be running."
 | 
			
		||||
                             "So, shutting it down and declare it killed")
 | 
			
		||||
            vm_entry.declare_killed()
 | 
			
		||||
            vm_pool.put(vm_entry)
 | 
			
		||||
            if _vm:
 | 
			
		||||
                running_vms.remove(_vm)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def transfer_vm(request_event):
 | 
			
		||||
    # This function would run on source host i.e host on which the vm
 | 
			
		||||
    # is running initially. This host would be responsible for transferring
 | 
			
		||||
    # vm state to destination host.
 | 
			
		||||
 | 
			
		||||
    _host, _port = request_event.parameters["host"], request_event.parameters["port"]
 | 
			
		||||
    _uuid = request_event.uuid
 | 
			
		||||
    _destination = request_event.destination_host_key
 | 
			
		||||
    vm = get_vm(running_vms, join("/v1/vm", _uuid))
 | 
			
		||||
 | 
			
		||||
    if vm:
 | 
			
		||||
        tunnel = sshtunnel.SSHTunnelForwarder(
 | 
			
		||||
            (_host, 22),
 | 
			
		||||
            ssh_username="meow",
 | 
			
		||||
            ssh_pkey="~/.ssh/id_rsa",
 | 
			
		||||
            ssh_private_key_password="***REMOVED***",
 | 
			
		||||
            remote_bind_address=('127.0.0.1', _port),
 | 
			
		||||
        )
 | 
			
		||||
        try:
 | 
			
		||||
            tunnel.start()
 | 
			
		||||
        except sshtunnel.BaseSSHTunnelForwarderError:
 | 
			
		||||
            logging.exception(f"Couldn't establish connection to ({_host}, 22)")
 | 
			
		||||
        else:
 | 
			
		||||
            vm.handle.command("migrate", uri=f"tcp:{_host}:{tunnel.local_bind_port}")
 | 
			
		||||
 | 
			
		||||
            status = vm.handle.command("query-migrate")["status"]
 | 
			
		||||
            while status not in ["failed", "completed"]:
 | 
			
		||||
                time.sleep(2)
 | 
			
		||||
                status = vm.handle.command("query-migrate")["status"]
 | 
			
		||||
 | 
			
		||||
            with vm_pool.get_put(request_event.uuid) as source_vm:
 | 
			
		||||
                if status == "failed":
 | 
			
		||||
                    source_vm.add_log("Migration Failed")
 | 
			
		||||
                elif status == "completed":
 | 
			
		||||
                    # If VM is successfully migrated then shutdown the VM
 | 
			
		||||
                    # on this host and update hostname to destination host key
 | 
			
		||||
                    source_vm.add_log("Successfully migrated")
 | 
			
		||||
                    source_vm.hostname = _destination
 | 
			
		||||
                    running_vms.remove(vm)
 | 
			
		||||
                    vm.handle.shutdown()
 | 
			
		||||
                source_vm.in_migration = False  # VM transfer finished
 | 
			
		||||
        finally:
 | 
			
		||||
            tunnel.close()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def init_vm_migration(vm_entry, destination_host_key):
 | 
			
		||||
    # This function would run on destination host i.e host on which the vm
 | 
			
		||||
    # would be transferred after migration. This host would be responsible
 | 
			
		||||
    # for starting VM that would receive state of VM running on source host.
 | 
			
		||||
 | 
			
		||||
    _vm = get_vm(running_vms, vm_entry.key)
 | 
			
		||||
 | 
			
		||||
    if _vm:
 | 
			
		||||
        # VM already running. No need to proceed further.
 | 
			
		||||
        logging.log(f"{_vm.key} Already running")
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    logging.info(f"Starting {vm_entry.key}")
 | 
			
		||||
 | 
			
		||||
    # FIXME: There should be better vnc port allocation scheme
 | 
			
		||||
    actual_vm = qmp.QEMUMachine(
 | 
			
		||||
        "/usr/bin/qemu-system-x86_64",
 | 
			
		||||
        args=get_start_command_args(vm_entry.path, 100, migration=True, migration_port=4444),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        actual_vm.launch()
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        # We don't care whether MachineError or any other error occurred
 | 
			
		||||
        logging.exception(e)
 | 
			
		||||
        actual_vm.shutdown()
 | 
			
		||||
    else:
 | 
			
		||||
        vm_entry.in_migration = True
 | 
			
		||||
        vm_pool.put(vm_entry)
 | 
			
		||||
 | 
			
		||||
        running_vms.append(VM(vm_entry.key, actual_vm))
 | 
			
		||||
        r = RequestEntry.from_scratch(type=RequestType.TransferVM,
 | 
			
		||||
                                      hostname=vm_entry.hostname,
 | 
			
		||||
                                      parameters={
 | 
			
		||||
                                        "host": get_ipv4_address(),
 | 
			
		||||
                                        "port": 4444,
 | 
			
		||||
                                        },
 | 
			
		||||
                                      uuid=vm_entry.uuid,
 | 
			
		||||
                                      destination_host_key=destination_host_key
 | 
			
		||||
                                      )
 | 
			
		||||
        request_pool.put(r)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    argparser = argparse.ArgumentParser()
 | 
			
		||||
    argparser.add_argument(
 | 
			
		||||
        "hostname", help="Name of this host. e.g /v1/host/1"
 | 
			
		||||
    )
 | 
			
		||||
    argparser.add_argument("hostname", help="Name of this host. e.g /v1/host/1")
 | 
			
		||||
    args = argparser.parse_args()
 | 
			
		||||
 | 
			
		||||
    global HOST_POOL, VM_POOL
 | 
			
		||||
    HOST_POOL = HostPool(client, "/v1/host")
 | 
			
		||||
    VM_POOL = VmPool(client, "/v1/vm")
 | 
			
		||||
    global host_pool, vm_pool, request_pool
 | 
			
		||||
    host_pool = HostPool(client, "/v1/host")
 | 
			
		||||
    vm_pool = VmPool(client, "/v1/vm")
 | 
			
		||||
    request_pool = RequestPool(client, "/v1/request")
 | 
			
		||||
 | 
			
		||||
    host = HOST_POOL.get(args.hostname)
 | 
			
		||||
    host = host_pool.get(args.hostname)
 | 
			
		||||
    if not host:
 | 
			
		||||
        print("No Such Host")
 | 
			
		||||
        exit(1)
 | 
			
		||||
 | 
			
		||||
    logging.info(f"{'*' * 5} Session Started {'*' * 5}")
 | 
			
		||||
 | 
			
		||||
    # It is seen that under heavy load, timeout event doesn't come
 | 
			
		||||
    # in a predictive manner which delays heart beat update which
 | 
			
		||||
    # in turn misunderstood by scheduler that the host is dead
 | 
			
		||||
    # when it is actually alive. So, to ensure that we update the
 | 
			
		||||
    # heart beat in a predictive manner we start Heart beat updating
 | 
			
		||||
    # mechanism in separated thread
 | 
			
		||||
 | 
			
		||||
    heartbeat_updating_thread = threading.Thread(target=update_heartbeat, args=(host,))
 | 
			
		||||
    heartbeat_updating_thread.start()
 | 
			
		||||
    try:
 | 
			
		||||
        heartbeat_updating_thread.start()
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        print("No Need To Go Further. Our heartbeat updating mechanism is not working")
 | 
			
		||||
        logging.exception(e)
 | 
			
		||||
        exit(-1)
 | 
			
		||||
 | 
			
		||||
    for events_iterator in [
 | 
			
		||||
        client.get_prefix("/v1/vm/", value_in_json=True),
 | 
			
		||||
        client.watch_prefix("/v1/vm/", timeout=10, value_in_json=True),
 | 
			
		||||
        client.get_prefix("/v1/request/", value_in_json=True),
 | 
			
		||||
        client.watch_prefix("/v1/request/", timeout=10, value_in_json=True),
 | 
			
		||||
    ]:
 | 
			
		||||
        for e in events_iterator:
 | 
			
		||||
            e = VMEntry(e)
 | 
			
		||||
        for request_event in events_iterator:
 | 
			
		||||
            request_event = RequestEntry(request_event)
 | 
			
		||||
 | 
			
		||||
            if e.status == "TIMEOUT":
 | 
			
		||||
                logging.info("Timeout")
 | 
			
		||||
            if request_event.type == "TIMEOUT":
 | 
			
		||||
                logging.info("Timeout Event")
 | 
			
		||||
                maintenance(host)
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            # TODO: Re-evaluate Migration Design
 | 
			
		||||
            if hasattr(e, "migration_destination"):
 | 
			
		||||
                e_migration_destination = e.value["migration_destination"]
 | 
			
		||||
            else:
 | 
			
		||||
                e_migration_destination = ""
 | 
			
		||||
            # If the event is directed toward me OR I am destination of a InitVMMigration
 | 
			
		||||
            if hasattr(request_event, "hostname") and request_event.hostname == host.key or\
 | 
			
		||||
               hasattr(request_event, "destination") and request_event.destination == host.key:
 | 
			
		||||
                request_pool.client.client.delete(request_event.key)
 | 
			
		||||
                vm_entry = vm_pool.get(request_event.uuid)
 | 
			
		||||
 | 
			
		||||
            # If the event is directed toward me or
 | 
			
		||||
            # I am destination of a REQUESTED_MIGRATION
 | 
			
		||||
            if e.hostname == host.key or e_migration_destination == host.key:
 | 
			
		||||
                logging.debug(f"EVENT: {e}")
 | 
			
		||||
                logging.debug(f"EVENT: {request_event}")
 | 
			
		||||
 | 
			
		||||
                if e.status == "SCHEDULED_DEPLOY":
 | 
			
		||||
                    create_vm(e)
 | 
			
		||||
                if request_event.type == RequestType.StartVM:
 | 
			
		||||
                    start_vm(vm_entry)
 | 
			
		||||
 | 
			
		||||
                elif e.status == "REQUESTED_SUSPEND":
 | 
			
		||||
                    suspend_vm(e)
 | 
			
		||||
                elif request_event.type == RequestType.StopVM:
 | 
			
		||||
                    stop_vm(vm_entry)
 | 
			
		||||
 | 
			
		||||
                elif e.status == "REQUESTED_RESUME":
 | 
			
		||||
                    resume_vm(e)
 | 
			
		||||
                elif request_event.type == RequestType.DeleteVM:
 | 
			
		||||
                    delete_vm(vm_entry)
 | 
			
		||||
 | 
			
		||||
                elif e.status == "REQUESTED_START":
 | 
			
		||||
                    start_vm(e)
 | 
			
		||||
                elif request_event.type == RequestType.InitVMMigration:
 | 
			
		||||
                    init_vm_migration(vm_entry, host.key)
 | 
			
		||||
 | 
			
		||||
                elif e.status == "REQUESTED_SHUTDOWN":
 | 
			
		||||
                    shutdown_vm(e)
 | 
			
		||||
 | 
			
		||||
                elif e.status == "DELETED":
 | 
			
		||||
                    delete_vm(e)
 | 
			
		||||
                elif request_event.type == RequestType.TransferVM:
 | 
			
		||||
                    transfer_vm(request_event)
 | 
			
		||||
 | 
			
		||||
                logging.info(f"Running VMs {running_vms}")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue