Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
bf9bb1b9
Commit
bf9bb1b9
authored
Dec 24, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改ops task运行
parent
30efec1b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
273 additions
and
232 deletions
+273
-232
api.py
apps/assets/api.py
+8
-8
const.py
apps/assets/const.py
+15
-11
user.py
apps/assets/models/user.py
+2
-1
tasks.py
apps/assets/tasks.py
+0
-0
asset_modal_list.html
apps/assets/templates/assets/asset_modal_list.html
+0
-3
asset.py
apps/assets/views/asset.py
+1
-5
celery.py
apps/common/celery.py
+172
-1
tasks.py
apps/common/tasks.py
+1
-1
utils.py
apps/common/utils.py
+18
-56
settings.py
apps/jumpserver/settings.py
+2
-1
decorators.py
apps/ops/decorators.py
+0
-38
models.py
apps/ops/models.py
+10
-5
tasks.py
apps/ops/tasks.py
+2
-2
task_list.html
apps/ops/templates/ops/task_list.html
+11
-5
utils.py
apps/ops/utils.py
+21
-77
jumpserver.js
apps/static/js/jumpserver.js
+0
-3
_left_side_bar.html
apps/templates/_left_side_bar.html
+1
-1
_user_profile.html
apps/templates/_user_profile.html
+3
-3
group.py
apps/users/models/group.py
+0
-7
user.py
apps/users/models/user.py
+2
-2
serializers.py
apps/users/serializers.py
+3
-1
run_server.py
run_server.py
+1
-1
No files found.
apps/assets/api.py
View file @
bf9bb1b9
...
...
@@ -25,9 +25,9 @@ from .hands import IsSuperUser, IsValidUser, IsSuperUserOrAppUser, \
get_user_granted_assets
from
.models
import
AssetGroup
,
Asset
,
Cluster
,
SystemUser
,
AdminUser
from
.
import
serializers
from
.tasks
import
update_assets_hardware_info
,
test_admin_user_connectability
,
\
test_a
dmin_user_connectability_manual
,
push_system_user_to_cluster_assets
,
\
test_system_user_connectability
from
.tasks
import
update_assets_hardware_info
_manual
,
test_admin_user_connectability_util
,
\
test_a
sset_connectability_manual
,
push_system_user_to_cluster_assets_manual
,
\
test_system_user_connectability
_manual
class
AssetViewSet
(
IDInFilterMixin
,
BulkModelViewSet
):
...
...
@@ -222,7 +222,7 @@ class AssetRefreshHardwareApi(generics.RetrieveAPIView):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
asset_id
=
kwargs
.
get
(
'pk'
)
asset
=
get_object_or_404
(
Asset
,
pk
=
asset_id
)
summary
=
update_assets_hardware_info
([
asset
])
summary
=
update_assets_hardware_info
_manual
([
asset
])
if
summary
.
get
(
'dark'
):
return
Response
(
summary
[
'dark'
]
.
values
(),
status
=
501
)
else
:
...
...
@@ -239,7 +239,7 @@ class AssetAdminUserTestApi(generics.RetrieveAPIView):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
asset_id
=
kwargs
.
get
(
'pk'
)
asset
=
get_object_or_404
(
Asset
,
pk
=
asset_id
)
ok
,
msg
=
test_a
dmin_user
_connectability_manual
(
asset
)
ok
,
msg
=
test_a
sset
_connectability_manual
(
asset
)
if
ok
:
return
Response
({
"msg"
:
"pong"
})
else
:
...
...
@@ -255,7 +255,7 @@ class AdminUserTestConnectiveApi(generics.RetrieveAPIView):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
admin_user
=
self
.
get_object
()
test_admin_user_connectability
.
delay
(
admin_user
,
force
=
True
)
test_admin_user_connectability
_util
.
delay
(
admin_user
,
force
=
True
)
return
Response
({
"msg"
:
"Task created"
})
...
...
@@ -268,7 +268,7 @@ class SystemUserPushApi(generics.RetrieveAPIView):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
system_user
=
self
.
get_object
()
push_system_user_to_cluster_assets
.
delay
(
system_user
,
force
=
True
)
push_system_user_to_cluster_assets
_manual
.
delay
(
system_user
,
force
=
True
)
return
Response
({
"msg"
:
"Task created"
})
...
...
@@ -281,5 +281,5 @@ class SystemUserTestConnectiveApi(generics.RetrieveAPIView):
def
retrieve
(
self
,
request
,
*
args
,
**
kwargs
):
system_user
=
self
.
get_object
()
test_system_user_connectability
.
delay
(
system_user
,
force
=
True
)
test_system_user_connectability
_manual
.
delay
(
system_user
,
force
=
True
)
return
Response
({
"msg"
:
"Task created"
})
apps/assets/const.py
View file @
bf9bb1b9
...
...
@@ -2,14 +2,20 @@
#
from
django.utils.translation
import
ugettext
as
_
PUSH_SYSTEM_USER_PERIOD_LOCK_KEY
=
"PUSH_SYSTEM_USER_PERIOD_KEY"
PUSH_SYSTEM_USER_PERIOD_TASK_NAME
=
_
(
"PUSH SYSTEM USER TO CLUSTER PERIOD TASK"
)
# PUSH_SYSTEM_USER_PERIOD_LOCK_KEY = "PUSH_SYSTEM_USER_PERIOD_KEY"
PUSH_SYSTEM_USER_PERIOD_TASK_NAME
=
_
(
"PUSH SYSTEM USER TO CLUSTER PERIOD: {}"
)
PUSH_SYSTEM_USER_MANUAL_TASK_NAME
=
_
(
"PUSH SYSTEM USER TO CLUSTER MANUALLY: {}"
)
PUSH_SYSTEM_USER_TASK_NAME
=
_
(
"PUSH SYSTEM USER TO CLUSTER: {}"
)
PUSH_SYSTEM_USER_LOCK_KEY
=
"PUSH_SYSTEM_USER_TO_CLUSTER_LOCK_{}"
# PUSH_SYSTEM_USER_LOCK_KEY = "PUSH_SYSTEM_USER_TO_CLUSTER_LOCK_{}"
PUSH_SYSTEM_USER_ON_CHANGE_TASK_NAME
=
_
(
"PUSH SYSTEM USER ON CHANGE: {}"
)
PUSH_SYSTEM_USER_ON_CREATE_TASK_NAME
=
_
(
"PUSH SYSTEM USER ON CREATE: {}"
)
PUSH_SYSTEM_USERS_ON_ASSET_CREATE_TASK_NAME
=
_
(
"PUSH SYSTEM USERS ON ASSET CREAT: {}"
)
UPDATE_ASSETS_HARDWARE_TASK_NAME
=
_
(
'UPDATE ASSETS HARDWARE INFO'
)
UPDATE_ASSETS_HARDWARE_PERIOD_LOCK_KEY
=
"UPDATE_ASSETS_HARDWARE_PERIOD_LOCK_KEY"
UPDATE_ASSETS_HARDWARE_MANUAL_TASK_NAME
=
_
(
'UPDATE ASSETS HARDWARE INFO MANUALLY'
)
UPDATE_ASSETS_HARDWARE_ON_CREATE_TASK_NAME
=
_
(
'UPDATE ASSETS HARDWARE INFO ON CREATE'
)
# UPDATE_ASSETS_HARDWARE_PERIOD_LOCK_KEY = "UPDATE_ASSETS_HARDWARE_PERIOD_LOCK_KEY"
UPDATE_ASSETS_HARDWARE_PERIOD_TASK_NAME
=
_
(
'UPDATE ASSETS HARDWARE INFO PERIOD'
)
UPDATE_ASSETS_HARDWARE_TASKS
=
[
{
...
...
@@ -20,10 +26,10 @@ UPDATE_ASSETS_HARDWARE_TASKS = [
}
]
TEST_ADMIN_USER_CONN_PERIOD_LOCK_KEY
=
"TEST_ADMIN_USER_CONN_PERIOD_KEY"
TEST_ADMIN_USER_CONN_PERIOD_TASK_NAME
=
_
(
"TEST ADMIN USER CONN PERIOD TASK"
)
# TEST_ADMIN_USER_CONN_PERIOD_LOCK_KEY = "TEST_ADMIN_USER_CONN_PERIOD_KEY"
TEST_ADMIN_USER_CONN_PERIOD_TASK_NAME
=
_
(
"TEST ADMIN USER CONN PERIOD: {}"
)
TEST_ADMIN_USER_CONN_MANUAL_TASK_NAME
=
_
(
"TEST ADMIN USER CONN MANUALLY: {}"
)
TEST_ADMIN_USER_CONN_TASK_NAME
=
_
(
"TEST ADMIN USER CONN: {}"
)
TEST_ADMIN_USER_CONN_LOCK_KEY
=
TEST_ADMIN_USER_CONN_TASK_NAME
ADMIN_USER_CONN_CACHE_KEY
=
"ADMIN_USER_CONN_{}"
TEST_ADMIN_USER_CONN_TASKS
=
[
{
...
...
@@ -38,10 +44,8 @@ ASSET_ADMIN_CONN_CACHE_KEY = "ASSET_ADMIN_USER_CONN_{}"
TEST_ASSET_CONN_TASK_NAME
=
_
(
"ASSET CONN TEST MANUAL"
)
TEST_SYSTEM_USER_CONN_PERIOD_LOCK_KEY
=
"TEST_SYSTEM_USER_CONN_PERIOD_KEY"
TEST_SYSTEM_USER_CONN_PERIOD_TASK_NAME
=
_
(
"TEST SYSTEM USER CONN PERIOD TASK"
)
TEST_SYSTEM_USER_CONN_CACHE_KEY_PREFIX
=
"SYSTEM_USER_CONN_"
TEST_SYSTEM_USER_CONN_TASK_NAME
=
_
(
"TEST SYSTEM USER CONN: {}"
)
TEST_SYSTEM_USER_CONN_LOCK_KEY
=
"TEST_SYSTEM_USER_CONN_{}"
TEST_SYSTEM_USER_CONN_PERIOD_TASK_NAME
=
_
(
"TEST SYSTEM USER CONN PERIOD: {}"
)
TEST_SYSTEM_USER_CONN_MANUAL_TASK_NAME
=
_
(
"TEST SYSTEM USER CONN MANUALLY: {}"
)
SYSTEM_USER_CONN_CACHE_KEY
=
"SYSTEM_USER_CONN_{}"
TEST_SYSTEM_USER_CONN_TASKS
=
[
{
...
...
apps/assets/models/user.py
View file @
bf9bb1b9
...
...
@@ -13,13 +13,14 @@ from django.db import models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.conf
import
settings
from
common.utils
import
signer
,
ssh_key_string_to_obj
,
ssh_key_gen
from
common.utils
import
get_
signer
,
ssh_key_string_to_obj
,
ssh_key_gen
from
.utils
import
private_key_validator
from
..const
import
SYSTEM_USER_CONN_CACHE_KEY
__all__
=
[
'AdminUser'
,
'SystemUser'
,]
logger
=
logging
.
getLogger
(
__name__
)
signer
=
get_signer
()
class
AssetUser
(
models
.
Model
):
...
...
apps/assets/tasks.py
View file @
bf9bb1b9
This diff is collapsed.
Click to expand it.
apps/assets/templates/assets/asset_modal_list.html
View file @
bf9bb1b9
...
...
@@ -49,9 +49,6 @@ $(document).ready(function(){
"aaSorting"
:
[[
2
,
"asc"
]],
"aoColumnDefs"
:
[
{
"bSortable"
:
false
,
"aTargets"
:
[
0
]
}],
"bAutoWidth"
:
false
,
"language"
:
{
"url"
:
"/static/js/plugins/dataTables/i18n/zh-hans.json"
},
columns
:
[
{
data
:
"checkbox"
},
{
data
:
"id"
},
...
...
apps/assets/views/asset.py
View file @
bf9bb1b9
...
...
@@ -28,7 +28,7 @@ from common.utils import get_object_or_none, get_logger, is_uuid
from
..
import
forms
from
..models
import
Asset
,
AssetGroup
,
AdminUser
,
Cluster
,
SystemUser
from
..hands
import
AdminUserRequiredMixin
from
..tasks
import
update_assets_hardware_info
from
..tasks
import
update_assets_hardware_info
_util
__all__
=
[
...
...
@@ -314,10 +314,6 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
except
Exception
as
e
:
failed
.
append
(
'
%
s:
%
s'
%
(
asset_dict
[
'hostname'
],
str
(
e
)))
if
assets
:
update_assets_hardware_info
.
delay
([
asset
.
_to_secret_json
()
for
asset
in
assets
])
data
=
{
'created'
:
created
,
'created_info'
:
'Created {}'
.
format
(
len
(
created
)),
...
...
apps/common/celery.py
View file @
bf9bb1b9
# ~*~ coding: utf-8 ~*~
import
os
import
json
from
functools
import
wraps
from
celery
import
Celery
from
celery
import
Celery
,
subtask
from
celery.signals
import
worker_ready
,
worker_shutdown
from
.utils
import
get_logger
logger
=
get_logger
(
__file__
)
# set the default Django settings module for the 'celery' program.
os
.
environ
.
setdefault
(
'DJANGO_SETTINGS_MODULE'
,
'jumpserver.settings'
)
...
...
@@ -15,3 +22,167 @@ app = Celery('jumpserver')
# pickle the object when using Windows.
app
.
config_from_object
(
'django.conf:settings'
,
namespace
=
'CELERY'
)
app
.
autodiscover_tasks
(
lambda
:
[
app_config
.
split
(
'.'
)[
0
]
for
app_config
in
settings
.
INSTALLED_APPS
])
def
create_or_update_celery_periodic_tasks
(
tasks
):
from
django_celery_beat.models
import
PeriodicTask
,
IntervalSchedule
,
CrontabSchedule
"""
:param tasks: {
'add-every-monday-morning': {
'task': 'tasks.add' # A registered celery task,
'interval': 30,
'crontab': "30 7 * * *",
'args': (16, 16),
'kwargs': {},
'enabled': False,
},
}
:return:
"""
# Todo: check task valid, task and callback must be a celery task
for
name
,
detail
in
tasks
.
items
():
interval
=
None
crontab
=
None
if
isinstance
(
detail
.
get
(
"interval"
),
int
):
intervals
=
IntervalSchedule
.
objects
.
filter
(
every
=
detail
[
"interval"
],
period
=
IntervalSchedule
.
SECONDS
)
if
intervals
:
interval
=
intervals
[
0
]
else
:
interval
=
IntervalSchedule
.
objects
.
create
(
every
=
detail
[
'interval'
],
period
=
IntervalSchedule
.
SECONDS
,
)
elif
isinstance
(
detail
.
get
(
"crontab"
),
str
):
try
:
minute
,
hour
,
day
,
month
,
week
=
detail
[
"crontab"
]
.
split
()
except
ValueError
:
raise
SyntaxError
(
"crontab is not valid"
)
kwargs
=
dict
(
minute
=
minute
,
hour
=
hour
,
day_of_week
=
week
,
day_of_month
=
day
,
month_of_year
=
month
,
)
contabs
=
CrontabSchedule
.
objects
.
filter
(
**
kwargs
)
if
contabs
:
crontab
=
contabs
[
0
]
else
:
crontab
=
CrontabSchedule
.
objects
.
create
(
**
kwargs
)
else
:
raise
SyntaxError
(
"Schedule is not valid"
)
defaults
=
dict
(
interval
=
interval
,
crontab
=
crontab
,
name
=
name
,
task
=
detail
[
'task'
],
args
=
json
.
dumps
(
detail
.
get
(
'args'
,
[])),
kwargs
=
json
.
dumps
(
detail
.
get
(
'kwargs'
,
{})),
enabled
=
detail
.
get
(
'enabled'
,
True
),
)
task
=
PeriodicTask
.
objects
.
update_or_create
(
defaults
=
defaults
,
name
=
name
,
)
return
task
def
disable_celery_periodic_task
(
task_name
):
from
django_celery_beat.models
import
PeriodicTask
PeriodicTask
.
objects
.
filter
(
name
=
task_name
)
.
update
(
enabled
=
False
)
def
delete_celery_periodic_task
(
task_name
):
from
django_celery_beat.models
import
PeriodicTask
PeriodicTask
.
objects
.
filter
(
name
=
task_name
)
.
delete
()
__REGISTER_PERIODIC_TASKS
=
[]
__AFTER_APP_SHUTDOWN_CLEAN_TASKS
=
[]
__AFTER_APP_READY_RUN_TASKS
=
[]
def
register_as_period_task
(
crontab
=
None
,
interval
=
None
):
"""
Warning: Task must be have not any args and kwargs
:param crontab: "* * * * *"
:param interval: 60*60*60
:return:
"""
if
crontab
is
None
and
interval
is
None
:
raise
SyntaxError
(
"Must set crontab or interval one"
)
def
decorate
(
func
):
if
crontab
is
None
and
interval
is
None
:
raise
SyntaxError
(
"Interval and crontab must set one"
)
# Because when this decorator run, the task was not created,
# So we can't use func.name
name
=
'{func.__module__}.{func.__name__}'
.
format
(
func
=
func
)
if
name
not
in
__REGISTER_PERIODIC_TASKS
:
create_or_update_celery_periodic_tasks
({
name
:
{
'task'
:
name
,
'interval'
:
interval
,
'crontab'
:
crontab
,
'args'
:
(),
'enabled'
:
True
,
}
})
__REGISTER_PERIODIC_TASKS
.
append
(
name
)
@wraps
(
func
)
def
wrapper
(
*
args
,
**
kwargs
):
return
func
(
*
args
,
**
kwargs
)
return
wrapper
return
decorate
def
after_app_ready_start
(
func
):
# Because when this decorator run, the task was not created,
# So we can't use func.name
name
=
'{func.__module__}.{func.__name__}'
.
format
(
func
=
func
)
if
name
not
in
__AFTER_APP_READY_RUN_TASKS
:
__AFTER_APP_READY_RUN_TASKS
.
append
(
name
)
@wraps
(
func
)
def
decorate
(
*
args
,
**
kwargs
):
return
func
(
*
args
,
**
kwargs
)
return
decorate
def
after_app_shutdown_clean
(
func
):
# Because when this decorator run, the task was not created,
# So we can't use func.name
name
=
'{func.__module__}.{func.__name__}'
.
format
(
func
=
func
)
if
name
not
in
__AFTER_APP_READY_RUN_TASKS
:
__AFTER_APP_SHUTDOWN_CLEAN_TASKS
.
append
(
name
)
@wraps
(
func
)
def
decorate
(
*
args
,
**
kwargs
):
return
func
(
*
args
,
**
kwargs
)
return
decorate
@worker_ready.connect
def
on_app_ready
(
sender
=
None
,
headers
=
None
,
body
=
None
,
**
kwargs
):
logger
.
debug
(
"App ready signal recv"
)
logger
.
debug
(
"Start need start task: [{}]"
.
format
(
", "
.
join
(
__AFTER_APP_READY_RUN_TASKS
))
)
for
task
in
__AFTER_APP_READY_RUN_TASKS
:
subtask
(
task
)
.
delay
()
@worker_shutdown.connect
def
after_app_shutdown
(
sender
=
None
,
headers
=
None
,
body
=
None
,
**
kwargs
):
from
django_celery_beat.models
import
PeriodicTask
logger
.
debug
(
"App shutdown signal recv"
)
logger
.
debug
(
"Clean need cleaned period tasks: [{}]"
.
format
(
', '
.
join
(
__AFTER_APP_SHUTDOWN_CLEAN_TASKS
))
)
PeriodicTask
.
objects
.
filter
(
name__in
=
__AFTER_APP_SHUTDOWN_CLEAN_TASKS
)
.
delete
()
apps/common/tasks.py
View file @
bf9bb1b9
from
django.core.mail
import
send_mail
from
django.conf
import
settings
from
common
import
celery_app
as
app
from
.celery
import
app
from
.utils
import
get_logger
...
...
apps/common/utils.py
View file @
bf9bb1b9
# -*- coding: utf-8 -*-
#
import
json
import
re
from
collections
import
OrderedDict
from
six
import
string_types
import
base64
import
os
from
itertools
import
chain
import
string
import
logging
import
datetime
import
time
...
...
@@ -27,9 +25,6 @@ from django.conf import settings
from
django.utils
import
timezone
from
.compat
import
to_bytes
,
to_string
SECRET_KEY
=
settings
.
SECRET_KEY
UUID_PATTERN
=
re
.
compile
(
r'[0-9a-zA-Z\-]{36}'
)
...
...
@@ -51,9 +46,22 @@ def get_object_or_none(model, **kwargs):
return
obj
class
Signer
(
object
):
class
Singleton
(
type
):
def
__init__
(
cls
,
*
args
,
**
kwargs
):
cls
.
__instance
=
None
super
()
.
__init__
(
*
args
,
**
kwargs
)
def
__call__
(
cls
,
*
args
,
**
kwargs
):
if
cls
.
__instance
is
None
:
cls
.
__instance
=
super
()
.
__call__
(
*
args
,
**
kwargs
)
return
cls
.
__instance
else
:
return
cls
.
__instance
class
Signer
(
metaclass
=
Singleton
):
"""用来加密,解密,和基于时间戳的方式验证token"""
def
__init__
(
self
,
secret_key
=
SECRET_KEY
):
def
__init__
(
self
,
secret_key
=
None
):
self
.
secret_key
=
secret_key
def
sign
(
self
,
value
):
...
...
@@ -100,58 +108,10 @@ def combine_seq(s1, s2, callback=None):
return
seq
def
search_object_attr
(
obj
,
value
=
''
,
attr_list
=
None
,
ignore_case
=
False
):
"""It's provide a method to search a object attribute equal some value
If object some attribute equal :param: value, return True else return False
class A():
name = 'admin'
age = 7
:param obj: A object
:param value: A string match object attribute
:param attr_list: Only match attribute in attr_list
:param ignore_case: Ignore case
:return: Boolean
"""
if
value
==
''
:
return
True
try
:
object_attr
=
obj
.
__dict__
except
AttributeError
:
return
False
if
attr_list
is
not
None
:
new_object_attr
=
{}
for
attr
in
attr_list
:
new_object_attr
[
attr
]
=
object_attr
.
pop
(
attr
)
object_attr
=
new_object_attr
if
ignore_case
:
if
not
isinstance
(
value
,
string_types
):
return
False
if
value
.
lower
()
in
map
(
string
.
lower
,
map
(
str
,
object_attr
.
values
())):
return
True
else
:
if
value
in
object_attr
.
values
():
return
True
return
False
def
get_logger
(
name
=
None
):
return
logging
.
getLogger
(
'jumpserver.
%
s'
%
name
)
def
int_seq
(
seq
):
try
:
return
map
(
int
,
seq
)
except
ValueError
:
return
seq
def
timesince
(
dt
,
since
=
''
,
default
=
"just now"
):
"""
Returns string representing "time since" e.g.
...
...
@@ -391,4 +351,6 @@ def is_uuid(s):
return
False
signer
=
Signer
()
def
get_signer
():
signer
=
Signer
(
settings
.
SECRET_KEY
)
return
signer
apps/jumpserver/settings.py
View file @
bf9bb1b9
...
...
@@ -337,8 +337,9 @@ CELERY_ACCEPT_CONTENT = ['json', 'pickle']
CELERY_RESULT_EXPIRES
=
3600
CELERY_WORKER_LOG_FORMAT
=
'
%(asctime)
s [
%(module)
s
%(levelname)
s]
%(message)
s'
CELERY_WORKER_TASK_LOG_FORMAT
=
'
%(asctime)
s [
%(module)
s
%(levelname)
s]
%(message)
s'
CELERY_TASK_EAGER_PROPAGATES
=
True
CELERY_TIMEZONE
=
TIME_ZONE
#
TERMINAL_HEATBEAT_INTERVAL = CONFIG.TERMINAL_HEATBEAT_INTERVAL or 30
#
CELERY_ENABLE_UTC = True
# Cache use redis
...
...
apps/ops/decorators.py
deleted
100644 → 0
View file @
30efec1b
# -*- coding: utf-8 -*-
#
from
functools
import
wraps
TASK_PREFIX
=
"TOOT"
CALLBACK_PREFIX
=
"COC"
def
register_as_period_task
(
crontab
=
None
,
interval
=
None
):
"""
:param crontab: "* * * * *"
:param interval: 60*60*60
:return:
"""
from
.utils
import
create_or_update_celery_periodic_tasks
if
crontab
is
None
and
interval
is
None
:
raise
SyntaxError
(
"Must set crontab or interval one"
)
def
decorate
(
func
):
@wraps
(
func
)
def
wrapper
(
*
args
,
**
kwargs
):
tasks
=
{
func
.
__name__
:
{
'task'
:
func
.
__name__
,
'args'
:
args
,
'kwargs'
:
kwargs
,
'interval'
:
interval
,
'crontab'
:
crontab
,
'enabled'
:
True
,
}
}
create_or_update_celery_periodic_tasks
(
tasks
)
return
func
(
*
args
,
**
kwargs
)
return
wrapper
return
decorate
apps/ops/models.py
View file @
bf9bb1b9
...
...
@@ -9,7 +9,9 @@ from django.utils import timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
django_celery_beat.models
import
CrontabSchedule
,
IntervalSchedule
,
PeriodicTask
from
common.utils
import
signer
,
get_logger
from
common.utils
import
get_signer
,
get_logger
from
common.celery
import
delete_celery_periodic_task
,
create_or_update_celery_periodic_tasks
,
\
disable_celery_periodic_task
from
.ansible
import
AdHocRunner
,
AnsibleError
from
.inventory
import
JMSInventory
...
...
@@ -17,6 +19,7 @@ __all__ = ["Task", "AdHoc", "AdHocRunHistory"]
logger
=
get_logger
(
__file__
)
signer
=
get_signer
()
class
Task
(
models
.
Model
):
...
...
@@ -82,8 +85,6 @@ class Task(models.Model):
def
save
(
self
,
force_insert
=
False
,
force_update
=
False
,
using
=
None
,
update_fields
=
None
):
from
.utils
import
create_or_update_celery_periodic_tasks
,
\
disable_celery_periodic_task
from
.tasks
import
run_ansible_task
super
()
.
save
(
force_insert
=
force_insert
,
force_update
=
force_update
,
...
...
@@ -114,7 +115,6 @@ class Task(models.Model):
disable_celery_periodic_task
(
self
.
name
)
def
delete
(
self
,
using
=
None
,
keep_parents
=
False
):
from
.utils
import
delete_celery_periodic_task
super
()
.
delete
(
using
=
using
,
keep_parents
=
keep_parents
)
delete_celery_periodic_task
(
self
.
name
)
...
...
@@ -246,7 +246,7 @@ class AdHoc(models.Model):
}
:return:
"""
self
.
_become
=
signer
.
sign
(
json
.
dumps
(
item
))
self
.
_become
=
signer
.
sign
(
json
.
dumps
(
item
))
.
decode
(
'utf-8'
)
@property
def
options
(
self
):
...
...
@@ -271,6 +271,11 @@ class AdHoc(models.Model):
except
AdHocRunHistory
.
DoesNotExist
:
return
None
def
save
(
self
,
force_insert
=
False
,
force_update
=
False
,
using
=
None
,
update_fields
=
None
):
super
()
.
save
(
force_insert
=
force_insert
,
force_update
=
force_update
,
using
=
using
,
update_fields
=
update_fields
)
def
__str__
(
self
):
return
"{} of {}"
.
format
(
self
.
task
.
name
,
self
.
short_id
)
...
...
apps/ops/tasks.py
View file @
bf9bb1b9
...
...
@@ -21,9 +21,9 @@ def run_ansible_task(task_id, callback=None, **kwargs):
task
=
get_object_or_none
(
Task
,
id
=
task_id
)
if
task
:
result
=
task
.
object
.
run
()
result
=
task
.
run
()
if
callback
is
not
None
:
subtask
(
callback
)
.
delay
(
result
)
subtask
(
callback
)
.
delay
(
result
,
task_name
=
task
.
name
)
return
result
else
:
logger
.
error
(
"No task found"
)
...
...
apps/ops/templates/ops/task_list.html
View file @
bf9bb1b9
...
...
@@ -57,14 +57,20 @@
<td
class=
"text-center"
>
{{ object.adhoc.all | length}}
</td>
<td
class=
"text-center"
>
{{ object.latest_adhoc.hosts | length}}
</td>
<td
class=
"text-center"
>
{% if object.latest_history.is_success %}
<i
class=
"fa fa-check text-navy"
></i>
{% else %}
<i
class=
"fa fa-times text-danger"
></i>
{% if object.latest_history %}
{% if object.latest_history.is_success %}
<i
class=
"fa fa-check text-navy"
></i>
{% else %}
<i
class=
"fa fa-times text-danger"
></i>
{% endif %}
{% endif %}
</td>
<td
class=
"text-center"
>
{{ object.latest_history.date_start }}
</td>
<td
class=
"text-center"
>
{{ object.latest_history.timedelta|floatformat }} s
</td>
<td
class=
"text-center"
>
{% if object.latest_history %}
{{ object.latest_history.timedelta|floatformat }} s
{% endif %}
</td>
<td
class=
"text-center"
>
<a
href=
"{% url 'ops:task-run' pk=object.id %}"
class=
"btn btn-xs btn-info"
>
{% trans "Run" %}
</a>
<a
data-uid=
"{{ object.id }}"
class=
"btn btn-xs btn-danger btn-del"
>
{% trans "Delete" %}
</a>
...
...
apps/ops/utils.py
View file @
bf9bb1b9
# ~*~ coding: utf-8 ~*~
import
json
from
django_celery_beat.models
import
PeriodicTask
,
IntervalSchedule
,
CrontabSchedule
from
common.utils
import
get_logger
,
get_object_or_none
from
.models
import
Task
,
AdHoc
...
...
@@ -13,22 +9,27 @@ def get_task_by_id(task_id):
return
get_object_or_none
(
Task
,
id
=
task_id
)
def
create_or_update_ansible_task
(
task_name
,
hosts
,
tasks
,
pattern
=
'all'
,
options
=
None
,
def
update_or_create_ansible_task
(
task_name
,
hosts
,
tasks
,
interval
=
None
,
crontab
=
None
,
is_periodic
=
False
,
callback
=
None
,
pattern
=
'all'
,
options
=
None
,
run_as_admin
=
False
,
run_as
=
""
,
become_info
=
None
,
created_by
=
None
,
interval
=
None
,
crontab
=
None
,
is_periodic
=
False
,
callback
=
None
,
created_by
=
None
,
):
task
=
get_object_or_none
(
Task
,
name
=
task_name
)
defaults
=
{
'name'
:
task_name
,
'interval'
:
interval
,
'crontab'
:
crontab
,
'is_periodic'
:
is_periodic
,
'callback'
:
callback
,
'created_by'
:
created_by
,
}
if
task
is
None
:
task
=
Task
(
name
=
task_name
,
interval
=
interval
,
crontab
=
crontab
,
is_periodic
=
is_periodic
,
callback
=
callback
,
created_by
=
created_by
)
task
.
save
()
created
=
False
task
,
_
=
Task
.
objects
.
update_or_create
(
defaults
=
defaults
,
name
=
task_name
,
)
adhoc
=
task
.
latest_adhoc
new_adhoc
=
AdHoc
(
task
=
task
,
pattern
=
pattern
,
...
...
@@ -38,70 +39,13 @@ def create_or_update_ansible_task(
new_adhoc
.
tasks
=
tasks
new_adhoc
.
options
=
options
new_adhoc
.
become
=
become_info
if
not
adhoc
or
adhoc
!=
new_adhoc
:
logger
.
debug
(
"Task create new adhoc: {}"
.
format
(
task_name
))
new_adhoc
.
save
()
task
.
latest_adhoc
=
new_adhoc
return
task
def
create_or_update_celery_periodic_tasks
(
tasks
):
"""
:param tasks: {
'add-every-monday-morning': {
'task': 'tasks.add' # A registered celery task,
'interval': 30,
'crontab': "30 7 * * *",
'args': (16, 16),
'kwargs': {},
'enabled': False,
},
}
:return:
"""
# Todo: check task valid, task and callback must be a celery task
for
name
,
detail
in
tasks
.
items
():
interval
=
None
crontab
=
None
if
isinstance
(
detail
.
get
(
"interval"
),
int
):
interval
,
_
=
IntervalSchedule
.
objects
.
get_or_create
(
every
=
detail
[
'interval'
],
period
=
IntervalSchedule
.
SECONDS
,
)
elif
isinstance
(
detail
.
get
(
"crontab"
),
str
):
try
:
minute
,
hour
,
day
,
month
,
week
=
detail
[
"crontab"
]
.
split
()
except
ValueError
:
raise
SyntaxError
(
"crontab is not valid"
)
crontab
,
_
=
CrontabSchedule
.
objects
.
get_or_create
(
minute
=
minute
,
hour
=
hour
,
day_of_week
=
week
,
day_of_month
=
day
,
month_of_year
=
month
,
)
else
:
raise
SyntaxError
(
"Schedule is not valid"
)
defaults
=
dict
(
interval
=
interval
,
crontab
=
crontab
,
name
=
name
,
task
=
detail
[
'task'
],
args
=
json
.
dumps
(
detail
.
get
(
'args'
,
[])),
kwargs
=
json
.
dumps
(
detail
.
get
(
'kwargs'
,
{})),
enabled
=
detail
[
'enabled'
]
)
task
=
PeriodicTask
.
objects
.
update_or_create
(
defaults
=
defaults
,
name
=
name
,
)
logger
.
info
(
"Create periodic task: {}"
.
format
(
task
))
return
task
def
disable_celery_periodic_task
(
task_name
):
PeriodicTask
.
objects
.
filter
(
name
=
task_name
)
.
update
(
enabled
=
False
)
created
=
True
return
task
,
created
def
delete_celery_periodic_task
(
task_name
):
PeriodicTask
.
objects
.
filter
(
name
=
task_name
)
.
delete
()
apps/static/js/jumpserver.js
View file @
bf9bb1b9
...
...
@@ -262,9 +262,6 @@ jumpserver.initDataTable = function (options) {
var
table
=
ele
.
DataTable
({
pageLength
:
options
.
pageLength
||
15
,
dom
:
options
.
dom
||
'<"#uc.pull-left">flt<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>'
,
language
:
{
url
:
options
.
i18n_url
||
"/static/js/plugins/dataTables/i18n/zh-hans.json"
},
order
:
options
.
order
||
[],
select
:
options
.
select
||
'multi'
,
buttons
:
[],
...
...
apps/templates/_left_side_bar.html
View file @
bf9bb1b9
...
...
@@ -2,7 +2,7 @@
<div
class=
"sidebar-collapse"
>
<ul
class=
"nav"
id=
"side-menu"
>
{% include '_user_profile.html' %}
{% if request.user.is_superuser and request.COOKIES.
admin == "Yes
" %}
{% if request.user.is_superuser and request.COOKIES.
IN_ADMIN_PAGE != "No
" %}
{% include '_nav.html' %}
{% else %}
{% include '_nav_user.html' %}
...
...
apps/templates/_user_profile.html
View file @
bf9bb1b9
...
...
@@ -20,7 +20,7 @@
<li><a
href=
"{% url 'users:user-profile-update' %}"
>
{% trans 'Profile settings' %}
</a></li>
<li
class=
"divider"
></li>
{% if request.user.is_superuser %}
{% if request.COOKIES.
admin
== 'No' %}
{% if request.COOKIES.
IN_ADMIN_PAGE
== 'No' %}
<li><a
id=
"switch_admin"
>
{% trans 'Admin page' %}
</a></li>
{% else %}
<li><a
id=
"switch_user"
>
{% trans 'User page' %}
</a></li>
...
...
@@ -37,11 +37,11 @@
$
(
document
).
ready
(
function
()
{
})
.
on
(
'click'
,
'#switch_admin'
,
function
()
{
setCookie
(
"
admin
"
,
"Yes"
);
setCookie
(
"
IN_ADMIN_PAGE
"
,
"Yes"
);
window
.
location
=
"/"
})
.
on
(
'click'
,
'#switch_user'
,
function
()
{
setCookie
(
"
admin
"
,
"No"
);
setCookie
(
"
IN_ADMIN_PAGE
"
,
"No"
);
window
.
location
=
"/"
})
</script>
apps/users/models/group.py
View file @
bf9bb1b9
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
from
__future__
import
unicode_literals
import
uuid
from
django.db
import
models
,
IntegrityError
from
django.contrib.auth.models
import
Group
from
django.utils.translation
import
ugettext_lazy
as
_
from
common.utils
import
signer
,
date_expired_default
from
common.mixins
import
NoDeleteModelMixin
__all__
=
[
'UserGroup'
]
...
...
apps/users/models/user.py
View file @
bf9bb1b9
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
import
os
import
uuid
from
collections
import
OrderedDict
...
...
@@ -15,10 +14,11 @@ from django.utils import timezone
from
django.shortcuts
import
reverse
from
.group
import
UserGroup
from
common.utils
import
signer
,
date_expired_default
from
common.utils
import
get_
signer
,
date_expired_default
__all__
=
[
'User'
]
signer
=
get_signer
()
class
User
(
AbstractUser
):
...
...
apps/users/serializers.py
View file @
bf9bb1b9
...
...
@@ -5,10 +5,12 @@ from django.utils.translation import ugettext_lazy as _
from
rest_framework
import
serializers
from
rest_framework_bulk
import
BulkListSerializer
from
common.utils
import
signer
,
validate_ssh_public_key
from
common.utils
import
get_
signer
,
validate_ssh_public_key
from
common.mixins
import
BulkSerializerMixin
from
.models
import
User
,
UserGroup
signer
=
get_signer
()
class
UserSerializer
(
BulkSerializerMixin
,
serializers
.
ModelSerializer
):
groups_display
=
serializers
.
SerializerMethodField
()
...
...
run_server.py
View file @
bf9bb1b9
...
...
@@ -45,7 +45,7 @@ def start_beat():
os
.
chdir
(
APPS_DIR
)
os
.
environ
.
setdefault
(
'PYTHONOPTIMIZE'
,
'1'
)
scheduler
=
"django_celery_beat.schedulers:DatabaseScheduler"
cmd
=
'celery -A common beat -l {} --scheduler {} --max-interval
30
'
.
format
(
LOG_LEVEL
,
scheduler
)
cmd
=
'celery -A common beat -l {} --scheduler {} --max-interval
5
'
.
format
(
LOG_LEVEL
,
scheduler
)
subprocess
.
call
(
cmd
,
shell
=
True
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment