add releasemgr

This commit is contained in:
zhuyj17 2019-05-06 01:52:52 +08:00
parent fb3258e395
commit 677465209d
2 changed files with 106 additions and 1 deletions

99
src/master/releasemgr.py Normal file
View File

@ -0,0 +1,99 @@
import threading, time
from utils import env
from utils.log import logger
from utils.model import db, VCluster, Container
import datetime
userpoint = "http://" + env.getenv('USER_IP') + ":" + str(env.getenv('USER_PORT'))
def post_to_user(url = '/', data={}):
return requests.post(userpoint+url,data=data).json()
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class ReleaseMgr(threading.Thread):
def __init__(self, vclustermgr, ulockmgr, check_interval=_ONE_DAY_IN_SECONDS):
threading.Thread.__init__(self)
self.thread_stop = False
self.vclustermgr = vclustermgr
self.ulockmgr = ulockmgr
self.check_interval = check_interval
self.warning_days = 7
self.release_days = 14
def _send_email(to_address, username, vcluster, days, is_released=True):
email_from_address = settings.get('EMAIL_FROM_ADDRESS')
if (email_from_address in ['\'\'', '\"\"', '']):
return
text = '<html><h4>Dear '+ username + ':</h4>'
text += '''<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Your workspace/vcluster(name:%s id:%d) in <a href='%s'>%s</a>
has been stopped more than %d days now. </p>
''' % (vc.clustername, vc.clusterid, env.getenv("PORTAL_URL"), env.getenv("PORTAL_URL"), days)
if is_released:
text += '''<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Therefore, the workspace/vcluster has been released now.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>And the data in it couldn't be recoverd</b> unless you save it.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;You can create new workspace/vcluster if you need.</p>
'''
else:
day_d = self.release_days - self.warning_days
release_date = datetime.datetime.now() + datetime.timedelta(days=day_d)
rd_str = release_date.strftime("%Y-%m-%d %H:%M:%S")
text += '''<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;It will be released at <b>%s(in about %d days)</b>.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>And the data in it couldn't be recoverd after releasing.</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Please start or save it before <b>%s(in about %d days)</b> if you want to keep the data.</p>
''' % (rd_str, day_d, rd_str, day_d)
text += '''<br>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Note: DO NOT reply to this email!</p>
<br><br>
<p> <a href='http://docklet.unias.org'>Docklet Team</a>, SEI, PKU</p>
'''
subject = 'Docklet workspace/vcluster releasing alert'
msg = MIMEMultipart()
textmsg = MIMEText(text,'html','utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = email_from_address
msg['To'] = to_address
msg.attach(textmsg)
s = smtplib.SMTP()
s.connect()
try:
s.sendmail(email_from_address, to_address, msg.as_string())
except Exception as err:
logger.error(traceback.format_exc())
s.close()
def run(self):
while not self.thread_stop:
logger.info("[ReleaseMgr] Begin checking each vcluster if it needs to be released...")
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']
vcs = VCluster.query.filter_by(status='stopped').all()
for vc in vcs:
if vc.stop_time is None:
continue
days = (datetime.datetime.now() - vc.stop_time).days
if days >= self.release_days:
logger.info("[ReleaseMgr] VCluster(id:%d,user:%s) has been stopped(%s) for more than %d days, it will be released."
% (vc.clusterid, vc.ownername, vc.stop_time.strftime("%Y-%m-%d %H:%M:%S"), self.release_days))
rc_info = post_to_user("/master/user/recoverinfo/", {'username':username,'auth_key':auth_key})
logger.info("[ReleaseMgr] %s"%str(rc_info))
groupname = rc_info['groupname']
user_info = {"data":{"id":rc_info['uid'],"groupinfo":quotas[groupname]}}
success, msg = self.vclustermgr.delete_cluster(vc.clustername, vc.ownername, user_info)
if not success:
logger.error("[ReleaseMgr] Can't release VCluster(id:%d,user:%s) for %s"%(vc.clusterid, vc.ownername, msg))
else:
self._send_email()
elif days >= self.warning_days:
pass #send warning
time.sleep(self.check_interval)
def stop(self):
self.thread_stop = True
return

View File

@ -378,6 +378,7 @@ class VCluster(db.Model):
nextcid = db.Column(db.Integer) nextcid = db.Column(db.Integer)
create_time = db.Column(db.DateTime) create_time = db.Column(db.DateTime)
start_time = db.Column(db.String(20)) start_time = db.Column(db.String(20))
stop_time = db.Column(db.DateTime)
proxy_server_ip = db.Column(db.String(20)) proxy_server_ip = db.Column(db.String(20))
proxy_public_ip = db.Column(db.String(20)) proxy_public_ip = db.Column(db.String(20))
port_mapping = db.relationship('PortMapping', backref='v_cluster', lazy='dynamic') port_mapping = db.relationship('PortMapping', backref='v_cluster', lazy='dynamic')
@ -397,6 +398,7 @@ class VCluster(db.Model):
self.billing_history = [] self.billing_history = []
self.create_time = datetime.now() self.create_time = datetime.now()
self.start_time = "------" self.start_time = "------"
self.stop_time = None
def __repr__(self): def __repr__(self):
info = {} info = {}
@ -410,6 +412,10 @@ class VCluster(db.Model):
info["nextcid"] = self.nextcid info["nextcid"] = self.nextcid
info["create_time"] = self.create_time.strftime("%Y-%m-%d %H:%M:%S") info["create_time"] = self.create_time.strftime("%Y-%m-%d %H:%M:%S")
info["start_time"] = self.start_time info["start_time"] = self.start_time
if self.stop_time is None:
info['stop_time'] = "------"
else:
info['stop_time'] = self.stop_time.strftime("%Y-%m-%d %H:%M:%S")
info["containers"] = [dict(eval(str(con))) for con in self.containers] info["containers"] = [dict(eval(str(con))) for con in self.containers]
info["port_mapping"] = [dict(eval(str(pm))) for pm in self.port_mapping] info["port_mapping"] = [dict(eval(str(pm))) for pm in self.port_mapping]
info["billing_history"] = [dict(eval(str(bh))) for bh in self.billing_history] info["billing_history"] = [dict(eval(str(bh))) for bh in self.billing_history]
@ -517,7 +523,7 @@ class Batchtask(db.Model):
self.running_time = 0 self.running_time = 0
self.billing = 0 self.billing = 0
self.tried_times = 0 self.tried_times = 0
def __repr__(self): def __repr__(self):
info = {} info = {}
info['id'] = self.id info['id'] = self.id