Compare commits

..

7 commits

Author SHA1 Message Date
a722e21bc4 a 2019-09-03 20:44:57 +05:00
8ca850a6fe a 2019-08-31 17:28:43 +05:00
59d34fd7f8 a 2019-08-31 16:29:12 +05:00
bdb23fb3e2 a 2019-08-30 23:40:17 +05:00
7b5e8b0515 a 2019-08-30 19:30:59 +05:00
12b6b027d3 a 2019-08-30 19:30:33 +05:00
fe1913a195 a 2019-08-28 20:21:41 +05:00
4 changed files with 59 additions and 33 deletions

1
.gitignore vendored
View file

@ -5,4 +5,3 @@ venv/
settings.json
ucloud_common
etcd3_wrapper
log.txt

View file

@ -1,17 +1,5 @@
import logging
from etcd3_wrapper import Etcd3Wrapper
from decouple import config
logging.basicConfig(
level=logging.DEBUG,
filename="log.txt",
filemode="a",
format="%(asctime)s: %(levelname)s - %(message)s",
datefmt="%d-%b-%y %H:%M:%S",
)
WITHOUT_CEPH = config("WITHOUT_CEPH", False, cast=bool)
# TODO: Remove timeout, use certificate authentication
etcd_client = Etcd3Wrapper(host=config("ETCD_URL"))

44
main.py
View file

@ -4,14 +4,12 @@
import json
import subprocess
import os
from flask import Flask, request
from flask_restful import Resource, Api
from uuid import uuid4
from os.path import join
from config import etcd_client as client
from config import WITHOUT_CEPH, logging
from ucloud_common.vm import VmPool, VMStatus
from ucloud_common.host import HostPool
@ -19,7 +17,7 @@ from ucloud_common.request import RequestEntry, RequestPool, RequestType
from schemas import (CreateVMSchema, VMStatusSchema,
CreateImageSchema, VmActionSchema,
OTPSchema, CreateHostSchema,
VmMigrationSchema)
VmMigrationSchema, CreateNetworkSchema)
app = Flask(__name__)
api = Api(app)
@ -125,23 +123,15 @@ class VMAction(Resource):
if action == "delete" and vm_entry.hostname == "":
try:
path_without_protocol = vm_entry.path[vm_entry.path.find(":")+1:]
if WITHOUT_CEPH:
command_to_delete = ["rm", os.path.join("/var/vm", vm_entry.uuid)]
else:
command_to_delete = ["rbd", "rm", path_without_protocol]
subprocess.check_output(command_to_delete, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
if "No such file" in e.stderr.decode("utf-8"):
rc = subprocess.call(f"rbd rm {path_without_protocol}".split(" "))
except FileNotFoundError:
return {"message": "VM image does not exists"}
else:
if rc == 0:
client.client.delete(vm_entry.key)
return {"message": "VM successfully deleted"}
else:
logging.exception(e)
return {"message": "Some error occurred while deleting VM"}
else:
client.client.delete(vm_entry.key)
return {"message": "VM successfully deleted"}
r = RequestEntry.from_scratch(type=f"{action.title()}VM",
uuid=data['uuid'],
@ -152,6 +142,26 @@ class VMAction(Resource):
return validator.get_errors(), 400
class CreateNetwork(Resource):
@staticmethod
def post():
data = request.json
validator = CreateNetwork(data)
if validator.is_valid():
network_entry_json = {
"name": data["network_name"],
"type": data["network_type"],
"first_mac_address": data["first_mac_address"],
"network_size": data["network_size"],
"network_address": data["network_address"],
"dns": data["dns"]
}
client.put(f"/v1/network/{uuid4()}", json.dumps(network_entry_json))
else:
return validator.get_errors(), 400
class VMMigration(Resource):
@staticmethod
def post():
@ -257,6 +267,8 @@ api.add_resource(VmStatus, "/vm/status")
api.add_resource(VMAction, "/vm/action")
api.add_resource(VMMigration, "/vm/migrate")
api.add_resource(CreateNetwork, "/network/create")
api.add_resource(CreateImage, "/image/create")
api.add_resource(ListPublicImages, "/image/list-public")

View file

@ -11,8 +11,10 @@ host_pool = HostPool(client, "/v1/host")
vm_pool = VmPool(client, "/v1/vm")
class BaseSchema:
class BaseSchema(object):
def __init__(self, data, fields=None):
_ = data
self.__errors = []
if fields is None:
self.fields = []
@ -84,6 +86,33 @@ class CreateVMSchema(OTPSchema):
self.add_error("Image UUID not valid")
class CreateNetworkSchema(OTPSchema):
def __init__(self, data):
self.network_name = Field("network_name", str, data.get("network_name", KeyError))
self.network_type = Field("network_type", str, data.get("network_type", KeyError))
self.first_mac_address = Field("first_mac_address", str, data.get("first_mac_address", KeyError))
self.network_size = Field("network_size", str, data.get("network_size", KeyError))
self.network_address = Field("network_address", str, data.get("network_address", KeyError))
self.dns = Field("dns", str, data.get("dns", KeyError))
self.network_type.validation = self.network_type_validation
self.network_size.validation = self.network_size.validation
fields = [self.network_name, self.network_type, self.first_mac_address,
self.network_size, self.network_address, self.dns]
if fields:
fields += fields
super().__init__(data=data, fields=fields)
def network_type_validation(self):
if self.network_type.value not in ["bridged", "vxlan"]:
self.add_error(f"{self.network_type.value} not supported.")
def network_size_validation(self):
if self.network_size.value <= 0:
self.add_error(f"Network Size must be a positive number")
class VMStatusSchema(BaseSchema):
def __init__(self, data):
self.uuid = VmUUIDField(data)
@ -99,10 +128,8 @@ class CreateImageSchema(BaseSchema):
self.uuid: Field = Field("uuid", str, data.get("uuid", KeyError))
self.name = Field("name", str, data.get("name", KeyError))
self.image_store = Field("image_store", str, data.get("image_store", KeyError))
# Validations
self.uuid.validation = self.file_uuid_validation
self.image_store.validation = self.image_store_name_validation
# All Fields
fields = [self.uuid, self.name, self.image_store]