From 677465209d6e57e273c792a7fa3343a92822bd87 Mon Sep 17 00:00:00 2001 From: zhuyj17 Date: Mon, 6 May 2019 01:52:52 +0800 Subject: [PATCH] add releasemgr --- src/master/releasemgr.py | 99 ++++++++++++++++++++++++++++++++++++++++ src/utils/model.py | 8 +++- 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 src/master/releasemgr.py diff --git a/src/master/releasemgr.py b/src/master/releasemgr.py new file mode 100644 index 0000000..4f5f104 --- /dev/null +++ b/src/master/releasemgr.py @@ -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 = '

Dear '+ username + ':

' + text += '''

      Your workspace/vcluster(name:%s id:%d) in %s + has been stopped more than %d days now.

+ ''' % (vc.clustername, vc.clusterid, env.getenv("PORTAL_URL"), env.getenv("PORTAL_URL"), days) + if is_released: + text += '''

      Therefore, the workspace/vcluster has been released now.

+

      And the data in it couldn't be recoverd unless you save it.

+

      You can create new workspace/vcluster if you need.

+ ''' + 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 += '''

      It will be released at %s(in about %d days).

+

      And the data in it couldn't be recoverd after releasing.

+

      Please start or save it before %s(in about %d days) if you want to keep the data.

+ ''' % (rd_str, day_d, rd_str, day_d) + text += '''
+

      Note: DO NOT reply to this email!

+

+

Docklet Team, SEI, PKU

+ ''' + 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 diff --git a/src/utils/model.py b/src/utils/model.py index 959d7d5..9437a51 100755 --- a/src/utils/model.py +++ b/src/utils/model.py @@ -378,6 +378,7 @@ class VCluster(db.Model): nextcid = db.Column(db.Integer) create_time = db.Column(db.DateTime) start_time = db.Column(db.String(20)) + stop_time = db.Column(db.DateTime) proxy_server_ip = db.Column(db.String(20)) proxy_public_ip = db.Column(db.String(20)) port_mapping = db.relationship('PortMapping', backref='v_cluster', lazy='dynamic') @@ -397,6 +398,7 @@ class VCluster(db.Model): self.billing_history = [] self.create_time = datetime.now() self.start_time = "------" + self.stop_time = None def __repr__(self): info = {} @@ -410,6 +412,10 @@ class VCluster(db.Model): info["nextcid"] = self.nextcid info["create_time"] = self.create_time.strftime("%Y-%m-%d %H:%M:%S") 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["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] @@ -517,7 +523,7 @@ class Batchtask(db.Model): self.running_time = 0 self.billing = 0 self.tried_times = 0 - + def __repr__(self): info = {} info['id'] = self.id