New Features + Refactoring

1. User can now use image name instead of image uuid when creation vm.
   For Example, now user can create an alpine vm using the following
   command
   ```shell
   ucloud-cli vm create --vm-name myvm --cpu 2 --ram '2GB' \
       --os-ssd '10GB' --image images:alpine
   ```
2. Instead of directly running code, code is now placed under a function
   main and is called using the following code
   ```python
   if __name__ == "__main__":
       main()
   ```
3. Multiprocess (Process) is used instead of threading (Thread) to update
   heart beat of host.
4. IP Address of vm is included in vm's status which is retrieved by the
   following command
   ```shell
   ucloud-cli vm status --vm-name myvm
   ```
This commit is contained in:
ahmadbilalkhalid 2019-11-02 20:42:24 +05:00
commit 93dee1c9fc
13 changed files with 354 additions and 233 deletions

View file

@ -1,6 +1,9 @@
import json
import subprocess
import os
import schemas
from uuid import uuid4
from flask import Flask, request
@ -9,7 +12,7 @@ from flask_restful import Resource, Api
from ucloud_common.vm import VMStatus
from ucloud_common.request import RequestEntry, RequestType
from helper import generate_mac
from helper import generate_mac, get_ip_addr
from config import (
etcd_client,
@ -23,18 +26,6 @@ from config import (
VM_POOL,
HOST_POOL,
)
from schemas import (
CreateVMSchema,
VMStatusSchema,
CreateImageSchema,
VmActionSchema,
OTPSchema,
CreateHostSchema,
VmMigrationSchema,
AddSSHSchema,
RemoveSSHSchema,
GetSSHSchema
)
app = Flask(__name__)
api = Api(app)
@ -45,7 +36,7 @@ class CreateVM(Resource):
def post():
data = request.json
print(data)
validator = CreateVMSchema(data)
validator = schemas.CreateVMSchema(data)
if validator.is_valid():
vm_uuid = uuid4().hex
vm_key = os.path.join(VM_PREFIX, vm_uuid)
@ -63,7 +54,7 @@ class CreateVM(Resource):
"specs": specs,
"hostname": "",
"status": "",
"image_uuid": data["image_uuid"],
"image_uuid": validator.image_uuid,
"log": [],
"vnc_socket": "",
"mac": str(generate_mac()),
@ -85,10 +76,14 @@ class VmStatus(Resource):
@staticmethod
def get():
data = request.json
validator = VMStatusSchema(data)
validator = schemas.VMStatusSchema(data)
if validator.is_valid():
vm = VM_POOL.get(os.path.join(VM_PREFIX, data["uuid"]))
return json.dumps(str(vm))
vm_value = vm.value.copy()
vm_value["ip"] = list(map(str, get_ip_addr(vm.mac, "br0")))
vm.value = vm_value
print(vm.value)
return vm.value
else:
return validator.get_errors(), 400
@ -97,7 +92,7 @@ class CreateImage(Resource):
@staticmethod
def post():
data = request.json
validator = CreateImageSchema(data)
validator = schemas.CreateImageSchema(data)
if validator.is_valid():
file_entry = etcd_client.get(os.path.join(FILE_PREFIX, data["uuid"]))
file_entry_value = json.loads(file_entry.value)
@ -121,10 +116,15 @@ class CreateImage(Resource):
class ListPublicImages(Resource):
@staticmethod
def get():
images = etcd_client.get_prefix(IMAGE_PREFIX)
images = etcd_client.get_prefix(IMAGE_PREFIX, value_in_json=True)
r = {}
r["images"] = []
for image in images:
r[image.key.split("/")[-1]] = json.loads(image.value)
image_key = "{}:{}".format(image.value["store_name"], image.value["name"])
r["images"].append({
"name":image_key,
"status": image.value["status"]
})
return r, 200
@ -132,7 +132,7 @@ class VMAction(Resource):
@staticmethod
def post():
data = request.json
validator = VmActionSchema(data)
validator = schemas.VmActionSchema(data)
if validator.is_valid():
vm_entry = VM_POOL.get(os.path.join(VM_PREFIX, data["uuid"]))
@ -182,7 +182,7 @@ class VMMigration(Resource):
@staticmethod
def post():
data = request.json
validator = VmMigrationSchema(data)
validator = schemas.VmMigrationSchema(data)
if validator.is_valid():
vm = VM_POOL.get(data["uuid"])
@ -203,7 +203,7 @@ class ListUserVM(Resource):
@staticmethod
def get():
data = request.json
validator = OTPSchema(data)
validator = schemas.OTPSchema(data)
if validator.is_valid():
vms = etcd_client.get_prefix(VM_PREFIX, value_in_json=True)
@ -235,7 +235,7 @@ class ListUserFiles(Resource):
@staticmethod
def get():
data = request.json
validator = OTPSchema(data)
validator = schemas.OTPSchema(data)
if validator.is_valid():
files = etcd_client.get_prefix(FILE_PREFIX, value_in_json=True)
@ -257,7 +257,7 @@ class CreateHost(Resource):
@staticmethod
def post():
data = request.json
validator = CreateHostSchema(data)
validator = schemas.CreateHostSchema(data)
if validator.is_valid():
host_key = os.path.join(HOST_PREFIX, uuid4().hex)
host_entry = {
@ -292,7 +292,7 @@ class GetSSHKeys(Resource):
@staticmethod
def get():
data = request.json
validator = GetSSHSchema(data)
validator = schemas.GetSSHSchema(data)
if validator.is_valid():
if not validator.key_name.value:
@ -321,7 +321,7 @@ class AddSSHKey(Resource):
@staticmethod
def post():
data = request.json
validator = AddSSHSchema(data)
validator = schemas.AddSSHSchema(data)
if validator.is_valid():
# {user_prefix}/{realm}/{name}/key/{key_name}
@ -342,7 +342,7 @@ class RemoveSSHKey(Resource):
@staticmethod
def get():
data = request.json
validator = RemoveSSHSchema(data)
validator = schemas.RemoveSSHSchema(data)
if validator.is_valid():
# {user_prefix}/{realm}/{name}/key/{key_name}