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
2ac5786b
Commit
2ac5786b
authored
Aug 16, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Bugfix] 修复Hostname可能不唯一引起的任务执行失败
parent
5b93a1a0
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
113 additions
and
34 deletions
+113
-34
asset.py
apps/assets/api/asset.py
+1
-1
asset.py
apps/assets/models/asset.py
+15
-5
label.py
apps/assets/models/label.py
+1
-1
tasks.py
apps/assets/tasks.py
+7
-7
utils.py
apps/assets/utils.py
+2
-2
inventory.py
apps/ops/inventory.py
+2
-2
mixins.py
apps/orgs/mixins.py
+59
-1
models.py
apps/orgs/models.py
+26
-15
No files found.
apps/assets/api/asset.py
View file @
2ac5786b
...
@@ -48,7 +48,7 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
...
@@ -48,7 +48,7 @@ class AssetViewSet(IDInFilterMixin, LabelFilter, BulkModelViewSet):
return
return
node
=
get_object_or_404
(
Node
,
id
=
node_id
)
node
=
get_object_or_404
(
Node
,
id
=
node_id
)
show_current_asset
=
self
.
request
.
query_params
.
get
(
"show_current_asset"
)
show_current_asset
=
self
.
request
.
query_params
.
get
(
"show_current_asset"
)
in
(
'1'
,
'true'
)
if
node
.
is_root
():
if
node
.
is_root
():
if
show_current_asset
:
if
show_current_asset
:
...
...
apps/assets/models/asset.py
View file @
2ac5786b
...
@@ -6,8 +6,10 @@ import uuid
...
@@ -6,8 +6,10 @@ import uuid
import
logging
import
logging
import
random
import
random
from
functools
import
reduce
from
functools
import
reduce
from
collections
import
defaultdict
from
django.db
import
models
from
django.db
import
models
from
django.db.models
import
Q
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.core.cache
import
cache
from
django.core.cache
import
cache
...
@@ -162,11 +164,19 @@ class Asset(OrgModelMixin):
...
@@ -162,11 +164,19 @@ class Asset(OrgModelMixin):
nodes
=
list
(
reduce
(
lambda
x
,
y
:
set
(
x
)
|
set
(
y
),
nodes
))
nodes
=
list
(
reduce
(
lambda
x
,
y
:
set
(
x
)
|
set
(
y
),
nodes
))
return
nodes
return
nodes
@property
@classmethod
def
org_name
(
self
):
def
get_queryset_by_fullname_list
(
cls
,
fullname_list
):
from
orgs.models
import
Organization
org_fullname_map
=
defaultdict
(
list
)
org
=
Organization
.
get_instance
(
self
.
org_id
)
for
fullname
in
fullname_list
:
return
org
.
name
hostname
,
org
=
cls
.
split_fullname
(
fullname
)
org_fullname_map
[
org
]
.
append
(
hostname
)
filter_arg
=
Q
()
for
org
,
hosts
in
org_fullname_map
.
items
():
if
org
.
is_real
():
filter_arg
|=
Q
(
hostname__in
=
hosts
,
org_id
=
org
.
id
)
else
:
filter_arg
|=
Q
(
Q
(
org_id__isnull
=
True
)
|
Q
(
org_id
=
''
),
hostname__in
=
hosts
)
return
Asset
.
objects
.
filter
(
filter_arg
)
@property
@property
def
hardware_info
(
self
):
def
hardware_info
(
self
):
...
...
apps/assets/models/label.py
View file @
2ac5786b
...
@@ -35,4 +35,4 @@ class Label(OrgModelMixin):
...
@@ -35,4 +35,4 @@ class Label(OrgModelMixin):
class
Meta
:
class
Meta
:
db_table
=
"assets_label"
db_table
=
"assets_label"
unique_together
=
[(
'name'
,
'value'
)]
unique_together
=
[(
'name'
,
'value'
,
'org_id'
)]
apps/assets/tasks.py
View file @
2ac5786b
...
@@ -44,7 +44,7 @@ def set_assets_hardware_info(result, **kwargs):
...
@@ -44,7 +44,7 @@ def set_assets_hardware_info(result, **kwargs):
logger
.
error
(
"Get asset info failed: {}"
.
format
(
hostname
))
logger
.
error
(
"Get asset info failed: {}"
.
format
(
hostname
))
continue
continue
asset
=
get_object_or_none
(
Asset
,
hostname
=
hostname
)
asset
=
Asset
.
objects
.
get_object_by_fullname
(
hostname
)
if
not
asset
:
if
not
asset
:
continue
continue
...
@@ -96,7 +96,7 @@ def update_assets_hardware_info_util(assets, task_name=None):
...
@@ -96,7 +96,7 @@ def update_assets_hardware_info_util(assets, task_name=None):
# task_name = _("Update some assets hardware info")
# task_name = _("Update some assets hardware info")
task_name
=
_
(
"更新资产硬件信息"
)
task_name
=
_
(
"更新资产硬件信息"
)
tasks
=
const
.
UPDATE_ASSETS_HARDWARE_TASKS
tasks
=
const
.
UPDATE_ASSETS_HARDWARE_TASKS
hostname_list
=
[
asset
.
host
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
hostname_list
=
[
asset
.
full
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
if
not
hostname_list
:
if
not
hostname_list
:
logger
.
info
(
"Not hosts get, may be asset is not active or not unixlike platform"
)
logger
.
info
(
"Not hosts get, may be asset is not active or not unixlike platform"
)
return
{}
return
{}
...
@@ -135,7 +135,7 @@ def update_assets_hardware_info_period():
...
@@ -135,7 +135,7 @@ def update_assets_hardware_info_period():
# task_name = _("Update assets hardware info period")
# task_name = _("Update assets hardware info period")
task_name
=
_
(
"定期更新资产硬件信息"
)
task_name
=
_
(
"定期更新资产硬件信息"
)
hostname_list
=
[
hostname_list
=
[
asset
.
host
name
for
asset
in
Asset
.
objects
.
all
()
asset
.
full
name
for
asset
in
Asset
.
objects
.
all
()
if
asset
.
is_active
and
asset
.
is_unixlike
()
if
asset
.
is_active
and
asset
.
is_unixlike
()
]
]
tasks
=
const
.
UPDATE_ASSETS_HARDWARE_TASKS
tasks
=
const
.
UPDATE_ASSETS_HARDWARE_TASKS
...
@@ -182,7 +182,7 @@ def test_admin_user_connectability_util(admin_user, task_name):
...
@@ -182,7 +182,7 @@ def test_admin_user_connectability_util(admin_user, task_name):
from
ops.utils
import
update_or_create_ansible_task
from
ops.utils
import
update_or_create_ansible_task
assets
=
admin_user
.
get_related_assets
()
assets
=
admin_user
.
get_related_assets
()
hosts
=
[
asset
.
host
name
for
asset
in
assets
hosts
=
[
asset
.
full
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
if
asset
.
is_active
and
asset
.
is_unixlike
()]
if
not
hosts
:
if
not
hosts
:
return
return
...
@@ -229,7 +229,7 @@ def test_asset_connectability_util(assets, task_name=None):
...
@@ -229,7 +229,7 @@ def test_asset_connectability_util(assets, task_name=None):
if
task_name
is
None
:
if
task_name
is
None
:
# task_name = _("Test assets connectability")
# task_name = _("Test assets connectability")
task_name
=
_
(
"测试资产可连接性"
)
task_name
=
_
(
"测试资产可连接性"
)
hosts
=
[
asset
.
host
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
hosts
=
[
asset
.
full
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
if
not
hosts
:
if
not
hosts
:
logger
.
info
(
"No hosts, passed"
)
logger
.
info
(
"No hosts, passed"
)
return
{}
return
{}
...
@@ -281,7 +281,7 @@ def test_system_user_connectability_util(system_user, task_name):
...
@@ -281,7 +281,7 @@ def test_system_user_connectability_util(system_user, task_name):
"""
"""
from
ops.utils
import
update_or_create_ansible_task
from
ops.utils
import
update_or_create_ansible_task
assets
=
system_user
.
get_assets
()
assets
=
system_user
.
get_assets
()
hosts
=
[
asset
.
host
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
hosts
=
[
asset
.
full
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
tasks
=
const
.
TEST_SYSTEM_USER_CONN_TASKS
tasks
=
const
.
TEST_SYSTEM_USER_CONN_TASKS
if
not
hosts
:
if
not
hosts
:
logger
.
info
(
"No hosts, passed"
)
logger
.
info
(
"No hosts, passed"
)
...
@@ -379,7 +379,7 @@ def push_system_user_util(system_users, assets, task_name):
...
@@ -379,7 +379,7 @@ def push_system_user_util(system_users, assets, task_name):
logger
.
info
(
"Not tasks, passed"
)
logger
.
info
(
"Not tasks, passed"
)
return
{}
return
{}
hosts
=
[
asset
.
host
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
hosts
=
[
asset
.
full
name
for
asset
in
assets
if
asset
.
is_active
and
asset
.
is_unixlike
()]
if
not
hosts
:
if
not
hosts
:
logger
.
info
(
"Not hosts, passed"
)
logger
.
info
(
"Not hosts, passed"
)
return
{}
return
{}
...
...
apps/assets/utils.py
View file @
2ac5786b
...
@@ -12,8 +12,8 @@ def get_assets_by_id_list(id_list):
...
@@ -12,8 +12,8 @@ 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_
host
name_list
(
hostname_list
):
def
get_assets_by_
full
name_list
(
hostname_list
):
return
Asset
.
objects
.
filter
(
hostname__in
=
hostname_list
)
return
Asset
.
objects
.
get_queryset_by_fullname_list
(
hostname_list
)
def
get_system_user_by_name
(
name
):
def
get_system_user_by_name
(
name
):
...
...
apps/ops/inventory.py
View file @
2ac5786b
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
#
#
from
.ansible.inventory
import
BaseInventory
from
.ansible.inventory
import
BaseInventory
from
assets.utils
import
get_assets_by_
host
name_list
,
get_system_user_by_name
from
assets.utils
import
get_assets_by_
full
name_list
,
get_system_user_by_name
__all__
=
[
__all__
=
[
'JMSInventory'
'JMSInventory'
...
@@ -44,7 +44,7 @@ class JMSInventory(BaseInventory):
...
@@ -44,7 +44,7 @@ class JMSInventory(BaseInventory):
super
()
.
__init__
(
host_list
=
host_list
)
super
()
.
__init__
(
host_list
=
host_list
)
def
get_jms_assets
(
self
):
def
get_jms_assets
(
self
):
assets
=
get_assets_by_
host
name_list
(
self
.
hostname_list
)
assets
=
get_assets_by_
full
name_list
(
self
.
hostname_list
)
return
assets
return
assets
def
convert_to_ansible
(
self
,
asset
,
run_as_admin
=
False
):
def
convert_to_ansible
(
self
,
asset
,
run_as_admin
=
False
):
...
...
apps/orgs/mixins.py
View file @
2ac5786b
...
@@ -8,7 +8,7 @@ from django.shortcuts import redirect
...
@@ -8,7 +8,7 @@ from django.shortcuts import redirect
from
django.forms
import
ModelForm
from
django.forms
import
ModelForm
from
django.http.response
import
HttpResponseForbidden
from
django.http.response
import
HttpResponseForbidden
from
common.utils
import
get_logger
from
common.utils
import
get_logger
,
is_uuid
from
.utils
import
current_org
,
set_current_org
,
set_to_root_org
from
.utils
import
current_org
,
set_current_org
,
set_to_root_org
from
.models
import
Organization
from
.models
import
Organization
...
@@ -39,6 +39,25 @@ class OrgManager(models.Manager):
...
@@ -39,6 +39,25 @@ class OrgManager(models.Manager):
tl
.
times
+=
1
tl
.
times
+=
1
return
queryset
return
queryset
def
filter_by_fullname
(
self
,
fullname
,
field
=
None
):
ori_org
=
current_org
value
,
org
=
self
.
model
.
split_fullname
(
fullname
)
set_current_org
(
org
)
if
not
field
:
if
hasattr
(
self
.
model
,
'name'
):
field
=
'name'
elif
hasattr
(
self
.
model
,
'hostname'
):
field
=
'hostname'
queryset
=
self
.
get_queryset
()
.
filter
(
**
{
field
:
value
})
set_current_org
(
ori_org
)
return
queryset
def
get_object_by_fullname
(
self
,
fullname
,
field
=
None
):
queryset
=
self
.
filter_by_fullname
(
fullname
,
field
=
field
)
if
len
(
queryset
)
==
1
:
return
queryset
[
0
]
return
None
def
all
(
self
):
def
all
(
self
):
if
not
current_org
:
if
not
current_org
:
msg
=
'You can `objects.set_current_org(org).all()` then run it'
msg
=
'You can `objects.set_current_org(org).all()` then run it'
...
@@ -57,11 +76,50 @@ class OrgModelMixin(models.Model):
...
@@ -57,11 +76,50 @@ class OrgModelMixin(models.Model):
org_id
=
models
.
CharField
(
max_length
=
36
,
null
=
True
,
blank
=
True
,
default
=
None
)
org_id
=
models
.
CharField
(
max_length
=
36
,
null
=
True
,
blank
=
True
,
default
=
None
)
objects
=
OrgManager
()
objects
=
OrgManager
()
sep
=
'@'
def
save
(
self
,
*
args
,
**
kwargs
):
def
save
(
self
,
*
args
,
**
kwargs
):
if
current_org
and
current_org
.
is_real
():
if
current_org
and
current_org
.
is_real
():
self
.
org_id
=
current_org
.
id
self
.
org_id
=
current_org
.
id
return
super
()
.
save
(
*
args
,
**
kwargs
)
return
super
()
.
save
(
*
args
,
**
kwargs
)
@classmethod
def
split_fullname
(
cls
,
fullname
,
sep
=
None
):
if
not
sep
:
sep
=
cls
.
sep
index
=
fullname
.
rfind
(
sep
)
if
index
==
-
1
:
value
=
fullname
org
=
Organization
.
default
()
else
:
value
=
fullname
[:
index
]
org
=
Organization
.
get_instance
(
fullname
[
index
+
1
:])
return
value
,
org
@property
def
org
(
self
):
from
orgs.models
import
Organization
org
=
Organization
.
get_instance
(
self
.
org_id
)
return
org
@property
def
org_name
(
self
):
return
self
.
org
.
name
@property
def
fullname
(
self
,
attr
=
None
):
name
=
''
if
attr
and
hasattr
(
self
,
attr
):
name
=
getattr
(
self
,
attr
)
elif
hasattr
(
self
,
'name'
):
name
=
self
.
name
elif
hasattr
(
self
,
'hostname'
):
name
=
self
.
hostname
if
self
.
org
.
is_real
():
return
name
+
self
.
sep
+
self
.
org_name
else
:
return
name
class
Meta
:
class
Meta
:
abstract
=
True
abstract
=
True
...
...
apps/orgs/models.py
View file @
2ac5786b
...
@@ -4,6 +4,8 @@ from django.db import models
...
@@ -4,6 +4,8 @@ from django.db import models
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
common.utils
import
is_uuid
class
Organization
(
models
.
Model
):
class
Organization
(
models
.
Model
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
...
@@ -15,19 +17,23 @@ class Organization(models.Model):
...
@@ -15,19 +17,23 @@ class Organization(models.Model):
comment
=
models
.
TextField
(
max_length
=
128
,
default
=
''
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
comment
=
models
.
TextField
(
max_length
=
128
,
default
=
''
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
CACHE_PREFIX
=
'JMS_ORG_{}'
CACHE_PREFIX
=
'JMS_ORG_{}'
ROOT_ID
=
'ROOT'
ROOT_ID
_NAME
=
'ROOT'
DEFAULT_ID
=
'DEFAULT'
DEFAULT_ID
_NAME
=
'DEFAULT'
def
__str__
(
self
):
def
__str__
(
self
):
return
self
.
name
return
self
.
name
def
set_to_cache
(
self
):
def
set_to_cache
(
self
):
key
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
key_id
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
cache
.
set
(
key
,
self
,
3600
)
key_name
=
self
.
CACHE_PREFIX
.
format
(
self
.
name
)
cache
.
set
(
key_id
,
self
,
3600
)
cache
.
set
(
key_name
,
self
,
3600
)
def
expire_cache
(
self
):
def
expire_cache
(
self
):
key
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
key_id
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
cache
.
set
(
key
,
self
,
1
)
key_name
=
self
.
CACHE_PREFIX
.
format
(
self
.
name
)
cache
.
delete
(
key_id
)
cache
.
delete
(
key_name
)
@classmethod
@classmethod
def
get_instance_from_cache
(
cls
,
oid
):
def
get_instance_from_cache
(
cls
,
oid
):
...
@@ -35,18 +41,23 @@ class Organization(models.Model):
...
@@ -35,18 +41,23 @@ class Organization(models.Model):
return
cache
.
get
(
key
,
None
)
return
cache
.
get
(
key
,
None
)
@classmethod
@classmethod
def
get_instance
(
cls
,
oid
,
default
=
True
):
def
get_instance
(
cls
,
id_or_name
,
default
=
True
):
cached
=
cls
.
get_instance_from_cache
(
oid
)
cached
=
cls
.
get_instance_from_cache
(
id_or_name
)
if
cached
:
if
cached
:
return
cached
return
cached
if
oid
==
cls
.
DEFAULT_ID
:
if
not
id_or_name
:
return
cls
.
default
()
if
default
else
None
elif
id_or_name
==
cls
.
DEFAULT_ID_NAME
:
return
cls
.
default
()
return
cls
.
default
()
elif
oid
==
cls
.
ROOT_ID
:
elif
id_or_name
==
cls
.
ROOT_ID_NAME
:
return
cls
.
root
()
return
cls
.
root
()
try
:
try
:
org
=
cls
.
objects
.
get
(
id
=
oid
)
if
is_uuid
(
id_or_name
):
org
=
cls
.
objects
.
get
(
id
=
id_or_name
)
else
:
org
=
cls
.
objects
.
get
(
name
=
id_or_name
)
org
.
set_to_cache
()
org
.
set_to_cache
()
except
cls
.
DoesNotExist
:
except
cls
.
DoesNotExist
:
org
=
cls
.
default
()
if
default
else
None
org
=
cls
.
default
()
if
default
else
None
...
@@ -92,20 +103,20 @@ class Organization(models.Model):
...
@@ -92,20 +103,20 @@ class Organization(models.Model):
@classmethod
@classmethod
def
default
(
cls
):
def
default
(
cls
):
return
cls
(
id
=
cls
.
DEFAULT_ID
,
name
=
"Default"
)
return
cls
(
id
=
cls
.
DEFAULT_ID
_NAME
,
name
=
cls
.
DEFAULT_ID_NAME
)
@classmethod
@classmethod
def
root
(
cls
):
def
root
(
cls
):
return
cls
(
id
=
cls
.
ROOT_ID
,
name
=
'Root'
)
return
cls
(
id
=
cls
.
ROOT_ID
_NAME
,
name
=
cls
.
ROOT_ID_NAME
)
def
is_root
(
self
):
def
is_root
(
self
):
if
self
.
id
is
self
.
ROOT_ID
:
if
self
.
id
is
self
.
ROOT_ID
_NAME
:
return
True
return
True
else
:
else
:
return
False
return
False
def
is_default
(
self
):
def
is_default
(
self
):
if
self
.
id
is
self
.
DEFAULT_ID
:
if
self
.
id
is
self
.
DEFAULT_ID
_NAME
:
return
True
return
True
else
:
else
:
return
False
return
False
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