Skip to content

Commit e978260

Browse files
authored
Merge pull request #53 from supermeng/master
Added pod status histories
2 parents f1b875d + dde7137 commit e978260

File tree

8 files changed

+177
-4
lines changed

8 files changed

+177
-4
lines changed

apis/models.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,29 @@ def podgroup_status(self, name):
116116
return None
117117
return None
118118

119+
def podgroup_status_history(self, procname, instance):
120+
for pg in self.app_spec.PodGroups:
121+
if pg.Name.split('.')[2] == procname:
122+
r = self.default_deploy.get_podhistory(pg.Name, int(instance))
123+
if r.status_code < 400:
124+
status_histories = r.json()
125+
for history in status_histories:
126+
image, node = history['from'].split(' ')
127+
history['image'] = image.split('/')[1]
128+
history['node'] = node[5:] # len('node:')
129+
del history['from']
130+
status_histories.reverse()
131+
return {
132+
'Name': pg.Name,
133+
'Instance': instance,
134+
'StatusHistory': status_histories
135+
}
136+
else:
137+
logger.warning(
138+
"fail getting PodGroup status history: %s" % r.content)
139+
return None
140+
return None
141+
119142
def dependency_status(self, name):
120143
r = self.default_deploy.get_dependency(name)
121144
if r.status_code < 400:
@@ -524,6 +547,11 @@ def podgroup_remove(self, podgroup_name):
524547
(podgroup_name, self.appname))
525548
return self.default_deploy.remove_podgroup(podgroup_name)
526549

550+
def podgroup_operate(self, podgroup_name, instance, optype):
551+
logger.info("operate podgroup %s of app %s " %
552+
(podgroup_name, self.appname))
553+
return self.default_deploy.operate_podgroup(podgroup_name, instance, optype)
554+
527555
def dependency_register(self, service_app, service_appname, dependency_pod_name):
528556
# service may not been deployed yet, so may need force generate the
529557
# calico profile of service_profile

apis/utils.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
from log import logger
2121
from .calico import (calico_profile_rule_add)
2222
import pycalico.datastore_datatypes
23+
from django.utils.dateparse import parse_datetime
24+
from pytz import timezone
2325

2426

2527
def read_from_etcd(key):
@@ -221,9 +223,21 @@ def get_current_time():
221223
return strftime("%Y-%m-%d %H:%M:%S", gmtime())
222224

223225

224-
def convert_time_from_deployd(d_time):
226+
def orc_convert_time_from_deployd(d_time):
225227
c_times = d_time.split("T")
226228
if len(c_times) <= 1:
227229
return d_time
228230
else:
229231
return "%s %s" % (c_times[0], c_times[1].split('.')[0])
232+
233+
234+
def convert_time_from_deployd(d_time):
235+
t_time = parse_datetime(d_time)
236+
tzchina = timezone('Asia/Shanghai')
237+
utc = timezone('UTC')
238+
t_time = t_time.replace(tzinfo=utc).astimezone(tzchina)
239+
try:
240+
return t_time.strftime('%Y-%m-%d %H:%M:%S')
241+
except Exception as e:
242+
logger.error("strftime error:%s d_time:%s", str(e), d_time)
243+
return orc_convert_time_from_deployd(t_time)

apis/views.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,31 @@ def get_app_proc(cls, appname, procname, options=None):
952952
appname, procname, e),
953953
reverse('api_procs', kwargs={'appname': appname}))
954954

955+
@classmethod
956+
def get_proc_history(cls, appname, procname, instance, options=None):
957+
try:
958+
app = App.get_or_none(appname)
959+
if not app.is_reachable():
960+
return (404, None,
961+
'app with appname %s has not been deployd\n' % appname,
962+
reverse('api_apps'))
963+
status_history = app.podgroup_status_history(procname, instance)
964+
if status_history:
965+
return (200, status_history,
966+
'', reverse('api_proc_history',
967+
kwargs={'appname': appname, 'procname': procname, 'instance': instance}))
968+
else:
969+
return (200, [],
970+
'proc %s do not exists' % (procname),
971+
reverse('api_proc_history',
972+
kwargs={'appname': appname, 'procname': procname, 'instance': instance}))
973+
except Exception, e:
974+
client.captureException()
975+
return (500, None,
976+
'fatal error when get app %s proc %s:\n%s\nplease contact with admin of lain\n' % (
977+
appname, procname, e),
978+
reverse('api_procs', kwargs={'appname': appname}))
979+
955980
@classmethod
956981
def update_app_proc(cls, appname, procname, options):
957982
def verify_options(options):
@@ -1104,6 +1129,59 @@ def delete_app_proc(cls, appname, procname, options=None):
11041129
appname, procname, e),
11051130
reverse('api_proc', kwargs={'appname': appname, 'procname': procname}))
11061131

