2019-10-25 06:42:40 +00:00
|
|
|
import argparse
|
2019-11-02 15:42:24 +00:00
|
|
|
import multiprocessing as mp
|
2019-11-18 17:39:57 +00:00
|
|
|
import time
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-12-03 10:40:41 +00:00
|
|
|
from ucloud.common.request import RequestEntry, RequestType
|
2019-12-22 07:26:48 +00:00
|
|
|
from ucloud.shared import shared
|
|
|
|
from ucloud.settings import settings
|
2019-12-28 10:39:11 +00:00
|
|
|
from ucloud.common.vm import VMStatus
|
|
|
|
from ucloud.vmm import VMM
|
|
|
|
from os.path import join as join_path
|
2019-11-25 06:52:36 +00:00
|
|
|
|
2019-12-21 09:36:55 +00:00
|
|
|
from . import virtualmachine, logger
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-11-25 06:52:36 +00:00
|
|
|
|
|
|
|
def update_heartbeat(hostname):
|
|
|
|
"""Update Last HeartBeat Time for :param hostname: in etcd"""
|
2019-12-23 07:58:04 +00:00
|
|
|
host_pool = shared.host_pool
|
2019-12-30 09:35:07 +00:00
|
|
|
this_host = next(
|
|
|
|
filter(lambda h: h.hostname == hostname, host_pool.hosts), None
|
|
|
|
)
|
2019-10-25 06:42:40 +00:00
|
|
|
while True:
|
2019-11-02 15:42:24 +00:00
|
|
|
this_host.update_heartbeat()
|
|
|
|
host_pool.put(this_host)
|
2019-12-30 10:18:25 +00:00
|
|
|
time.sleep(10)
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-11-18 17:39:57 +00:00
|
|
|
|
2019-12-30 09:35:07 +00:00
|
|
|
def maintenance(host):
|
2019-12-28 10:39:11 +00:00
|
|
|
vmm = VMM()
|
|
|
|
running_vms = vmm.discover()
|
|
|
|
for vm_uuid in running_vms:
|
2019-12-30 09:35:07 +00:00
|
|
|
if (
|
|
|
|
vmm.is_running(vm_uuid)
|
|
|
|
and vmm.get_status(vm_uuid) == "running"
|
|
|
|
):
|
|
|
|
vm = shared.vm_pool.get(
|
|
|
|
join_path(settings["etcd"]["vm_prefix"], vm_uuid)
|
|
|
|
)
|
2019-12-28 10:39:11 +00:00
|
|
|
vm.status = VMStatus.running
|
2019-12-30 09:35:07 +00:00
|
|
|
vm.vnc_socket = vmm.get_vnc(vm_uuid)
|
|
|
|
vm.hostname = host
|
2019-12-28 10:39:11 +00:00
|
|
|
shared.vm_pool.put(vm)
|
|
|
|
|
|
|
|
|
2019-11-18 17:39:57 +00:00
|
|
|
def main(hostname):
|
2019-12-23 07:58:04 +00:00
|
|
|
host_pool = shared.host_pool
|
2019-12-30 09:35:07 +00:00
|
|
|
host = next(
|
|
|
|
filter(lambda h: h.hostname == hostname, host_pool.hosts), None
|
|
|
|
)
|
|
|
|
assert host is not None, "No such host with name = {}".format(
|
|
|
|
hostname
|
|
|
|
)
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-11-02 15:42:24 +00:00
|
|
|
try:
|
2019-12-30 09:35:07 +00:00
|
|
|
heartbeat_updating_process = mp.Process(
|
|
|
|
target=update_heartbeat, args=(hostname,)
|
|
|
|
)
|
2019-11-02 15:42:24 +00:00
|
|
|
heartbeat_updating_process.start()
|
|
|
|
except Exception as e:
|
2019-12-30 09:35:07 +00:00
|
|
|
raise Exception(
|
|
|
|
"ucloud-host heartbeat updating mechanism is not working"
|
|
|
|
) from e
|
2019-10-25 06:42:40 +00:00
|
|
|
|
|
|
|
for events_iterator in [
|
2019-12-30 09:35:07 +00:00
|
|
|
shared.etcd_client.get_prefix(
|
|
|
|
settings["etcd"]["request_prefix"], value_in_json=True
|
|
|
|
),
|
|
|
|
shared.etcd_client.watch_prefix(
|
|
|
|
settings["etcd"]["request_prefix"],
|
|
|
|
timeout=10,
|
|
|
|
value_in_json=True,
|
|
|
|
),
|
2019-10-25 06:42:40 +00:00
|
|
|
]:
|
|
|
|
for request_event in events_iterator:
|
|
|
|
request_event = RequestEntry(request_event)
|
|
|
|
|
|
|
|
if request_event.type == "TIMEOUT":
|
2019-12-30 09:35:07 +00:00
|
|
|
maintenance(host.key)
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-12-28 10:39:11 +00:00
|
|
|
if request_event.hostname == host.key:
|
2019-11-27 07:12:29 +00:00
|
|
|
logger.debug("VM Request: %s", request_event)
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-12-30 09:35:07 +00:00
|
|
|
shared.request_pool.client.client.delete(
|
|
|
|
request_event.key
|
|
|
|
)
|
|
|
|
vm_entry = shared.etcd_client.get(
|
|
|
|
join_path(
|
|
|
|
settings["etcd"]["vm_prefix"],
|
|
|
|
request_event.uuid,
|
|
|
|
)
|
|
|
|
)
|
2019-10-25 06:42:40 +00:00
|
|
|
|
|
|
|
if vm_entry:
|
2019-12-28 10:39:11 +00:00
|
|
|
vm = virtualmachine.VM(vm_entry)
|
2019-10-25 06:42:40 +00:00
|
|
|
if request_event.type == RequestType.StartVM:
|
2019-12-28 10:39:11 +00:00
|
|
|
vm.start()
|
2019-10-25 06:42:40 +00:00
|
|
|
|
|
|
|
elif request_event.type == RequestType.StopVM:
|
2019-12-28 10:39:11 +00:00
|
|
|
vm.stop()
|
2019-10-25 06:42:40 +00:00
|
|
|
|
|
|
|
elif request_event.type == RequestType.DeleteVM:
|
2019-12-28 10:39:11 +00:00
|
|
|
vm.delete()
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-12-30 09:35:07 +00:00
|
|
|
elif (
|
|
|
|
request_event.type
|
|
|
|
== RequestType.InitVMMigration
|
|
|
|
):
|
2019-12-28 10:39:11 +00:00
|
|
|
vm.start(destination_host_key=host.key)
|
2019-10-25 06:42:40 +00:00
|
|
|
|
|
|
|
elif request_event.type == RequestType.TransferVM:
|
2019-12-30 09:35:07 +00:00
|
|
|
host = host_pool.get(
|
|
|
|
request_event.destination_host_key
|
|
|
|
)
|
2019-12-28 10:39:11 +00:00
|
|
|
if host:
|
2019-12-30 09:35:07 +00:00
|
|
|
vm.migrate(
|
|
|
|
destination_host=host.hostname,
|
|
|
|
destination_sock_path=request_event.destination_sock_path,
|
|
|
|
)
|
2019-12-28 10:39:11 +00:00
|
|
|
else:
|
2019-12-30 09:35:07 +00:00
|
|
|
logger.error(
|
|
|
|
"Host %s not found!",
|
|
|
|
request_event.destination_host_key,
|
|
|
|
)
|
2019-10-25 06:42:40 +00:00
|
|
|
else:
|
2019-11-18 17:39:57 +00:00
|
|
|
logger.info("VM Entry missing")
|
|
|
|
|
2019-10-25 06:42:40 +00:00
|
|
|
|
2019-11-02 15:42:24 +00:00
|
|
|
if __name__ == "__main__":
|
2019-11-18 17:39:57 +00:00
|
|
|
argparser = argparse.ArgumentParser()
|
2019-12-30 09:35:07 +00:00
|
|
|
argparser.add_argument(
|
|
|
|
"hostname", help="Name of this host. e.g uncloud1.ungleich.ch"
|
|
|
|
)
|
2019-11-18 17:39:57 +00:00
|
|
|
args = argparser.parse_args()
|
2019-12-30 09:35:07 +00:00
|
|
|
mp.set_start_method("spawn")
|
2019-11-18 17:39:57 +00:00
|
|
|
main(args.hostname)
|