user can copy an image to other masters
This commit is contained in:
parent
0e0cd8110b
commit
d9cc0c2c9f
|
@ -398,6 +398,16 @@ def delete_image(user, beans, form):
|
||||||
G_imagemgr.removeImage(user,image)
|
G_imagemgr.removeImage(user,image)
|
||||||
return json.dumps({'success':'true', 'action':'delete'})
|
return json.dumps({'success':'true', 'action':'delete'})
|
||||||
|
|
||||||
|
@app.route("/image/copy/", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def copy_image(user, beans, form):
|
||||||
|
global G_imagemgr
|
||||||
|
image = form.get('image', None)
|
||||||
|
target = form.get('target',None)
|
||||||
|
res = G_imagemgr.copyImage(user,image,target)
|
||||||
|
return json.dumps(res)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/addproxy/", methods=['POST'])
|
@app.route("/addproxy/", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def addproxy(user, beans, form):
|
def addproxy(user, beans, form):
|
||||||
|
|
|
@ -257,6 +257,33 @@ class ImageMgr():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
||||||
|
def copyImage(self,user,image,target):
|
||||||
|
path = "/opt/docklet/global/images/private/"+user+"/"
|
||||||
|
image_info_file = open(path+"."+image+".info", 'r')
|
||||||
|
[createtime, isshare] = image_info_file.readlines()
|
||||||
|
recordshare = isshare
|
||||||
|
isshare = "unshared"
|
||||||
|
image_info_file.close()
|
||||||
|
image_info_file = open(path+"."+image+".info", 'w')
|
||||||
|
image_info_file.writelines([createtime, isshare])
|
||||||
|
image_info_file.close()
|
||||||
|
try:
|
||||||
|
sys_run('ssh root@%s "mkdir -p %s"' % (target,path))
|
||||||
|
sys_run('scp %s%s.tz root@%s:%s' % (path,image,target,path))
|
||||||
|
sys_run('scp %s.%s.description root@%s:%s' % (path,image,target,path))
|
||||||
|
sys_run('scp %s.%s.info root@%s:%s' % (path,image,target,path))
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
image_info_file = open(path+"."+image+".info", 'w')
|
||||||
|
image_info_file.writelines([createtime, recordshare])
|
||||||
|
image_info_file.close()
|
||||||
|
return {'success':'false', 'message':str(e)}
|
||||||
|
image_info_file = open(path+"."+image+".info", 'w')
|
||||||
|
image_info_file.writelines([createtime, recordshare])
|
||||||
|
image_info_file.close()
|
||||||
|
logger.info("copy image %s of %s to %s success" % (image,user,target))
|
||||||
|
return {'success':'true', 'action':'copy image'}
|
||||||
|
|
||||||
def update_basefs(self,image):
|
def update_basefs(self,image):
|
||||||
imgpath = self.imgpath + "private/root/"
|
imgpath = self.imgpath + "private/root/"
|
||||||
basefs = self.NFS_PREFIX+"/local/packagefs/"
|
basefs = self.NFS_PREFIX+"/local/packagefs/"
|
||||||
|
|
|
@ -358,12 +358,51 @@
|
||||||
<td>
|
<td>
|
||||||
<a href="/image/{{master.split("@")[0]}}/share/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-success">share</button></a>
|
<a href="/image/{{master.split("@")[0]}}/share/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-success">share</button></a>
|
||||||
<a href="/image/{{master.split("@")[0]}}/delete/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-danger">delete</button></a>
|
<a href="/image/{{master.split("@")[0]}}/delete/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-danger">delete</button></a>
|
||||||
|
<button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#Copyimage_{{ image['name'] }}_{{master.split("@")[1]}}">copy</button>
|
||||||
|
<div class="modal inmodal" id="Copyimage_{{ image['name'] }}_{{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">Copy image to other location</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form action="/image/{{master.split("@")[0]}}/copy/{{image['name']}}/" method="POST" id="CopyImageForm">
|
||||||
|
<table class="table table-striped table-bordered table-hover table-image">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Location</th>
|
||||||
|
<th>choose</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for targetmaster in masterips %}
|
||||||
|
{% if not master==targetmaster %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ targetmaster.split("@")[1]}}</td>
|
||||||
|
<td><input type="radio" name="target" value="{{targetmaster.split("@")[0]}}"></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>
|
||||||
</td>
|
</td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td>shared</td>
|
<td>shared</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/image/{{master.split("@")[0]}}/unshare/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-warning">unshare</button></a>
|
<a href="/image/{{master.split("@")[0]}}/unshare/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-warning">unshare</button></a>
|
||||||
<a href="/image/{{master.split("@")[0]}}/delete/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-danger">delete</button></a>
|
<a href="/image/{{master.split("@")[0]}}/delete/{{ image['name'] }}/"><button type="button" class="btn btn-xs btn-danger">delete</button></a>
|
||||||
|
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#Copyimage_{{ image['name'] }}_{{master.split("@")[1]}}"><i class="fa fa-plus"></i>Copy</button>
|
||||||
</td>
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -294,6 +294,15 @@ def deleteImage(image,masterip):
|
||||||
deleteImageView.masterip = masterip
|
deleteImageView.masterip = masterip
|
||||||
return deleteImageView.as_view()
|
return deleteImageView.as_view()
|
||||||
|
|
||||||
|
@app.route("/image/<masterip>/copy/<image>/", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def copyImage(image,masterip):
|
||||||
|
copyImageView.image = image
|
||||||
|
copyImageView.masterip = masterip
|
||||||
|
copyImageView.target = request.form['target']
|
||||||
|
return copyImageView.as_view()
|
||||||
|
|
||||||
|
|
||||||
@app.route("/image/<masterip>/updatebase/<image>/", methods=['GET'])
|
@app.route("/image/<masterip>/updatebase/<image>/", methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def updatebaseImage(image,masterip):
|
def updatebaseImage(image,masterip):
|
||||||
|
|
|
@ -298,6 +298,25 @@ class unshareImageView(normalView):
|
||||||
else:
|
else:
|
||||||
self.error()
|
self.error()
|
||||||
|
|
||||||
|
class copyImageView(normalView):
|
||||||
|
error_path = "error.html"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def post(self):
|
||||||
|
masterip = self.masterip
|
||||||
|
data = {
|
||||||
|
"image": self.image,
|
||||||
|
"target": self.target
|
||||||
|
}
|
||||||
|
result = dockletRequest.post("/image/copy/", data, masterip)
|
||||||
|
if result:
|
||||||
|
if result.get('success') == 'true':
|
||||||
|
return redirect("/config/")
|
||||||
|
else:
|
||||||
|
return self.render(self.error_path,message=result.get('message'))
|
||||||
|
else:
|
||||||
|
self.error()
|
||||||
|
|
||||||
class deleteImageView(normalView):
|
class deleteImageView(normalView):
|
||||||
template_path = "dashboard.html"
|
template_path = "dashboard.html"
|
||||||
|
|
||||||
|
@ -350,6 +369,7 @@ class deleteproxyView(normalView):
|
||||||
class configView(normalView):
|
class configView(normalView):
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(self):
|
def get(self):
|
||||||
|
masterips = dockletRequest.post_to_all()
|
||||||
allimages = dockletRequest.post_to_all('/image/list/')
|
allimages = dockletRequest.post_to_all('/image/list/')
|
||||||
for master in allimages:
|
for master in allimages:
|
||||||
allimages[master] = allimages[master].get('images')
|
allimages[master] = allimages[master].get('images')
|
||||||
|
@ -398,7 +418,7 @@ class configView(normalView):
|
||||||
'memory': defaultmemory,
|
'memory': defaultmemory,
|
||||||
'disk': defaultdisk
|
'disk': defaultdisk
|
||||||
}
|
}
|
||||||
return self.render("config.html", allimages = allimages, allclusters = allclusters_info, mysession=dict(session), quota = quota, usage = usage, defaultsetting = defaultsetting)
|
return self.render("config.html", allimages = allimages, allclusters = allclusters_info, mysession=dict(session), quota = quota, usage = usage, defaultsetting = defaultsetting, masterips = masterips)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def post(self):
|
def post(self):
|
||||||
|
|
|
@ -97,8 +97,11 @@ class dockletRequest():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
continue
|
continue
|
||||||
result[masterip] = res
|
if 'success' in res and res['success'] == 'true':
|
||||||
logger.debug("get result from " + getip(masterip))
|
result[masterip] = res
|
||||||
|
logger.info("get result from %s success" % getip(masterip))
|
||||||
|
else:
|
||||||
|
logger.error("get result from %s failed" % getip(masterip))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue