-
Notifications
You must be signed in to change notification settings - Fork 2
/
cloudlet_handoff.py
executable file
·205 lines (156 loc) · 5.98 KB
/
cloudlet_handoff.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/usr/bin/env /usr/local/bin/python
# encoding: utf-8
import socket
import struct
from cloudlet_filesystem import cloudlet_filesystem
from cloudlet_memory import cloudlet_memory
from docker import Client
from cloudlet_utl import *
import logging
import time
BUF_SIZE = 1024
class cloudlet_socket:
def __init__(self, dst_ip):
# port is defined in cloudlet_utl.
HOST = dst_ip
logging.info('dst ip %s:' % HOST)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.socket.connect((HOST, port))
except Exception, e:
logging.error('Error connecting to server:%s' % e)
return False
def send_file(self, file_path):
filehandle = open(file_path, 'rb')
self.socket.sendall(filehandle.read())
filehandle.close()
def send(self, msg):
length = len(msg)
self.socket.sendall(struct.pack('!I', length))
self.socket.sendall(msg)
def close(self):
self.socket.close()
def recv(self):
len_buf = self.socket.recv(4)
length, = struct.unpack('!I', len_buf)
return self.socket.recv(length)
def get_con_info(name):
cli = Client(version='1.21')
out = cli.inspect_container(name)
if 'Error' in out:
logging.error('get container id failed')
return None, None
image = out['Config']['Image']
image_id = out['Image']
label = name + '-' + image + '-' + image_id
logging.info(label)
# get pid.
pid = out['State']['Pid']
logging.info(pid)
return out['Id'], label, pid
def sizeof_fmt(num, suffix='B'):
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Yi', suffix)
def check_container_status(id):
cli = Client(version='1.21')
out = cli.containers(id)
lines = str(out)
if 'Id' in lines:
logging.info('id get by docker-py:%s' % out[0]['Id'])
return True
return False
class handoff:
def __init__(self, con, dst_ip):
self.dst_ip = dst_ip
self.task_id = random_str()
self.con = con
self.con_id, self.label, self.pid = get_con_info(con)
def run(self):
print("task id:" + self.task_id)
start_time = time.time()
#-----step1: check status.
if not check_container_status(self.con_id):
logging.error("container is not runing,please check")
return False
#---: we need to know the status of destionation node.
# for eaxmple, CRIU version and docker version.
clet_socket = cloudlet_socket(self.dst_ip)
msg = 'init#' + self.task_id + '#' + self.label
clet_socket.send(msg)
data = clet_socket.recv()
if 'success' not in data:
logging.error('send msg failed\n')
return False
#---step2: fils system:
fs_handle = cloudlet_filesystem(self.con_id, self.task_id)
if not fs_handle.checkpoint():
logging.error("extract file failed")
return False
fs_img = fs_handle.image_path()
msg_fs = 'fs#' + str(os.path.getsize(fs_img)) + '#'
clet_socket.send(msg_fs)
clet_socket.send_file(fs_img)
data = clet_socket.recv()
#logging.debug('start send predump mm file ....')
#---step3: predump:
pre_time_start = time.time()
mm_handle = cloudlet_memory(self.task_id)
start_predump = True
while(start_predump):
if not mm_handle.predump(self.pid):
return False
premm_img = mm_handle.premm_img_path()
premm_size = os.path.getsize(premm_img)
# send predump image:
msg_premm = 'premm#' + \
mm_handle.premm_name() + '#' + str(premm_size)+'#'
clet_socket.send(msg_premm)
send_pre_img_time = time.time()
clet_socket.send_file(premm_img)
data = clet_socket.recv()
pre_time_end = time.time()
send_time = (pre_time_end - send_pre_img_time)
print("predump mm size: "+sizeof_fmt(premm_size))
logging.debug('send time:' + str(send_time))
logging.debug('send predump image time: %f ' % send_time)
print('measure bandwith:' +
sizeof_fmt((premm_size*8)/(send_time)) + '/s')
# if you only try to pre-dump one time. just break the while loop.
#start_predump = False
# mm_handle.rename()
if(premm_size <= (premm_size/send_time)*1.5):
start_predump = False
mm_handle.rename()
#-----step4: dump and send the dump images.
predump_end_time = time.time()
if not mm_handle.dump(self.con):
logging.error("memory dump failed")
return False
dump_time = time.time()
mm_img = mm_handle.mm_img_path()
mm_size = os.path.getsize(mm_img)
msg_mm = 'mm#' + str(mm_size)+'#' + mm_handle.premm_name()+'#'
# logging.info(msg_mm)
clet_socket.send(msg_mm)
#send_begin_time = time.time()
clet_socket.send_file(mm_img)
#send_dump_time= time.time()
# print('measure bandwith:' +
# sizeof_fmt((mm_size*8)/(send_dump_time - send_begin_time)) + '/s')
#test_time = time.time()
#print('test caculate time: %f ' % (test_time - send_dump_time))
data = clet_socket.recv()
# logging.debug(data)
data = clet_socket.recv()
down_time_end = time.time()
logging.info(data)
print("mm size: "+sizeof_fmt(mm_size))
#print('dump time:%f' % (dump_time - pre_time_end))
# print('predump total time: %f ' %
# (predump_end_time - pre_time_start))
print('migration total time: %f ' % (down_time_end - start_time))
print('migration down time: %f ' % (down_time_end - predump_end_time))
return True