Merge pull request #384 from zhongyehong/master
add page for migrating host
This commit is contained in:
commit
e37c9eb6de
|
@ -432,6 +432,23 @@ def migrate_cluster():
|
|||
finally:
|
||||
G_ulockmgr.release(user)
|
||||
|
||||
@app.route("/host/migrate/", methods=['POST'])
|
||||
@login_required
|
||||
def migrate_host(user, beans, form):
|
||||
global G_vclustermgr
|
||||
global G_ulockmgr
|
||||
src_host = request.form.get('src_host', None)
|
||||
dst_host_list = request.form.getlist('dst_host_list', None)
|
||||
|
||||
if src_host is None or dst_host_list is None:
|
||||
return json.dumps({'success':'false', 'message': 'src host or dst host list is null'})
|
||||
[status, msg] = G_vclustermgr.migrate_host(src_host, dst_host_list)
|
||||
if status:
|
||||
return json.dumps({'success': 'true', 'action': 'migrate_host'})
|
||||
else:
|
||||
return json.dumps({'success': 'false', 'message': msg})
|
||||
|
||||
|
||||
|
||||
@app.route("/image/list/", methods=['POST'])
|
||||
@login_required
|
||||
|
|
|
@ -789,14 +789,14 @@ class VclusterMgr(object):
|
|||
self.imgmgr.removeImage(username,imagename)
|
||||
return [True,""]
|
||||
|
||||
def migrate_cluster(self, clustername, username, new_host_list, user_info):
|
||||
def migrate_cluster(self, clustername, username, src_host, new_host_list, user_info):
|
||||
[status, info] = self.get_clusterinfo(clustername, username)
|
||||
if not status:
|
||||
return [False, "cluster not found"]
|
||||
prestatus = info['status']
|
||||
self.stop_cluster(clustername, username)
|
||||
for container in info['containers']:
|
||||
if container['host'] in new_host_list:
|
||||
if not container['host'] == src_host:
|
||||
continue
|
||||
random.shuffle(new_host_list)
|
||||
for new_host in new_host_list:
|
||||
|
@ -816,6 +816,29 @@ class VclusterMgr(object):
|
|||
return [False, msg]
|
||||
return [True, ""]
|
||||
|
||||
def migrate_host(self, src_host, new_host_list):
|
||||
[status, vcluster_list] = self.get_all_clusterinfo()
|
||||
if not status:
|
||||
return [False, vcluster_list]
|
||||
auth_key = env.getenv('AUTH_KEY')
|
||||
res = post_to_user("/master/user/groupinfo/", {'auth_key':auth_key})
|
||||
groups = json.loads(res['groups'])
|
||||
quotas = {}
|
||||
for group in groups:
|
||||
quotas[group['name']] = group['quotas']
|
||||
|
||||
for vcluster in vcluster_list:
|
||||
try:
|
||||
clustername = vcluster['clustername']
|
||||
username = vcluster['ownername']
|
||||
rc_info = post_to_user("/master/user/recoverinfo/", {'username':username,'auth_key':auth_key})
|
||||
groupname = rc_info['groupname']
|
||||
user_info = {"data":{"id":rc_info['uid'],"groupinfo":quotas[groupname]}}
|
||||
self.migrate_cluster(clustername, username, src_host, new_host_list, user_info)
|
||||
except Exception as ex:
|
||||
return [False, str(ex)]
|
||||
return [True, ""]
|
||||
|
||||
def is_cluster(self, clustername, username):
|
||||
[status, clusters] = self.list_clusters(username)
|
||||
if clustername in clusters:
|
||||
|
@ -862,6 +885,14 @@ class VclusterMgr(object):
|
|||
else:
|
||||
return [True, vcluster]
|
||||
|
||||
def get_all_clusterinfo(self):
|
||||
vcluster_list = VCluster.query.all()
|
||||
logger.info(str(vcluster_list))
|
||||
if vcluster_list is None:
|
||||
return [False, None]
|
||||
else:
|
||||
return [True, json.loads(str(vcluster_list))]
|
||||
|
||||
# acquire cluster id from etcd
|
||||
def _acquire_id(self):
|
||||
self.clusterid_locks.acquire()
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
</ol>
|
||||
{% endblock %}
|
||||
|
||||
{% block css_src %}
|
||||
<link href="//cdn.bootcss.com/datatables/1.10.11/css/dataTables.bootstrap.min.css" rel="stylesheet">
|
||||
<link href="//cdn.bootcss.com/datatables/1.10.11/css/jquery.dataTables_themeroller.css" rel="stylesheet">
|
||||
<link href="/static/dist/css/modalconfig.css" rel="stylesheet">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<ul class="nav nav-tabs" role="tablist" id="myTabs">
|
||||
{% for master in allmachines %}
|
||||
|
@ -59,7 +65,7 @@
|
|||
<th>Mem used</th>
|
||||
<th>Disk used</th>
|
||||
<th>Summary</th>
|
||||
<th>Delete</th>
|
||||
<th>Operation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -80,7 +86,50 @@
|
|||
<td id='{{master.split("@")[1]}}_{{ loop.index }}_mem'>--</td>
|
||||
<td id='{{master.split("@")[1]}}_{{ loop.index }}_disk'>--</td>
|
||||
<td><a class="btn btn-info btn-xs" href='/hosts/{{master.split("@")[0]}}/{{ phym['ip'] }}/'>Realtime</a></td>
|
||||
<td><button class="btn btn-xs btn-default">Delete</button></td>
|
||||
<td><button class="btn btn-xs btn-default">Delete</button>
|
||||
<button class="btn btn-xs btn-danger" data-toggle="modal" data-target="#Migrate_{{loop.index}}_{{master.split("@")[1]}}">Migrate</button>
|
||||
<div class="modal inmodal" id="Migrate_{{loop.index}}_{{master.split("@")[1]}}" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content animated fadeIn">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<i class="fa fa-plus modal-icon"></i>
|
||||
<h4 class="modal-title">Migrate Container from {{phym['ip']}} to Another Hosts [dangerous!!!]</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form action="/hosts/{{master.split("@")[0]}}/migrate/{{ phym['ip'] }}/" method="POST" id="MigrateForm">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<table class="table table-striped table-bordered table-hover table-image">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>HostIp</th>
|
||||
<th>Nodes</th>
|
||||
<th>choose</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for tphym in allmachines[master] %}
|
||||
{% if not phym == tphym %}
|
||||
<tr>
|
||||
<td>{{ tphym['ip'] }}</td>
|
||||
<td>{{ tphym['containers']['running']}} / {{ tphym['containers']['total'] }}</td>
|
||||
<td><input type="checkbox" name="target" value="{{tphym['ip']}}"></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-white" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
|
@ -315,6 +315,7 @@ def masterdesc(mastername):
|
|||
descriptionMasterView.desc=env.getenv(mastername+"_desc")[1:-1]
|
||||
return descriptionMasterView.as_view()
|
||||
|
||||
|
||||
@app.route("/image/<masterip>/list/", methods=['POST'])
|
||||
@login_required
|
||||
def image_list(masterip):
|
||||
|
@ -376,6 +377,14 @@ def updatebaseImage(image,masterip):
|
|||
def hosts():
|
||||
return hostsView.as_view()
|
||||
|
||||
@app.route("/hosts/<masterip>/migrate/<hostip>/", methods=['POST'])
|
||||
@administration_required
|
||||
def hostMigrate(hostip, masterip):
|
||||
hostMigrateView.hostip = hostip
|
||||
hostMigrateView.masterip = masterip
|
||||
hostMigrateView.target = request.form.getlist('target')
|
||||
return hostMigrateView.as_view()
|
||||
|
||||
@app.route("/hosts/<masterip>/<com_ip>/", methods=['GET'])
|
||||
@administration_required
|
||||
def hostsRealtime(com_ip,masterip):
|
||||
|
|
|
@ -113,3 +113,13 @@ class updatebaseImageView(normalView):
|
|||
}
|
||||
dockletRequest.post('/image/updatebase/', data)
|
||||
return redirect("/settings/")
|
||||
|
||||
class hostMigrateView(normalView):
|
||||
@classmethod
|
||||
def post(self):
|
||||
data = {
|
||||
"src_host": self.hostip,
|
||||
"dst_host_list": self.target
|
||||
}
|
||||
dockletRequest.post("/host/migrate/", data, self.masterip)
|
||||
return redirect("/hosts/")
|
||||
|
|
Loading…
Reference in New Issue