import os from flask import Flask, request from flask_restful import Resource, Api from werkzeug.exceptions import HTTPException from uncloud.settings import settings from uncloud.shared import shared app = Flask(__name__) api = Api(app) app.logger.handlers.clear() @app.errorhandler(Exception) def handle_exception(e): app.logger.error(e) # pass through HTTP errors if isinstance(e, HTTPException): return e # now you're handling non-HTTP exceptions only return {"message": "Server Error"}, 500 def get_vm_entry(mac_addr): return next( filter( lambda vm: mac_addr in list(zip(*vm.network))[1], shared.vm_pool.vms, ), None, ) # https://stackoverflow.com/questions/37140846/how-to-convert-ipv6-link-local-address-to-mac-address-in-python def ipv62mac(ipv6): # remove subnet info if given subnet_index = ipv6.find("/") if subnet_index != -1: ipv6 = ipv6[:subnet_index] ipv6_parts = ipv6.split(":") mac_parts = list() for ipv6_part in ipv6_parts[-4:]: while len(ipv6_part) < 4: ipv6_part = "0" + ipv6_part mac_parts.append(ipv6_part[:2]) mac_parts.append(ipv6_part[-2:]) # modify parts to match MAC value mac_parts[0] = "%02x" % (int(mac_parts[0], 16) ^ 2) del mac_parts[4] del mac_parts[3] return ":".join(mac_parts) class Root(Resource): @staticmethod def get(): data = get_vm_entry(ipv62mac(request.remote_addr)) if not data: return ( {"message": "Metadata for such VM does not exists."}, 404, ) else: etcd_key = os.path.join( settings["etcd"]["user_prefix"], data.value["owner_realm"], data.value["owner"], "key", ) etcd_entry = shared.etcd_client.get_prefix( etcd_key, value_in_json=True ) user_personal_ssh_keys = [key.value for key in etcd_entry] data.value["metadata"]["ssh-keys"] += user_personal_ssh_keys return data.value["metadata"], 200 @staticmethod def post(): return {"message": "Previous Implementation is deprecated."} # data = etcd_client.get("/v1/metadata/{}".format(request.remote_addr), value_in_json=True) # print(data) # if data: # for k in request.json: # if k not in data.value: # data.value[k] = request.json[k] # if k.endswith("-list"): # data.value[k] = [request.json[k]] # else: # if k.endswith("-list"): # data.value[k].append(request.json[k]) # else: # data.value[k] = request.json[k] # etcd_client.put("/v1/metadata/{}".format(request.remote_addr), # data.value, value_in_json=True) # else: # data = {} # for k in request.json: # data[k] = request.json[k] # if k.endswith("-list"): # data[k] = [request.json[k]] # etcd_client.put("/v1/metadata/{}".format(request.remote_addr), # data, value_in_json=True) api.add_resource(Root, "/") def main(): app.run(debug=True, host="::", port="80") if __name__ == "__main__": main()