1132+
@classmethod
1133+
def operate_proc(cls, appname, procname, operation, options=None):
1134+
try:
1135+
instance = int(options.get('instance', 0))
1136+
app = App.get_or_none(appname)
1137+
if not app.is_reachable():
1138+
return (404, None,
1139+
'app with appname %s has not been deployd\n' % appname,
1140+
reverse('api_apps'))
1141+
proc, pg_status = app.proc_and_pg_status(procname)
1142+
if proc is None:
1143+
return (404, None,
1144+
'no such proc %s in app %s' % (procname, appname),
1145+
reverse('api_procs', kwargs={'appname': appname}))
1146+
if pg_status:
1147+
container_name = None
1148+
if instance != 0:
1149+
pods = pg_status['Status']['Pods']
1150+
if instance <= len(pods):
1151+
container_name = pods[
1152+
instance - 1]['Containers'][0]['Runtime']['Name']
1153+
else:
1154+
return (404, None, 'no such proc %s instance %d, in app %s' % (procname, instance, appname),
1155+
reverse('api_procs', kwargs={'appname': appname}))
1156+
if container_name:
1157+
add_oplog(AuthApi.operater, operation.upper(), appname, "",
1158+
"%s container %s" % (operation, container_name))
1159+
else:
1160+
add_oplog(AuthApi.operater, operation.upper(), appname, "",
1161+
"%s proc %s" % (operation, procname))
1162+
1163+
podgroup_name = "%s.%s.%s" % (
1164+
appname, proc.type.name, proc.name)
1165+
result = app.podgroup_operate(podgroup_name, instance, operation)
1166+
if result.status_code < 400:
1167+
return (202, ProcApi.render_proc_data(appname, proc),
1168+
render_op_result_to_msg(result),
1169+
reverse('api_procs', kwargs={'appname': appname}))
1170+
else:
1171+
return (500, ProcApi.render_proc_data(appname, proc),
1172+
render_op_result_to_msg(result),
1173+
reverse('api_proc', kwargs={'appname': appname, 'procname': procname}))
1174+
else:
1175+
return (400, ProcApi.render_proc_data(appname, proc),
1176+
'proc %s exists but not deployed\nplease deploy it first\n' % (
1177+
procname),
1178+
reverse('api_proc', kwargs={'appname': appname, 'procname': procname}))
1179+
except Exception, e:
1180+
client.captureException()
1181+
return (500, None,
1182+
'fatal error when %s app %s proc %s:\n%s\nplease contact with admin of lain\n' % (
1183+
operation, appname, procname, e),
1184+
reverse('api_proc', kwargs={'appname': appname, 'procname': procname}))
11071185

