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
b60e5a7e
Commit
b60e5a7e
authored
Mar 23, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Change] 修改一些view
parent
c940a4c0
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
300 additions
and
25 deletions
+300
-25
asset.py
apps/assets/models/asset.py
+6
-1
user.py
apps/assets/models/user.py
+16
-2
proxy_log_offline_list.html
apps/audits/templates/audits/proxy_log_offline_list.html
+0
-0
proxy_log_online_list.html
apps/audits/templates/audits/proxy_log_online_list.html
+173
-0
views_urls.py
apps/audits/urls/views_urls.py
+7
-5
views.py
apps/audits/views.py
+33
-1
utils.py
apps/common/utils.py
+4
-2
inventory.py
apps/ops/ansible/inventory.py
+6
-6
runner.py
apps/ops/ansible/runner.py
+4
-2
task_detail.html
apps/ops/templates/ops/task_detail.html
+35
-0
utils.py
apps/ops/utils.py
+7
-2
views.py
apps/ops/views.py
+2
-0
tasks.py
apps/perms/tasks.py
+2
-2
_nav.html
apps/templates/_nav.html
+5
-2
.gitkeep
tmp/.gitkeep
+0
-0
No files found.
apps/assets/models/asset.py
View file @
b60e5a7e
...
@@ -112,7 +112,12 @@ class Asset(models.Model):
...
@@ -112,7 +112,12 @@ class Asset(models.Model):
'groups'
:
[
group
.
name
for
group
in
self
.
groups
.
all
()],
'groups'
:
[
group
.
name
for
group
in
self
.
groups
.
all
()],
'username'
:
self
.
admin_user
.
username
if
self
.
admin_user
else
''
,
'username'
:
self
.
admin_user
.
username
if
self
.
admin_user
else
''
,
'password'
:
self
.
admin_user
.
password
if
self
.
admin_user
else
''
,
'password'
:
self
.
admin_user
.
password
if
self
.
admin_user
else
''
,
'private_key'
:
self
.
admin_user
.
private_key
if
self
.
admin_user
else
None
,
'private_key'
:
self
.
admin_user
.
private_key_file
if
self
.
admin_user
else
None
,
'become'
:
{
'method'
:
self
.
admin_user
.
become_method
,
'user'
:
self
.
admin_user
.
become_user
,
'pass'
:
self
.
admin_user
.
become_pass
,
}
if
self
.
admin_user
.
become
else
{},
}
}
class
Meta
:
class
Meta
:
...
...
apps/assets/models/user.py
View file @
b60e5a7e
...
@@ -3,12 +3,14 @@
...
@@ -3,12 +3,14 @@
#
#
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
import
os
import
logging
import
logging
from
hashlib
import
md5
from
django.core.exceptions
import
ValidationError
from
django.core.exceptions
import
ValidationError
from
django.db
import
models
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.conf
import
settings
from
common.utils
import
signer
,
validate_ssh_private_key
,
ssh_key_string_to_obj
from
common.utils
import
signer
,
validate_ssh_private_key
,
ssh_key_string_to_obj
...
@@ -38,7 +40,7 @@ class AdminUser(models.Model):
...
@@ -38,7 +40,7 @@ class AdminUser(models.Model):
become
=
models
.
BooleanField
(
default
=
True
)
become
=
models
.
BooleanField
(
default
=
True
)
become_method
=
models
.
CharField
(
choices
=
BECOME_METHOD_CHOICES
,
default
=
'sudo'
,
max_length
=
4
)
become_method
=
models
.
CharField
(
choices
=
BECOME_METHOD_CHOICES
,
default
=
'sudo'
,
max_length
=
4
)
become_user
=
models
.
CharField
(
default
=
'root'
,
max_length
=
64
)
become_user
=
models
.
CharField
(
default
=
'root'
,
max_length
=
64
)
become_pass
word
=
models
.
CharField
(
default
=
''
,
max_length
=
128
)
become_pass
=
models
.
CharField
(
default
=
''
,
max_length
=
128
)
_public_key
=
models
.
CharField
(
_public_key
=
models
.
CharField
(
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
...
@@ -74,6 +76,18 @@ class AdminUser(models.Model):
...
@@ -74,6 +76,18 @@ class AdminUser(models.Model):
def
private_key
(
self
,
private_key_raw
):
def
private_key
(
self
,
private_key_raw
):
self
.
_private_key
=
signer
.
sign
(
private_key_raw
)
self
.
_private_key
=
signer
.
sign
(
private_key_raw
)
@property
def
private_key_file
(
self
):
if
not
self
.
private_key
:
return
None
project_dir
=
settings
.
PROJECT_DIR
tmp_dir
=
os
.
path
.
join
(
project_dir
,
'tmp'
)
key_name
=
md5
(
self
.
_private_key
)
.
hexdigest
()
key_path
=
os
.
path
.
join
(
tmp_dir
,
key_name
)
if
not
os
.
path
.
exists
(
key_path
):
self
.
private_key
.
write_private_key_file
(
key_path
)
return
key_path
@property
@property
def
public_key
(
self
):
def
public_key
(
self
):
return
signer
.
unsign
(
self
.
_public_key
)
return
signer
.
unsign
(
self
.
_public_key
)
...
...
apps/audits/templates/audits/proxy_log_list.html
→
apps/audits/templates/audits/proxy_log_
offline_
list.html
View file @
b60e5a7e
File moved
apps/audits/templates/audits/proxy_log_online_list.html
0 → 100644
View file @
b60e5a7e
{% extends '_base_list.html' %}
{% load i18n %}
{% load static %}
{% block content_left_head %}
<link
href=
"{% static 'css/plugins/datepicker/datepicker3.css' %}"
rel=
"stylesheet"
>
<style>
#search_btn
{
margin-bottom
:
0
;
}
</style>
{% endblock %}
{% block table_search %}
<form
id=
"search_form"
method=
"get"
action=
""
class=
"pull-right form-inline"
>
<div
class=
"form-group"
id=
"date"
>
<div
class=
"input-daterange input-group"
id=
"datepicker"
>
<span
class=
"input-group-addon"
><i
class=
"fa fa-calendar"
></i></span>
<input
type=
"text"
class=
"input-sm form-control"
style=
"width: 100px;"
name=
"date_from"
value=
"{{ date_from }}"
>
<span
class=
"input-group-addon"
>
to
</span>
<input
type=
"text"
class=
"input-sm form-control"
style=
"width: 100px;"
name=
"date_to"
value=
"{{ date_to }}"
>
</div>
</div>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"username"
>
<option
value=
""
>
{% trans 'User' %}
</option>
{% for user in user_list %}
<option
value=
"{{ user }}"
{%
if
user =
=
username
%}
selected
{%
endif
%}
>
{{ user }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"ip"
>
<option
value=
""
>
{% trans 'Asset' %}
</option>
{% for asset in asset_list %}
<option
value=
"{{ asset }}"
{%
if
asset =
=
ip
%}
selected
{%
endif
%}
>
{{ asset }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<select
class=
"select2 form-control"
name=
"system_user"
>
<option
value=
""
>
{% trans 'System user' %}
</option>
{% for su in system_user_list %}
<option
value=
"{{ su }}"
{%
if
su =
=
system_user
%}
selected
{%
endif
%}
>
{{ su }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"input-group"
>
<input
type=
"text"
class=
"form-control input-sm"
name=
"keyword"
placeholder=
"Keyword"
value=
"{{ keyword }}"
>
</div>
<div
class=
"input-group"
>
<div
class=
"input-group-btn"
>
<button
id=
'search_btn'
type=
"submit"
class=
"btn btn-sm btn-primary"
>
搜索
</button>
</div>
</div>
</form>
{% endblock %}
{% block table_head %}
<th
class=
"text-center"
></th>
<th
class=
"text-center"
>
{% trans 'ID' %}
</th>
<th
class=
"text-center"
>
{% trans 'User' %}
</th>
<th
class=
"text-center"
>
{% trans 'Asset' %}
</th>
<th
class=
"text-center"
>
{% trans 'System user' %}
</th>
<th
class=
"text-center"
>
{% trans 'Terminal' %}
</th>
<th
class=
"text-center"
>
{% trans 'Command' %}
</th>
<th
class=
"text-center"
>
{% trans 'Success' %}
</th>
<th
class=
"text-center"
>
{% trans 'Finished' %}
</th>
<th
class=
"text-center"
>
{% trans 'R/M' %}
</th>
<th
class=
"text-center"
>
{% trans 'Date start' %}
</th>
<th
class=
"text-center"
>
{% trans 'Time' %}
</th>
{% endblock %}
{% block table_body %}
{% for proxy_log in proxy_log_list %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
><input
type=
"checkbox"
class=
"cbx-term"
value=
"{{ proxy_log.id }}"
></td>
<td
class=
"text-center"
>
<a
href=
"{% url 'audits:proxy-log-detail' pk=proxy_log.id %}"
>
{{ proxy_log.id }}
</a>
</td>
<td
class=
"text-center"
>
{{ proxy_log.user }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.asset }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.system_user }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.terminal }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.commands.all|length}}
</td>
<td
class=
"text-center"
>
{% if proxy_log.is_failed %}
<i
class=
"fa fa-times text-danger"
></i>
{% else %}
<i
class=
"fa fa-check text-navy"
></i>
{% endif %}
</td>
{% if proxy_log.is_finished %}
<td
class=
"text-center"
>
<i
class=
"fa fa-check text-navy"
></i>
</td>
<td
class=
"text-center"
>
<a><span
class=
"text-navy"
><i
class=
"fa fa-play-circle"
></i></span></a>
</td>
{% else %}
<td
class=
"text-center"
>
<a
class=
"btn-term"
value=
"{{ proxy_log.id }}"
><i
class=
"fa fa-times text-danger"
></i></a>
</td>
<td
class=
"text-center"
>
<a><span
class=
"text-danger"
><i
class=
"fa fa-eye"
></i></span></a>
</td>
{% endif %}
<td
class=
"text-center"
>
{{ proxy_log.date_start }}
</td>
<td
class=
"text-center"
>
{{ proxy_log.date_finished|timeuntil:proxy_log.date_start }}
</td>
</tr>
{% endfor %}
{% endblock %}
{% block content_bottom_left %}
<div
id=
"actions"
>
<div
class=
"input-group"
>
<select
class=
"form-control m-b"
style=
"width: auto"
id=
"slct_bulk_update"
>
<option
value=
"terminate"
>
{% trans 'Terminate selected' %}
</option>
</select>
<div
class=
"input-group-btn pull-left"
style=
"padding-left: 5px;"
>
<button
id=
'btn_bulk_update'
style=
"height: 32px;"
class=
"btn btn-sm btn-primary"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script
src=
"{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"
></script>
<script>
function
terminateConnection
(
data
)
{
function
success
()
{
window
.
setTimeout
(
function
()
{
window
.
location
.
reload
()
},
300
)
}
var
the_url
=
"{% url 'api-applications:terminate-connection' %}"
;
APIUpdateAttr
({
url
:
the_url
,
method
:
'POST'
,
body
:
JSON
.
stringify
(
data
),
success
:
success
,
success_message
:
'Terminate success'
});
}
$
(
document
).
ready
(
function
()
{
$
(
'table'
).
DataTable
({
"searching"
:
false
,
"paging"
:
false
,
"bInfo"
:
false
,
"order"
:
[]
});
$
(
'.select2'
).
select2
();
$
(
'#date .input-daterange'
).
datepicker
({
dateFormat
:
'mm/dd/yy'
,
keyboardNavigation
:
false
,
forceParse
:
false
,
autoclose
:
true
});
}).
on
(
'click'
,
'.btn-term'
,
function
()
{
var
$this
=
$
(
this
);
var
proxy_log_id
=
$this
.
attr
(
'value'
);
var
data
=
{
proxy_log_id
:
proxy_log_id
};
terminateConnection
(
data
)
}).
on
(
'click'
,
'#btn_bulk_update'
,
function
()
{
var
data
=
[];
$
(
'.cbx-term:checked'
).
each
(
function
()
{
data
.
push
({
proxy_log_id
:
$
(
this
).
attr
(
'value'
)})
});
terminateConnection
(
data
)
})
</script>
{% endblock %}
apps/audits/urls/views_urls.py
View file @
b60e5a7e
...
@@ -4,14 +4,16 @@ from .. import views
...
@@ -4,14 +4,16 @@ from .. import views
app_name
=
'audits'
app_name
=
'audits'
urlpatterns
=
[
urlpatterns
=
[
url
(
r'^proxy-log$'
,
views
.
ProxyLogListView
.
as_view
(),
url
(
r'^proxy-log-offline/$'
,
views
.
ProxyLogOfflineListView
.
as_view
(),
name
=
'proxy-log-list'
),
name
=
'proxy-log-offline-list'
),
url
(
r'^proxy-log/(?P<pk>\d+)$'
,
views
.
ProxyLogDetailView
.
as_view
(),
url
(
r'^proxy-log-online/$'
,
views
.
ProxyLogOnlineListView
.
as_view
(),
name
=
'proxy-log-online-list'
),
url
(
r'^proxy-log/(?P<pk>\d+)/$'
,
views
.
ProxyLogDetailView
.
as_view
(),
name
=
'proxy-log-detail'
),
name
=
'proxy-log-detail'
),
# url(r'^proxy-log/(?P<pk>\d+)/commands$', views.ProxyLogCommandsListView.as_view(), name='proxy-log-commands-list'),
# url(r'^proxy-log/(?P<pk>\d+)/commands$', views.ProxyLogCommandsListView.as_view(), name='proxy-log-commands-list'),
url
(
r'^command-log$'
,
views
.
CommandLogListView
.
as_view
(),
url
(
r'^command-log
/
$'
,
views
.
CommandLogListView
.
as_view
(),
name
=
'command-log-list'
),
name
=
'command-log-list'
),
url
(
r'^login-log$'
,
views
.
LoginLogListView
.
as_view
(),
url
(
r'^login-log
/
$'
,
views
.
LoginLogListView
.
as_view
(),
name
=
'login-log-list'
),
name
=
'login-log-list'
),
]
]
...
...
apps/audits/views.py
View file @
b60e5a7e
...
@@ -22,7 +22,7 @@ from audits.backends import CommandLogSerializer
...
@@ -22,7 +22,7 @@ from audits.backends import CommandLogSerializer
class
ProxyLogListView
(
AdminUserRequiredMixin
,
ListView
):
class
ProxyLogListView
(
AdminUserRequiredMixin
,
ListView
):
model
=
ProxyLog
model
=
ProxyLog
template_name
=
'audits/proxy_log_list.html'
template_name
=
'audits/proxy_log_
online_
list.html'
context_object_name
=
'proxy_log_list'
context_object_name
=
'proxy_log_list'
paginate_by
=
settings
.
CONFIG
.
DISPLAY_PER_PAGE
paginate_by
=
settings
.
CONFIG
.
DISPLAY_PER_PAGE
keyword
=
user
=
asset
=
system_user
=
date_from_s
=
date_to_s
=
''
keyword
=
user
=
asset
=
system_user
=
date_from_s
=
date_to_s
=
''
...
@@ -89,6 +89,38 @@ class ProxyLogListView(AdminUserRequiredMixin, ListView):
...
@@ -89,6 +89,38 @@ class ProxyLogListView(AdminUserRequiredMixin, ListView):
return
super
(
ProxyLogListView
,
self
)
.
get_context_data
(
**
kwargs
)
return
super
(
ProxyLogListView
,
self
)
.
get_context_data
(
**
kwargs
)
class
ProxyLogOfflineListView
(
ProxyLogListView
):
template_name
=
'audits/proxy_log_online_list.html'
def
get_queryset
(
self
):
queryset
=
super
(
ProxyLogOfflineListView
,
self
)
.
get_queryset
()
queryset
=
queryset
.
filter
(
is_finished
=
True
)
return
queryset
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'action'
:
_
(
'Proxy log offline list'
),
}
kwargs
.
update
(
context
)
return
super
(
ProxyLogOfflineListView
,
self
)
.
get_context_data
(
**
kwargs
)
class
ProxyLogOnlineListView
(
ProxyLogListView
):
template_name
=
'audits/proxy_log_online_list.html'
def
get_queryset
(
self
):
queryset
=
super
(
ProxyLogOnlineListView
,
self
)
.
get_queryset
()
queryset
=
queryset
.
filter
(
is_finished
=
False
)
return
queryset
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'action'
:
_
(
'Proxy log online list'
),
}
kwargs
.
update
(
context
)
return
super
(
ProxyLogOnlineListView
,
self
)
.
get_context_data
(
**
kwargs
)
class
ProxyLogDetailView
(
AdminUserRequiredMixin
,
class
ProxyLogDetailView
(
AdminUserRequiredMixin
,
SingleObjectMixin
,
SingleObjectMixin
,
ListView
):
ListView
):
...
...
apps/common/utils.py
View file @
b60e5a7e
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#
#
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
collections
import
OrderedDict
from
six
import
string_types
from
six
import
string_types
import
base64
import
base64
import
os
import
os
...
@@ -53,6 +54,7 @@ def get_object_or_none(model, **kwargs):
...
@@ -53,6 +54,7 @@ def get_object_or_none(model, **kwargs):
class
Signer
(
object
):
class
Signer
(
object
):
"""用来加密,解密,和基于时间戳的方式验证token"""
def
__init__
(
self
,
secret_key
=
SECRET_KEY
):
def
__init__
(
self
,
secret_key
=
SECRET_KEY
):
self
.
secret_key
=
secret_key
self
.
secret_key
=
secret_key
...
@@ -330,13 +332,13 @@ def encrypt_password(password):
...
@@ -330,13 +332,13 @@ def encrypt_password(password):
return
None
return
None
from
collections
import
OrderedDict
def
capacity_convert
(
size
,
expect
=
'auto'
,
rate
=
1000
):
def
capacity_convert
(
size
,
expect
=
'auto'
,
rate
=
1000
):
"""
"""
:param
cap
: '100MB', '1G'
:param
size
: '100MB', '1G'
:param expect: 'K, M, G, T
:param expect: 'K, M, G, T
:param rate: Default 1000, may be 1024
:return:
:return:
"""
"""
rate_mapping
=
(
rate_mapping
=
(
...
...
apps/ops/ansible/inventory.py
View file @
b60e5a7e
...
@@ -21,16 +21,16 @@ class JMSHost(Host):
...
@@ -21,16 +21,16 @@ class JMSHost(Host):
# 添加密码和秘钥
# 添加密码和秘钥
if
asset
.
get
(
'password'
):
if
asset
.
get
(
'password'
):
self
.
set_variable
(
'ansible_ssh_pass'
,
asset
[
'password'
])
self
.
set_variable
(
'ansible_ssh_pass'
,
asset
[
'password'
])
if
asset
.
get
(
'key'
):
if
asset
.
get
(
'
private_
key'
):
self
.
set_variable
(
'ansible_ssh_private_key_file'
,
asset
[
'private_key'
])
self
.
set_variable
(
'ansible_ssh_private_key_file'
,
asset
[
'private_key'
])
# 添加become支持
# 添加become支持
become
=
asset
.
get
(
"become"
,
Non
e
)
become
=
asset
.
get
(
"become"
,
Fals
e
)
if
become
is
not
None
:
if
become
:
self
.
set_variable
(
"ansible_become"
,
True
)
self
.
set_variable
(
"ansible_become"
,
True
)
self
.
set_variable
(
"ansible_become_method"
,
become
.
get
(
'method'
))
self
.
set_variable
(
"ansible_become_method"
,
become
.
get
(
'method'
,
'sudo'
))
self
.
set_variable
(
"ansible_become_user"
,
become
.
get
(
'user'
))
self
.
set_variable
(
"ansible_become_user"
,
become
.
get
(
'user'
,
'root'
))
self
.
set_variable
(
"ansible_become_pass"
,
become
.
get
(
'pass'
))
self
.
set_variable
(
"ansible_become_pass"
,
become
.
get
(
'pass'
,
''
))
else
:
else
:
self
.
set_variable
(
"ansible_become"
,
False
)
self
.
set_variable
(
"ansible_become"
,
False
)
...
...
apps/ops/ansible/runner.py
View file @
b60e5a7e
...
@@ -265,8 +265,10 @@ class AdHocRunner(object):
...
@@ -265,8 +265,10 @@ class AdHocRunner(object):
result
[
'success'
]
.
append
(
host
)
result
[
'success'
]
.
append
(
host
)
for
host
,
msgs
in
self
.
results_callback
.
result_q
[
'dark'
]
.
items
():
for
host
,
msgs
in
self
.
results_callback
.
result_q
[
'dark'
]
.
items
():
msg
=
'
\n
'
.
join
([
'{}: {}'
.
format
(
msg
.
get
(
'invocation'
,
{})
.
get
(
'module_name'
),
msg
=
'
\n
'
.
join
([
'{} {}: {}'
.
format
(
msg
.
get
(
'msg'
,
''
))
for
msg
in
msgs
])
msg
.
get
(
'module_stdout'
,
''
),
msg
.
get
(
'invocation'
,
{})
.
get
(
'module_name'
),
msg
.
get
(
'msg'
,
''
))
for
msg
in
msgs
])
result
[
'failed'
]
.
append
((
host
,
msg
))
result
[
'failed'
]
.
append
((
host
,
msg
))
return
result
return
result
...
...
apps/ops/templates/ops/task_detail.html
View file @
b60e5a7e
...
@@ -68,7 +68,17 @@
...
@@ -68,7 +68,17 @@
</tr>
</tr>
<tr>
<tr>
<td>
{% trans 'Is success ' %}:
</td>
<td>
{% trans 'Is success ' %}:
</td>
{% if object.is_finished %}
<td><b>
{{ object.is_success|yesno:"Yes,No,Unkown" }}
</b></td>
<td><b>
{{ object.is_success|yesno:"Yes,No,Unkown" }}
</b></td>
{% else %}
<td>
<div
class=
"progress progress-striped active"
>
<div
style=
"width: 50%"
aria-valuemax=
"100"
aria-valuemin=
"0"
aria-valuenow=
"75"
role=
"progressbar"
class=
"progress-bar progress-bar-danger"
>
<span
class=
"sr-only"
>
40% Complete (success)
</span>
</div>
</div>
</td>
{% endif %}
</tr>
</tr>
<tr>
<tr>
<td>
{% trans 'Assets ' %}:
</td>
<td>
{% trans 'Assets ' %}:
</td>
...
@@ -84,6 +94,31 @@
...
@@ -84,6 +94,31 @@
</table>
</table>
</div>
</div>
</div>
</div>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<span><b>
Result
</b></span>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<ul
class=
"dropdown-menu dropdown-user"
>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<pre>
{{ object.result }}
</pre>
</div>
</div>
</div>
</div>
</div>
<div
class=
"col-sm-5"
style=
"padding-left: 0;padding-right: 0"
>
<div
class=
"col-sm-5"
style=
"padding-left: 0;padding-right: 0"
>
<div
class=
"panel panel-danger"
>
<div
class=
"panel panel-danger"
>
...
...
apps/ops/utils.py
View file @
b60e5a7e
...
@@ -18,7 +18,7 @@ logger = get_logger(__file__)
...
@@ -18,7 +18,7 @@ logger = get_logger(__file__)
def
run_AdHoc
(
task_tuple
,
assets
,
def
run_AdHoc
(
task_tuple
,
assets
,
task_name
=
'Ansible AdHoc runner'
,
task_name
=
'Ansible AdHoc runner'
,
task_id
=
None
,
pattern
=
'all'
,
task_id
=
None
,
pattern
=
'all'
,
record
=
True
,
verbose
=
Fals
e
):
record
=
True
,
verbose
=
Tru
e
):
"""
"""
:param task_tuple: (('module_name', 'module_args'), ('module_name', 'module_args'))
:param task_tuple: (('module_name', 'module_args'), ('module_name', 'module_args'))
:param assets: [asset1, asset2]
:param assets: [asset1, asset2]
...
@@ -51,6 +51,11 @@ def run_AdHoc(task_tuple, assets,
...
@@ -51,6 +51,11 @@ def run_AdHoc(task_tuple, assets,
else
:
else
:
record
=
Task
.
objects
.
get
(
uuid
=
task_id
)
record
=
Task
.
objects
.
get
(
uuid
=
task_id
)
record
.
date_start
=
timezone
.
now
()
record
.
date_start
=
timezone
.
now
()
record
.
date_finished
=
None
record
.
timedelta
=
None
record
.
is_finished
=
False
record
.
is_success
=
False
record
.
save
()
ts_start
=
time
.
time
()
ts_start
=
time
.
time
()
if
verbose
:
if
verbose
:
logger
.
debug
(
'Start runner {}'
.
format
(
task_name
))
logger
.
debug
(
'Start runner {}'
.
format
(
task_name
))
...
@@ -61,7 +66,7 @@ def run_AdHoc(task_tuple, assets,
...
@@ -61,7 +66,7 @@ def run_AdHoc(task_tuple, assets,
record
.
date_finished
=
timezone
.
now
()
record
.
date_finished
=
timezone
.
now
()
record
.
is_finished
=
True
record
.
is_finished
=
True
if
verbose
:
if
verbose
:
record
.
result
=
json
.
dumps
(
result
)
record
.
result
=
json
.
dumps
(
result
,
indent
=
4
,
sort_keys
=
True
)
record
.
summary
=
json
.
dumps
(
summary
)
record
.
summary
=
json
.
dumps
(
summary
)
record
.
timedelta
=
timedelta
record
.
timedelta
=
timedelta
if
len
(
summary
[
'failed'
])
==
0
:
if
len
(
summary
[
'failed'
])
==
0
:
...
...
apps/ops/views.py
View file @
b60e5a7e
# ~*~ coding: utf-8 ~*~
# ~*~ coding: utf-8 ~*~
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
import
time
import
json
import
json
from
datetime
import
datetime
from
datetime
import
datetime
...
@@ -81,4 +82,5 @@ class TaskRunView(View):
...
@@ -81,4 +82,5 @@ class TaskRunView(View):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
pk
=
kwargs
.
get
(
self
.
pk_url_kwarg
)
pk
=
kwargs
.
get
(
self
.
pk_url_kwarg
)
rerun_task
.
delay
(
pk
)
rerun_task
.
delay
(
pk
)
time
.
sleep
(
0.5
)
return
redirect
(
reverse
(
'ops:task-detail'
,
kwargs
=
{
'pk'
:
pk
}))
return
redirect
(
reverse
(
'ops:task-detail'
,
kwargs
=
{
'pk'
:
pk
}))
apps/perms/tasks.py
View file @
b60e5a7e
...
@@ -35,10 +35,10 @@ def push_users(self, assets, users):
...
@@ -35,10 +35,10 @@ def push_users(self, assets, users):
(
'authorized_key'
,
"user={} state=present key='{}'"
.
format
(
(
'authorized_key'
,
"user={} state=present key='{}'"
.
format
(
user
[
'username'
],
user
[
'public_key'
])),
user
[
'username'
],
user
[
'public_key'
])),
(
'lineinfile'
,
(
'lineinfile'
,
"
name=/etc/sudoers state=present regexp='^{0} ALL=(ALL)
' "
"
dest=/etc/sudoers state=present regexp='^{0} ALL=
' "
"line='{0} ALL=(ALL) NOPASSWD: {1}' "
"line='{0} ALL=(ALL) NOPASSWD: {1}' "
"validate='visudo -cf
%
s'"
.
format
(
"validate='visudo -cf
%
s'"
.
format
(
user
[
'username'
],
user
.
get
(
'sudo'
,
'/
bin/whoami
'
)
user
[
'username'
],
user
.
get
(
'sudo'
,
'/
sbin/ifconfig
'
)
))
))
])
])
task_name
=
'Push user {}'
.
format
(
','
.
join
([
user
[
'name'
]
for
user
in
users
]))
task_name
=
'Push user {}'
.
format
(
','
.
join
([
user
[
'name'
]
for
user
in
users
]))
...
...
apps/templates/_nav.html
View file @
b60e5a7e
...
@@ -56,8 +56,11 @@
...
@@ -56,8 +56,11 @@
<li
id=
"audits"
>
<li
id=
"audits"
>
<a
href=
"#"
><i
class=
"fa fa-files-o"
></i>
<span
class=
"nav-label"
>
{% trans 'Audits' %}
</span><span
class=
"fa arrow"
></span></a>
<a
href=
"#"
><i
class=
"fa fa-files-o"
></i>
<span
class=
"nav-label"
>
{% trans 'Audits' %}
</span><span
class=
"fa arrow"
></span></a>
<ul
class=
"nav nav-second-level"
>
<ul
class=
"nav nav-second-level"
>
<li
id=
"proxy-log"
>
<li
id=
"proxy-log-offline"
>
<a
href=
"{% url 'audits:proxy-log-list' %}"
>
{% trans 'Proxy log' %}
</a>
<a
href=
"{% url 'audits:proxy-log-offline-list' %}"
>
{% trans 'Session online' %}
</a>
</li>
<li
id=
"proxy-log-online"
>
<a
href=
"{% url 'audits:proxy-log-online-list' %}"
>
{% trans 'Session history' %}
</a>
</li>
</li>
<li
id=
"command-log"
>
<li
id=
"command-log"
>
<a
href=
"{% url 'audits:command-log-list' %}"
>
{% trans 'Command log' %}
</a>
<a
href=
"{% url 'audits:command-log-list' %}"
>
{% trans 'Command log' %}
</a>
...
...
tmp/.gitkeep
0 → 100644
View file @
b60e5a7e
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