uncloud/metadata/main.py
meow 93dee1c9fc New Features + Refactoring
1. User can now use image name instead of image uuid when creation vm.
   For Example, now user can create an alpine vm using the following
   command
   ```shell
   ucloud-cli vm create --vm-name myvm --cpu 2 --ram '2GB' \
       --os-ssd '10GB' --image images:alpine
   ```
2. Instead of directly running code, code is now placed under a function
   main and is called using the following code
   ```python
   if __name__ == "__main__":
       main()
   ```
3. Multiprocess (Process) is used instead of threading (Thread) to update
   heart beat of host.
4. IP Address of vm is included in vm's status which is retrieved by the
   following command
   ```shell
   ucloud-cli vm status --vm-name myvm
   ```
2019-11-02 20:42:24 +05:00

85 lines
2.9 KiB
Python

import os
from flask import Flask, request
from flask_restful import Resource, Api
from config import etcd_client, VM_POOL, USER_PREFIX
app = Flask(__name__)
api = Api(app)
def get_vm_entry(mac_addr):
return next(filter(lambda vm: vm.mac == mac_addr, 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:
# {user_prefix}/{realm}/{name}/key
etcd_key = os.path.join(USER_PREFIX, data.value['owner_realm'],
data.value['owner'], 'key')
etcd_entry = 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, '/')
if __name__ == '__main__':
app.run(debug=True, host="::", port="80")