forked from uncloud/uncloud
meow
93dee1c9fc
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 ```
85 lines
2.9 KiB
Python
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")
|