forked from uncloud/uncloud
96 lines
2.5 KiB
Python
96 lines
2.5 KiB
Python
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.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(port=None, debug=False):
|
|
app.run(debug=debug, host="::", port=port)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|