Merge branch 'master' of code.ungleich.ch:ucloud/ucloud

This commit is contained in:
llnu 2019-12-08 13:32:01 +01:00
commit 6c56a7a7c6
6 changed files with 75 additions and 55 deletions

View file

@ -1,12 +1,33 @@
# This section contains default values for all other sections # This section contains default values for all other sections
[DEFAULT] [DEFAULT]
AUTH_NAME = "replace me"
AUTH_SEED = "replace me"
AUTH_REALM = "replace me"
NETWORK_PREFIX = moo NETWORK_PREFIX = moo
OTP_VERIFY_ENDPOINT = verify/
[api] [api]
NETWORK_PREFIX = foo NETWORK_PREFIX = foo
[woo] [network]
NETWORK_PREFIX = foo PREFIX_LENGTH = 64
PREFIX = 2001:db8::/48
[noval] [netbox]
NETBOX_URL = https://replace-me.example.com
NETBOX_TOKEN = replace me
[etcd]
FILE_PREFIX = file/
HOST_PREFIx = host/
IMAGE_PREFIX = image/
IMAGE_STORE_PREFIX = imagestore/
NETWORK_PREFIX = network/
REQUEST_PREFIX = request/
USER_PREFIX = user/
VM_PREFIX = vm/

View file

@ -1,7 +1,6 @@
import os import os
from ucloud.config import etcd_client, env_vars from ucloud.config import etcd_client, config
class Optional: class Optional:
pass pass
@ -48,6 +47,6 @@ class VmUUIDField(Field):
self.validation = self.vm_uuid_validation self.validation = self.vm_uuid_validation
def vm_uuid_validation(self): def vm_uuid_validation(self):
r = etcd_client.get(os.path.join(env_vars.get('VM_PREFIX'), self.uuid)) r = etcd_client.get(os.path.join(config['api']['VM_PREFIX'], self.uuid))
if not r: if not r:
self.add_error("VM with uuid {} does not exists".format(self.uuid)) self.add_error("VM with uuid {} does not exists".format(self.uuid))

View file

