commit ba8748f2f374761b4c72abfe9aac86e2efa0d710 Author: Ahmad Bilal Khalid Date: Wed Jul 3 16:26:33 2019 +0500 initial code diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c28386c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +venv/ +.idea/ +.vscode/ +.env diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..0abd36c --- /dev/null +++ b/Pipfile @@ -0,0 +1,14 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +requests = "*" +python-decouple = "*" +pyotp = "*" + +[requires] +python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..a95d37a --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,72 @@ +{ + "_meta": { + "hash": { + "sha256": "e9d4e4efe74bd8386357563e682181c69cbbc66d40fc02931fd0f730ae6053e4" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "certifi": { + "hashes": [ + "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", + "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" + ], + "version": "==2019.6.16" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "pyotp": { + "hashes": [ + "sha256:1e3dc3d16919c4efac528d1dbecc17de1a97c4ecfdacb89d7726ed2c6645adff", + "sha256:be0ffeabddaa5ee53e7204e7740da842d070cf69168247a3d0c08541b84de602" + ], + "index": "pypi", + "version": "==2.2.7" + }, + "python-decouple": { + "hashes": [ + "sha256:1317df14b43efee4337a4aa02914bf004f010cd56d6c4bd894e6474ec8c4fe2d" + ], + "index": "pypi", + "version": "==3.1" + }, + "requests": { + "hashes": [ + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + ], + "index": "pypi", + "version": "==2.22.0" + }, + "urllib3": { + "hashes": [ + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + ], + "version": "==1.25.3" + } + }, + "develop": {} +} diff --git a/ucloud.py b/ucloud.py new file mode 100644 index 0000000..df8ecdd --- /dev/null +++ b/ucloud.py @@ -0,0 +1,109 @@ +import argparse +import requests +import json + +from decouple import config +from pyotp import TOTP + +def add_otp(parser): + parser.add_argument("--name", required=True) + parser.add_argument("--realm", required=True) + parser.add_argument("--seed", required=True) + return parser + +def add_vmid(parser): + parser.add_argument("--vmid", required=True) + return parser + +argparser = argparse.ArgumentParser() +subparser = argparser.add_subparsers(dest="command") + +create_image_parser = subparser.add_parser("create-image-from-file") +create_image_parser.add_argument("--uuid", required=True) +create_image_parser.add_argument("--name", required=True) +create_image_parser.add_argument("--image-store", + dest="image_store_name", + required=True) + +images_parser = subparser.add_parser("images") +images_parser.add_argument("--list", + choices=["public", "private"], + required=True) + +vm_parser = subparser.add_parser("vm") +vm_subparser = vm_parser.add_subparsers(dest="vmcommand") + +vm_create_parser = vm_subparser.add_parser("create") +add_otp(vm_create_parser) +vm_create_parser.add_argument("--specs_file", required=True) +vm_create_parser.add_argument("--image_uuid", required=True) + + +vm_start_parser = vm_subparser.add_parser("start") +vm_suspend_parser = vm_subparser.add_parser("suspend") +vm_resume_parser = vm_subparser.add_parser("resume") +vm_status_parser = vm_subparser.add_parser("status") + +add_vmid(add_otp(vm_start_parser)) +add_vmid(add_otp(vm_suspend_parser)) +add_vmid(add_otp(vm_resume_parser)) +add_vmid(add_otp(vm_status_parser)) + + +vm_list_parser = vm_subparser.add_parser("list") +add_otp(vm_list_parser) + +args = argparser.parse_args() + +if args.command == "create-image-from-file": + name = args.name + uuid = args.uuid + image_store_name = args.image_store_name + data = { + "name": args.name, + "uuid": uuid, + "image_store": image_store_name + } + r = requests.post(f"{config('UCLOUD_API_SERVER')}/image/create", data) + print(r.content.decode("utf-8")) + +elif args.command == "images": + if args.list == "public": + r = requests.get(f"{config('UCLOUD_API_SERVER')}/image/list-public") + print(json.loads(r.content)) + +elif args.command == "vm": + if args.vmcommand == "create": + with open(args.specs_file, "r") as specs_f: + specs = json.loads(specs_f.read()) + data = { + "name": args.name, + "realm": args.realm, + "token": TOTP(args.seed).now(), + "specs": specs, + "image_uuid": args.image_uuid + } + r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/create", + json=data) + print(json.loads(r.content)) + elif args.vmcommand == "list": + data = { + "name": args.name, + "realm": args.realm, + "token": TOTP(args.seed).now() + } + r = requests.get(f"{config('UCLOUD_API_SERVER')}/user/vms", + json=data) + print(json.loads(r.content)) + elif args.vmcommand in ["start", "suspend", "resume", "status"]: + data = { + "name": args.name, + "realm": args.realm, + "token": TOTP(args.seed).now(), + "vmid": args.vmid, + } + if args.vmcommand == "status": + r = requests.get(f"{config('UCLOUD_API_SERVER')}/vm/{args.vmcommand}", json=data) + else: + r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/{args.vmcommand}", json=data) + print(json.loads(r.content))