From fb3258e3952a5844dddb1d5bba8fee286ccc69f9 Mon Sep 17 00:00:00 2001
From: zhuyj17
Date: Sun, 5 May 2019 23:58:50 +0800
Subject: [PATCH 1/6] fix some bugs in monitor
---
src/worker/monitor.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/worker/monitor.py b/src/worker/monitor.py
index 99170ed..a5c4af0 100755
--- a/src/worker/monitor.py
+++ b/src/worker/monitor.py
@@ -372,7 +372,7 @@ class Container_Collector(threading.Thread):
# deal with network used data
containerids = re.split("-",container_name)
- if not is_batch and len(containerids) >= 3:
+ if not is_batch and len(containerids) >= 3 and (containerids[1] + "-" + containerids[2]) in self.net_stats.keys():
workercinfo[container_name]['net_stats'] = self.net_stats[containerids[1] + '-' + containerids[2]]
#logger.info(workercinfo[container_name]['net_stats'])
@@ -658,7 +658,11 @@ class History_Manager:
laststopruntime[vnode_name] = runtime
vnode.laststopruntime = runtime
db.session.add(history)
- db.session.commit()
+ try:
+ db.session.commit()
+ except Exception as err:
+ db.session.rollback()
+ logger.warning(traceback.format_exc())
def getHistory(self,vnode_name):
vnode = VNode.query.filter_by(name=vnode_name).first()
From 677465209d6e57e273c792a7fa3343a92822bd87 Mon Sep 17 00:00:00 2001
From: zhuyj17
Date: Mon, 6 May 2019 01:52:52 +0800
Subject: [PATCH 2/6] 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
From 332a8b8ae1ed677f292f2ddc7112f5e3912d2861 Mon Sep 17 00:00:00 2001
From: Firmlyzhu
Date: Tue, 7 May 2019 17:34:17 +0800
Subject: [PATCH 3/6] Complete releasemgr
---
conf/docklet.conf.template | 10 +++++++++
src/master/httprest.py | 6 +++++-
src/master/releasemgr.py | 43 +++++++++++++++++++++++++++-----------
src/master/vclustermgr.py | 1 +
src/utils/env.py | 4 ++++
user/user.py | 2 +-
6 files changed, 52 insertions(+), 14 deletions(-)
diff --git a/conf/docklet.conf.template b/conf/docklet.conf.template
index d0aa9a8..69f20b6 100644
--- a/conf/docklet.conf.template
+++ b/conf/docklet.conf.template
@@ -183,6 +183,16 @@
# Only when you deploy docklet on the cloud can you set it to True
# ALLOW_SCALE_OUT=False
+# WARNING_DAYS: user will receive a warning email for releasing
+# when his/her vcluster has been stopped for more then the days.
+# Default: 7
+# WARNING_DAYS=7
+
+# RELEASE_DAYS: the vcluster will be released when it has been
+# stopped for more then the days. Needs to be larger then WARNING_DAYS.
+# Default: 14
+# RELEASE_DAYS=14
+
# ==================================================
#
# Batch Config
diff --git a/src/master/httprest.py b/src/master/httprest.py
index 4da0739..51f47df 100755
--- a/src/master/httprest.py
+++ b/src/master/httprest.py
@@ -29,7 +29,7 @@ from socketserver import ThreadingMixIn
from utils import etcdlib, imagemgr
from master import nodemgr, vclustermgr, notificationmgr, lockmgr, cloudmgr, jobmgr, taskmgr
from utils.logs import logs
-from master import userManager, beansapplicationmgr, monitor, sysmgr, network
+from master import userManager, beansapplicationmgr, monitor, sysmgr, network, releasemgr
from worker.monitor import History_Manager
import threading
import requests
@@ -1162,6 +1162,10 @@ if __name__ == '__main__':
G_imagemgr = imagemgr.ImageMgr()
logger.info("imagemgr started")
+ G_releasemgr = releasemgr.ReleaseMgr(G_vclustermgr,G_ulockmgr,10)
+ G_releasemgr.start()
+ logger.info("releasemgr started")
+
logger.info("startting to listen on: ")
masterip = env.getenv('MASTER_IP')
logger.info("using MASTER_IP %s", masterip)
diff --git a/src/master/releasemgr.py b/src/master/releasemgr.py
index 4f5f104..1d75eb6 100644
--- a/src/master/releasemgr.py
+++ b/src/master/releasemgr.py
@@ -2,7 +2,11 @@ import threading, time
from utils import env
from utils.log import logger
from utils.model import db, VCluster, Container
-import datetime
+import smtplib, datetime
+from email.mime.text import MIMEText
+from email.mime.multipart import MIMEMultipart
+from email.header import Header
+from master.settings import settings
userpoint = "http://" + env.getenv('USER_IP') + ":" + str(env.getenv('USER_PORT'))
def post_to_user(url = '/', data={}):
@@ -18,8 +22,10 @@ class ReleaseMgr(threading.Thread):
self.vclustermgr = vclustermgr
self.ulockmgr = ulockmgr
self.check_interval = check_interval
- self.warning_days = 7
- self.release_days = 14
+ self.warning_days = int(env.getenv("WARNING_DAYS"))
+ self.release_days = int(env.getenv("RELEASE_DAYS"))
+ if self.release_days <= self.warning_days:
+ self.release_days = self.warning_days+1
def _send_email(to_address, username, vcluster, days, is_released=True):
email_from_address = settings.get('EMAIL_FROM_ADDRESS')
@@ -35,10 +41,11 @@ class ReleaseMgr(threading.Thread):
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)
+ #day_d = self.release_days - (datetime.datetime.now() - vcluster.stop_time).days
+ release_date = vcluster.stop_time + datetime.timedelta(days=self.release_days)
+ day_d = (release_date - vcluster.stop_time).days
rd_str = release_date.strftime("%Y-%m-%d %H:%M:%S")
- text += ''' It will be released at %s(in about %d days).
+ text += ''' It will be released after %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)
@@ -78,6 +85,7 @@ class ReleaseMgr(threading.Thread):
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))
@@ -85,13 +93,24 @@ class ReleaseMgr(threading.Thread):
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()
+ self.ulockmgr.acquire(vc.ownername)
+ try:
+ 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(rc_info['email'], vc.ownername, vc, days)
+ except Exception as err:
+ logger.error(err)
+ finally:
+ self.ulockmgr.release(vc.ownername)
+
elif days >= self.warning_days:
- pass #send warning
+ logger.info("[ReleaseMgr] VCluster(id:%d,user:%s) has been stopped(%s) for more than %d days. A warning email will be sent to the user."
+ % (vc.clusterid, vc.ownername, vc.stop_time.strftime("%Y-%m-%d %H:%M:%S"), self.warning_days))
+ rc_info = post_to_user("/master/user/recoverinfo/", {'username':username,'auth_key':auth_key})
+ logger.info("[ReleaseMgr] %s"%str(rc_info))
+ self._send_email(rc_info['email'], vc.ownername, vc, days, False)
time.sleep(self.check_interval)
def stop(self):
diff --git a/src/master/vclustermgr.py b/src/master/vclustermgr.py
index 32a825e..e264871 100755
--- a/src/master/vclustermgr.py
+++ b/src/master/vclustermgr.py
@@ -707,6 +707,7 @@ class VclusterMgr(object):
[status, vcluster] = self.get_vcluster(clustername, username)
vcluster.status = 'stopped'
vcluster.start_time ="------"
+ vcluster.stop_time = datetime.datetime.now()
if not db_commit():
return [False, "Commit Errror"]
return [True, "stop cluster"]
diff --git a/src/utils/env.py b/src/utils/env.py
index edd892f..16eacb5 100755
--- a/src/utils/env.py
+++ b/src/utils/env.py
@@ -79,6 +79,10 @@ def getenv(key):
return os.environ.get("ALLOCATED_PORTS","10000-65535")
elif key =="ALLOW_SCALE_OUT":
return os.environ.get("ALLOW_SCALE_OUT", "False")
+ elif key == "WARNING_DAYS":
+ return os.environ.get("WARNING_DAYS"."7")
+ elif key == "RELEASE_DAYS":
+ return os.environ.get("RELEASE_DAYS"."14")
elif key == "BATCH_ON":
return os.environ.get("BATCH_ON","True")
elif key == "BATCH_MASTER_PORT":
diff --git a/user/user.py b/user/user.py
index fea7f41..abfbdbc 100755
--- a/user/user.py
+++ b/user/user.py
@@ -314,7 +314,7 @@ def get_master_recoverinfo():
return json.dumps({'success':'false', 'message':'username field is required.'})
else:
user = User.query.filter_by(username=username).first()
- return json.dumps({'success':'true', 'uid':user.id, 'groupname':user.user_group})
+ return json.dumps({'success':'true', 'uid':user.id, 'email':user.e_mail, 'groupname':user.user_group})
@app.route("/master/user/groupinfo/", methods=['POST'])
@auth_key_required
From 0ea558b98819311f25745fb85fc8f74ca0bc3a84 Mon Sep 17 00:00:00 2001
From: Firmlyzhu
Date: Tue, 7 May 2019 18:29:59 +0800
Subject: [PATCH 4/6] Fix some bugs
---
src/master/releasemgr.py | 2 +-
src/utils/env.py | 4 ++--
src/utils/manage.py | 5 ++++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/master/releasemgr.py b/src/master/releasemgr.py
index 1d75eb6..2d276fd 100644
--- a/src/master/releasemgr.py
+++ b/src/master/releasemgr.py
@@ -1,4 +1,4 @@
-import threading, time
+import threading, time, requests, json
from utils import env
from utils.log import logger
from utils.model import db, VCluster, Container
diff --git a/src/utils/env.py b/src/utils/env.py
index 16eacb5..b75bca0 100755
--- a/src/utils/env.py
+++ b/src/utils/env.py
@@ -80,9 +80,9 @@ def getenv(key):
elif key =="ALLOW_SCALE_OUT":
return os.environ.get("ALLOW_SCALE_OUT", "False")
elif key == "WARNING_DAYS":
- return os.environ.get("WARNING_DAYS"."7")
+ return os.environ.get("WARNING_DAYS", "7")
elif key == "RELEASE_DAYS":
- return os.environ.get("RELEASE_DAYS"."14")
+ return os.environ.get("RELEASE_DAYS", "14")
elif key == "BATCH_ON":
return os.environ.get("BATCH_ON","True")
elif key == "BATCH_MASTER_PORT":
diff --git a/src/utils/manage.py b/src/utils/manage.py
index f947b9a..67e4940 100644
--- a/src/utils/manage.py
+++ b/src/utils/manage.py
@@ -1,5 +1,8 @@
+import sys
+if sys.path[0].endswith("utils"):
+ sys.path[0] = sys.path[0][:-5]
from flask_migrate import Migrate,MigrateCommand
-from model import *
+from utils.model import *
from flask_script import Manager
from flask import Flask
From 6251be7e3d33700fe0366a3427d4c1ff338894e1 Mon Sep 17 00:00:00 2001
From: Firmlyzhu
Date: Wed, 8 May 2019 18:19:08 +0800
Subject: [PATCH 5/6] Make releasemgr work
---
src/master/httprest.py | 2 +-
src/master/releasemgr.py | 43 ++++++++++++++++++++++++++++-----------
src/master/taskmgr.py | 2 +-
src/master/vclustermgr.py | 1 +
src/utils/model.py | 7 +++++--
user/user.py | 15 ++++++++++++++
6 files changed, 54 insertions(+), 16 deletions(-)
diff --git a/src/master/httprest.py b/src/master/httprest.py
index 51f47df..907fdbc 100755
--- a/src/master/httprest.py
+++ b/src/master/httprest.py
@@ -1162,7 +1162,7 @@ if __name__ == '__main__':
G_imagemgr = imagemgr.ImageMgr()
logger.info("imagemgr started")
- G_releasemgr = releasemgr.ReleaseMgr(G_vclustermgr,G_ulockmgr,10)
+ G_releasemgr = releasemgr.ReleaseMgr(G_vclustermgr,G_ulockmgr)
G_releasemgr.start()
logger.info("releasemgr started")
diff --git a/src/master/releasemgr.py b/src/master/releasemgr.py
index 2d276fd..afa4915 100644
--- a/src/master/releasemgr.py
+++ b/src/master/releasemgr.py
@@ -1,4 +1,4 @@
-import threading, time, requests, json
+import threading, time, requests, json, traceback
from utils import env
from utils.log import logger
from utils.model import db, VCluster, Container
@@ -26,15 +26,17 @@ class ReleaseMgr(threading.Thread):
self.release_days = int(env.getenv("RELEASE_DAYS"))
if self.release_days <= self.warning_days:
self.release_days = self.warning_days+1
+ logger.info("[ReleaseMgr] start withe warning_days=%d release_days=%d"%(self.warning_days, self.release_days))
- def _send_email(to_address, username, vcluster, days, is_released=True):
+ def _send_email(self, 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 + ':
'
+ st_str = vcluster.stop_time.strftime("%Y-%m-%d %H:%M:%S")
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)
+ has been stopped more than %d days now(stopped at:%s).
+ ''' % (vcluster.clustername, vcluster.clusterid, env.getenv("PORTAL_URL"), env.getenv("PORTAL_URL"), days, st_str)
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.
@@ -43,7 +45,7 @@ class ReleaseMgr(threading.Thread):
else:
#day_d = self.release_days - (datetime.datetime.now() - vcluster.stop_time).days
release_date = vcluster.stop_time + datetime.timedelta(days=self.release_days)
- day_d = (release_date - vcluster.stop_time).days
+ day_d = (release_date - datetime.datetime.now()).days
rd_str = release_date.strftime("%Y-%m-%d %H:%M:%S")
text += ''' It will be released after %s(in about %d days).
And the data in it couldn't be recoverd after releasing.
@@ -81,6 +83,7 @@ class ReleaseMgr(threading.Thread):
quotas[group['name']] = group['quotas']
vcs = VCluster.query.filter_by(status='stopped').all()
+ #logger.info(str(vcs))
for vc in vcs:
if vc.stop_time is None:
continue
@@ -89,28 +92,44 @@ class ReleaseMgr(threading.Thread):
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})
+ rc_info = post_to_user("/master/user/recoverinfo/", {'username':vc.ownername,'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]}}
+ user_info = {"data":{"id":rc_info['uid'],"group":groupname,"groupinfo":quotas[groupname]}}
self.ulockmgr.acquire(vc.ownername)
try:
- success, msg = self.vclustermgr.delete_cluster(vc.clustername, vc.ownername, user_info)
+ [status, usage_info] = self.vclustermgr.get_clustersetting(vc.clustername, vc.ownername, "all", True)
+ success, msg = self.vclustermgr.delete_cluster(vc.clustername, vc.ownername, json.dumps(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(rc_info['email'], vc.ownername, vc, days)
+ if status:
+ logger.info("[ReleaseMgr] Release Quota.")
+ post_to_user("/master/user/usageRelease/", {'auth_key':auth_key,'username':vc.ownername,
+ 'cpu':usage_info['cpu'], 'memory':usage_info['memory'],'disk':usage_info['disk']})
+ self._send_email(rc_info['email'], vc.ownername, vc, self.release_days)
+ logger.info("[ReleaseMgr] Succeed to releasing VCluster(id:%d,user:%s) for %s. Send mail to info."%(vc.clusterid, vc.ownername, msg))
except Exception as err:
- logger.error(err)
+ logger.error(traceback.format_exc())
finally:
self.ulockmgr.release(vc.ownername)
elif days >= self.warning_days:
logger.info("[ReleaseMgr] VCluster(id:%d,user:%s) has been stopped(%s) for more than %d days. A warning email will be sent to the user."
% (vc.clusterid, vc.ownername, vc.stop_time.strftime("%Y-%m-%d %H:%M:%S"), self.warning_days))
- rc_info = post_to_user("/master/user/recoverinfo/", {'username':username,'auth_key':auth_key})
+ if vc.is_warned:
+ logger.info("[ReleaseMgr] VCluster(id:%d,user:%s) has been warned before. Skip it."% (vc.clusterid, vc.ownername))
+ continue
+ rc_info = post_to_user("/master/user/recoverinfo/", {'username':vc.ownername,'auth_key':auth_key})
logger.info("[ReleaseMgr] %s"%str(rc_info))
- self._send_email(rc_info['email'], vc.ownername, vc, days, False)
+ self._send_email(rc_info['email'], vc.ownername, vc, self.warning_days, False)
+ vc.is_warned = True
+
+ try:
+ db.session.commit()
+ except Exception as err:
+ db.session.rollback()
+ logger.warning(traceback.format_exc())
time.sleep(self.check_interval)
def stop(self):
diff --git a/src/master/taskmgr.py b/src/master/taskmgr.py
index 0bed1a6..65a93b9 100644
--- a/src/master/taskmgr.py
+++ b/src/master/taskmgr.py
@@ -179,7 +179,7 @@ class TaskMgr(threading.Thread):
self.free_nets = []
for i in range(0, (1 << (32-self.batch_cidr)) - 1, (1 << self.task_cidr)):
self.free_nets.append(i)
- self.logger.info("Free nets addresses pool %s" % str(self.free_nets))
+ #self.logger.info("Free nets addresses pool %s" % str(self.free_nets))
self.logger.info("Each Batch Net CIDR:%s"%(str(self.task_cidr)))
def data_lock(lockname):
diff --git a/src/master/vclustermgr.py b/src/master/vclustermgr.py
index e264871..26f5980 100755
--- a/src/master/vclustermgr.py
+++ b/src/master/vclustermgr.py
@@ -624,6 +624,7 @@ class VclusterMgr(object):
[status,vcluster] = self.get_vcluster(clustername,username)
vcluster.status ='running'
vcluster.start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ vcluster.is_warned = False
if not db_commit():
return [False, "Commit Errror"]
return [True, "start cluster"]
diff --git a/src/utils/model.py b/src/utils/model.py
index 9437a51..fa04df1 100755
--- a/src/utils/model.py
+++ b/src/utils/model.py
@@ -160,7 +160,7 @@ class UserUsage(db.Model):
self.disk = '0'
def __repr__(self):
- return '' % self.name
+ return 'cpu:%s memory:%s disk:%s' % (self.username,self.cpu,self.memory,self.disk)
class Notification(db.Model):
id = db.Column(db.Integer, primary_key=True)
@@ -379,6 +379,7 @@ class VCluster(db.Model):
create_time = db.Column(db.DateTime)
start_time = db.Column(db.String(20))
stop_time = db.Column(db.DateTime)
+ is_warned = db.Column(db.Boolean)
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')
@@ -398,7 +399,8 @@ class VCluster(db.Model):
self.billing_history = []
self.create_time = datetime.now()
self.start_time = "------"
- self.stop_time = None
+ self.stop_time = datetime.now()
+ self.is_warned = False
def __repr__(self):
info = {}
@@ -416,6 +418,7 @@ class VCluster(db.Model):
info['stop_time'] = "------"
else:
info['stop_time'] = self.stop_time.strftime("%Y-%m-%d %H:%M:%S")
+ info["is_warned"] = self.is_warned
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]
diff --git a/user/user.py b/user/user.py
index abfbdbc..ec9f9b7 100755
--- a/user/user.py
+++ b/user/user.py
@@ -325,6 +325,21 @@ def get_master_groupinfo():
groupfile.close()
return json.dumps({'success':'true', 'groups':json.dumps(groups)})
+@app.route("/master/user/usageRelease/", methods=['POST'])
+@auth_key_required
+def usageRelease_master():
+ global G_usermgr
+ logger.info("handle request: /master/user/usageRelease/")
+ form = request.form
+ user = form.get("username",None)
+ cur_user = User.query.filter_by(username=user).first()
+ if user is None or cur_user is None:
+ return json.dumps({'success':'false', 'message':'Null username field or user does not exist.'})
+ G_lockmgr.acquire('__usage_'+str(user))
+ result = G_usermgr.usageRelease(cur_user = cur_user, cpu = form.get('cpu'), memory = form.get('memory'), disk = form.get('disk'))
+ G_lockmgr.release('__usage_'+str(user))
+ return json.dumps(result)
+
@app.route("/user/selfModify/", methods=['POST'])
@login_required
def selfModify_user(cur_user, user, form):
From 7e296dde09981c2905bfd34c02da5516bb4f0bae Mon Sep 17 00:00:00 2001
From: Firmlyzhu
Date: Wed, 8 May 2019 18:37:13 +0800
Subject: [PATCH 6/6] Fix a bug in networkmgr
---
src/master/network.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/master/network.py b/src/master/network.py
index e1d0aac..623c5f6 100755
--- a/src/master/network.py
+++ b/src/master/network.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
-import json, sys, netifaces, threading
+import json, sys, netifaces, threading, traceback
from utils.nettools import netcontrol,ovscontrol
from utils.log import logger
@@ -507,6 +507,7 @@ class NetworkMgr(object):
self.user_locks.release()
def del_usrgwbr(self, username, uid, nodemgr):
+ self.load_usrgw(username)
if username not in self.usrgws.keys():
return [False, "user does't have gateway or user doesn't exist."]
ip = self.usrgws[username]
@@ -539,7 +540,7 @@ class NetworkMgr(object):
del self.users[username]
return [True, 'delete user success']
except Exception as ex:
- logger.error(str(ex))
+ logger.error(traceback.format_exc())
return [False, str(ex)]
finally:
self.user_locks.release()