import os import argparse from flask import Flask, request from flask_restful import Resource, Api from werkzeug.exceptions import HTTPException from uncloud.common.settings import settings from uncloud.common.shared import shared app = Flask(__name__) api = Api(app) app.logger.handlers.clear() arg_parser = argparse.ArgumentParser('metadata', add_help=False) arg_parser.add_argument('--port', '-p', default=80, help='By default bind to port 80') @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 api.add_resource(Root, "/") def main(arguments): port = arguments['port'] debug = arguments['debug'] app.run(debug=debug, host="::", port=port)