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
ebd92547
Commit
ebd92547
authored
Aug 01, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
[Update] merged
parents
f6f8d13b
ba288396
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
289 additions
and
141 deletions
+289
-141
tasks.py
apps/assets/tasks.py
+34
-26
utils.py
apps/assets/utils.py
+2
-2
middleware.py
apps/jumpserver/middleware.py
+2
-0
settings.py
apps/jumpserver/settings.py
+4
-4
__init__.py
apps/ops/celery/__init__.py
+9
-0
tasks.py
apps/ops/tasks.py
+2
-2
apps.py
apps/perms/apps.py
+3
-0
asset_permission_list.html
apps/perms/templates/perms/asset_permission_list.html
+2
-1
asset_permission.py
apps/perms/utils/asset_permission.py
+8
-5
terminal_list.html
apps/terminal/templates/terminal/terminal_list.html
+3
-2
user.py
apps/users/models/user.py
+1
-1
tasks.py
apps/users/tasks.py
+4
-4
user_group_list.html
apps/users/templates/users/user_group_list.html
+2
-1
user_list.html
apps/users/templates/users/user_list.html
+3
-2
jms
jms
+209
-91
requirements.txt
requirements/requirements.txt
+1
-0
No files found.
apps/assets/tasks.py
View file @
ebd92547
...
@@ -62,7 +62,7 @@ def clean_hosts_by_protocol(system_user, assets):
...
@@ -62,7 +62,7 @@ def clean_hosts_by_protocol(system_user, assets):
return
hosts
return
hosts
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
set_assets_hardware_info
(
assets
,
result
,
**
kwargs
):
def
set_assets_hardware_info
(
assets
,
result
,
**
kwargs
):
"""
"""
Using ops task run result, to update asset info
Using ops task run result, to update asset info
...
@@ -148,7 +148,7 @@ def update_assets_hardware_info_util(assets, task_name=None):
...
@@ -148,7 +148,7 @@ def update_assets_hardware_info_util(assets, task_name=None):
return
result
return
result
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
update_asset_hardware_info_manual
(
asset
):
def
update_asset_hardware_info_manual
(
asset
):
task_name
=
_
(
"Update asset hardware info: {}"
)
.
format
(
asset
.
hostname
)
task_name
=
_
(
"Update asset hardware info: {}"
)
.
format
(
asset
.
hostname
)
update_assets_hardware_info_util
(
update_assets_hardware_info_util
(
...
@@ -156,7 +156,7 @@ def update_asset_hardware_info_manual(asset):
...
@@ -156,7 +156,7 @@ def update_asset_hardware_info_manual(asset):
)
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
update_assets_hardware_info_period
():
def
update_assets_hardware_info_period
():
"""
"""
Update asset hardware period task
Update asset hardware period task
...
@@ -170,7 +170,7 @@ def update_assets_hardware_info_period():
...
@@ -170,7 +170,7 @@ def update_assets_hardware_info_period():
## ADMIN USER CONNECTIVE ##
## ADMIN USER CONNECTIVE ##
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_asset_connectivity_util
(
assets
,
task_name
=
None
):
def
test_asset_connectivity_util
(
assets
,
task_name
=
None
):
from
ops.utils
import
update_or_create_ansible_task
from
ops.utils
import
update_or_create_ansible_task
...
@@ -227,7 +227,7 @@ def test_asset_connectivity_util(assets, task_name=None):
...
@@ -227,7 +227,7 @@ def test_asset_connectivity_util(assets, task_name=None):
return
results_summary
return
results_summary
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_asset_connectivity_manual
(
asset
):
def
test_asset_connectivity_manual
(
asset
):
task_name
=
_
(
"Test assets connectivity: {}"
)
.
format
(
asset
)
task_name
=
_
(
"Test assets connectivity: {}"
)
.
format
(
asset
)
summary
=
test_asset_connectivity_util
([
asset
],
task_name
=
task_name
)
summary
=
test_asset_connectivity_util
([
asset
],
task_name
=
task_name
)
...
@@ -238,7 +238,7 @@ def test_asset_connectivity_manual(asset):
...
@@ -238,7 +238,7 @@ def test_asset_connectivity_manual(asset):
return
True
,
""
return
True
,
""
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_admin_user_connectivity_util
(
admin_user
,
task_name
):
def
test_admin_user_connectivity_util
(
admin_user
,
task_name
):
"""
"""
Test asset admin user can connect or not. Using ansible api do that
Test asset admin user can connect or not. Using ansible api do that
...
@@ -254,7 +254,7 @@ def test_admin_user_connectivity_util(admin_user, task_name):
...
@@ -254,7 +254,7 @@ def test_admin_user_connectivity_util(admin_user, task_name):
return
summary
return
summary
@shared_task
@shared_task
(
queue
=
"ansible"
)
@register_as_period_task
(
interval
=
3600
)
@register_as_period_task
(
interval
=
3600
)
def
test_admin_user_connectivity_period
():
def
test_admin_user_connectivity_period
():
"""
"""
...
@@ -276,7 +276,7 @@ def test_admin_user_connectivity_period():
...
@@ -276,7 +276,7 @@ def test_admin_user_connectivity_period():
cache
.
set
(
key
,
1
,
60
*
40
)
cache
.
set
(
key
,
1
,
60
*
40
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_admin_user_connectivity_manual
(
admin_user
):
def
test_admin_user_connectivity_manual
(
admin_user
):
task_name
=
_
(
"Test admin user connectivity: {}"
)
.
format
(
admin_user
.
name
)
task_name
=
_
(
"Test admin user connectivity: {}"
)
.
format
(
admin_user
.
name
)
test_admin_user_connectivity_util
(
admin_user
,
task_name
)
test_admin_user_connectivity_util
(
admin_user
,
task_name
)
...
@@ -286,7 +286,7 @@ def test_admin_user_connectivity_manual(admin_user):
...
@@ -286,7 +286,7 @@ def test_admin_user_connectivity_manual(admin_user):
## System user connective ##
## System user connective ##
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_system_user_connectivity_util
(
system_user
,
assets
,
task_name
):
def
test_system_user_connectivity_util
(
system_user
,
assets
,
task_name
):
"""
"""
Test system cant connect his assets or not.
Test system cant connect his assets or not.
...
@@ -344,14 +344,14 @@ def test_system_user_connectivity_util(system_user, assets, task_name):
...
@@ -344,14 +344,14 @@ def test_system_user_connectivity_util(system_user, assets, task_name):
return
results_summary
return
results_summary
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_system_user_connectivity_manual
(
system_user
):
def
test_system_user_connectivity_manual
(
system_user
):
task_name
=
_
(
"Test system user connectivity: {}"
)
.
format
(
system_user
)
task_name
=
_
(
"Test system user connectivity: {}"
)
.
format
(
system_user
)
assets
=
system_user
.
get_all_assets
()
assets
=
system_user
.
get_all_assets
()
return
test_system_user_connectivity_util
(
system_user
,
assets
,
task_name
)
return
test_system_user_connectivity_util
(
system_user
,
assets
,
task_name
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_system_user_connectivity_a_asset
(
system_user
,
asset
):
def
test_system_user_connectivity_a_asset
(
system_user
,
asset
):
task_name
=
_
(
"Test system user connectivity: {} => {}"
)
.
format
(
task_name
=
_
(
"Test system user connectivity: {} => {}"
)
.
format
(
system_user
,
asset
system_user
,
asset
...
@@ -359,7 +359,7 @@ def test_system_user_connectivity_a_asset(system_user, asset):
...
@@ -359,7 +359,7 @@ def test_system_user_connectivity_a_asset(system_user, asset):
return
test_system_user_connectivity_util
(
system_user
,
[
asset
],
task_name
)
return
test_system_user_connectivity_util
(
system_user
,
[
asset
],
task_name
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_system_user_connectivity_period
():
def
test_system_user_connectivity_period
():
if
PERIOD_TASK
!=
"on"
:
if
PERIOD_TASK
!=
"on"
:
logger
.
debug
(
"Period task disabled, test system user connectivity pass"
)
logger
.
debug
(
"Period task disabled, test system user connectivity pass"
)
...
@@ -374,19 +374,16 @@ def test_system_user_connectivity_period():
...
@@ -374,19 +374,16 @@ def test_system_user_connectivity_period():
#### Push system user tasks ####
#### Push system user tasks ####
def
get_push_linux_system_user_tasks
(
system_user
):
def
get_push_linux_system_user_tasks
(
system_user
):
tasks
=
[]
tasks
=
[
if
system_user
.
password
:
{
tasks
.
append
({
'name'
:
'Add user {}'
.
format
(
system_user
.
username
),
'name'
:
'Add user {}'
.
format
(
system_user
.
username
),
'action'
:
{
'action'
:
{
'module'
:
'user'
,
'module'
:
'user'
,
'args'
:
'name={} shell={} state=present
password={}
'
.
format
(
'args'
:
'name={} shell={} state=present'
.
format
(
system_user
.
username
,
system_user
.
shell
,
system_user
.
username
,
system_user
.
shell
,
encrypt_password
(
system_user
.
password
,
salt
=
"K3mIlKK"
),
),
),
}
}
})
},
tasks
.
extend
([
{
{
'name'
:
'Check home dir exists'
,
'name'
:
'Check home dir exists'
,
'action'
:
{
'action'
:
{
...
@@ -403,7 +400,18 @@ def get_push_linux_system_user_tasks(system_user):
...
@@ -403,7 +400,18 @@ def get_push_linux_system_user_tasks(system_user):
},
},
'when'
:
'home_existed.stat.exists == true'
'when'
:
'home_existed.stat.exists == true'
}
}
])
]
if
system_user
.
password
:
tasks
.
append
({
'name'
:
'Set {} password'
.
format
(
system_user
.
username
),
'action'
:
{
'module'
:
'user'
,
'args'
:
'name={} shell={} state=present password={}'
.
format
(
system_user
.
username
,
system_user
.
shell
,
encrypt_password
(
system_user
.
password
,
salt
=
"K3mIlKK"
),
),
}
})
if
system_user
.
public_key
:
if
system_user
.
public_key
:
tasks
.
append
({
tasks
.
append
({
'name'
:
'Set {} authorized key'
.
format
(
system_user
.
username
),
'name'
:
'Set {} authorized key'
.
format
(
system_user
.
username
),
...
@@ -475,7 +483,7 @@ def get_push_system_user_tasks(host, system_user):
...
@@ -475,7 +483,7 @@ def get_push_system_user_tasks(host, system_user):
return
tasks
return
tasks
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
push_system_user_util
(
system_user
,
assets
,
task_name
):
def
push_system_user_util
(
system_user
,
assets
,
task_name
):
from
ops.utils
import
update_or_create_ansible_task
from
ops.utils
import
update_or_create_ansible_task
if
not
system_user
.
is_need_push
():
if
not
system_user
.
is_need_push
():
...
@@ -511,14 +519,14 @@ def push_system_user_util(system_user, assets, task_name):
...
@@ -511,14 +519,14 @@ def push_system_user_util(system_user, assets, task_name):
task
.
run
()
task
.
run
()
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
push_system_user_to_assets_manual
(
system_user
):
def
push_system_user_to_assets_manual
(
system_user
):
assets
=
system_user
.
get_all_assets
()
assets
=
system_user
.
get_all_assets
()
task_name
=
_
(
"Push system users to assets: {}"
)
.
format
(
system_user
.
name
)
task_name
=
_
(
"Push system users to assets: {}"
)
.
format
(
system_user
.
name
)
return
push_system_user_util
(
system_user
,
assets
,
task_name
=
task_name
)
return
push_system_user_util
(
system_user
,
assets
,
task_name
=
task_name
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
push_system_user_a_asset_manual
(
system_user
,
asset
):
def
push_system_user_a_asset_manual
(
system_user
,
asset
):
task_name
=
_
(
"Push system users to asset: {} => {}"
)
.
format
(
task_name
=
_
(
"Push system users to asset: {} => {}"
)
.
format
(
system_user
.
name
,
asset
system_user
.
name
,
asset
...
@@ -526,7 +534,7 @@ def push_system_user_a_asset_manual(system_user, asset):
...
@@ -526,7 +534,7 @@ def push_system_user_a_asset_manual(system_user, asset):
return
push_system_user_util
(
system_user
,
[
asset
],
task_name
=
task_name
)
return
push_system_user_util
(
system_user
,
[
asset
],
task_name
=
task_name
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
push_system_user_to_assets
(
system_user
,
assets
):
def
push_system_user_to_assets
(
system_user
,
assets
):
task_name
=
_
(
"Push system users to assets: {}"
)
.
format
(
system_user
.
name
)
task_name
=
_
(
"Push system users to assets: {}"
)
.
format
(
system_user
.
name
)
return
push_system_user_util
(
system_user
,
assets
,
task_name
)
return
push_system_user_util
(
system_user
,
assets
,
task_name
)
...
@@ -561,7 +569,7 @@ def get_test_asset_user_connectivity_tasks(asset):
...
@@ -561,7 +569,7 @@ def get_test_asset_user_connectivity_tasks(asset):
return
tasks
return
tasks
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_asset_user_connectivity_util
(
asset_user
,
task_name
,
run_as_admin
=
False
):
def
test_asset_user_connectivity_util
(
asset_user
,
task_name
,
run_as_admin
=
False
):
"""
"""
:param asset_user: <AuthBook>对象
:param asset_user: <AuthBook>对象
...
@@ -594,7 +602,7 @@ def test_asset_user_connectivity_util(asset_user, task_name, run_as_admin=False)
...
@@ -594,7 +602,7 @@ def test_asset_user_connectivity_util(asset_user, task_name, run_as_admin=False)
asset_user
.
set_connectivity
(
summary
)
asset_user
.
set_connectivity
(
summary
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
test_asset_users_connectivity_manual
(
asset_users
,
run_as_admin
=
False
):
def
test_asset_users_connectivity_manual
(
asset_users
,
run_as_admin
=
False
):
"""
"""
:param asset_users: <AuthBook>对象
:param asset_users: <AuthBook>对象
...
...
apps/assets/utils.py
View file @
ebd92547
...
@@ -213,10 +213,10 @@ class NodeUtil:
...
@@ -213,10 +213,10 @@ class NodeUtil:
children
.
add
(
node
)
children
.
add
(
node
)
return
list
(
children
)
return
list
(
children
)
def
get_children
(
self
,
node
,
with_self
=
True
):
def
get_
all_
children
(
self
,
node
,
with_self
=
True
):
return
self
.
get_all_children_by_key
(
node
.
key
,
with_self
=
with_self
)
return
self
.
get_all_children_by_key
(
node
.
key
,
with_self
=
with_self
)
def
get_children_keys_by_key
(
self
,
key
,
with_self
=
True
):
def
get_
all_
children_keys_by_key
(
self
,
key
,
with_self
=
True
):
nodes
=
self
.
get_all_children_by_key
(
key
,
with_self
=
with_self
)
nodes
=
self
.
get_all_children_by_key
(
key
,
with_self
=
with_self
)
return
[
n
.
key
for
n
in
nodes
]
return
[
n
.
key
for
n
in
nodes
]
...
...
apps/jumpserver/middleware.py
View file @
ebd92547
...
@@ -5,6 +5,7 @@ import re
...
@@ -5,6 +5,7 @@ import re
import
pytz
import
pytz
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.shortcuts
import
HttpResponse
from
django.shortcuts
import
HttpResponse
from
django.conf
import
settings
from
.utils
import
set_current_request
from
.utils
import
set_current_request
...
@@ -56,6 +57,7 @@ class RequestMiddleware:
...
@@ -56,6 +57,7 @@ class RequestMiddleware:
def
__call__
(
self
,
request
):
def
__call__
(
self
,
request
):
set_current_request
(
request
)
set_current_request
(
request
)
response
=
self
.
get_response
(
request
)
response
=
self
.
get_response
(
request
)
if
not
settings
.
SESSION_EXPIRE_AT_BROWSER_CLOSE
:
age
=
request
.
session
.
get_expiry_age
()
age
=
request
.
session
.
get_expiry_age
()
request
.
session
.
set_expiry
(
age
)
request
.
session
.
set_expiry
(
age
)
return
response
return
response
apps/jumpserver/settings.py
View file @
ebd92547
...
@@ -297,10 +297,10 @@ LOGGING = {
...
@@ -297,10 +297,10 @@ LOGGING = {
'handlers'
:
[
'console'
,
'file'
],
'handlers'
:
[
'console'
,
'file'
],
'level'
:
"INFO"
,
'level'
:
"INFO"
,
},
},
'gunicorn'
:
{
#
'gunicorn': {
'handlers'
:
[
'gunicorn_console'
,
'gunicorn_file'
],
#
'handlers': ['gunicorn_console', 'gunicorn_file'],
'level'
:
'INFO'
,
#
'level': 'INFO',
},
#
},
# 'django.db': {
# 'django.db': {
# 'handlers': ['console', 'file'],
# 'handlers': ['console', 'file'],
# 'level': 'DEBUG'
# 'level': 'DEBUG'
...
...
apps/ops/celery/__init__.py
View file @
ebd92547
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
import
os
import
os
from
kombu
import
Exchange
,
Queue
from
celery
import
Celery
from
celery
import
Celery
# set the default Django settings module for the 'celery' program.
# set the default Django settings module for the 'celery' program.
...
@@ -15,6 +16,14 @@ configs = {k: v for k, v in settings.__dict__.items() if k.startswith('CELERY')}
...
@@ -15,6 +16,14 @@ configs = {k: v for k, v in settings.__dict__.items() if k.startswith('CELERY')}
# Using a string here means the worker will not have to
# Using a string here means the worker will not have to
# pickle the object when using Windows.
# pickle the object when using Windows.
# app.config_from_object('django.conf:settings', namespace='CELERY')
# app.config_from_object('django.conf:settings', namespace='CELERY')
configs
[
"CELERY_QUEUES"
]
=
[
Queue
(
"celery"
,
Exchange
(
"celery"
),
routing_key
=
"celery"
),
Queue
(
"ansible"
,
Exchange
(
"ansible"
),
routing_key
=
"ansible"
),
]
configs
[
"CELERY_ROUTES"
]
=
{
"ops.tasks.run_ansible_task"
:
{
'exchange'
:
'ansible'
,
'routing_key'
:
'ansible'
},
}
app
.
namespace
=
'CELERY'
app
.
namespace
=
'CELERY'
app
.
conf
.
update
(
configs
)
app
.
conf
.
update
(
configs
)
app
.
autodiscover_tasks
(
lambda
:
[
app_config
.
split
(
'.'
)[
0
]
for
app_config
in
settings
.
INSTALLED_APPS
])
app
.
autodiscover_tasks
(
lambda
:
[
app_config
.
split
(
'.'
)[
0
]
for
app_config
in
settings
.
INSTALLED_APPS
])
apps/ops/tasks.py
View file @
ebd92547
...
@@ -23,7 +23,7 @@ def rerun_task():
...
@@ -23,7 +23,7 @@ def rerun_task():
pass
pass
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
run_ansible_task
(
tid
,
callback
=
None
,
**
kwargs
):
def
run_ansible_task
(
tid
,
callback
=
None
,
**
kwargs
):
"""
"""
:param tid: is the tasks serialized data
:param tid: is the tasks serialized data
...
@@ -98,7 +98,7 @@ def create_or_update_registered_periodic_tasks():
...
@@ -98,7 +98,7 @@ def create_or_update_registered_periodic_tasks():
create_or_update_celery_periodic_tasks
(
task
)
create_or_update_celery_periodic_tasks
(
task
)
@shared_task
@shared_task
(
queue
=
"ansible"
)
def
hello
(
name
,
callback
=
None
):
def
hello
(
name
,
callback
=
None
):
import
time
import
time
time
.
sleep
(
10
)
time
.
sleep
(
10
)
...
...
apps/perms/apps.py
View file @
ebd92547
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
django.conf
import
settings
from
django.apps
import
AppConfig
from
django.apps
import
AppConfig
...
@@ -8,4 +9,6 @@ class PermsConfig(AppConfig):
...
@@ -8,4 +9,6 @@ class PermsConfig(AppConfig):
def
ready
(
self
):
def
ready
(
self
):
from
.
import
signals_handler
from
.
import
signals_handler
if
not
settings
.
XPACK_ENABLED
:
settings
.
ASSETS_PERM_CACHE_ENABLE
=
False
return
super
()
.
ready
()
return
super
()
.
ready
()
apps/perms/templates/perms/asset_permission_list.html
View file @
ebd92547
...
@@ -174,10 +174,11 @@ function initTable() {
...
@@ -174,10 +174,11 @@ function initTable() {
}
}
}},
}},
{
targets
:
8
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
8
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
name
=
htmlEscape
(
rowData
.
name
);
var
update_btn
=
'<a href="{% url "perms:asset-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
update_btn
=
'<a href="{% url "perms:asset-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" mark=1 data-name="99991938">{% trans "Delete" %}</a>'
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" mark=1 data-name="99991938">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
.
replace
(
'99991938'
,
name
);
if
(
rowData
.
inherit
)
{
if
(
rowData
.
inherit
)
{
del_btn
=
del_btn
.
replace
(
"mark"
,
"disabled"
)
del_btn
=
del_btn
.
replace
(
"mark"
,
"disabled"
)
}
}
...
...
apps/perms/utils/asset_permission.py
View file @
ebd92547
...
@@ -449,6 +449,8 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
...
@@ -449,6 +449,8 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
self
.
_nodes
=
None
self
.
_nodes
=
None
self
.
_assets_direct
=
None
self
.
_assets_direct
=
None
self
.
_nodes_direct
=
None
self
.
_nodes_direct
=
None
self
.
node_util
=
NodeUtil
()
self
.
tree
.
_node_util
=
self
.
node_util
@staticmethod
@staticmethod
def
change_org_if_need
():
def
change_org_if_need
():
...
@@ -491,13 +493,14 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
...
@@ -491,13 +493,14 @@ class AssetPermissionUtil(AssetPermissionCacheMixin):
self
.
tree
.
add_nodes
(
nodes_keys
)
self
.
tree
.
add_nodes
(
nodes_keys
)
pattern
=
set
()
all_nodes_keys
=
set
()
for
key
in
nodes_keys
:
for
key
in
nodes_keys
:
pattern
.
add
(
r'^{0}$|^{0}:'
.
format
(
key
))
children_keys
=
self
.
node_util
.
get_all_children_keys_by_key
(
key
)
pattern
=
'|'
.
join
(
list
(
pattern
))
all_nodes_keys
.
update
(
set
(
children_keys
))
if
pattern
:
if
all_nodes_keys
:
assets_ids
=
Asset
.
objects
.
filter
(
assets_ids
=
Asset
.
objects
.
filter
(
nodes__key__
regex
=
pattern
nodes__key__
in
=
all_nodes_keys
)
.
valid
()
.
values_list
(
"id"
,
flat
=
True
)
.
distinct
()
)
.
valid
()
.
values_list
(
"id"
,
flat
=
True
)
.
distinct
()
else
:
else
:
assets_ids
=
[]
assets_ids
=
[]
...
...
apps/terminal/templates/terminal/terminal_list.html
View file @
ebd92547
...
@@ -69,16 +69,17 @@ function initTable() {
...
@@ -69,16 +69,17 @@ function initTable() {
}
}
}},
}},
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
6
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
name
=
htmlEscape
(
rowData
.
name
);
var
update_btn
=
'<a href="{% url "terminal:terminal-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
var
update_btn
=
'<a href="{% url "terminal:terminal-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
delete_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
var
delete_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
.
replace
(
'99991938'
,
name
);
var
accept_btn
=
'<a class="btn btn-xs btn-primary btn-accept" data-id="{{ DEFAULT_PK }}">{% trans "Accept" %}</a> '
var
accept_btn
=
'<a class="btn btn-xs btn-primary btn-accept" data-id="{{ DEFAULT_PK }}">{% trans "Accept" %}</a> '
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
reject_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Reject" %}</a>'
var
reject_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn-del" data-id="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Reject" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
.
replace
(
'99991938'
,
name
);
if
(
rowData
.
is_accepted
)
{
if
(
rowData
.
is_accepted
)
{
$
(
td
).
html
(
update_btn
+
delete_btn
);
$
(
td
).
html
(
update_btn
+
delete_btn
);
}
else
{
}
else
{
...
...
apps/users/models/user.py
View file @
ebd92547
...
@@ -111,7 +111,7 @@ class AuthMixin:
...
@@ -111,7 +111,7 @@ class AuthMixin:
@property
@property
def
password_will_expired
(
self
):
def
password_will_expired
(
self
):
if
self
.
is_local
and
self
.
password_expired_remain_days
<
5
:
if
self
.
is_local
and
0
<=
self
.
password_expired_remain_days
<
5
:
return
True
return
True
return
False
return
False
...
...
apps/users/tasks.py
View file @
ebd92547
...
@@ -20,13 +20,13 @@ logger = get_logger(__file__)
...
@@ -20,13 +20,13 @@ logger = get_logger(__file__)
def
check_password_expired
():
def
check_password_expired
():
users
=
User
.
objects
.
exclude
(
role
=
User
.
ROLE_APP
)
users
=
User
.
objects
.
exclude
(
role
=
User
.
ROLE_APP
)
for
user
in
users
:
for
user
in
users
:
if
not
user
.
is_valid
:
continue
if
not
user
.
password_will_expired
:
if
not
user
.
password_will_expired
:
continue
continue
send_password_expiration_reminder_mail
(
user
)
send_password_expiration_reminder_mail
(
user
)
logger
.
info
(
"The user {} password expires in {} days"
.
format
(
msg
=
"The user {} password expires in {} days"
user
,
user
.
password_expired_remain_days
)
logger
.
info
(
msg
.
format
(
user
,
user
.
password_expired_remain_days
))
)
@shared_task
@shared_task
...
...
apps/users/templates/users/user_group_list.html
View file @
ebd92547
...
@@ -67,11 +67,12 @@ function initTable() {
...
@@ -67,11 +67,12 @@ function initTable() {
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
$
(
td
).
html
(
'<span href="javascript:void(0);" data-toggle="tooltip" title="'
+
cellData
+
'">'
+
innerHtml
+
'</span>'
);
}},
}},
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
4
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
name
=
htmlEscape
(
rowData
.
name
);
var
update_btn
=
'<a href="{% url "users:user-group-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
var
update_btn
=
'<a href="{% url "users:user-group-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
);
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_delete_user_group" data-gid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
var
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_delete_user_group" data-gid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
.
replace
(
'99991938'
,
name
);
if
(
rowData
.
id
===
1
)
{
if
(
rowData
.
id
===
1
)
{
$
(
td
).
html
(
update_btn
)
$
(
td
).
html
(
update_btn
)
}
else
{
}
else
{
...
...
apps/users/templates/users/user_list.html
View file @
ebd92547
...
@@ -97,6 +97,7 @@ function initTable() {
...
@@ -97,6 +97,7 @@ function initTable() {
}
}
}},
}},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
name
=
htmlEscape
(
rowData
.
name
);
var
update_btn
=
""
;
var
update_btn
=
""
;
if
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
))
{
if
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
))
{
update_btn
=
'<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>'
;
update_btn
=
'<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>'
;
...
@@ -109,11 +110,11 @@ function initTable() {
...
@@ -109,11 +110,11 @@ function initTable() {
if
(
rowData
.
id
===
1
||
rowData
.
username
===
"admin"
||
rowData
.
username
===
"{{ request.user.username }}"
||
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
)))
{
if
(
rowData
.
id
===
1
||
rowData
.
username
===
"admin"
||
rowData
.
username
===
"{{ request.user.username }}"
||
(
rowData
.
role
===
'Admin'
&&
(
'{{ request.user.role }}'
!==
'Admin'
)))
{
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
.
replace
(
'99991938'
,
name
);
}
else
{
}
else
{
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
del_btn
=
'<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'{{ DEFAULT_PK }}'
,
cellData
)
.
replace
(
'99991938'
,
rowData
.
name
);
.
replace
(
'99991938'
,
name
);
}
}
$
(
td
).
html
(
update_btn
+
del_btn
)
$
(
td
).
html
(
update_btn
+
del_btn
)
}}],
}}],
...
...
jms
View file @
ebd92547
...
@@ -4,10 +4,15 @@
...
@@ -4,10 +4,15 @@
import
os
import
os
import
subprocess
import
subprocess
import
threading
import
threading
import
logging
import
logging.handlers
import
time
import
time
import
argparse
import
argparse
import
sys
import
sys
import
signal
import
signal
from
collections
import
defaultdict
import
daemon
from
daemon
import
pidfile
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
sys
.
path
.
insert
(
0
,
BASE_DIR
)
sys
.
path
.
insert
(
0
,
BASE_DIR
)
...
@@ -50,7 +55,9 @@ WORKERS = 4
...
@@ -50,7 +55,9 @@ WORKERS = 4
DAEMON
=
False
DAEMON
=
False
EXIT_EVENT
=
threading
.
Event
()
EXIT_EVENT
=
threading
.
Event
()
all_services
=
[
'gunicorn'
,
'celery'
,
'beat'
]
LOCK
=
threading
.
Lock
()
daemon_pid_file
=
''
try
:
try
:
os
.
makedirs
(
os
.
path
.
join
(
BASE_DIR
,
"data"
,
"static"
))
os
.
makedirs
(
os
.
path
.
join
(
BASE_DIR
,
"data"
,
"static"
))
...
@@ -58,6 +65,58 @@ try:
...
@@ -58,6 +65,58 @@ try:
except
:
except
:
pass
pass
class
LogPipe
(
threading
.
Thread
):
def
__init__
(
self
,
name
,
file_path
,
to_stdout
=
False
):
"""Setup the object with a logger and a loglevel
and start the thread
"""
threading
.
Thread
.
__init__
(
self
)
self
.
daemon
=
False
self
.
name
=
name
self
.
file_path
=
file_path
self
.
to_stdout
=
to_stdout
self
.
fdRead
,
self
.
fdWrite
=
os
.
pipe
()
self
.
pipeReader
=
os
.
fdopen
(
self
.
fdRead
)
self
.
logger
=
self
.
init_logger
()
self
.
start
()
def
init_logger
(
self
):
_logger
=
logging
.
getLogger
(
self
.
name
)
_logger
.
setLevel
(
logging
.
INFO
)
_formatter
=
logging
.
Formatter
(
'
%(message)
s'
)
_handler
=
logging
.
handlers
.
RotatingFileHandler
(
self
.
file_path
,
mode
=
'a'
,
maxBytes
=
5
*
1024
*
1024
,
backupCount
=
5
)
_handler
.
setFormatter
(
_formatter
)
_handler
.
setLevel
(
logging
.
INFO
)
_logger
.
addHandler
(
_handler
)
if
self
.
to_stdout
:
_console
=
logging
.
StreamHandler
()
_console
.
setLevel
(
logging
.
INFO
)
_console
.
setFormatter
(
_formatter
)
_logger
.
addHandler
(
_console
)
return
_logger
def
fileno
(
self
):
"""Return the write file descriptor of the pipe
"""
return
self
.
fdWrite
def
run
(
self
):
"""Run the thread, logging everything.
"""
for
line
in
iter
(
self
.
pipeReader
.
readline
,
''
):
self
.
logger
.
info
(
line
.
strip
(
'
\n
'
))
self
.
pipeReader
.
close
()
def
close
(
self
):
"""Close the write end of the pipe.
"""
os
.
close
(
self
.
fdWrite
)
def
check_database_connection
():
def
check_database_connection
():
os
.
chdir
(
os
.
path
.
join
(
BASE_DIR
,
'apps'
))
os
.
chdir
(
os
.
path
.
join
(
BASE_DIR
,
'apps'
))
for
i
in
range
(
60
):
for
i
in
range
(
60
):
...
@@ -81,7 +140,9 @@ def make_migrations():
...
@@ -81,7 +140,9 @@ def make_migrations():
def
collect_static
():
def
collect_static
():
print
(
"Collect static files"
)
print
(
"Collect static files"
)
os
.
chdir
(
os
.
path
.
join
(
BASE_DIR
,
'apps'
))
os
.
chdir
(
os
.
path
.
join
(
BASE_DIR
,
'apps'
))
subprocess
.
call
(
'python3 manage.py collectstatic --no-input -c &> /dev/null && echo "Collect static file done"'
,
shell
=
True
)
command
=
'python3 manage.py collectstatic --no-input -c &> /dev/null '
\
'&& echo "Collect static file done"'
subprocess
.
call
(
command
,
shell
=
True
)
def
prepare
():
def
prepare
():
...
@@ -100,18 +161,17 @@ def check_pid(pid):
...
@@ -100,18 +161,17 @@ def check_pid(pid):
return
True
return
True
def
get_pid_file_path
(
s
ervice
):
def
get_pid_file_path
(
s
):
return
os
.
path
.
join
(
TMP_DIR
,
'{}.pid'
.
format
(
service
))
return
os
.
path
.
join
(
'/tmp'
,
'{}.pid'
.
format
(
s
))
def
get_log_file_path
(
s
ervice
):
def
get_log_file_path
(
s
):
return
os
.
path
.
join
(
LOG_DIR
,
'{}.log'
.
format
(
s
ervice
))
return
os
.
path
.
join
(
LOG_DIR
,
'{}.log'
.
format
(
s
))
def
get_pid
(
service
):
def
get_pid_from_file
(
path
):
pid_file
=
get_pid_file_path
(
service
)
if
os
.
path
.
isfile
(
path
):
if
os
.
path
.
isfile
(
pid_file
):
with
open
(
path
)
as
f
:
with
open
(
pid_file
)
as
f
:
try
:
try
:
return
int
(
f
.
read
()
.
strip
())
return
int
(
f
.
read
()
.
strip
())
except
ValueError
:
except
ValueError
:
...
@@ -119,12 +179,19 @@ def get_pid(service):
...
@@ -119,12 +179,19 @@ def get_pid(service):
return
0
return
0
def
get_pid
(
s
):
pid_file
=
get_pid_file_path
(
s
)
return
get_pid_from_file
(
pid_file
)
def
is_running
(
s
,
unlink
=
True
):
def
is_running
(
s
,
unlink
=
True
):
pid_file
=
get_pid_file_path
(
s
)
pid_file
=
get_pid_file_path
(
s
)
if
os
.
path
.
isfile
(
pid_file
):
if
os
.
path
.
isfile
(
pid_file
):
pid
=
get_pid
(
s
)
pid
=
get_pid
(
s
)
if
check_pid
(
pid
):
if
pid
==
0
:
return
False
elif
check_pid
(
pid
):
return
True
return
True
if
unlink
:
if
unlink
:
...
@@ -133,82 +200,73 @@ def is_running(s, unlink=True):
...
@@ -133,82 +200,73 @@ def is_running(s, unlink=True):
def
parse_service
(
s
):
def
parse_service
(
s
):
all_services
=
[
'gunicorn'
,
'celery_ansible'
,
'celery_default'
,
'beat'
]
if
s
==
'all'
:
if
s
==
'all'
:
return
all_services
return
all_services
elif
s
==
"celery"
:
return
[
"celery_ansible"
,
"celery_default"
]
elif
","
in
s
:
elif
","
in
s
:
return
[
i
.
strip
()
for
i
in
s
.
split
(
','
)]
services
=
set
()
for
i
in
s
.
split
(
','
):
services
.
update
(
parse_service
(
i
))
return
services
else
:
else
:
return
[
s
]
return
[
s
]
def
start_gunicorn
():
def
get_start_gunicorn_kwargs
():
print
(
"
\n
- Start Gunicorn WSGI HTTP Server"
)
print
(
"
\n
- Start Gunicorn WSGI HTTP Server"
)
prepare
()
prepare
()
service
=
'gunicorn'
service
=
'gunicorn'
bind
=
'{}:{}'
.
format
(
HTTP_HOST
,
HTTP_PORT
)
bind
=
'{}:{}'
.
format
(
HTTP_HOST
,
HTTP_PORT
)
log_format
=
'
%(h)
s
%(t)
s "
%(r)
s"
%(s)
s
%(b)
s '
log_format
=
'
%(h)
s
%(t)
s "
%(r)
s"
%(s)
s
%(b)
s '
pid_file
=
get_pid_file_path
(
service
)
pid_file
=
get_pid_file_path
(
service
)
log_file
=
get_log_file_path
(
service
)
cmd
=
[
cmd
=
[
'gunicorn'
,
'jumpserver.wsgi'
,
'gunicorn'
,
'jumpserver.wsgi'
,
'-b'
,
bind
,
'-b'
,
bind
,
#'-k', 'eventlet',
'-k'
,
'gthread'
,
'-k'
,
'gthread'
,
'--threads'
,
'10'
,
'--threads'
,
'10'
,
'-w'
,
str
(
WORKERS
),
'-w'
,
str
(
WORKERS
),
'--max-requests'
,
'4096'
,
'--max-requests'
,
'4096'
,
'--access-logformat'
,
log_format
,
'--access-logformat'
,
log_format
,
'-p'
,
pid_file
,
'-p'
,
pid_file
,
'--access-logfile'
,
'-'
]
]
if
DAEMON
:
cmd
.
extend
([
'--daemon'
,
])
else
:
cmd
.
extend
([
'--access-logfile'
,
'-'
])
if
DEBUG
:
if
DEBUG
:
cmd
.
append
(
'--reload'
)
cmd
.
append
(
'--reload'
)
p
=
subprocess
.
Popen
(
cmd
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
cwd
=
APPS_DIR
)
return
{
'cmd'
:
cmd
,
'cwd'
:
APPS_DIR
}
return
p
def
start_celery
():
def
get_start_celery_ansible_kwargs
():
print
(
"
\n
- Start Celery as Distributed Task Queue"
)
print
(
"
\n
- Start Celery as Distributed Task Queue"
)
return
get_start_worker_kwargs
(
'ansible'
,
4
)
def
get_start_celery_default_kwargs
():
return
get_start_worker_kwargs
(
'celery'
,
2
)
def
get_start_worker_kwargs
(
queue
,
num
):
# Todo: Must set this environment, otherwise not no ansible result return
# Todo: Must set this environment, otherwise not no ansible result return
os
.
environ
.
setdefault
(
'PYTHONOPTIMIZE'
,
'1'
)
os
.
environ
.
setdefault
(
'PYTHONOPTIMIZE'
,
'1'
)
if
os
.
getuid
()
==
0
:
if
os
.
getuid
()
==
0
:
os
.
environ
.
setdefault
(
'C_FORCE_ROOT'
,
'1'
)
os
.
environ
.
setdefault
(
'C_FORCE_ROOT'
,
'1'
)
service
=
'celery'
pid_file
=
get_pid_file_path
(
service
)
cmd
=
[
cmd
=
[
'celery'
,
'worker'
,
'celery'
,
'worker'
,
'-A'
,
'ops'
,
'-A'
,
'ops'
,
'-l'
,
'INFO'
,
'-l'
,
'INFO'
,
'-
-pidfile'
,
pid_file
,
'-
c'
,
str
(
num
)
,
'-
-autoscale'
,
'20,4'
,
'-
Q'
,
queue
,
]
]
if
DAEMON
:
return
{
"cmd"
:
cmd
,
"cwd"
:
APPS_DIR
}
cmd
.
extend
([
'--logfile'
,
os
.
path
.
join
(
LOG_DIR
,
'celery.log'
),
'--detach'
,
])
p
=
subprocess
.
Popen
(
cmd
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
cwd
=
APPS_DIR
)
return
p
def
start_beat
():
def
get_start_beat_kwargs
():
print
(
"
\n
- Start Beat as Periodic Task Scheduler"
)
print
(
"
\n
- Start Beat as Periodic Task Scheduler"
)
pid_file
=
get_pid_file_path
(
'beat'
)
log_file
=
get_log_file_path
(
'beat'
)
os
.
environ
.
setdefault
(
'PYTHONOPTIMIZE'
,
'1'
)
os
.
environ
.
setdefault
(
'PYTHONOPTIMIZE'
,
'1'
)
if
os
.
getuid
()
==
0
:
if
os
.
getuid
()
==
0
:
os
.
environ
.
setdefault
(
'C_FORCE_ROOT'
,
'1'
)
os
.
environ
.
setdefault
(
'C_FORCE_ROOT'
,
'1'
)
...
@@ -217,72 +275,116 @@ def start_beat():
...
@@ -217,72 +275,116 @@ def start_beat():
cmd
=
[
cmd
=
[
'celery'
,
'beat'
,
'celery'
,
'beat'
,
'-A'
,
'ops'
,
'-A'
,
'ops'
,
'--pidfile'
,
pid_file
,
'-l'
,
'INFO'
,
'-l'
,
LOG_LEVEL
,
'--scheduler'
,
scheduler
,
'--scheduler'
,
scheduler
,
'--max-interval'
,
'60'
'--max-interval'
,
'60'
]
]
if
DAEMON
:
return
{
"cmd"
:
cmd
,
'cwd'
:
APPS_DIR
}
cmd
.
extend
([
'--logfile'
,
log_file
,
'--detach'
,
])
p
=
subprocess
.
Popen
(
cmd
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
cwd
=
APPS_DIR
)
return
p
def
start_service
(
s
):
processes
=
{}
print
(
time
.
ctime
())
print
(
'Jumpserver version {}, more see https://www.jumpserver.org'
.
format
(
__version__
))
services_handler
=
{
"gunicorn"
:
start_gunicorn
,
"celery"
:
start_celery
,
"beat"
:
start_beat
}
services_set
=
parse_service
(
s
)
def
watch_services
():
processes
=
[]
max_retry
=
3
for
i
in
services_set
:
signal
.
signal
(
signal
.
SIGTERM
,
lambda
x
,
y
:
clean_up
())
if
is_running
(
i
):
services_retry
=
defaultdict
(
int
)
show_service_status
(
i
)
stopped_services
=
{}
continue
func
=
services_handler
.
get
(
i
)
p
=
func
()
processes
.
append
(
p
)
now
=
int
(
time
.
time
())
def
check_services
():
for
i
in
services_set
:
for
s
,
p
in
processes
.
items
():
while
not
is_running
(
i
):
try
:
if
int
(
time
.
time
())
-
now
<
START_TIMEOUT
:
p
.
wait
(
timeout
=
1
)
time
.
sleep
(
1
)
stopped_services
[
s
]
=
''
except
subprocess
.
TimeoutExpired
:
stopped_services
.
pop
(
s
,
None
)
services_retry
.
pop
(
s
,
None
)
continue
continue
else
:
print
(
"Error: {} start error"
.
format
(
i
))
stop_multi_services
(
services_set
)
return
stop_event
=
threading
.
Event
()
def
retry_start_stopped_services
():
for
s
in
stopped_services
:
if
services_retry
[
s
]
>
max_retry
:
print
(
"
\n
Service start failed, exit: "
,
s
)
EXIT_EVENT
.
set
()
break
if
not
DAEMON
:
print
(
"
\n
> Find {} stopped, retry {}"
.
format
(
signal
.
signal
(
signal
.
SIGTERM
,
lambda
x
,
y
:
stop_event
.
set
())
s
,
services_retry
[
s
]
+
1
)
while
not
stop_event
.
is_set
():
)
p
=
start_service
(
s
)
processes
[
s
]
=
p
services_retry
[
s
]
+=
1
while
not
EXIT_EVENT
.
is_set
():
try
:
try
:
with
LOCK
:
check_services
()
retry_start_stopped_services
()
time
.
sleep
(
10
)
time
.
sleep
(
10
)
except
KeyboardInterrupt
:
except
KeyboardInterrupt
:
stop_event
.
set
(
)
time
.
sleep
(
1
)
break
break
clean_up
()
def
start_service
(
s
):
services_kwargs
=
{
"gunicorn"
:
get_start_gunicorn_kwargs
,
"celery_ansible"
:
get_start_celery_ansible_kwargs
,
"celery_default"
:
get_start_celery_default_kwargs
,
"beat"
:
get_start_beat_kwargs
,
}
kwargs
=
services_kwargs
.
get
(
s
)()
pid_file
=
get_pid_file_path
(
s
)
print
(
"Stop services"
)
if
os
.
path
.
isfile
(
pid_file
):
for
p
in
processes
:
os
.
unlink
(
pid_file
)
p
.
terminate
(
)
cmd
=
kwargs
.
pop
(
'cmd'
)
to_stdout
=
False
if
not
DAEMON
:
to_stdout
=
True
log_file
=
get_log_file_path
(
s
)
_logger
=
LogPipe
(
s
,
log_file
,
to_stdout
=
to_stdout
)
stderr
=
stdout
=
_logger
kwargs
.
update
({
"stderr"
:
stderr
,
"stdout"
:
stdout
})
p
=
subprocess
.
Popen
(
cmd
,
**
kwargs
)
with
open
(
pid_file
,
'w'
)
as
f
:
f
.
write
(
str
(
p
.
pid
))
return
p
def
start_services_and_watch
(
s
):
print
(
time
.
ctime
())
print
(
'Jumpserver version {}, more see https://www.jumpserver.org'
.
format
(
__version__
)
)
services_set
=
parse_service
(
s
)
for
i
in
services_set
:
for
i
in
services_set
:
stop_service
(
i
)
if
is_running
(
i
):
show_service_status
(
i
)
continue
p
=
start_service
(
i
)
time
.
sleep
(
2
)
processes
[
i
]
=
p
if
not
DAEMON
:
watch_services
()
else
:
else
:
print
()
show_service_status
(
s
)
show_service_status
(
s
)
global
daemon_pid_file
daemon_pid_file
=
get_pid_file_path
(
'jms'
)
context
=
daemon
.
DaemonContext
(
pidfile
=
pidfile
.
TimeoutPIDLockFile
(
daemon_pid_file
),
signal_map
=
{
signal
.
SIGTERM
:
clean_up
,
signal
.
SIGHUP
:
'terminate'
,
},
)
with
context
:
watch_services
()
def
stop_service
(
s
,
sig
=
15
):
def
stop_service
(
s
,
sig
=
15
):
...
@@ -294,6 +396,12 @@ def stop_service(s, sig=15):
...
@@ -294,6 +396,12 @@ def stop_service(s, sig=15):
print
(
"Stop service: {}"
.
format
(
s
))
print
(
"Stop service: {}"
.
format
(
s
))
pid
=
get_pid
(
s
)
pid
=
get_pid
(
s
)
os
.
kill
(
pid
,
sig
)
os
.
kill
(
pid
,
sig
)
with
LOCK
:
processes
.
pop
(
s
,
None
)
if
s
==
"all"
:
pid
=
get_pid
(
'jms'
)
os
.
kill
(
pid
,
sig
)
def
stop_multi_services
(
services
):
def
stop_multi_services
(
services
):
...
@@ -305,6 +413,15 @@ def stop_service_force(s):
...
@@ -305,6 +413,15 @@ def stop_service_force(s):
stop_service
(
s
,
sig
=
9
)
stop_service
(
s
,
sig
=
9
)
def
clean_up
():
if
not
EXIT_EVENT
.
is_set
():
EXIT_EVENT
.
set
()
processes_dump
=
{
k
:
v
for
k
,
v
in
processes
.
items
()}
for
s1
,
p1
in
processes_dump
.
items
():
stop_service
(
s1
)
p1
.
wait
()
def
show_service_status
(
s
):
def
show_service_status
(
s
):
services_set
=
parse_service
(
s
)
services_set
=
parse_service
(
s
)
for
ns
in
services_set
:
for
ns
in
services_set
:
...
@@ -348,13 +465,14 @@ if __name__ == '__main__':
...
@@ -348,13 +465,14 @@ if __name__ == '__main__':
srv
=
args
.
service
srv
=
args
.
service
if
action
==
"start"
:
if
action
==
"start"
:
start_service
(
srv
)
start_services_and_watch
(
srv
)
os
.
_exit
(
0
)
elif
action
==
"stop"
:
elif
action
==
"stop"
:
stop_service
(
srv
)
stop_service
(
srv
)
elif
action
==
"restart"
:
elif
action
==
"restart"
:
DAEMON
=
True
DAEMON
=
True
stop_service
(
srv
)
stop_service
(
srv
)
time
.
sleep
(
5
)
time
.
sleep
(
5
)
start_service
(
srv
)
start_service
s_and_watch
(
srv
)
else
:
else
:
show_service_status
(
srv
)
show_service_status
(
srv
)
requirements/requirements.txt
View file @
ebd92547
...
@@ -81,4 +81,5 @@ django-radius==1.3.3
...
@@ -81,4 +81,5 @@ django-radius==1.3.3
ipip-ipdb==1.2.1
ipip-ipdb==1.2.1
django-redis-sessions==0.6.1
django-redis-sessions==0.6.1
unicodecsv==0.14.1
unicodecsv==0.14.1
python-daemon==2.2.3
httpsig==1.3.0
httpsig==1.3.0
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