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
e57121a7
Commit
e57121a7
authored
Dec 06, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Feature] 优化Ops ansible api
parent
ec8106e4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
336 additions
and
149 deletions
+336
-149
utils.py
apps/assets/utils.py
+5
-1
django.po
apps/locale/zh/LC_MESSAGES/django.po
+6
-6
callback.py
apps/ops/ansible/callback.py
+56
-45
exceptions.py
apps/ops/ansible/exceptions.py
+6
-0
inventory.py
apps/ops/ansible/inventory.py
+91
-55
runner.py
apps/ops/ansible/runner.py
+0
-0
test_inventory.py
apps/ops/ansible/test_inventory.py
+63
-0
test_runner.py
apps/ops/ansible/test_runner.py
+54
-0
api.py
apps/ops/api.py
+2
-2
models.py
apps/ops/models.py
+22
-21
serializers.py
apps/ops/serializers.py
+2
-2
tasks.py
apps/ops/tasks.py
+2
-2
utils.py
apps/ops/utils.py
+20
-8
views.py
apps/ops/views.py
+5
-5
_nav.html
apps/templates/_nav.html
+1
-1
models.py
apps/terminal/models.py
+1
-1
No files found.
apps/assets/utils.py
View file @
e57121a7
# ~*~ coding: utf-8 ~*~
# ~*~ coding: utf-8 ~*~
#
#
from
ops.utils
import
run_AdHoc
from
.models
import
Asset
def
test_admin_user_connective_manual
(
asset
):
def
test_admin_user_connective_manual
(
asset
):
from
ops.utils
import
run_AdHoc
if
not
isinstance
(
asset
,
list
):
if
not
isinstance
(
asset
,
list
):
asset
=
[
asset
]
asset
=
[
asset
]
task_tuple
=
(
task_tuple
=
(
...
@@ -15,3 +16,6 @@ def test_admin_user_connective_manual(asset):
...
@@ -15,3 +16,6 @@ def test_admin_user_connective_manual(asset):
else
:
else
:
return
True
return
True
def
get_assets_by_id_list
(
id_list
):
return
Asset
.
objects
.
filter
(
id__in
=
id_list
)
apps/locale/zh/LC_MESSAGES/django.po
View file @
e57121a7
...
@@ -1418,23 +1418,23 @@ msgid "Assets id"
...
@@ -1418,23 +1418,23 @@ msgid "Assets id"
msgstr "资产id"
msgstr "资产id"
#: ops/models.py:27
#: ops/models.py:27
msgid "
Tas
k module and args json format"
msgid "
Playboo
k module and args json format"
msgstr ""
msgstr ""
#: ops/models.py:28
#: ops/models.py:28
msgid "
Tas
k run pattern"
msgid "
Playboo
k run pattern"
msgstr ""
msgstr ""
#: ops/models.py:29
#: ops/models.py:29
msgid "
Tas
k raw result"
msgid "
Playboo
k raw result"
msgstr ""
msgstr ""
#: ops/models.py:30
#: ops/models.py:30
msgid "
Tas
k summary"
msgid "
Playboo
k summary"
msgstr ""
msgstr ""
#: ops/templates/ops/task_detail.html:19
#: ops/templates/ops/task_detail.html:19
msgid "
Tas
k replay detail"
msgid "
Playboo
k replay detail"
msgstr "任务记录详情"
msgstr "任务记录详情"
#: ops/templates/ops/task_detail.html:62
#: ops/templates/ops/task_detail.html:62
...
@@ -1669,7 +1669,7 @@ msgid "Job Center"
...
@@ -1669,7 +1669,7 @@ msgid "Job Center"
msgstr "作业中心"
msgstr "作业中心"
#: templates/_nav.html:51
#: templates/_nav.html:51
msgid "
Tas
k"
msgid "
Playboo
k"
msgstr "任务"
msgstr "任务"
#: templates/_nav.html:62
#: templates/_nav.html:62
...
...
apps/ops/ansible/callback.py
View file @
e57121a7
# ~*~ coding: utf-8 ~*~
# ~*~ coding: utf-8 ~*~
from
collections
import
defaultdict
from
ansible.plugins.callback
import
CallbackBase
from
ansible.plugins.callback
import
CallbackBase
class
CommandResultCallback
(
CallbackBase
):
def
__init__
(
self
,
display
=
None
):
self
.
result_q
=
dict
(
contacted
=
{},
dark
=
{})
super
(
CommandResultCallback
,
self
)
.
__init__
(
display
)
def
gather_result
(
self
,
n
,
res
):
self
.
result_q
[
n
][
res
.
_host
.
name
]
=
{}
self
.
result_q
[
n
][
res
.
_host
.
name
][
'cmd'
]
=
res
.
_result
.
get
(
'cmd'
)
self
.
result_q
[
n
][
res
.
_host
.
name
][
'stderr'
]
=
res
.
_result
.
get
(
'stderr'
)
self
.
result_q
[
n
][
res
.
_host
.
name
][
'stdout'
]
=
res
.
_result
.
get
(
'stdout'
)
self
.
result_q
[
n
][
res
.
_host
.
name
][
'rc'
]
=
res
.
_result
.
get
(
'rc'
)
def
v2_runner_on_ok
(
self
,
result
):
self
.
gather_result
(
"contacted"
,
result
)
def
v2_runner_on_failed
(
self
,
result
,
ignore_errors
=
False
):
self
.
gather_result
(
"dark"
,
result
)
def
v2_runner_on_unreachable
(
self
,
result
):
self
.
gather_result
(
"dark"
,
result
)
def
v2_runner_on_skipped
(
self
,
result
):
self
.
gather_result
(
"dark"
,
result
)
class
AdHocResultCallback
(
CallbackBase
):
class
AdHocResultCallback
(
CallbackBase
):
"""
"""
AdHoc result Callback
AdHoc result Callback
"""
"""
def
__init__
(
self
,
display
=
None
):
def
__init__
(
self
,
display
=
None
):
self
.
result_q
=
dict
(
contacted
=
{},
dark
=
{})
# result_raw example: {
super
(
AdHocResultCallback
,
self
)
.
__init__
(
display
)
# "ok": {"hostname": []},
# "failed": {"hostname": []},
def
gather_result
(
self
,
n
,
res
):
# "unreachable: {"hostname": []},
if
res
.
_host
.
name
in
self
.
result_q
[
n
]:
# "skipped": {"hostname": []},
self
.
result_q
[
n
][
res
.
_host
.
name
]
.
append
(
res
.
_result
)
# }
# results_summary example: {
# "contacted": {"hostname",...},
# "dark": {"hostname": ["error",...],},
# }
self
.
results_raw
=
dict
(
ok
=
{},
failed
=
{},
unreachable
=
{},
skipped
=
{})
self
.
results_summary
=
dict
(
contacted
=
set
(),
dark
=
{})
super
()
.
__init__
(
display
)
def
gather_result
(
self
,
t
,
host
,
res
):
if
self
.
results_raw
[
t
]
.
get
(
host
):
self
.
results_raw
[
t
][
host
]
.
append
(
res
)
else
:
self
.
results_raw
[
t
][
host
]
=
[
res
]
self
.
clean_result
(
t
,
host
,
res
)
def
clean_result
(
self
,
t
,
host
,
res
):
contacted
=
self
.
results_summary
[
"contacted"
]
dark
=
self
.
results_summary
[
"dark"
]
if
t
in
(
"ok"
,
"skipped"
)
and
host
not
in
dark
:
contacted
.
add
(
host
)
else
:
else
:
self
.
result_q
[
n
][
res
.
_host
.
name
]
=
[
res
.
_result
]
dark
[
host
]
.
append
(
res
)
if
host
in
contacted
:
contacted
.
remove
(
dark
)
def
v2_runner_on_ok
(
self
,
result
):
def
runner_on_ok
(
self
,
host
,
res
):
self
.
gather_result
(
"
contacted"
,
result
)
self
.
gather_result
(
"
ok"
,
host
,
res
)
def
v2_runner_on_failed
(
self
,
result
,
ignore_errors
=
False
):
def
runner_on_failed
(
self
,
host
,
res
,
ignore_errors
=
False
):
self
.
gather_result
(
"
dark"
,
result
)
self
.
gather_result
(
"
failed"
,
host
,
res
)
def
v2_runner_on_unreachable
(
self
,
result
):
def
runner_on_unreachable
(
self
,
host
,
res
):
self
.
gather_result
(
"
dark"
,
result
)
self
.
gather_result
(
"
unreachable"
,
host
,
res
)
def
v2_runner_on_skipped
(
self
,
result
):
def
runner_on_skipped
(
self
,
host
,
item
=
None
):
self
.
gather_result
(
"
dark"
,
result
)
self
.
gather_result
(
"
skipped"
,
host
,
item
)
def
v2_playbook_on_task_start
(
self
,
task
,
is_conditional
):
pass
def
v2_playbook_on_play_start
(
self
,
play
):
class
CommandResultCallback
(
AdHocResultCallback
):
pass
def
__init__
(
self
,
display
=
None
):
self
.
results_command
=
dict
()
super
()
.
__init__
(
display
)
def
gather_result
(
self
,
t
,
host
,
res
):
super
()
.
gather_result
(
t
,
host
,
res
)
self
.
gather_cmd
(
t
,
host
,
res
)
def
gather_cmd
(
self
,
t
,
host
,
res
):
cmd
=
{}
if
t
==
"ok"
:
cmd
[
'cmd'
]
=
res
.
get
(
'cmd'
)
cmd
[
'stderr'
]
=
res
.
get
(
'stderr'
)
cmd
[
'stdout'
]
=
res
.
get
(
'stdout'
)
cmd
[
'rc'
]
=
res
.
get
(
'rc'
)
else
:
cmd
[
'err'
]
=
"Error: {}"
.
format
(
res
)
self
.
results_command
[
host
]
=
cmd
class
PlaybookResultCallBack
(
CallbackBase
):
class
PlaybookResultCallBack
(
CallbackBase
):
...
...
apps/ops/ansible/exceptions.py
0 → 100644
View file @
e57121a7
# -*- coding: utf-8 -*-
#
class
AnsibleError
(
Exception
):
pass
apps/ops/ansible/inventory.py
View file @
e57121a7
# ~*~ coding: utf-8 ~*~
# ~*~ coding: utf-8 ~*~
from
ansible.inventory
import
Inventory
,
Host
,
Group
from
ansible.inventory.group
import
Group
from
ansible.vars
import
VariableManager
from
ansible.inventory.host
import
Host
from
ansible.vars.manager
import
VariableManager
from
ansible.inventory.manager
import
InventoryManager
from
ansible.parsing.dataloader
import
DataLoader
from
ansible.parsing.dataloader
import
DataLoader
class
JMSHost
(
Host
):
class
JMSHost
(
Host
):
def
__init__
(
self
,
asset
):
def
__init__
(
self
,
host_data
):
self
.
asset
=
asset
"""
self
.
name
=
name
=
asset
.
get
(
'hostname'
)
or
asset
.
get
(
'ip'
)
初始化
self
.
port
=
port
=
asset
.
get
(
'port'
)
or
22
:param host_data: {
super
(
JMSHost
,
self
)
.
__init__
(
name
,
port
)
"hostname": "",
self
.
set_all_variable
()
"ip": "",
"port": "",
"username": "",
"password": "",
"private_key": "",
"become": {
"method": "",
"user": "",
"pass": "",
}
"groups": [],
"vars": {},
}
"""
self
.
host_data
=
host_data
hostname
=
host_data
.
get
(
'hostname'
)
or
host_data
.
get
(
'ip'
)
port
=
host_data
.
get
(
'port'
)
or
22
super
(
JMSHost
,
self
)
.
__init__
(
hostname
,
port
)
self
.
__set_required_variables
()
self
.
__set_extra_variables
()
def
set_all_variable
(
self
):
def
__set_required_variables
(
self
):
asset
=
self
.
asset
host_data
=
self
.
host_data
self
.
set_variable
(
'ansible_host'
,
asset
[
'ip'
])
self
.
set_variable
(
'ansible_host'
,
host_data
[
'ip'
])
self
.
set_variable
(
'ansible_port'
,
asset
[
'port'
])
self
.
set_variable
(
'ansible_port'
,
host_data
[
'port'
])
self
.
set_variable
(
'ansible_user'
,
asset
[
'username'
])
self
.
set_variable
(
'ansible_user'
,
host_data
[
'username'
])
# 添加密码和秘钥
# 添加密码和秘钥
if
asset
.
get
(
'password'
):
if
host_data
.
get
(
'password'
):
self
.
set_variable
(
'ansible_ssh_pass'
,
asset
[
'password'
])
self
.
set_variable
(
'ansible_ssh_pass'
,
host_data
[
'password'
])
if
asset
.
get
(
'private_key'
):
if
host_data
.
get
(
'private_key'
):
self
.
set_variable
(
'ansible_ssh_private_key_file'
,
asset
[
'private_key'
])
self
.
set_variable
(
'ansible_ssh_private_key_file'
,
host_data
[
'private_key'
])
# 添加become支持
# 添加become支持
become
=
asset
.
get
(
"become"
,
False
)
become
=
host_data
.
get
(
"become"
,
False
)
if
become
:
if
become
:
self
.
set_variable
(
"ansible_become"
,
True
)
self
.
set_variable
(
"ansible_become"
,
True
)
self
.
set_variable
(
"ansible_become_method"
,
become
.
get
(
'method'
,
'sudo'
))
self
.
set_variable
(
"ansible_become_method"
,
become
.
get
(
'method'
,
'sudo'
))
...
@@ -34,58 +55,73 @@ class JMSHost(Host):
...
@@ -34,58 +55,73 @@ class JMSHost(Host):
else
:
else
:
self
.
set_variable
(
"ansible_become"
,
False
)
self
.
set_variable
(
"ansible_become"
,
False
)
def
__set_extra_variables
(
self
):
for
k
,
v
in
self
.
host_data
.
get
(
'vars'
,
{})
.
items
():
self
.
set_variable
(
k
,
v
)
def
__repr__
(
self
):
return
self
.
name
class
JMSInventory
(
Inventory
):
class
JMSInventory
(
InventoryManager
):
"""
"""
提供生成Ansible inventory对象的方法
提供生成Ansible inventory对象的方法
"""
"""
loader_class
=
DataLoader
variable_manager_class
=
VariableManager
host_manager_class
=
JMSHost
def
__init__
(
self
,
host_list
=
None
):
def
__init__
(
self
,
host_list
=
None
):
if
host_list
is
None
:
if
host_list
is
None
:
host_list
=
[]
host_list
=
[]
assert
isinstance
(
host_list
,
list
)
self
.
host_list
=
host_list
self
.
host_list
=
host_list
self
.
loader
=
DataLoader
(
)
assert
isinstance
(
host_list
,
list
)
self
.
variable_manager
=
VariableManager
()
self
.
loader
=
self
.
loader_class
()
s
uper
(
JMSInventory
,
self
)
.
__init__
(
self
.
loader
,
self
.
variable_manager
,
s
elf
.
variable_manager
=
self
.
variable_manager_class
()
host_list
=
host_list
)
super
()
.
__init__
(
self
.
loader
)
def
parse_inventory
(
self
,
host_list
):
def
get_groups
(
self
):
"""用于生成动态构建Ansible Inventory.
return
self
.
_inventory
.
groups
self.host_list: [
{"name": "asset_name",
def
get_group
(
self
,
name
):
"ip": <ip>,
return
self
.
_inventory
.
groups
.
get
(
name
,
None
)
"port": <port>,
"user": <user>,
"pass": <pass>,
"key": <sshKey>,
"groups": ['group1', 'group2'],
"other_host_var": <other>},
{...},
]
:return: 返回一个Ansible的inventory对象
def
parse_sources
(
self
,
cache
=
False
):
"""
"""
用于生成动态构建Ansible Inventory. super().__init__ 会自动调用
host_list: [{
"hostname": "",
"ip": "",
"port": "",
"username": "",
"password": "",
"private_key": "",
"become": {
"method": "",
"user": "",
"pass": "",
},
"groups": [],
"vars": {},
},
]
# TODO: 验证输入
:return: None
# 创建Ansible Group,如果没有则创建default组
"""
ungrouped
=
Group
(
'ungrouped'
)
group_all
=
self
.
get_group
(
'all'
)
all
=
Group
(
'all'
)
ungrouped
=
self
.
get_group
(
'ungrouped'
)
all
.
add_child_group
(
ungrouped
)
self
.
groups
=
dict
(
all
=
all
,
ungrouped
=
ungrouped
)
for
asset
in
host_list
:
for
host_data
in
self
.
host_list
:
host
=
JMSHost
(
asset
=
asset
)
host
=
self
.
host_manager_class
(
host_data
=
host_data
)
asset_groups
=
asset
.
get
(
'groups'
)
self
.
hosts
[
host_data
[
'hostname'
]]
=
host
if
asset_groups
:
groups_data
=
host_data
.
get
(
'groups'
)
for
group_name
in
asset_groups
:
if
groups_data
:
if
group_name
not
in
self
.
groups
:
for
group_name
in
groups_data
:
group
=
self
.
get_group
(
group_name
)
if
group
is
None
:
group
=
Group
(
group_name
)
group
=
Group
(
group_name
)
self
.
groups
[
group_name
]
=
group
self
.
add_group
(
group
)
else
:
group
=
self
.
groups
[
group_name
]
group
.
add_host
(
host
)
group
.
add_host
(
host
)
else
:
else
:
ungrouped
.
add_host
(
host
)
ungrouped
.
add_host
(
host
)
all
.
add_host
(
host
)
group_all
.
add_host
(
host
)
apps/ops/ansible/runner.py
View file @
e57121a7
This diff is collapsed.
Click to expand it.
apps/ops/ansible/test_inventory.py
0 → 100644
View file @
e57121a7
# -*- coding: utf-8 -*-
#
import
sys
import
unittest
sys
.
path
.
insert
(
0
,
'../..'
)
from
ops.ansible.inventory
import
JMSInventory
class
TestJMSInventory
(
unittest
.
TestCase
):
def
setUp
(
self
):
host_list
=
[{
"hostname"
:
"testserver1"
,
"ip"
:
"102.1.1.1"
,
"port"
:
22
,
"username"
:
"root"
,
"password"
:
"password"
,
"private_key"
:
"/tmp/private_key"
,
"become"
:
{
"method"
:
"sudo"
,
"user"
:
"root"
,
"pass"
:
None
,
},
"groups"
:
[
"group1"
,
"group2"
],
"vars"
:
{
"sexy"
:
"yes"
},
},
{
"hostname"
:
"testserver2"
,
"ip"
:
"8.8.8.8"
,
"port"
:
2222
,
"username"
:
"root"
,
"password"
:
"password"
,
"private_key"
:
"/tmp/private_key"
,
"become"
:
{
"method"
:
"su"
,
"user"
:
"root"
,
"pass"
:
"123"
,
},
"groups"
:
[
"group3"
,
"group4"
],
"vars"
:
{
"love"
:
"yes"
},
}]
self
.
inventory
=
JMSInventory
(
host_list
=
host_list
)
def
test_hosts
(
self
):
print
(
"#"
*
10
+
"Hosts"
+
"#"
*
10
)
for
host
in
self
.
inventory
.
hosts
:
print
(
host
)
def
test_groups
(
self
):
print
(
"#"
*
10
+
"Groups"
+
"#"
*
10
)
for
group
in
self
.
inventory
.
groups
:
print
(
group
)
def
test_group_all
(
self
):
print
(
"#"
*
10
+
"all group hosts"
+
"#"
*
10
)
group
=
self
.
inventory
.
get_group
(
'all'
)
print
(
group
.
hosts
)
if
__name__
==
'__main__'
:
unittest
.
main
()
apps/ops/ansible/test_runner.py
0 → 100644
View file @
e57121a7
# -*- coding: utf-8 -*-
#
import
unittest
import
sys
sys
.
path
.
insert
(
0
,
"../.."
)
from
ops.ansible.runner
import
AdHocRunner
,
CommandRunner
class
TestAdHocRunner
(
unittest
.
TestCase
):
def
setUp
(
self
):
host_data
=
[
{
"hostname"
:
"testserver"
,
"ip"
:
"192.168.244.168"
,
"port"
:
22
,
"username"
:
"root"
,
"password"
:
"redhat"
,
},
]
self
.
runner
=
AdHocRunner
(
hosts
=
host_data
)
def
test_run
(
self
):
tasks
=
[
{
"action"
:
{
"module"
:
"shell"
,
"args"
:
"ls"
}},
{
"action"
:
{
"module"
:
"shell"
,
"args"
:
"whoami"
}},
]
ret
=
self
.
runner
.
run
(
tasks
,
"all"
)
print
(
ret
.
results_summary
)
print
(
ret
.
results_raw
)
class
TestCommandRunner
(
unittest
.
TestCase
):
def
setUp
(
self
):
host_data
=
[
{
"hostname"
:
"testserver"
,
"ip"
:
"192.168.244.168"
,
"port"
:
22
,
"username"
:
"root"
,
"password"
:
"redhat"
,
},
]
self
.
runner
=
CommandRunner
(
hosts
=
host_data
)
def
test_execute
(
self
):
res
=
self
.
runner
.
execute
(
'ls'
,
'all'
)
print
(
res
.
results_command
)
if
__name__
==
"__main__"
:
unittest
.
main
()
apps/ops/api.py
View file @
e57121a7
...
@@ -4,12 +4,12 @@
...
@@ -4,12 +4,12 @@
from
rest_framework
import
viewsets
from
rest_framework
import
viewsets
from
.hands
import
IsSuperUser
from
.hands
import
IsSuperUser
from
.models
import
Tas
k
from
.models
import
Playboo
k
from
.serializers
import
TaskSerializer
from
.serializers
import
TaskSerializer
class
TaskViewSet
(
viewsets
.
ModelViewSet
):
class
TaskViewSet
(
viewsets
.
ModelViewSet
):
queryset
=
Tas
k
.
objects
.
all
()
queryset
=
Playboo
k
.
objects
.
all
()
serializer_class
=
TaskSerializer
serializer_class
=
TaskSerializer
permission_classes
=
(
IsSuperUser
,)
permission_classes
=
(
IsSuperUser
,)
apps/ops/models.py
View file @
e57121a7
...
@@ -7,40 +7,32 @@ import uuid
...
@@ -7,40 +7,32 @@ import uuid
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
assets.models
import
Asset
__all__
=
[
"
Tas
k"
]
__all__
=
[
"
Playboo
k"
]
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
class
Task
(
models
.
Model
):
class
AdHoc
(
models
.
Model
):
uuid
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
uuid
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Name'
))
name
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Name'
))
date_start
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Start time'
))
tasks
=
models
.
TextField
(
verbose_name
=
_
(
'Tasks'
))
# [{'name': 'task_name', 'module': '', 'args': ''}, ]
date_finished
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'End time'
))
hosts
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Hosts'
))
# Asset inventory may be change
timedelta
=
models
.
FloatField
(
default
=
0.0
,
verbose_name
=
_
(
'Time'
),
null
=
True
)
pattern
=
models
.
CharField
(
max_length
=
64
,
default
=
'all'
,
verbose_name
=
_
(
'Playbook run pattern'
))
is_finished
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is finished'
))
is_success
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is success'
))
assets
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Assets id'
))
# Asset inventory may be change
_modules_args
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Task module and args json format'
))
pattern
=
models
.
CharField
(
max_length
=
64
,
default
=
'all'
,
verbose_name
=
_
(
'Task run pattern'
))
result
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Task raw result'
))
summary
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Task summary'
))
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
"
%
s"
%
self
.
uuid
return
"
%
s"
%
self
.
name
@property
def
get_hosts_mapped_assets
(
self
):
def
total_assets
(
self
):
from
assets.utils
import
get_assets_by_id_list
assets_id
=
[
i
for
i
in
self
.
assets
.
split
(
','
)
if
i
.
isdigit
(
)]
assets_id
=
[
i
for
i
in
self
.
hosts
.
split
(
','
)]
assets
=
Asset
.
objects
.
filter
(
id__in
=
assets_id
)
assets
=
get_assets_by_id_list
(
assets_id
)
return
assets
return
assets
@property
@property
def
assets_json
(
self
):
def
inventory
(
self
):
return
[
asset
.
_to_secret_json
()
for
asset
in
self
.
total_assets
]
return
[
asset
.
_to_secret_json
()
for
asset
in
self
.
get_hosts_mapped_assets
()
]
@property
@property
def
module_args
(
self
):
def
module_args
(
self
):
...
@@ -57,3 +49,12 @@ class Task(models.Model):
...
@@ -57,3 +49,12 @@ class Task(models.Model):
self
.
_modules_args
=
json
.
dumps
(
module_args_
)
self
.
_modules_args
=
json
.
dumps
(
module_args_
)
class
History
(
models
.
Model
):
uuid
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
date_start
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Start time'
))
date_finished
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'End time'
))
timedelta
=
models
.
FloatField
(
default
=
0.0
,
verbose_name
=
_
(
'Time'
),
null
=
True
)
is_finished
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is finished'
))
is_success
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is success'
))
result
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Playbook raw result'
))
summary
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Playbook summary'
))
apps/ops/serializers.py
View file @
e57121a7
...
@@ -2,12 +2,12 @@
...
@@ -2,12 +2,12 @@
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
.models
import
Tas
k
from
.models
import
Playboo
k
class
TaskSerializer
(
serializers
.
ModelSerializer
):
class
TaskSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
class
Meta
:
model
=
Tas
k
model
=
Playboo
k
fields
=
'__all__'
fields
=
'__all__'
apps/ops/tasks.py
View file @
e57121a7
...
@@ -12,8 +12,8 @@ logger = get_logger(__file__)
...
@@ -12,8 +12,8 @@ logger = get_logger(__file__)
@shared_task
@shared_task
def
rerun_task
(
task_id
):
def
rerun_task
(
task_id
):
from
.models
import
Tas
k
from
.models
import
Playboo
k
record
=
Tas
k
.
objects
.
get
(
uuid
=
task_id
)
record
=
Playboo
k
.
objects
.
get
(
uuid
=
task_id
)
assets
=
record
.
assets_json
assets
=
record
.
assets_json
task_tuple
=
record
.
module_args
task_tuple
=
record
.
module_args
pattern
=
record
.
pattern
pattern
=
record
.
pattern
...
...
apps/ops/utils.py
View file @
e57121a7
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
from
__future__
import
absolute_import
,
unicode_literals
from
__future__
import
absolute_import
,
unicode_literals
import
json
import
json
import
re
import
time
import
time
import
uuid
import
uuid
...
@@ -41,16 +42,16 @@ def run_AdHoc(task_tuple, assets,
...
@@ -41,16 +42,16 @@ def run_AdHoc(task_tuple, assets,
runner
=
AdHocRunner
(
assets
)
runner
=
AdHocRunner
(
assets
)
if
record
:
if
record
:
from
.models
import
Tas
k
from
.models
import
Playboo
k
if
not
Tas
k
.
objects
.
filter
(
uuid
=
task_id
):
if
not
Playboo
k
.
objects
.
filter
(
uuid
=
task_id
):
record
=
Tas
k
(
uuid
=
task_id
,
record
=
Playboo
k
(
uuid
=
task_id
,
name
=
task_name
,
name
=
task_name
,
assets
=
','
.
join
(
str
(
asset
[
'id'
])
for
asset
in
assets
),
assets
=
','
.
join
(
str
(
asset
[
'id'
])
for
asset
in
assets
),
module_args
=
task_tuple
,
module_args
=
task_tuple
,
pattern
=
pattern
)
pattern
=
pattern
)
record
.
save
()
record
.
save
()
else
:
else
:
record
=
Tas
k
.
objects
.
get
(
uuid
=
task_id
)
record
=
Playboo
k
.
objects
.
get
(
uuid
=
task_id
)
record
.
date_start
=
timezone
.
now
()
record
.
date_start
=
timezone
.
now
()
record
.
date_finished
=
None
record
.
date_finished
=
None
record
.
timedelta
=
None
record
.
timedelta
=
None
...
@@ -76,3 +77,14 @@ def run_AdHoc(task_tuple, assets,
...
@@ -76,3 +77,14 @@ def run_AdHoc(task_tuple, assets,
record
.
is_success
=
False
record
.
is_success
=
False
record
.
save
()
record
.
save
()
return
summary
,
result
return
summary
,
result
UUID_PATTERN
=
re
.
compile
(
r'[0-9a-zA-Z\-]{36}'
)
def
is_uuid
(
s
):
if
UUID_PATTERN
.
match
(
s
):
return
True
else
:
return
False
apps/ops/views.py
View file @
e57121a7
...
@@ -9,13 +9,13 @@ from django.views.generic import ListView, DetailView, View
...
@@ -9,13 +9,13 @@ from django.views.generic import ListView, DetailView, View
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.shortcuts
import
redirect
,
reverse
from
django.shortcuts
import
redirect
,
reverse
from
.models
import
Tas
k
from
.models
import
Playboo
k
from
ops.tasks
import
rerun_task
from
ops.tasks
import
rerun_task
class
TaskListView
(
ListView
):
class
TaskListView
(
ListView
):
paginate_by
=
settings
.
CONFIG
.
DISPLAY_PER_PAGE
paginate_by
=
settings
.
CONFIG
.
DISPLAY_PER_PAGE
model
=
Tas
k
model
=
Playboo
k
ordering
=
(
'-date_start'
,)
ordering
=
(
'-date_start'
,)
context_object_name
=
'task_list'
context_object_name
=
'task_list'
template_name
=
'ops/task_list.html'
template_name
=
'ops/task_list.html'
...
@@ -53,7 +53,7 @@ class TaskListView(ListView):
...
@@ -53,7 +53,7 @@ class TaskListView(ListView):
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
context
=
{
'app'
:
'Ops'
,
'app'
:
'Ops'
,
'action'
:
'
Tas
k record list'
,
'action'
:
'
Playboo
k record list'
,
'date_from'
:
self
.
date_from_s
,
'date_from'
:
self
.
date_from_s
,
'date_to'
:
self
.
date_to_s
,
'date_to'
:
self
.
date_to_s
,
'keyword'
:
self
.
keyword
,
'keyword'
:
self
.
keyword
,
...
@@ -63,13 +63,13 @@ class TaskListView(ListView):
...
@@ -63,13 +63,13 @@ class TaskListView(ListView):
class
TaskDetailView
(
DetailView
):
class
TaskDetailView
(
DetailView
):
model
=
Tas
k
model
=
Playboo
k
template_name
=
'ops/task_detail.html'
template_name
=
'ops/task_detail.html'
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
context
=
{
'app'
:
'Ops'
,
'app'
:
'Ops'
,
'action'
:
'
Tas
k record detail'
,
'action'
:
'
Playboo
k record detail'
,
'results'
:
json
.
loads
(
self
.
object
.
summary
or
'{}'
),
'results'
:
json
.
loads
(
self
.
object
.
summary
or
'{}'
),
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
...
...
apps/templates/_nav.html
View file @
e57121a7
...
@@ -52,7 +52,7 @@
...
@@ -52,7 +52,7 @@
<i
class=
"fa fa-coffee"
></i>
<span
class=
"nav-label"
>
{% trans 'Job Center' %}
</span><span
class=
"fa arrow"
></span>
<i
class=
"fa fa-coffee"
></i>
<span
class=
"nav-label"
>
{% trans 'Job Center' %}
</span><span
class=
"fa arrow"
></span>
</a>
</a>
<ul
class=
"nav nav-second-level"
>
<ul
class=
"nav nav-second-level"
>
<li
id=
"task"
><a
href=
"{% url 'ops:task-list' %}"
>
{% trans '
Tas
k' %}
</a></li>
<li
id=
"task"
><a
href=
"{% url 'ops:task-list' %}"
>
{% trans '
Playboo
k' %}
</a></li>
</ul>
</ul>
</li>
</li>
...
...
apps/terminal/models.py
View file @
e57121a7
...
@@ -113,7 +113,7 @@ class Task(models.Model):
...
@@ -113,7 +113,7 @@ 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
,
choices
=
NAME_CHOICES
,
verbose_name
=
_
(
"Name"
))
name
=
models
.
CharField
(
max_length
=
128
,
choices
=
NAME_CHOICES
,
verbose_name
=
_
(
"Name"
))
args
=
models
.
CharField
(
max_length
=
1024
,
verbose_name
=
_
(
"
Tas
k Args"
))
args
=
models
.
CharField
(
max_length
=
1024
,
verbose_name
=
_
(
"
Playboo
k Args"
))
terminal
=
models
.
ForeignKey
(
Terminal
,
null
=
True
,
on_delete
=
models
.
CASCADE
)
terminal
=
models
.
ForeignKey
(
Terminal
,
null
=
True
,
on_delete
=
models
.
CASCADE
)
is_finished
=
models
.
BooleanField
(
default
=
False
)
is_finished
=
models
.
BooleanField
(
default
=
False
)
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
date_created
=
models
.
DateTimeField
(
auto_now_add
=
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