Shutdown VM, ListUserFiles added. Able to parse units included in specs
This commit is contained in:
parent
993fbbc3ac
commit
68f9bebccb
4 changed files with 115 additions and 35 deletions
1
Pipfile
1
Pipfile
|
@ -13,6 +13,7 @@ flask = "*"
|
||||||
flask-restful = "*"
|
flask-restful = "*"
|
||||||
etcd3 = "*"
|
etcd3 = "*"
|
||||||
gunicorn = "*"
|
gunicorn = "*"
|
||||||
|
bitmath = "*"
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
python_version = "3.7"
|
python_version = "3.7"
|
||||||
|
|
75
Pipfile.lock
generated
75
Pipfile.lock
generated
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "87f5447c7fa8d96dacc7c638075cc31842ef676f6d1c35214e1960572d44e929"
|
"sha256": "fa257b2f0b607e37897d62a624b656fdf219f74dc0a943f481ba6ef0d1a92c90"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -23,6 +23,13 @@
|
||||||
],
|
],
|
||||||
"version": "==7.0.0"
|
"version": "==7.0.0"
|
||||||
},
|
},
|
||||||
|
"bitmath": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:293325f01e65defe966853111df11d39215eb705a967cb115851da8c4cfa3eb8"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.3.3.1"
|
||||||
|
},
|
||||||
"certifi": {
|
"certifi": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939",
|
"sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939",
|
||||||
|
@ -69,40 +76,40 @@
|
||||||
},
|
},
|
||||||
"grpcio": {
|
"grpcio": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0232add03144dd3cf9b660e2718244cb8e175370dca4d3855cb4e489a7811b53",
|
"sha256:03b78b4e7dcdfe3e257bb528cc93923f9cbbab6d5babf15a60d21e9a4a70b1a2",
|
||||||
"sha256:0f20e6dcb1b8662cdca033bb97c0a8116a5343e3ebc7f71c5fe7f89039978350",
|
"sha256:1ce0ccfbdfe84387dbcbf44adb4ae16ec7ae70e166ffab478993eb1ea1cba3ce",
|
||||||
"sha256:10b07a623d33d4966f45c85d410bc6a79c5ac6341f06c3beda6c22be12cbfe07",
|
"sha256:22e167a9406d73dd19ffe8ed6a485f17e6eac82505be8c108897f15e68badcbb",
|
||||||
"sha256:10c0476d5a52d21f402fc073745dc43b87cc8e080a1f49bbff4e1059019310fb",
|
"sha256:31d0aeca8d8ee2301c62c5c340e0889d653b1280d68f9fa203982cb6337b050e",
|
||||||
"sha256:289dae0b35c59d191c524e976dd0a6f8c995d2062e72621eb866ad0f4472a635",
|
"sha256:44c7f99ca17ebbcc96fc54ed00b454d8313f1eac28c563098d8b901025aff941",
|
||||||
"sha256:2be726f16142d358a0df1e81d583d6820ee561a7856a79cca2fbe49989308be7",
|
"sha256:5471444f53f9db6a1f1f11f5dbc173228881df8446380b6b98f90afb8fd8348e",
|
||||||
"sha256:4338d2a81f5b4ca022e085040b3cfce19419a5ce44aa7e6810ac1df05365bed7",
|
"sha256:561bca3b1bde6d6564306eb05848fd155136e9c3a25d2961129b1e2edba22fce",
|
||||||
"sha256:4c535b46f20e66bee3097583231977e721acdfcb1671d1490c99b7be8902ce18",
|
"sha256:5bf58e1d2c2f55365c06e8cb5abe067b88ca2e5550fb62009c41df4b54505acf",
|
||||||
"sha256:557154aef70a0e979700cc9528bc8b606b668084a29a0d57dbc4b06b078a2f1c",
|
"sha256:6b7163d1e85d76b0815df63fcc310daec02b44532bb433f743142d4febcb181f",
|
||||||
"sha256:5bfdd7e6647498f979dc46583723c852d97b25afe995d55aa1c76a5f9816bc1f",
|
"sha256:766d79cddad95f5f6020037fe60ea8b98578afdf0c59d5a60c106c1bdd886303",
|
||||||
"sha256:87d8943ae7aa6ca5bbad732867d7f17d2550e4966a0c15b52088e8b579422e47",
|
"sha256:770b7372d5ca68308ff66d7baee53369fa5ce985f84bcb6aa1948c1f2f7b02f2",
|
||||||
"sha256:89d8719d8de4d137678f7caa979e1b0a6fd4026f8096ceef8c2d164bbabefaf2",
|
"sha256:7ab178da777fc0f55b6aef5a755f99726e8e4b75e3903954df07b27059b54fcf",
|
||||||
"sha256:9c3f4af989ce860710ac1864dc2e867dd87e6cee51a2368df1b253596868e52f",
|
"sha256:8078305e77c2f6649d36b24d8778096413e474d9d7892c6f92cfb589c9d71b2e",
|
||||||
"sha256:9da52c3c728883aee429bb7c315049f50b2139f680cd86bb1165418e4f93a982",
|
"sha256:85600b63a386d860eeaa955e9335e18dd0d7e5477e9214825abf2c2884488369",
|
||||||
"sha256:9e9736659987beab42d18525ed10d21f80a1ba8389eac03425fbfd5684e6bbf0",
|
"sha256:857d9b939ae128be1c0c792eb885c7ff6a386b9dea899ac4b06f4d90a31f9d87",
|
||||||
"sha256:9ebcbb1a054cab362d29d3be571d43d6b9b23302d9fc4b43e5327000da1680a9",
|
"sha256:87a41630c90c179fa5c593400f30a467c498972c702f348d41e19dafeb1d319e",
|
||||||
"sha256:a93e08636623e24c939851e2e0c0140b14f524b2980c9cdc4ea52b70a871c7e0",
|
"sha256:8805d486c6128cc0fcc8ecf16c4095d99a8693a541ef851429ab334e028a4a97",
|
||||||
"sha256:ac322d86d1a079e0a118d544443ee16f320af0062c191b4754c0c6ec2fc79310",
|
"sha256:8d71b7a89c306a41ccc7741fc9409b14f5b86727455c2a1c0c7cfcb0f784e1f2",
|
||||||
"sha256:b1fb101459868f52df6b61e7bb13375e50badf17a160e39fe1d51ae19e53f461",
|
"sha256:9e1b80bd65f8f160880cb4dad7f55697f6d37b2d7f251fc0c2128e811928f369",
|
||||||
"sha256:b39aac96cceac624a23d540473835086a3ffa77c91030189988c073488434493",
|
"sha256:9e290c84a145ae2411ee0ec9913c41cd7500e2e7485fe93632434d84ef4fda67",
|
||||||
"sha256:b65507bc273c6dbf539175a786a344cc0ac78d50e5584f72c6599733f8a3301f",
|
"sha256:9ec9f88b5bc94bd99372f27cdd53af1c92ba06717380b127733b953cfb181174",
|
||||||
"sha256:be5bb6e47417e537c884a2e2ff2e1a8b2c064a998fcfdfcc67528d4e63e7ebaf",
|
"sha256:a0a02a8b4ba6deadf706d5f849539b3685b72b186a3c9ef5d43e8972ed60fb6f",
|
||||||
"sha256:c92de6a28a909c4f460dc1bbbcb50d676cf0b1f40224b222761f73fdd851b522",
|
"sha256:a4059c59519f5940e01a071f74ae2a60ea8f6185b03d22a09d40c7959a36b16b",
|
||||||
"sha256:c9f5962eb7fa7607b20eb0e4f59ed35829bd600fc0eacb626a6db83229a3e445",
|
"sha256:a6e028c2a6da2ebfa2365a5b32531d311fbfec0e3600fc27e901b64f0ff7e54e",
|
||||||
"sha256:d00bdf9c546ed6e649f785c55b05288e8b2dbb6bf2eb74b6c579fa0d591d35bd",
|
"sha256:adcdebf9f8463df4120c427cf6c9aed39258bccd03ed37b6939e7a145d64d6e0",
|
||||||
"sha256:da804b1dd8293bd9d61b1e6ea989c887ba042a808a4fbdd80001cfa059aafed2",
|
"sha256:bdec982610259d07156a58f80b8c3e69be7751a9208bc577b059c5193d087fad",
|
||||||
"sha256:ead6c5aa3e807345913649c3be395aaca2bbb2d225f18b8f31f37eab225508f6",
|
"sha256:cefc4d4251ffb73feb303d4b7e9d6c367cb60f2db16d259ea28b114045f965aa",
|
||||||
"sha256:eb4d81550ce6f826af4ec6e8d98be347fe96291d718bf115c3f254621ae8d98d",
|
"sha256:d4145c8aa6afbac10ad27e408f7ce15992fe89ba5d0b4abca31c0c2729864c03",
|
||||||
"sha256:ef6a18ec8fd32ec81748fe720544ea2fb2d2dc50fd6d06739d5e2eb8f0626a1c",
|
"sha256:da76dc5ad719ee99de5ea28a5629ff92172cbb4a70d8a6ae3a5b7a53c7382ce1",
|
||||||
"sha256:fad42835656e0b6d3b7ffc900598e776722e30f43b7234a48f2576ca30f31a47",
|
"sha256:dde2452c08ef8b6426ccab6b5b6de9f06d836d9937d6870e68153cbf8cb49348",
|
||||||
"sha256:fb98dbfee0d963b49ae5754554028cf62e6bd695f22de16d242ba9d2f0b7339b",
|
"sha256:e3d88091d2539a4868750914a6fe7b9ec50e42b913851fc1b77423b5bd918530",
|
||||||
"sha256:fb9cd9bb8d26dc17c2dd715a46bca3a879ec8283879b164e85863110dc6e3b2a"
|
"sha256:f9c67cfe6278499d7f83559dc6322a8bbb108e307817a3d7acbfea807b3603cc"
|
||||||
],
|
],
|
||||||
"version": "==1.21.1"
|
"version": "==1.22.0"
|
||||||
},
|
},
|
||||||
"gunicorn": {
|
"gunicorn": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
|
49
main.py
49
main.py
|
@ -1,6 +1,5 @@
|
||||||
# TODO
|
# TODO
|
||||||
# convert etcd3 usage to etcd3_wrapper
|
# convert etcd3 usage to etcd3_wrapper
|
||||||
|
|
||||||
import etcd3
|
import etcd3
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -10,6 +9,7 @@ from flask_restful import Resource, Api, reqparse
|
||||||
from decouple import config
|
from decouple import config
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from etcd3_wrapper import Etcd3Wrapper
|
from etcd3_wrapper import Etcd3Wrapper
|
||||||
|
from specs_parser import SpecsParser
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
api = Api(app)
|
api = Api(app)
|
||||||
|
@ -45,6 +45,9 @@ add_vmid_args(add_otp_args(startvm_argparser))
|
||||||
uservm_argparser = reqparse.RequestParser()
|
uservm_argparser = reqparse.RequestParser()
|
||||||
add_otp_args(uservm_argparser)
|
add_otp_args(uservm_argparser)
|
||||||
|
|
||||||
|
# Specs parser
|
||||||
|
specs_parser = SpecsParser(exceptional_devices=["cpu"])
|
||||||
|
|
||||||
|
|
||||||
def is_image_valid(image_uuid):
|
def is_image_valid(image_uuid):
|
||||||
images = client.get_prefix("/v1/image/")
|
images = client.get_prefix("/v1/image/")
|
||||||
|
@ -61,6 +64,10 @@ class CreateVM(Resource):
|
||||||
if check_otp(name, realm, token) == 200:
|
if check_otp(name, realm, token) == 200:
|
||||||
# User is good
|
# User is good
|
||||||
if is_image_valid(image_uuid):
|
if is_image_valid(image_uuid):
|
||||||
|
if not specs_parser.transform_specs(specs):
|
||||||
|
return {"message": f"""Invalid unit - Please use following units {specs_parser.get_allowed_units()}"""}, 400
|
||||||
|
|
||||||
|
print(specs)
|
||||||
vm_key = f"/v1/vm/{uuid4().hex}"
|
vm_key = f"/v1/vm/{uuid4().hex}"
|
||||||
vm_entry = {"owner": name,
|
vm_entry = {"owner": name,
|
||||||
"specs": specs,
|
"specs": specs,
|
||||||
|
@ -205,6 +212,23 @@ class ResumeVM(Resource):
|
||||||
return {"message": "Invalid Credentials"}, 400
|
return {"message": "Invalid Credentials"}, 400
|
||||||
|
|
||||||
|
|
||||||
|
class ShutdownVM(Resource):
|
||||||
|
def post(self):
|
||||||
|
args = startvm_argparser.parse_args()
|
||||||
|
name, realm, token, vm_uuid = args.name, args.realm, args.token, args.vmid
|
||||||
|
|
||||||
|
if check_otp(name, realm, token) == 200:
|
||||||
|
vm = client.get(f"/v1/vm/{vm_uuid}", value_in_json=True)
|
||||||
|
if vm:
|
||||||
|
vm.value["status"] = "REQUESTED_SHUTDOWN"
|
||||||
|
client.put(vm.key, json.dumps(vm.value))
|
||||||
|
return {"message": f"VM Shutdown Queued"}
|
||||||
|
else:
|
||||||
|
return {"message": "No such VM found"}
|
||||||
|
else:
|
||||||
|
return {"message": "Invalid Credentials"}, 400
|
||||||
|
|
||||||
|
|
||||||
class ListUserVM(Resource):
|
class ListUserVM(Resource):
|
||||||
def get(self):
|
def get(self):
|
||||||
args = uservm_argparser.parse_args()
|
args = uservm_argparser.parse_args()
|
||||||
|
@ -228,17 +252,40 @@ class ListUserVM(Resource):
|
||||||
return {"message": "Invalid Credentials"}, 400
|
return {"message": "Invalid Credentials"}, 400
|
||||||
|
|
||||||
|
|
||||||
|
class ListUserFiles(Resource):
|
||||||
|
def get(self):
|
||||||
|
args = uservm_argparser.parse_args()
|
||||||
|
name, realm, token = args.name, args.realm, args.token
|
||||||
|
|
||||||
|
if check_otp(name, realm, token) == 200:
|
||||||
|
files = client.get_prefix(f"/v1/files/", value_in_json=True)
|
||||||
|
if files:
|
||||||
|
return_files = []
|
||||||
|
user_files = list(filter(lambda f: f.value["owner"] == name, files))
|
||||||
|
for file in user_files:
|
||||||
|
return_files.append({
|
||||||
|
"filename": vm.value["filename"]
|
||||||
|
})
|
||||||
|
return {"message": return_files}, 200
|
||||||
|
else:
|
||||||
|
return {"message": "No File found"}, 404
|
||||||
|
else:
|
||||||
|
return {"message": "Invalid Credentials"}, 400
|
||||||
|
|
||||||
api.add_resource(CreateVM, "/vm/create")
|
api.add_resource(CreateVM, "/vm/create")
|
||||||
api.add_resource(DeleteVM, "/vm/delete")
|
api.add_resource(DeleteVM, "/vm/delete")
|
||||||
api.add_resource(VmStatus, "/vm/status")
|
api.add_resource(VmStatus, "/vm/status")
|
||||||
|
|
||||||
api.add_resource(StartVM, "/vm/start")
|
api.add_resource(StartVM, "/vm/start")
|
||||||
api.add_resource(SuspendVM, "/vm/suspend")
|
api.add_resource(SuspendVM, "/vm/suspend")
|
||||||
api.add_resource(ResumeVM, "/vm/resume")
|
api.add_resource(ResumeVM, "/vm/resume")
|
||||||
|
api.add_resource(ShutdownVM, "/vm/shutdown")
|
||||||
|
|
||||||
api.add_resource(CreateImage, "/image/create")
|
api.add_resource(CreateImage, "/image/create")
|
||||||
api.add_resource(ListPublicImages, "/image/list-public")
|
api.add_resource(ListPublicImages, "/image/list-public")
|
||||||
|
|
||||||
api.add_resource(ListUserVM, "/user/vms")
|
api.add_resource(ListUserVM, "/user/vms")
|
||||||
|
api.add_resource(ListUserFiles, "/user/files")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host="::", debug=True)
|
app.run(host="::", debug=True)
|
||||||
|
|
25
specs_parser.py
Normal file
25
specs_parser.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import bitmath
|
||||||
|
|
||||||
|
class SpecsParser(object):
|
||||||
|
def __init__(self, exceptional_devices, allowed_unit = 10):
|
||||||
|
self.exceptional_devices = exceptional_devices
|
||||||
|
self.allowed_unit = allowed_unit
|
||||||
|
|
||||||
|
def transform_specs(self, specs):
|
||||||
|
try:
|
||||||
|
for device in filter(lambda x: x not in self.exceptional_devices, specs):
|
||||||
|
parsed = bitmath.parse_string_unsafe(specs[device])
|
||||||
|
if parsed.base != self.allowed_unit:
|
||||||
|
return False
|
||||||
|
specs[device] = int(parsed.to_Byte())
|
||||||
|
return True
|
||||||
|
except ValueError as _:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_allowed_units(self):
|
||||||
|
if self.allowed_unit == 10:
|
||||||
|
unit_prefix = bitmath.SI_PREFIXES
|
||||||
|
else:
|
||||||
|
unit_prefix = bitmath.NIST_PREFIXES
|
||||||
|
|
||||||
|
return list(map(lambda u: u.upper() + "B", unit_prefix))
|
Loading…
Reference in a new issue