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
2b3551f1
Commit
2b3551f1
authored
Dec 07, 2017
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Feature] 修改ansible和ops
parent
e57121a7
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
228 additions
and
192 deletions
+228
-192
asset.py
apps/assets/models/asset.py
+19
-24
user.py
apps/assets/models/user.py
+36
-33
utils.py
apps/assets/utils.py
+29
-0
exceptions.py
apps/common/exceptions.py
+3
-0
callback.py
apps/ops/ansible/callback.py
+47
-27
runner.py
apps/ops/ansible/runner.py
+4
-0
test_runner.py
apps/ops/ansible/test_runner.py
+3
-2
api.py
apps/ops/api.py
+2
-2
models.py
apps/ops/models.py
+53
-26
serializers.py
apps/ops/serializers.py
+2
-2
utils.py
apps/ops/utils.py
+11
-0
views.py
apps/ops/views.py
+3
-3
utils.py
apps/perms/utils.py
+16
-73
No files found.
apps/assets/models/asset.py
View file @
2b3551f1
...
@@ -44,28 +44,18 @@ class Asset(models.Model):
...
@@ -44,28 +44,18 @@ class Asset(models.Model):
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
verbose_name
=
_
(
'IP'
),
db_index
=
True
)
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Hostname'
))
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Hostname'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
port
=
models
.
IntegerField
(
default
=
22
,
verbose_name
=
_
(
'Port'
))
groups
=
models
.
ManyToManyField
(
AssetGroup
,
blank
=
True
,
related_name
=
'assets'
,
groups
=
models
.
ManyToManyField
(
AssetGroup
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
'Asset groups'
))
verbose_name
=
_
(
'Asset groups'
))
admin_user
=
models
.
ForeignKey
(
AdminUser
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
"Admin user"
))
admin_user
=
models
.
ForeignKey
(
AdminUser
,
null
=
True
,
blank
=
True
,
related_name
=
'assets'
,
system_users
=
models
.
ManyToManyField
(
SystemUser
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"System User"
))
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
"Admin user"
))
idc
=
models
.
ForeignKey
(
IDC
,
blank
=
True
,
null
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
'IDC'
),)
system_users
=
models
.
ManyToManyField
(
SystemUser
,
blank
=
True
,
related_name
=
'assets'
,
verbose_name
=
_
(
"System User"
))
idc
=
models
.
ForeignKey
(
IDC
,
blank
=
True
,
null
=
True
,
related_name
=
'assets'
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
'IDC'
),)
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
type
=
models
.
CharField
(
choices
=
TYPE_CHOICES
,
max_length
=
16
,
blank
=
True
,
null
=
True
,
type
=
models
.
CharField
(
choices
=
TYPE_CHOICES
,
max_length
=
16
,
blank
=
True
,
null
=
True
,
default
=
'Server'
,
verbose_name
=
_
(
'Asset type'
),)
default
=
'Server'
,
verbose_name
=
_
(
'Asset type'
),)
env
=
models
.
CharField
(
choices
=
ENV_CHOICES
,
max_length
=
8
,
blank
=
True
,
null
=
True
,
default
=
'Prod'
,
verbose_name
=
_
(
'Asset environment'
),)
env
=
models
.
CharField
(
choices
=
ENV_CHOICES
,
max_length
=
8
,
blank
=
True
,
null
=
True
,
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
12
,
null
=
True
,
blank
=
True
,
default
=
'In use'
,
verbose_name
=
_
(
'Asset status'
))
default
=
'Prod'
,
verbose_name
=
_
(
'Asset environment'
),)
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
12
,
null
=
True
,
blank
=
True
,
default
=
'In use'
,
verbose_name
=
_
(
'Asset status'
))
# Some information
# Some information
public_ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
blank
=
True
,
public_ip
=
models
.
GenericIPAddressField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Public IP'
))
null
=
True
,
verbose_name
=
_
(
'Public IP'
))
remote_card_ip
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Remote control card IP'
))
remote_card_ip
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Remote control card IP'
))
cabinet_no
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet number'
))
cabinet_no
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet number'
))
cabinet_pos
=
models
.
IntegerField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet position'
))
cabinet_pos
=
models
.
IntegerField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet position'
))
number
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Asset number'
))
number
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Asset number'
))
...
@@ -114,21 +104,26 @@ class Asset(models.Model):
...
@@ -114,21 +104,26 @@ class Asset(models.Model):
def
_to_secret_json
(
self
):
def
_to_secret_json
(
self
):
"""Ansible use it create inventory"""
"""Ansible use it create inventory"""
return
{
data
=
{
'id'
:
self
.
id
,
'id'
:
self
.
id
,
'hostname'
:
self
.
hostname
,
'hostname'
:
self
.
hostname
,
'ip'
:
self
.
ip
,
'ip'
:
self
.
ip
,
'port'
:
self
.
port
,
'port'
:
self
.
port
,
'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
''
,
}
'password'
:
self
.
admin_user
.
password
if
self
.
admin_user
else
''
,
'private_key'
:
self
.
admin_user
.
private_key_file
if
self
.
admin_user
else
None
,
if
self
.
admin_user
:
data
.
update
({
'username'
:
self
.
admin_user
.
username
,
'password'
:
self
.
admin_user
.
password
,
'private_key'
:
self
.
admin_user
.
private_key_file
,
'become'
:
{
'become'
:
{
'method'
:
self
.
admin_user
.
become_method
,
'method'
:
self
.
admin_user
.
become_method
,
'user'
:
self
.
admin_user
.
become_user
,
'user'
:
self
.
admin_user
.
become_user
,
'pass'
:
self
.
admin_user
.
become_pass
,
'pass'
:
self
.
admin_user
.
become_pass
,
}
if
self
.
admin_user
and
self
.
admin_user
.
become
else
{},
}
}
})
return
data
class
Meta
:
class
Meta
:
unique_together
=
(
'ip'
,
'port'
)
unique_together
=
(
'ip'
,
'port'
)
...
...
apps/assets/models/user.py
View file @
2b3551f1
...
@@ -28,6 +28,9 @@ def private_key_validator(value):
...
@@ -28,6 +28,9 @@ def private_key_validator(value):
class
AdminUser
(
models
.
Model
):
class
AdminUser
(
models
.
Model
):
"""
Ansible use admin user as devops user to run adHoc and Playbook
"""
BECOME_METHOD_CHOICES
=
(
BECOME_METHOD_CHOICES
=
(
(
'sudo'
,
'sudo'
),
(
'sudo'
,
'sudo'
),
(
'su'
,
'su'
),
(
'su'
,
'su'
),
...
@@ -35,24 +38,19 @@ class AdminUser(models.Model):
...
@@ -35,24 +38,19 @@ class AdminUser(models.Model):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
username
=
models
.
CharField
(
max_length
=
16
,
verbose_name
=
_
(
'Username'
))
username
=
models
.
CharField
(
max_length
=
16
,
verbose_name
=
_
(
'Username'
))
_password
=
models
.
CharField
(
_password
=
models
.
CharField
(
max_length
=
256
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Password'
))
max_length
=
256
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Password'
))
_private_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'SSH private key'
),
validators
=
[
private_key_validator
,])
_private_key
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'SSH private key'
),
validators
=
[
private_key_validator
,])
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
=
models
.
CharField
(
default
=
''
,
max_length
=
128
)
become_pass
=
models
.
CharField
(
default
=
''
,
max_length
=
128
)
_public_key
=
models
.
TextField
(
_public_key
=
models
.
TextField
(
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'
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
)
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
,
null
=
True
)
created_by
=
models
.
CharField
(
created_by
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
verbose_name
=
_
(
'Created by'
))
max_length
=
32
,
null
=
True
,
verbose_name
=
_
(
'Created by'
))
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
self
.
name
return
self
.
name
__str__
=
__unicode__
@property
@property
def
password
(
self
):
def
password
(
self
):
...
@@ -134,33 +132,22 @@ class SystemUser(models.Model):
...
@@ -134,33 +132,22 @@ class SystemUser(models.Model):
(
'K'
,
'Public key'
),
(
'K'
,
'Public key'
),
)
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
verbose_name
=
_
(
'Name'
))
username
=
models
.
CharField
(
max_length
=
16
,
verbose_name
=
_
(
'Username'
))
username
=
models
.
CharField
(
max_length
=
16
,
verbose_name
=
_
(
'Username'
))
_password
=
models
.
CharField
(
_password
=
models
.
CharField
(
max_length
=
256
,
blank
=
True
,
verbose_name
=
_
(
'Password'
))
max_length
=
256
,
blank
=
True
,
verbose_name
=
_
(
'Password'
))
protocol
=
models
.
CharField
(
max_length
=
16
,
choices
=
PROTOCOL_CHOICES
,
default
=
'ssh'
,
verbose_name
=
_
(
'Protocol'
))
protocol
=
models
.
CharField
(
_private_key
=
models
.
TextField
(
max_length
=
8192
,
blank
=
True
,
verbose_name
=
_
(
'SSH private key'
))
max_length
=
16
,
choices
=
PROTOCOL_CHOICES
,
default
=
'ssh'
,
verbose_name
=
_
(
'Protocol'
))
_public_key
=
models
.
TextField
(
max_length
=
8192
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
_private_key
=
models
.
TextField
(
auth_method
=
models
.
CharField
(
choices
=
AUTH_METHOD_CHOICES
,
default
=
'K'
,
max_length
=
1
,
verbose_name
=
_
(
'Auth method'
))
max_length
=
8192
,
blank
=
True
,
verbose_name
=
_
(
'SSH private key'
))
_public_key
=
models
.
TextField
(
max_length
=
8192
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
auth_method
=
models
.
CharField
(
choices
=
AUTH_METHOD_CHOICES
,
default
=
'K'
,
max_length
=
1
,
verbose_name
=
_
(
'Auth method'
))
auto_push
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Auto push'
))
auto_push
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Auto push'
))
sudo
=
models
.
TextField
(
sudo
=
models
.
TextField
(
default
=
'/sbin/ifconfig'
,
verbose_name
=
_
(
'Sudo'
))
max_length
=
4096
,
default
=
'/sbin/ifconfig'
,
verbose_name
=
_
(
'Sudo'
))
shell
=
models
.
CharField
(
max_length
=
64
,
default
=
'/bin/bash'
,
verbose_name
=
_
(
'Shell'
))
shell
=
models
.
CharField
(
max_length
=
64
,
default
=
'/bin/bash'
,
verbose_name
=
_
(
'Shell'
))
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
date_created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
created_by
=
models
.
CharField
(
created_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
comment
=
models
.
TextField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
comment
=
models
.
TextField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
self
.
name
return
self
.
name
__str__
=
__unicode__
@property
@property
def
password
(
self
):
def
password
(
self
):
...
@@ -182,9 +169,24 @@ class SystemUser(models.Model):
...
@@ -182,9 +169,24 @@ class SystemUser(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
.
encode
())
.
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
):
if
self
.
_public_key
:
return
signer
.
unsign
(
self
.
_public_key
)
return
signer
.
unsign
(
self
.
_public_key
)
else
:
return
None
@public_key.setter
@public_key.setter
def
public_key
(
self
,
public_key_raw
):
def
public_key
(
self
,
public_key_raw
):
...
@@ -213,7 +215,8 @@ class SystemUser(models.Model):
...
@@ -213,7 +215,8 @@ class SystemUser(models.Model):
'shell'
:
self
.
shell
,
'shell'
:
self
.
shell
,
'sudo'
:
self
.
sudo
,
'sudo'
:
self
.
sudo
,
'password'
:
self
.
password
,
'password'
:
self
.
password
,
'public_key'
:
self
.
public_key
'public_key'
:
self
.
public_key
,
'private_key_file'
:
self
.
private_key_file
,
}
}
@property
@property
...
...
apps/assets/utils.py
View file @
2b3551f1
...
@@ -19,3 +19,32 @@ def test_admin_user_connective_manual(asset):
...
@@ -19,3 +19,32 @@ def test_admin_user_connective_manual(asset):
def
get_assets_by_id_list
(
id_list
):
def
get_assets_by_id_list
(
id_list
):
return
Asset
.
objects
.
filter
(
id__in
=
id_list
)
return
Asset
.
objects
.
filter
(
id__in
=
id_list
)
def
get_assets_by_hostname_list
(
hostname_list
):
return
Asset
.
objects
.
filter
(
hostname__in
=
hostname_list
)
def
get_asset_admin_user
(
user
,
asset
):
if
user
.
is_superuser
:
return
asset
.
admin_user
else
:
msg
=
"{} have no permission for admin user"
.
format
(
user
.
username
)
raise
PermissionError
(
msg
)
def
get_asset_system_user
(
user
,
asset
,
system_user_name
):
from
perms.utils
import
get_user_granted_assets
assets
=
get_user_granted_assets
(
user
)
system_users
=
{
system_user
.
name
:
system_user
for
system_user
in
assets
.
get
(
asset
)}
if
system_user_name
in
system_users
:
return
system_users
[
system_user_name
]
else
:
msg
=
"{} have no permission for {}"
.
format
(
user
.
name
,
system_user_name
)
raise
PermissionError
(
msg
)
def
get_assets_with_admin_by_hostname_list
(
hostname_list
):
assets
=
Asset
.
objects
.
filter
(
hostname__in
=
hostname_list
)
return
[(
asset
,
asset
.
admin_user
)
for
asset
in
assets
]
apps/common/exceptions.py
0 → 100644
View file @
2b3551f1
# -*- coding: utf-8 -*-
#
apps/ops/ansible/callback.py
View file @
2b3551f1
...
@@ -9,65 +9,85 @@ class AdHocResultCallback(CallbackBase):
...
@@ -9,65 +9,85 @@ class AdHocResultCallback(CallbackBase):
"""
"""
def
__init__
(
self
,
display
=
None
):
def
__init__
(
self
,
display
=
None
):
# result_raw example: {
# result_raw example: {
# "ok": {"hostname": [
]
},
# "ok": {"hostname": [
{"task_name": {},...],..
},
# "failed": {"hostname": [
]
},
# "failed": {"hostname": [
"task_name": {}..], ..
},
# "unreachable: {"hostname": []},
# "unreachable: {"hostname": [
"task_name": {}, ..
]},
# "skipped": {"hostname": [
]
},
# "skipped": {"hostname": [
"task_name": {}, ..], ..
},
# }
# }
# results_summary example: {
# results_summary example: {
# "contacted": {"hostname",...},
# "contacted": {"hostname",...},
# "dark": {"hostname": [
"error"
,...],},
# "dark": {"hostname": [
{"task_name": "error"}
,...],},
# }
# }
self
.
results_raw
=
dict
(
ok
=
{},
failed
=
{},
unreachable
=
{},
skipped
=
{})
self
.
results_raw
=
dict
(
ok
=
{},
failed
=
{},
unreachable
=
{},
skipped
=
{})
self
.
results_summary
=
dict
(
contacted
=
set
(),
dark
=
{})
self
.
results_summary
=
dict
(
contacted
=
set
(),
dark
=
{})
super
()
.
__init__
(
display
)
super
()
.
__init__
(
display
)
def
gather_result
(
self
,
t
,
host
,
res
):
def
gather_result
(
self
,
t
,
res
):
host
=
res
.
_host
.
get_name
()
task_name
=
res
.
task_name
task_result
=
res
.
_result
if
self
.
results_raw
[
t
]
.
get
(
host
):
if
self
.
results_raw
[
t
]
.
get
(
host
):
self
.
results_raw
[
t
][
host
]
.
append
(
res
)
self
.
results_raw
[
t
][
host
]
.
append
(
{
task_name
:
task_result
}
)
else
:
else
:
self
.
results_raw
[
t
][
host
]
=
[
res
]
self
.
results_raw
[
t
][
host
]
=
[
{
task_name
:
task_result
}
]
self
.
clean_result
(
t
,
host
,
res
)
self
.
clean_result
(
t
,
host
,
task_name
,
task_result
)
def
clean_result
(
self
,
t
,
host
,
res
):
def
clean_result
(
self
,
t
,
host
,
task_name
,
task_result
):
contacted
=
self
.
results_summary
[
"contacted"
]
contacted
=
self
.
results_summary
[
"contacted"
]
dark
=
self
.
results_summary
[
"dark"
]
dark
=
self
.
results_summary
[
"dark"
]
if
t
in
(
"ok"
,
"skipped"
)
and
host
not
in
dark
:
if
t
in
(
"ok"
,
"skipped"
)
and
host
not
in
dark
:
contacted
.
add
(
host
)
contacted
.
add
(
host
)
else
:
else
:
dark
[
host
]
.
append
(
res
)
if
dark
.
get
(
host
):
dark
[
host
]
.
append
({
task_name
:
task_result
})
else
:
dark
[
host
]
=
[{
task_name
:
task_result
}]
if
host
in
contacted
:
if
host
in
contacted
:
contacted
.
remove
(
dark
)
contacted
.
remove
(
dark
)
def
runner_on_ok
(
self
,
host
,
res
):
def
v2_runner_on_failed
(
self
,
result
,
ignore_errors
=
False
):
self
.
gather_result
(
"
ok"
,
host
,
res
)
self
.
gather_result
(
"
failed"
,
result
)
def
runner_on_failed
(
self
,
host
,
res
,
ignore_errors
=
False
):
def
v2_runner_on_ok
(
self
,
result
):
self
.
gather_result
(
"
failed"
,
host
,
res
)
self
.
gather_result
(
"
ok"
,
result
)
def
runner_on_unreachable
(
self
,
host
,
res
):
def
v2_runner_on_skipped
(
self
,
result
):
self
.
gather_result
(
"
unreachable"
,
host
,
res
)
self
.
gather_result
(
"
skipped"
,
result
)
def
runner_on_skipped
(
self
,
host
,
item
=
None
):
def
v2_runner_on_unreachable
(
self
,
result
):
self
.
gather_result
(
"
skipped"
,
host
,
item
)
self
.
gather_result
(
"
unreachable"
,
result
)
class
CommandResultCallback
(
AdHocResultCallback
):
class
CommandResultCallback
(
AdHocResultCallback
):
"""
Command result callback
"""
def
__init__
(
self
,
display
=
None
):
def
__init__
(
self
,
display
=
None
):
# results_command: {
# "cmd": "",
# "stderr": "",
# "stdout": "",
# "rc": 0,
# "delta": 0:0:0.123
# }
#
self
.
results_command
=
dict
()
self
.
results_command
=
dict
()
super
()
.
__init__
(
display
)
super
()
.
__init__
(
display
)
def
gather_result
(
self
,
t
,
host
,
res
):
def
gather_result
(
self
,
t
,
res
):
super
()
.
gather_result
(
t
,
host
,
res
)
super
()
.
gather_result
(
t
,
res
)
self
.
gather_cmd
(
t
,
host
,
res
)
self
.
gather_cmd
(
t
,
res
)
def
gather_cmd
(
self
,
t
,
host
,
res
):
def
gather_cmd
(
self
,
t
,
res
):
host
=
res
.
_host
.
get_name
()
cmd
=
{}
cmd
=
{}
if
t
==
"ok"
:
if
t
==
"ok"
:
cmd
[
'cmd'
]
=
res
.
get
(
'cmd'
)
cmd
[
'cmd'
]
=
res
.
_result
.
get
(
'cmd'
)
cmd
[
'stderr'
]
=
res
.
get
(
'stderr'
)
cmd
[
'stderr'
]
=
res
.
_result
.
get
(
'stderr'
)
cmd
[
'stdout'
]
=
res
.
get
(
'stdout'
)
cmd
[
'stdout'
]
=
res
.
_result
.
get
(
'stdout'
)
cmd
[
'rc'
]
=
res
.
get
(
'rc'
)
cmd
[
'rc'
]
=
res
.
_result
.
get
(
'rc'
)
cmd
[
'delta'
]
=
res
.
_result
.
get
(
'delta'
)
else
:
else
:
cmd
[
'err'
]
=
"Error: {}"
.
format
(
res
)
cmd
[
'err'
]
=
"Error: {}"
.
format
(
res
)
self
.
results_command
[
host
]
=
cmd
self
.
results_command
[
host
]
=
cmd
...
...
apps/ops/ansible/runner.py
View file @
2b3551f1
...
@@ -170,6 +170,10 @@ class AdHocRunner:
...
@@ -170,6 +170,10 @@ class AdHocRunner:
"pattern:
%
s dose not match any hosts."
%
pattern
"pattern:
%
s dose not match any hosts."
%
pattern
)
)
def
set_option
(
self
,
k
,
v
):
kwargs
=
{
k
:
v
}
self
.
options
=
self
.
options
.
_replace
(
**
kwargs
)
def
run
(
self
,
tasks
,
pattern
,
play_name
=
'Ansible Ad-hoc'
,
gather_facts
=
'no'
):
def
run
(
self
,
tasks
,
pattern
,
play_name
=
'Ansible Ad-hoc'
,
gather_facts
=
'no'
):
"""
"""
:param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
:param tasks: [{'action': {'module': 'shell', 'args': 'ls'}, ...}, ]
...
...
apps/ops/ansible/test_runner.py
View file @
2b3551f1
...
@@ -24,8 +24,8 @@ class TestAdHocRunner(unittest.TestCase):
...
@@ -24,8 +24,8 @@ class TestAdHocRunner(unittest.TestCase):
def
test_run
(
self
):
def
test_run
(
self
):
tasks
=
[
tasks
=
[
{
"action"
:
{
"module"
:
"shell"
,
"args"
:
"ls"
}},
{
"action"
:
{
"module"
:
"shell"
,
"args"
:
"ls"
}
,
"name"
:
"run_cmd"
},
{
"action"
:
{
"module"
:
"shell"
,
"args"
:
"whoami"
}},
{
"action"
:
{
"module"
:
"shell"
,
"args"
:
"whoami"
}
,
"name"
:
"run_whoami"
},
]
]
ret
=
self
.
runner
.
run
(
tasks
,
"all"
)
ret
=
self
.
runner
.
run
(
tasks
,
"all"
)
print
(
ret
.
results_summary
)
print
(
ret
.
results_summary
)
...
@@ -48,6 +48,7 @@ class TestCommandRunner(unittest.TestCase):
...
@@ -48,6 +48,7 @@ class TestCommandRunner(unittest.TestCase):
def
test_execute
(
self
):
def
test_execute
(
self
):
res
=
self
.
runner
.
execute
(
'ls'
,
'all'
)
res
=
self
.
runner
.
execute
(
'ls'
,
'all'
)
print
(
res
.
results_command
)
print
(
res
.
results_command
)
print
(
res
.
results_raw
)
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
...
...
apps/ops/api.py
View file @
2b3551f1
...
@@ -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
Playbook
from
.models
import
AdHoc
from
.serializers
import
TaskSerializer
from
.serializers
import
TaskSerializer
class
TaskViewSet
(
viewsets
.
ModelViewSet
):
class
TaskViewSet
(
viewsets
.
ModelViewSet
):
queryset
=
Playbook
.
objects
.
all
()
queryset
=
AdHoc
.
objects
.
all
()
serializer_class
=
TaskSerializer
serializer_class
=
TaskSerializer
permission_classes
=
(
IsSuperUser
,)
permission_classes
=
(
IsSuperUser
,)
apps/ops/models.py
View file @
2b3551f1
# ~*~ coding: utf-8 ~*~
# ~*~ coding: utf-8 ~*~
import
logging
import
logging
from
collections
import
OrderedDict
import
json
import
json
import
uuid
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
_
__all__
=
[
"
Playbook
"
]
__all__
=
[
"
AdHoc"
,
"History
"
]
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
class
AdHoc
(
models
.
Model
):
class
AdHoc
(
models
.
Model
):
uu
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
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'
))
tasks
=
models
.
TextField
(
verbose_name
=
_
(
'Tasks'
))
# [{'name': 'task_name', 'module': '', 'args': ''}, ]
hosts
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Hosts'
))
# Asset inventory may be change
@property
pattern
=
models
.
CharField
(
max_length
=
64
,
default
=
'all'
,
verbose_name
=
_
(
'Playbook run pattern'
))
def
short_id
(
self
):
return
str
(
self
.
id
)
.
split
(
'-'
)[
-
1
]
def
__str__
(
self
):
def
__str__
(
self
):
return
"
%
s"
%
self
.
name
return
self
.
name
def
get_hosts_mapped_assets
(
self
):
class
AdHocData
(
models
.
Model
):
from
assets.utils
import
get_assets_by_id_list
BECOME_METHOD_CHOICES
=
(
assets_id
=
[
i
for
i
in
self
.
hosts
.
split
(
','
)]
(
'sudo'
,
'sudo'
),
assets
=
get_assets_by_id_list
(
assets_id
)
(
'su'
,
'su'
),
return
assets
)
version
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
subject
=
models
.
ForeignKey
(
AdHoc
,
on_delete
=
models
.
CASCADE
)
_tasks
=
models
.
TextField
(
verbose_name
=
_
(
'Tasks'
))
# [{'name': 'task_name', 'action': {'module': '', 'args': ''}, 'other..': ''}, ]
_hosts
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Hosts'
))
# ['hostname1', 'hostname2']
run_as_admin
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Run as admin'
))
run_as
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Run as"
))
become
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
"Become"
))
become_method
=
models
.
CharField
(
choices
=
BECOME_METHOD_CHOICES
,
default
=
'sudo'
,
max_length
=
4
)
become_user
=
models
.
CharField
(
default
=
'root'
,
max_length
=
64
)
become_pass
=
models
.
CharField
(
default
=
''
,
max_length
=
128
)
pattern
=
models
.
CharField
(
max_length
=
64
,
default
=
''
,
verbose_name
=
_
(
'Pattern'
))
created_by
=
models
.
CharField
(
max_length
=
64
,
verbose_name
=
_
(
'Create by'
))
date_created
=
models
.
DateTimeField
(
auto_created
=
True
)
@property
@property
def
inventory
(
self
):
def
tasks
(
self
):
return
[
asset
.
_to_secret_json
()
for
asset
in
self
.
get_hosts_mapped_assets
()]
return
json
.
loads
(
self
.
_tasks
)
@tasks.setter
def
tasks
(
self
,
item
):
self
.
_tasks
=
json
.
dumps
(
item
)
@property
@property
def
module_args
(
self
):
def
hosts
(
self
):
task_tuple
=
[]
return
json
.
loads
(
self
.
_hosts
)
for
module
,
args
in
json
.
loads
(
self
.
_modules_args
,
object_pairs_hook
=
OrderedDict
)
.
items
():
task_tuple
.
append
((
module
,
args
))
return
task_tuple
@module_args.setter
@hosts.setter
def
module_args
(
self
,
task_tuple
):
def
hosts
(
self
,
item
):
module_args_
=
OrderedDict
({})
self
.
_hosts
=
json
.
dumps
(
item
)
for
module
,
args
in
task_tuple
:
module_args_
[
module
]
=
args
self
.
_modules_args
=
json
.
dumps
(
module_args_
)
@property
def
short_version
(
self
):
return
str
(
self
.
version
)
.
split
(
'-'
)[
-
1
]
class
History
(
models
.
Model
):
def
__str__
(
self
):
return
"{} of {}"
.
format
(
self
.
subject
.
name
,
self
.
short_version
)
class
AdHocHistory
(
models
.
Model
):
uuid
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
uuid
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
adhoc
=
models
.
ForeignKey
(
AdHocData
,
on_delete
=
models
.
CASCADE
)
date_start
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Start time'
))
date_start
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'Start time'
))
date_finished
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'End time'
))
date_finished
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'End time'
))
timedelta
=
models
.
FloatField
(
default
=
0.0
,
verbose_name
=
_
(
'Time'
),
null
=
True
)
timedelta
=
models
.
FloatField
(
default
=
0.0
,
verbose_name
=
_
(
'Time'
),
null
=
True
)
...
@@ -58,3 +78,10 @@ class History(models.Model):
...
@@ -58,3 +78,10 @@ class History(models.Model):
is_success
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is success'
))
is_success
=
models
.
BooleanField
(
default
=
False
,
verbose_name
=
_
(
'Is success'
))
result
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Playbook raw result'
))
result
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Playbook raw result'
))
summary
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Playbook summary'
))
summary
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Playbook summary'
))
@property
def
short_id
(
self
):
return
str
(
self
.
id
)
.
split
(
'-'
)[
-
1
]
def
__str__
(
self
):
return
self
.
short_id
apps/ops/serializers.py
View file @
2b3551f1
...
@@ -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
Playbook
from
.models
import
AdHoc
class
TaskSerializer
(
serializers
.
ModelSerializer
):
class
TaskSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
class
Meta
:
model
=
Playbook
model
=
AdHoc
fields
=
'__all__'
fields
=
'__all__'
apps/ops/utils.py
View file @
2b3551f1
...
@@ -88,3 +88,14 @@ def is_uuid(s):
...
@@ -88,3 +88,14 @@ def is_uuid(s):
else
:
else
:
return
False
return
False
def
asset_to_dict
(
asset
):
return
asset
.
to_json
()
def
asset_to_dict_with_credential
(
asset
):
return
asset
.
_to_secret_json
()
def
system_user_to_dict_with_credential
(
system_user
):
return
system_user
.
_to_secret_json
()
apps/ops/views.py
View file @
2b3551f1
...
@@ -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
Playbook
from
.models
import
AdHoc
,
AdHocData
,
AdHocHistory
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
=
Playbook
model
=
AdHoc
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'
...
@@ -63,7 +63,7 @@ class TaskListView(ListView):
...
@@ -63,7 +63,7 @@ class TaskListView(ListView):
class
TaskDetailView
(
DetailView
):
class
TaskDetailView
(
DetailView
):
model
=
Playbook
model
=
AdHocHistory
template_name
=
'ops/task_detail.html'
template_name
=
'ops/task_detail.html'
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
...
...
apps/perms/utils.py
View file @
2b3551f1
...
@@ -53,79 +53,6 @@ def get_user_group_granted_assets(user_group):
...
@@ -53,79 +53,6 @@ def get_user_group_granted_assets(user_group):
return
assets
return
assets
# def get_user_granted_asset_groups_direct(user):
# """Return asset groups granted of the user direct nor inherit from user group
#
# :param user: Instance of :class: ``User``
# :return: {asset_group: {system_user1, },
# asset_group2: {system_user1, system_user2]}
# """
# asset_groups = {}
# asset_permissions_direct = user.asset_permissions.all()
#
# for asset_permission in asset_permissions_direct:
# if not asset_permission.is_valid:
# continue
# for asset_group in asset_permission.asset_groups.all():
# if asset_group in asset_groups:
# asset_groups[asset_group] |= set(asset_permission.system_users.all())
# else:
# setattr(asset_group, 'inherited', False)
# asset_groups[asset_group] = set(asset_permission.system_users.all())
#
# return asset_groups
# def get_user_granted_asset_groups_inherit_from_user_groups(user):
# """Return asset groups granted of the user and inherit from user group
#
# :param user: Instance of :class: ``User``
# :return: {asset_group: {system_user1, },
# asset_group2: {system_user1, system_user2]}
# """
# asset_groups = {}
# user_groups = user.groups.all()
# asset_permissions = set()
#
# # Get asset permission list of user groups for this user
# for user_group in user_groups:
# asset_permissions |= set(user_group.asset_permissions.all())
#
# # Get asset groups granted from user groups
# for asset_permission in asset_permissions:
# if not asset_permission.is_valid:
# continue
# for asset_group in asset_permission.asset_groups.all():
# if asset_group in asset_groups:
# asset_groups[asset_group] |= set(asset_permission.system_users.all())
# else:
# setattr(asset_group, 'inherited', True)
# asset_groups[asset_group] = set(asset_permission.system_users.all())
#
# return asset_groups
# def get_user_granted_asset_groups(user):
# """Get user granted asset groups all, include direct and inherit from user group
#
# :param user: Instance of :class: ``User``
# :return: {asset_group1: {system_user1, system_user2}, asset_group2: {...}}
# """
#
# asset_groups_inherit_from_user_groups = \
# get_user_granted_asset_groups_inherit_from_user_groups(user)
# asset_groups_direct = get_user_granted_asset_groups_direct(user)
# asset_groups = asset_groups_inherit_from_user_groups
#
# # Merge direct granted and inherit from user group
# for asset_group, system_users in asset_groups_direct.items():
# if asset_group in asset_groups:
# asset_groups[asset_group] |= asset_groups_direct[asset_group]
# else:
# asset_groups[asset_group] = asset_groups_direct[asset_group]
# return asset_groups
def
get_user_granted_assets_direct
(
user
):
def
get_user_granted_assets_direct
(
user
):
"""Return assets granted of the user directly
"""Return assets granted of the user directly
...
@@ -225,6 +152,22 @@ def get_user_asset_permissions(user):
...
@@ -225,6 +152,22 @@ def get_user_asset_permissions(user):
return
direct_permissions
|
user_group_permissions
return
direct_permissions
|
user_group_permissions
def
get_user_granted_system_users
(
user
):
"""
:param user: the user
:return: {"system_user": ["asset", "asset1"], "system_user": []}
"""
assets
=
get_user_granted_assets
(
user
)
system_users_dict
=
{}
for
asset
,
system_users
in
assets
.
items
():
for
system_user
in
system_users
:
if
system_user
in
system_users_dict
:
system_users_dict
[
system_user
]
.
append
(
asset
)
else
:
system_users_dict
[
system_user
]
=
[
asset
]
return
system_users_dict
def
get_user_groups_granted_in_asset
(
asset
):
def
get_user_groups_granted_in_asset
(
asset
):
pass
pass
...
...
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