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
4893c466
Commit
4893c466
authored
Dec 21, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改task定时运行机制
parent
47040a61
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
175 additions
and
54 deletions
+175
-54
__init__.py
apps/__init__.py
+1
-3
tasks.py
apps/assets/tasks.py
+10
-6
mixins.py
apps/common/mixins.py
+0
-1
utils.py
apps/common/utils.py
+1
-0
settings.py
apps/jumpserver/settings.py
+2
-4
__init__.py
apps/ops/ansible/__init__.py
+1
-1
exceptions.py
apps/ops/ansible/exceptions.py
+4
-0
models.py
apps/ops/models.py
+73
-5
tasks.py
apps/ops/tasks.py
+4
-4
utils.py
apps/ops/utils.py
+16
-0
config_example.py
config_example.py
+20
-5
requirements.txt
requirements/requirements.txt
+2
-0
run_server.py
run_server.py
+41
-25
No files found.
apps/__init__.py
View file @
4893c466
...
@@ -2,6 +2,4 @@
...
@@ -2,6 +2,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
__version__
=
"0.5.0"
if
__name__
==
'__main__'
:
pass
apps/assets/tasks.py
View file @
4893c466
...
@@ -8,10 +8,8 @@ from django.db.models.signals import post_save
...
@@ -8,10 +8,8 @@ from django.db.models.signals import post_save
from
common.utils
import
get_object_or_none
,
capacity_convert
,
\
from
common.utils
import
get_object_or_none
,
capacity_convert
,
\
sum_capacity
,
encrypt_password
,
get_logger
sum_capacity
,
encrypt_password
,
get_logger
from
common.celery
import
app
as
celery_app
from
.models
import
SystemUser
,
AdminUser
,
Asset
from
.models
import
SystemUser
,
AdminUser
,
Asset
from
.
import
const
from
.
import
const
from
.signals
import
on_app_ready
FORKS
=
10
FORKS
=
10
...
@@ -402,22 +400,28 @@ def push_system_user_on_auth_change(sender, instance=None, update_fields=None, *
...
@@ -402,22 +400,28 @@ def push_system_user_on_auth_change(sender, instance=None, update_fields=None, *
push_system_user_to_cluster_assets
.
delay
(
instance
,
task_name
)
push_system_user_to_cluster_assets
.
delay
(
instance
,
task_name
)
celery_app
.
conf
[
'CELERYBEAT_SCHEDULE'
]
.
update
(
periodic_tasks
=
(
{
{
'update_assets_hardware_period'
:
{
'update_assets_hardware_period'
:
{
'task'
:
'assets.tasks.update_assets_hardware_period'
,
'task'
:
'assets.tasks.update_assets_hardware_period'
,
'schedule'
:
60
*
60
*
24
,
'schedule'
:
60
*
60
*
60
*
24
,
'args'
:
(),
'args'
:
(),
},
},
'test-admin-user-connectability_period'
:
{
'test-admin-user-connectability_period'
:
{
'task'
:
'assets.tasks.test_admin_user_connectability_period'
,
'task'
:
'assets.tasks.test_admin_user_connectability_period'
,
'schedule'
:
60
*
60
,
'schedule'
:
60
*
60
*
60
,
'args'
:
(),
'args'
:
(),
},
},
'push_system_user_period'
:
{
'push_system_user_period'
:
{
'task'
:
'assets.tasks.push_system_user_period'
,
'task'
:
'assets.tasks.push_system_user_period'
,
'schedule'
:
60
*
60
,
'schedule'
:
60
*
60
*
60
*
24
,
'args'
:
(),
'args'
:
(),
}
}
}
}
)
)
def
initial_periodic_tasks
():
from
ops.utils
import
create_periodic_tasks
create_periodic_tasks
(
periodic_tasks
)
apps/common/mixins.py
View file @
4893c466
...
@@ -7,7 +7,6 @@ from django.utils.timezone import now
...
@@ -7,7 +7,6 @@ from django.utils.timezone import now
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
class
NoDeleteQuerySet
(
models
.
query
.
QuerySet
):
class
NoDeleteQuerySet
(
models
.
query
.
QuerySet
):
def
delete
(
self
):
def
delete
(
self
):
...
...
apps/common/utils.py
View file @
4893c466
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
import
json
import
re
import
re
from
collections
import
OrderedDict
from
collections
import
OrderedDict
from
six
import
string_types
from
six
import
string_types
...
...
apps/jumpserver/settings.py
View file @
4893c466
...
@@ -27,9 +27,7 @@ sys.path.append(PROJECT_DIR)
...
@@ -27,9 +27,7 @@ sys.path.append(PROJECT_DIR)
# Import project config setting
# Import project config setting
try
:
try
:
from
config
import
config
as
env_config
,
env
from
config
import
config
as
CONFIG
CONFIG
=
env_config
.
get
(
env
,
'default'
)()
except
ImportError
:
except
ImportError
:
CONFIG
=
type
(
'_'
,
(),
{
'__getattr__'
:
lambda
arg1
,
arg2
:
None
})()
CONFIG
=
type
(
'_'
,
(),
{
'__getattr__'
:
lambda
arg1
,
arg2
:
None
})()
...
@@ -66,12 +64,12 @@ INSTALLED_APPS = [
...
@@ -66,12 +64,12 @@ INSTALLED_APPS = [
'django_filters'
,
'django_filters'
,
'bootstrap3'
,
'bootstrap3'
,
'captcha'
,
'captcha'
,
'django_celery_beat'
,
'django.contrib.auth'
,
'django.contrib.auth'
,
'django.contrib.contenttypes'
,
'django.contrib.contenttypes'
,
'django.contrib.sessions'
,
'django.contrib.sessions'
,
'django.contrib.messages'
,
'django.contrib.messages'
,
'django.contrib.staticfiles'
,
'django.contrib.staticfiles'
,
]
]
MIDDLEWARE
=
[
MIDDLEWARE
=
[
...
...
apps/ops/ansible/__init__.py
View file @
4893c466
...
@@ -3,4 +3,4 @@
...
@@ -3,4 +3,4 @@
from
.callback
import
*
from
.callback
import
*
from
.inventory
import
*
from
.inventory
import
*
from
.runner
import
*
from
.runner
import
*
from
.exceptions
import
*
apps/ops/ansible/exceptions.py
View file @
4893c466
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
__all__
=
[
'AnsibleError'
]
class
AnsibleError
(
Exception
):
class
AnsibleError
(
Exception
):
pass
pass
apps/ops/models.py
View file @
4893c466
...
@@ -4,10 +4,15 @@ import logging
...
@@ -4,10 +4,15 @@ import logging
import
json
import
json
import
uuid
import
uuid
import
time
from
django.db
import
models
from
django.db
import
models
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.core
import
serializers
from
django_celery_beat.models
import
CrontabSchedule
,
IntervalSchedule
,
PeriodicTask
from
common.utils
import
signer
from
common.utils
import
signer
from
.ansible
import
AdHocRunner
,
AnsibleError
__all__
=
[
"Task"
,
"AdHoc"
,
"AdHocRunHistory"
]
__all__
=
[
"Task"
,
"AdHoc"
,
"AdHocRunHistory"
]
...
@@ -22,7 +27,17 @@ class Task(models.Model):
...
@@ -22,7 +27,17 @@ class Task(models.Model):
"""
"""
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
interval
=
models
.
ForeignKey
(
IntervalSchedule
,
on_delete
=
models
.
CASCADE
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Interval'
),
)
crontab
=
models
.
ForeignKey
(
CrontabSchedule
,
on_delete
=
models
.
CASCADE
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Crontab'
),
help_text
=
_
(
'Use one of Interval/Crontab'
),
)
is_periodic
=
models
.
BooleanField
(
default
=
False
)
is_deleted
=
models
.
BooleanField
(
default
=
False
)
is_deleted
=
models
.
BooleanField
(
default
=
False
)
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
"Comment"
))
created_by
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
default
=
''
)
created_by
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
default
=
''
)
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
__latest_adhoc
=
None
__latest_adhoc
=
None
...
@@ -65,12 +80,32 @@ class Task(models.Model):
...
@@ -65,12 +80,32 @@ class Task(models.Model):
def
get_run_history
(
self
):
def
get_run_history
(
self
):
return
self
.
history
.
all
()
return
self
.
history
.
all
()
def
run
(
self
):
def
run
(
self
,
record
=
True
):
if
self
.
latest_adhoc
:
if
self
.
latest_adhoc
:
return
self
.
latest_adhoc
.
run
()
return
self
.
latest_adhoc
.
run
(
record
=
record
)
else
:
else
:
return
{
'error'
:
'No adhoc'
}
return
{
'error'
:
'No adhoc'
}
def
save
(
self
,
force_insert
=
False
,
force_update
=
False
,
using
=
None
,
update_fields
=
None
):
instance
=
super
()
.
save
(
force_insert
=
force_insert
,
force_update
=
force_update
,
using
=
using
,
update_fields
=
update_fields
,
)
if
instance
.
is_periodic
:
PeriodicTask
.
objects
.
update_or_create
(
interval
=
instance
.
interval
,
crontab
=
instance
.
crontab
,
name
=
self
.
name
,
task
=
'ops.run_task'
,
args
=
serializers
.
serialize
(
'json'
,
[
instance
]),
)
else
:
PeriodicTask
.
objects
.
filter
(
name
=
self
.
name
)
.
delete
()
return
instance
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
name
return
self
.
name
...
@@ -128,9 +163,42 @@ class AdHoc(models.Model):
...
@@ -128,9 +163,42 @@ class AdHoc(models.Model):
else
:
else
:
return
{}
return
{}
def
run
(
self
):
def
run
(
self
,
record
=
True
):
from
.utils
import
run_adhoc_object
if
record
:
return
run_adhoc_object
(
self
,
**
self
.
options
)
return
self
.
_run_and_record
()
else
:
return
self
.
_run_only
()
def
_run_and_record
(
self
):
history
=
AdHocRunHistory
(
adhoc
=
self
,
task
=
self
.
task
)
time_start
=
time
.
time
()
try
:
result
=
self
.
_run_only
()
history
.
is_finished
=
True
if
result
.
results_summary
.
get
(
'dark'
):
history
.
is_success
=
False
else
:
history
.
is_success
=
True
history
.
result
=
result
.
results_raw
history
.
summary
=
result
.
results_summary
return
result
finally
:
history
.
date_finished
=
timezone
.
now
()
history
.
timedelta
=
time
.
time
()
-
time_start
history
.
save
()
def
_run_only
(
self
):
from
.utils
import
get_adhoc_inventory
inventory
=
get_adhoc_inventory
(
self
)
runner
=
AdHocRunner
(
inventory
)
for
k
,
v
in
self
.
options
.
items
():
runner
.
set_option
(
k
,
v
)
try
:
result
=
runner
.
run
(
self
.
tasks
,
self
.
pattern
,
self
.
task
.
name
)
return
result
except
AnsibleError
as
e
:
logger
.
error
(
"Failed run adhoc {}, {}"
.
format
(
self
.
task
.
name
,
e
))
@become.setter
@become.setter
def
become
(
self
,
item
):
def
become
(
self
,
item
):
...
...
apps/ops/tasks.py
View file @
4893c466
# coding: utf-8
# coding: utf-8
from
celery
import
shared_task
from
celery
import
shared_task
from
django.core
import
serializers
from
.utils
import
run_adhoc
def
rerun_task
():
def
rerun_task
():
...
@@ -9,5 +8,6 @@ def rerun_task():
...
@@ -9,5 +8,6 @@ def rerun_task():
@shared_task
@shared_task
def
run_add_hoc_and_record_async
(
adhoc
,
**
options
):
def
run_task
(
tasks_json
):
return
run_adhoc
(
adhoc
,
**
options
)
for
task
in
serializers
.
deserialize
(
'json'
,
tasks_json
):
task
.
object
.
run
()
apps/ops/utils.py
View file @
4893c466
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
import
time
import
time
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.db
import
transaction
from
django.db
import
transaction
from
django_celery_beat.models
import
PeriodicTask
,
IntervalSchedule
from
common.utils
import
get_logger
,
get_object_or_none
,
get_short_uuid_str
from
common.utils
import
get_logger
,
get_object_or_none
,
get_short_uuid_str
from
.ansible
import
AdHocRunner
,
CommandResultCallback
from
.ansible
import
AdHocRunner
,
CommandResultCallback
...
@@ -131,4 +132,19 @@ def create_or_update_task(
...
@@ -131,4 +132,19 @@ def create_or_update_task(
return
task
return
task
def
create_periodic_tasks
(
tasks
):
for
name
,
detail
in
tasks
.
items
():
schedule
,
_
=
IntervalSchedule
.
objects
.
get_or_create
(
every
=
detail
[
'schedule'
],
period
=
IntervalSchedule
.
SECONDS
,
)
task
=
PeriodicTask
.
objects
.
create
(
interval
=
schedule
,
name
=
name
,
task
=
detail
[
'task'
],
args
=
json
.
dumps
(
detail
.
get
(
'args'
,
[])),
kwargs
=
json
.
dumps
(
detail
.
get
(
'kwargs'
,
{})),
)
print
(
"Create periodic task: {}"
.
format
(
task
))
config_example.py
View file @
4893c466
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
Jumpserver project setting file
Jumpserver project setting file
:copyright: (c) 2014-201
6 by Jumpserver Team.
:copyright: (c) 2014-201
7 by Jumpserver Team
:license: GPL v2, see LICENSE for more details.
:license: GPL v2, see LICENSE for more details.
"""
"""
import
os
import
os
...
@@ -50,6 +50,11 @@ class Config:
...
@@ -50,6 +50,11 @@ class Config:
# DB_PASSWORD = ''
# DB_PASSWORD = ''
# DB_NAME = 'jumpserver'
# DB_NAME = 'jumpserver'
# When Django start it will bind this host and port
# ./manage.py runserver 127.0.0.1:8080
HTTP_BIND_HOST
=
'0.0.0.0'
HTTP_LISTEN_PORT
=
8080
# Use Redis as broker for celery and web socket
# Use Redis as broker for celery and web socket
REDIS_HOST
=
'127.0.0.1'
REDIS_HOST
=
'127.0.0.1'
REDIS_PORT
=
6379
REDIS_PORT
=
6379
...
@@ -101,8 +106,18 @@ class Config:
...
@@ -101,8 +106,18 @@ class Config:
return
None
return
None
config
=
{
class
DevelopmentConfig
(
Config
):
'default'
:
Config
,
pass
}
class
TestConfig
(
Config
):
pass
class
ProductionConfig
(
Config
):
pass
# Default using Config settings, you can write if/else for different env
config
=
Config
()
env
=
'default'
requirements/requirements.txt
View file @
4893c466
...
@@ -57,3 +57,5 @@ uritemplate==3.0.0
...
@@ -57,3 +57,5 @@ uritemplate==3.0.0
urllib3==1.22
urllib3==1.22
vine==1.1.4
vine==1.1.4
gunicorn==19.7.1
gunicorn==19.7.1
django_celery_beat==1.1.0
ephem==3.7.6.0
run_server.py
View file @
4893c466
#!/usr/bin/env python
#!/usr/bin/env python
# ~*~ coding: utf-8 ~*~
from
threading
import
Thread
import
os
import
os
import
subprocess
import
subprocess
import
time
from
threading
import
Thread
try
:
from
apps
import
__version__
from
config
import
config
as
env_config
,
env
CONFIG
=
env_config
.
get
(
env
,
'default'
)()
try
:
from
config
import
config
as
CONFIG
except
ImportError
:
except
ImportError
:
CONFIG
=
type
(
'_'
,
(),
{
'__getattr__'
:
None
})()
CONFIG
=
type
(
'_'
,
(),
{
'__getattr__'
:
None
})()
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
APPS_DIR
=
os
.
path
.
join
(
BASE_DIR
,
'apps'
)
HTTP_HOST
=
CONFIG
.
HTTP_BIND_HOST
or
'127.0.0.1'
HTTP_PORT
=
CONFIG
.
HTTP_LISTEN_PORT
or
8080
LOG_LEVEL
=
CONFIG
.
LOG_LEVEL
WORKERS
=
4
apps_dir
=
os
.
path
.
join
(
BASE_DIR
,
'apps'
)
def
start_gunicorn
():
def
start_django
():
print
(
"- Start Gunicorn WSGI HTTP Server"
)
http_host
=
CONFIG
.
HTTP_BIND_HOST
or
'127.0.0.1'
os
.
chdir
(
APPS_DIR
)
http_port
=
CONFIG
.
HTTP_LISTEN_PORT
or
'8080'
cmd
=
"gunicorn jumpserver.wsgi -b {}:{} -w {}"
.
format
(
HTTP_HOST
,
HTTP_PORT
,
WORKERS
)
os
.
chdir
(
apps_dir
)
subprocess
.
call
(
cmd
,
shell
=
True
)
print
(
'start django'
)
subprocess
.
call
(
'python ./manage.py runserver
%
s:
%
s'
%
(
http_host
,
http_port
),
shell
=
True
)
def
start_celery
():
def
start_celery
():
os
.
chdir
(
apps_dir
)
print
(
"- Start Celery as Distributed Task Queue"
)
os
.
environ
.
setdefault
(
'C_FORCE_ROOT'
,
'1'
)
os
.
chdir
(
APPS_DIR
)
os
.
environ
.
setdefault
(
'PYTHONOPTIMIZE'
,
'1'
)
#
os.environ.setdefault('PYTHONOPTIMIZE', '1')
print
(
'start celery'
)
cmd
=
'celery -A common worker -l {}'
.
format
(
LOG_LEVEL
.
lower
()
)
subprocess
.
call
(
'celery -A common worker -B -s /tmp/celerybeat-schedule -l debug'
,
shell
=
True
)
subprocess
.
call
(
cmd
,
shell
=
True
)
def
main
():
def
start_beat
():
t1
=
Thread
(
target
=
start_django
,
args
=
())
print
(
"- Start Beat as Periodic Task Scheduler"
)
t2
=
Thread
(
target
=
start_celery
,
args
=
())
os
.
chdir
(
APPS_DIR
)
# os.environ.setdefault('PYTHONOPTIMIZE', '1')
schduler
=
"django_celery_beat.schedulers:DatabaseScheduler"
cmd
=
'celery -A common beat -l {} --scheduler {}'
.
format
(
LOG_LEVEL
,
schduler
)
subprocess
.
call
(
cmd
,
shell
=
True
)
t1
.
start
()
t2
.
start
()
t1
.
join
()
def
main
():
t2
.
join
()
print
(
time
.
ctime
())
print
(
'Jumpserver version {}, more see https://www.jumpserver.org'
.
format
(
__version__
))
print
(
'Quit the server with CONTROL-C.'
)
threads
=
[]
for
func
in
(
start_gunicorn
,
start_celery
,
start_beat
):
t
=
Thread
(
target
=
func
,
args
=
())
threads
.
append
(
t
)
t
.
start
()
for
t
in
threads
:
t
.
join
()
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
...
...
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