11081186
'''
11091187
这个类响应 console.views 关于 maintainer 的所有调用
@@ -1420,6 +1498,14 @@ def gen_release_image(cls, app, base_image, config_tag, config_layer_count):
14201498
app.appname, config_tag, config_layer_count, target_repo, target_tag)
14211499
return "%s:%s-%s" % (target_repo, target_tag, config_tag)
14221500

1501+
@classmethod
1502+
def list_ports(cls):
1503+
resp = Streamrouter.get_streamrouter_ports()
1504+
if resp == None:
1505+
return (400, None, '', reverse('api_streamrouter'))
1506+
else:
1507+
return (200, resp, '', reverse('api_streamrouter'))
1508+
14231509

14241510
class StreamrouterApi:
14251511

console/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
url(r'^(?:api/)?v1/apps/(?P<appname>[^/]+)/procs/(?P<procname>[^/]+)/$',
1919
'console.views.api_proc', name='api_proc'),
2020

21+
url(r'^(?:api/)?v1/apps/(?P<appname>[^/]+)/procs/(?P<procname>[^/]+)/instance/(?P<instance>[^/]+)/histories/$',
22+
'console.views.api_proc_history', name='api_proc_history'),
23+
2124
# authroze service for console ui
2225
url(r'^(?:api/)?v1/authorize/$',
2326
'console.views.api_authorize', name='api_authorize'),

console/views.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,23 @@ def api_proc(request, appname, procname):
210210
_invalid_request_method('proc', request.method)
211211

212212

213+
def api_proc_history(request, appname, procname, instance):
214+
if request.method == 'GET':
215+
return api_proc_history_get(request, appname, procname, instance)
216+
else:
217+
_invalid_request_method('proc history', request.method)
218+
219+
220+
@permission_required('maintain')
221+
def api_proc_history_get(request, appname, procname, instance):
222+
try:
223+
status_code, view_object, msg, url = ProcApi.get_proc_history(
224+
appname, procname, instance)
225+
return render_json_response(status_code, 'proc', view_object, msg, url)
226+
except Exception:
227+
return render_json_response(400, 'proc history', None, 'invalid request: should be json body with procname(detail string) instance(int)', reverse('api_docs'))
228+
229+
213230
@permission_required('maintain')
214231
@deployd_required
215232
def api_proc_high_permit(request, appname, procname):
@@ -220,10 +237,16 @@ def api_proc_high_permit(request, appname, procname):
220237
elif request.method == 'PATCH':
221238
try:
222239
options = json.loads(request.body)
240+
operation = options.get('operation', 'schedule')
241+
if operation == 'schedule':
242+
status_code, view_object, msg, url = ProcApi.update_app_proc(
243+
appname, procname, options)
244+
else:
245+
status_code, view_object, msg, url = ProcApi.operate_proc(
246+
appname, procname, operation, options)
223247
except Exception:
224248
return render_json_response(400, 'proc', None, 'invalid request: should be json body with num_instances(integer) or cpu(integer) or memory(str)', reverse('api_docs'))
225-
status_code, view_object, msg, url = ProcApi.update_app_proc(
226-
appname, procname, options)
249+
227250
return render_json_response(status_code, 'proc', view_object, msg, url)
228251

229252

deploys/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,15 @@ def create_podgroup(self, podgroup_json):
2828
def get_podgroup(self, podgroup_name):
2929
return deploys.utils.get_podgroup(podgroup_name, self.apiserver)
3030

31+
def get_podhistory(self, podgroup_name, instance):
32+
return deploys.utils.get_podhistory(podgroup_name, instance, self.apiserver)
33+
3134
def remove_podgroup(self, podgroup_name):
3235
return deploys.utils.remove_podgroup(podgroup_name, self.apiserver)
3336

37+
def operate_podgroup(self, podgroup_name, instance, operation):
38+
return deploys.utils.operate_podgroup(podgroup_name, instance, operation, self.apiserver)
39+
3440
def patch_podgroup_instance(self, podgroup_name, num_instances):
3541
return deploys.utils.patch_podgroup_instance(podgroup_name, num_instances, self.apiserver)
3642

deploys/utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,24 @@ def get_podgroup(podgroup_name, apiserver):
2424
return send_request("GET", url, None, None)
2525

2626

27+
def get_podhistory(podgroup_name, instance, apiserver):
28+
url = "%s/api/cntstatushistory?name=%s&instance=%d" % (
29+
apiserver, podgroup_name, instance)
30+
return send_request("GET", url, None, None)
31+
32+
2733
def remove_podgroup(podgroup_name, apiserver):
2834
url = "%s/api/podgroups?name=%s" % (apiserver, podgroup_name)
2935
return send_request("DELETE", url, None, None)
3036

3137

38+
def operate_podgroup(podgroup_name, instance, operation, apiserver):
39+
url = "%s/api/podgroups?name=%s&instance=%d&cmd=operation&optype=%s" % (
40+
apiserver, podgroup_name, instance, operation
41+
)
42+
return send_request("PATCH", url, None, None)
43+
44+
3245
def patch_podgroup_instance(podgroup_name, num_instances, apiserver):
3346
url = "%s/api/podgroups?name=%s&num_instances=%s&cmd=replica" % (
3447
apiserver, podgroup_name, num_instances

lain.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@ web.console:
5555
- console_op
5656

5757
notify:
58-
slack: "#lain"
58+
slack: "#lain"

0 commit comments

Comments
 (0)