user can copy an image to other masters

This commit is contained in:
zhongyehong 2018-04-08 15:05:04 +08:00
parent 0e0cd8110b
commit d9cc0c2c9f
6 changed files with 111 additions and 3 deletions

View File

@ -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):

View File

@ -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/"

View File

@ -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">&times;</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>

View File

@ -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):

View File

@ -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):

View File

@ -97,8 +97,11 @@ class dockletRequest():
except Exception as e: except Exception as e:
logger.debug(e) logger.debug(e)
continue continue
if 'success' in res and res['success'] == 'true':
result[masterip] = res result[masterip] = res
logger.debug("get result from " + getip(masterip)) logger.info("get result from %s success" % getip(masterip))
else:
logger.error("get result from %s failed" % getip(masterip))
return result return result