@ -3,7 +3,7 @@ import os
from uuid import uuid4 from uuid import uuid4
from ucloud.config import etcd_client, env_vars from ucloud.config import etcd_client, config
data = { data = {
"is_public": True, "is_public": True,
@ -13,4 +13,4 @@ data = {
"attributes": {"list": [], "key": [], "pool": "images"}, "attributes": {"list": [], "key": [], "pool": "images"},
} }
etcd_client.put(os.path.join(env_vars.get('IMAGE_STORE_PREFIX'), uuid4().hex), json.dumps(data)) etcd_client.put(os.path.join(config['api']['IMAGE_STORE_PREFIX'], uuid4().hex), json.dumps(data))

View file

@ -7,15 +7,15 @@ import requests
from pyotp import TOTP from pyotp import TOTP
from ucloud.config import vm_pool, env_vars from ucloud.config import vm_pool, config
def check_otp(name, realm, token): def check_otp(name, realm, token):
try: try:
data = { data = {
"auth_name": env_vars.get("AUTH_NAME"), "auth_name": config['api']["AUTH_NAME"],
"auth_token": TOTP(env_vars.get("AUTH_SEED")).now(), "auth_token": TOTP(config['api']["AUTH_SEED"]).now(),
"auth_realm": env_vars.get("AUTH_REALM"), "auth_realm": config['api']["AUTH_REALM"],
"name": name, "name": name,
"realm": realm, "realm": realm,
"token": token, "token": token,
@ -25,8 +25,8 @@ def check_otp(name, realm, token):
response = requests.post( response = requests.post(
"{OTP_SERVER}{OTP_VERIFY_ENDPOINT}".format( "{OTP_SERVER}{OTP_VERIFY_ENDPOINT}".format(
OTP_SERVER=env_vars.get("OTP_SERVER", ""), OTP_SERVER=config['api']["OTP_SERVER"],
OTP_VERIFY_ENDPOINT=env_vars.get("OTP_VERIFY_ENDPOINT", "verify/"), OTP_VERIFY_ENDPOINT=config['api']["OTP_VERIFY_ENDPOINT"]
), ),
json=data, json=data,
) )
@ -80,7 +80,7 @@ def resolve_image_name(name, etcd_client):
except Exception: except Exception:
raise ValueError("Image name not in correct format i.e {store_name}:{image_name}") raise ValueError("Image name not in correct format i.e {store_name}:{image_name}")
images = etcd_client.get_prefix(env_vars.get('IMAGE_PREFIX'), value_in_json=True) images = etcd_client.get_prefix(config['api']['IMAGE_PREFIX'], value_in_json=True)
# Try to find image with name == image_name and store_name == store_name # Try to find image with name == image_name and store_name == store_name
try: try:

View file

@ -10,7 +10,7 @@ from flask_restful import Resource, Api
from ucloud.common import counters from ucloud.common import counters
from ucloud.common.vm import VMStatus from ucloud.common.vm import VMStatus
from ucloud.common.request import RequestEntry, RequestType from ucloud.common.request import RequestEntry, RequestType
from ucloud.config import (etcd_client, request_pool, vm_pool, host_pool, env_vars, image_storage_handler) from ucloud.config import (etcd_client, request_pool, vm_pool, host_pool, config, image_storage_handler)
from . import schemas from . import schemas
from .helper import generate_mac, mac2ipv6 from .helper import generate_mac, mac2ipv6
from . import logger from . import logger
@ -28,7 +28,7 @@ class CreateVM(Resource):
validator = schemas.CreateVMSchema(data) validator = schemas.CreateVMSchema(data)
if validator.is_valid(): if validator.is_valid():
vm_uuid = uuid4().hex vm_uuid = uuid4().hex
vm_key = join_path(env_vars.get("VM_PREFIX"), vm_uuid) vm_key = join_path(config['api']["VM_PREFIX"), vm_uuid)
specs = { specs = {
"cpu": validator.specs["cpu"], "cpu": validator.specs["cpu"],
"ram": validator.specs["ram"], "ram": validator.specs["ram"],
@ -56,7 +56,7 @@ class CreateVM(Resource):
# Create ScheduleVM Request # Create ScheduleVM Request
r = RequestEntry.from_scratch( r = RequestEntry.from_scratch(
type=RequestType.ScheduleVM, uuid=vm_uuid, type=RequestType.ScheduleVM, uuid=vm_uuid,
request_prefix=env_vars.get("REQUEST_PREFIX") request_prefix=config['api']["REQUEST_PREFIX")
) )
request_pool.put(r) request_pool.put(r)
@ -71,7 +71,7 @@ class VmStatus(Resource):
validator = schemas.VMStatusSchema(data) validator = schemas.VMStatusSchema(data)
if validator.is_valid(): if validator.is_valid():
vm = vm_pool.get( vm = vm_pool.get(
join_path(env_vars.get("VM_PREFIX"), data["uuid"]) join_path(config['api']["VM_PREFIX"), data["uuid"])
) )
vm_value = vm.value.copy() vm_value = vm.value.copy()
vm_value["ip"] = [] vm_value["ip"] = []
@ -79,7 +79,7 @@ class VmStatus(Resource):
network_name, mac, tap = network_mac_and_tap network_name, mac, tap = network_mac_and_tap
network = etcd_client.get( network = etcd_client.get(
join_path( join_path(
env_vars.get("NETWORK_PREFIX"), config['api']["NETWORK_PREFIX"),
data["name"], data["name"],
network_name, network_name,
), ),
@ -100,7 +100,7 @@ class CreateImage(Resource):
validator = schemas.CreateImageSchema(data) validator = schemas.CreateImageSchema(data)
if validator.is_valid(): if validator.is_valid():
file_entry = etcd_client.get( file_entry = etcd_client.get(
join_path(env_vars.get("FILE_PREFIX"), data["uuid"]) join_path(config['api']["FILE_PREFIX"), data["uuid"])
) )
file_entry_value = json.loads(file_entry.value) file_entry_value = json.loads(file_entry.value)
@ -113,7 +113,7 @@ class CreateImage(Resource):
"visibility": "public", "visibility": "public",
} }
etcd_client.put( etcd_client.put(
join_path(env_vars.get("IMAGE_PREFIX"), data["uuid"]), join_path(config['etcd']["IMAGE_PREFIX"), data["uuid"]),
json.dumps(image_entry_json), json.dumps(image_entry_json),
) )
@ -125,7 +125,7 @@ class ListPublicImages(Resource):
@staticmethod @staticmethod
def get(): def get():
images = etcd_client.get_prefix( images = etcd_client.get_prefix(
env_vars.get("IMAGE_PREFIX"), value_in_json=True config['etcd']["IMAGE_PREFIX"), value_in_json=True
) )
r = { r = {
"images": [] "images": []
@ -148,7 +148,7 @@ class VMAction(Resource):
if validator.is_valid(): if validator.is_valid():
vm_entry = vm_pool.get( vm_entry = vm_pool.get(
join_path(env_vars.get("VM_PREFIX"), data["uuid"]) join_path(config['etcd']["VM_PREFIX"), data["uuid"])
) )
action = data["action"] action = data["action"]
@ -172,7 +172,7 @@ class VMAction(Resource):
type="{}VM".format(action.title()), type="{}VM".format(action.title()),
uuid=data["uuid"], uuid=data["uuid"],
hostname=vm_entry.hostname, hostname=vm_entry.hostname,
request_prefix=env_vars.get("REQUEST_PREFIX") request_prefix=config['etcd']["REQUEST_PREFIX"]
) )
request_pool.put(r) request_pool.put(r)
return {"message": "VM {} Queued".format(action.title())}, 200 return {"message": "VM {} Queued".format(action.title())}, 200
@ -193,10 +193,10 @@ class VMMigration(Resource):
type=RequestType.ScheduleVM, type=RequestType.ScheduleVM,
uuid=vm.uuid, uuid=vm.uuid,
destination=join_path( destination=join_path(
env_vars.get("HOST_PREFIX"), validator.destination.value config['etcd']["HOST_PREFIX"], validator.destination.value
), ),
migration=True, migration=True,
request_prefix=env_vars.get("REQUEST_PREFIX") request_prefix=config['etcd']["REQUEST_PREFIX"]
) )
request_pool.put(r) request_pool.put(r)
return {"message": "VM Migration Initialization Queued"}, 200 return {"message": "VM Migration Initialization Queued"}, 200
@ -212,7 +212,7 @@ class ListUserVM(Resource):
if validator.is_valid(): if validator.is_valid():
vms = etcd_client.get_prefix( vms = etcd_client.get_prefix(
env_vars.get("VM_PREFIX"), value_in_json=True config['etcd']["VM_PREFIX"], value_in_json=True
) )
return_vms = [] return_vms = []
user_vms = filter(lambda v: v.value["owner"] == data["name"], vms) user_vms = filter(lambda v: v.value["owner"] == data["name"], vms)
@ -246,7 +246,7 @@ class ListUserFiles(Resource):
if validator.is_valid(): if validator.is_valid():
files = etcd_client.get_prefix( files = etcd_client.get_prefix(
env_vars.get("FILE_PREFIX"), value_in_json=True config['etcd']["FILE_PREFIX"], value_in_json=True
) )
return_files = [] return_files = []
user_files = list( user_files = list(
@ -270,7 +270,7 @@ class CreateHost(Resource):
data = request.json data = request.json
validator = schemas.CreateHostSchema(data) validator = schemas.CreateHostSchema(data)
if validator.is_valid(): if validator.is_valid():
host_key = join_path(env_vars.get("HOST_PREFIX"), uuid4().hex) host_key = join_path(config['etcd']["HOST_PREFIX"], uuid4().hex)
host_entry = { host_entry = {
"specs": data["specs"], "specs": data["specs"],
"hostname": data["hostname"], "hostname": data["hostname"],
@ -309,7 +309,7 @@ class GetSSHKeys(Resource):
# {user_prefix}/{realm}/{name}/key/ # {user_prefix}/{realm}/{name}/key/
etcd_key = join_path( etcd_key = join_path(
env_vars.get('USER_PREFIX'), config['etcd']['USER_PREFIX'],
data["realm"], data["realm"],
data["name"], data["name"],
"key", "key",
@ -326,7 +326,7 @@ class GetSSHKeys(Resource):
# {user_prefix}/{realm}/{name}/key/{key_name} # {user_prefix}/{realm}/{name}/key/{key_name}
etcd_key = join_path( etcd_key = join_path(
env_vars.get('USER_PREFIX'), config['etcd']['USER_PREFIX'),
data["realm"], data["realm"],
data["name"], data["name"],
"key", "key",
@ -355,7 +355,7 @@ class AddSSHKey(Resource):
# {user_prefix}/{realm}/{name}/key/{key_name} # {user_prefix}/{realm}/{name}/key/{key_name}
etcd_key = join_path( etcd_key = join_path(
env_vars.get("USER_PREFIX"), config['etcd']["USER_PREFIX"],
data["realm"], data["realm"],
data["name"], data["name"],
"key", "key",
@ -385,7 +385,7 @@ class RemoveSSHKey(Resource):
# {user_prefix}/{realm}/{name}/key/{key_name} # {user_prefix}/{realm}/{name}/key/{key_name}
etcd_key = join_path( etcd_key = join_path(
env_vars.get("USER_PREFIX"), config['etcd']["USER_PREFIX"],
data["realm"], data["realm"],
data["name"], data["name"],
"key", "key",
@ -421,17 +421,17 @@ class CreateNetwork(Resource):
} }
if validator.user.value: if validator.user.value:
nb = pynetbox.api( nb = pynetbox.api(
url=env_vars.get("NETBOX_URL"), url=config['netbox']["NETBOX_URL"],
token=env_vars.get("NETBOX_TOKEN"), token=config['netbox']["NETBOX_TOKEN"],
) )
nb_prefix = nb.ipam.prefixes.get( nb_prefix = nb.ipam.prefixes.get(
prefix=env_vars.get("PREFIX") prefix=config['network']["PREFIX"]
) )
prefix = nb_prefix.available_prefixes.create( prefix = nb_prefix.available_prefixes.create(
data={ data={
"prefix_length": env_vars.get( "prefix_length": config['network'][
"PREFIX_LENGTH", cast=int "PREFIX_LENGTH"]
), ),
"description": '{}\'s network "{}"'.format( "description": '{}\'s network "{}"'.format(
data["name"], data["network_name"] data["name"], data["network_name"]
@ -444,7 +444,7 @@ class CreateNetwork(Resource):
network_entry["ipv6"] = "fd00::/64" network_entry["ipv6"] = "fd00::/64"
network_key = join_path( network_key = join_path(
env_vars.get("NETWORK_PREFIX"), config['network']["NETWORK_PREFIX"],
data["name"], data["name"],
data["network_name"], data["network_name"],
) )
@ -462,7 +462,7 @@ class ListUserNetwork(Resource):
if validator.is_valid(): if validator.is_valid():
prefix = join_path( prefix = join_path(
env_vars.get("NETWORK_PREFIX"), data["name"] config['network']["NETWORK_PREFIX"], data["name"]
) )
networks = etcd_client.get_prefix(prefix, value_in_json=True) networks = etcd_client.get_prefix(prefix, value_in_json=True)
user_networks = [] user_networks = []
@ -498,7 +498,7 @@ api.add_resource(CreateNetwork, "/network/create")
def main(): def main():
image_stores = list(etcd_client.get_prefix(env_vars.get('IMAGE_STORE_PREFIX'), value_in_json=True)) image_stores = list(etcd_client.get_prefix(config['etcd']['IMAGE_STORE_PREFIX'], value_in_json=True))
if len(image_stores) == 0: if len(image_stores) == 0:
data = { data = {
"is_public": True, "is_public": True,
@ -508,7 +508,7 @@ def main():
"attributes": {"list": [], "key": [], "pool": "images"}, "attributes": {"list": [], "key": [], "pool": "images"},
} }
etcd_client.put(join_path(env_vars.get('IMAGE_STORE_PREFIX'), uuid4().hex), json.dumps(data)) etcd_client.put(join_path(config['etcd']['IMAGE_STORE_PREFIX'], uuid4().hex), json.dumps(data))
app.run(host="::", debug=True) app.run(host="::", debug=True)

View file

@ -21,7 +21,7 @@ import bitmath
from ucloud.common.host import HostStatus from ucloud.common.host import HostStatus
from ucloud.common.vm import VMStatus from ucloud.common.vm import VMStatus
from ucloud.config import etcd_client, env_vars, vm_pool, host_pool from ucloud.config import etcd_client, config, vm_pool, host_pool
from . import helper from . import helper
from .common_fields import Field, VmUUIDField from .common_fields import Field, VmUUIDField
from .helper import check_otp, resolve_vm_name from .helper import check_otp, resolve_vm_name
@ -102,14 +102,14 @@ class CreateImageSchema(BaseSchema):
super().__init__(data, fields) super().__init__(data, fields)
def file_uuid_validation(self): def file_uuid_validation(self):
file_entry = etcd_client.get(os.path.join(env_vars.get('FILE_PREFIX'), self.uuid.value)) file_entry = etcd_client.get(os.path.join(config['etcd']['FILE_PREFIX'], self.uuid.value))
if file_entry is None: if file_entry is None:
self.add_error( self.add_error(
"Image File with uuid '{}' Not Found".format(self.uuid.value) "Image File with uuid '{}' Not Found".format(self.uuid.value)
) )
def image_store_name_validation(self): def image_store_name_validation(self):
image_stores = list(etcd_client.get_prefix(env_vars.get('IMAGE_STORE_PREFIX'))) image_stores = list(etcd_client.get_prefix(config['etcd']['IMAGE_STORE_PREFIX']))
image_store = next( image_store = next(
filter( filter(
@ -235,7 +235,7 @@ class CreateVMSchema(OTPSchema):
if _network: if _network:
for net in _network: for net in _network:
network = etcd_client.get(os.path.join(env_vars.get('NETWORK_PREFIX'), network = etcd_client.get(os.path.join(config['etcd']['NETWORK_PREFIX'],
self.name.value, self.name.value,
net), value_in_json=True) net), value_in_json=True)
if not network: if not network:
@ -400,7 +400,7 @@ class VmMigrationSchema(OTPSchema):
if vm.status != VMStatus.running: if vm.status != VMStatus.running:
self.add_error("Can't migrate non-running VM") self.add_error("Can't migrate non-running VM")
if vm.hostname == os.path.join(env_vars.get('HOST_PREFIX'), self.destination.value): if vm.hostname == os.path.join(config['etcd']['HOST_PREFIX'], self.destination.value):
self.add_error("Destination host couldn't be same as Source Host") self.add_error("Destination host couldn't be same as Source Host")
@ -442,7 +442,7 @@ class CreateNetwork(OTPSchema):
super().__init__(data, fields=fields) super().__init__(data, fields=fields)
def network_name_validation(self): def network_name_validation(self):
network = etcd_client.get(os.path.join(env_vars.get('NETWORK_PREFIX'), network = etcd_client.get(os.path.join(config['etcd']['NETWORK_PREFIX'],
self.name.value, self.name.value,
self.network_name.value), self.network_name.value),
value_in_json=True) value_in_json=True)