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):
return
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
show_current_asset
:
...
...
apps/assets/models/asset.py
View file @
2ac5786b
...
...
@@ -6,8 +6,10 @@ import uuid
import
logging
import
random
from
functools
import
reduce
from
collections
import
defaultdict
from
django.db
import
models
from
django.db.models
import
Q
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.core.cache
import
cache
...
...
@@ -162,11 +164,19 @@ class Asset(OrgModelMixin):
nodes
=
list
(
reduce
(
lambda
x
,
y
:
set
(
x
)
|
set
(
y
),
nodes
))
return
nodes
@property
def
org_name
(
self
):
from
orgs.models
import
Organization
org
=
Organization
.
get_instance
(
self
.
org_id
)
return
org
.
name
@classmethod
def
get_queryset_by_fullname_list
(
cls
,
fullname_list
):
org_fullname_map
=
defaultdict
(
list
)
for
fullname
in
fullname_list
:
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
def
hardware_info
(
self
):
...
...
apps/assets/models/label.py
View file @
2ac5786b
...
...
@@ -35,4 +35,4 @@ class Label(OrgModelMixin):
class
Meta
:
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):
logger
.
error
(
"Get asset info failed: {}"
.
format
(
hostname
))
continue
asset
=
get_object_or_none
(
Asset
,
hostname
=
hostname
)
asset
=
Asset
.
objects
.
get_object_by_fullname
(
hostname
)
if
not
asset
:
continue
...
...
@@ -96,7 +96,7 @@ def update_assets_hardware_info_util(assets, task_name=None):
# task_name = _("Update some assets hardware info")
task_name
=
_
(
"更新资产硬件信息"
)
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
:
logger
.
info
(
"Not hosts get, may be asset is not active or not unixlike platform"
)
return
{}
...
...
@@ -135,7 +135,7 @@ def update_assets_hardware_info_period():
# task_name = _("Update assets hardware info period")
task_name
=
_
(
"定期更新资产硬件信息"
)
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
()
]
tasks
=
const
.
UPDATE_ASSETS_HARDWARE_TASKS
...
...
@@ -182,7 +182,7 @@ def test_admin_user_connectability_util(admin_user, task_name):
from
ops.utils
import
update_or_create_ansible_task
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
not
hosts
:
return
...
...
@@ -229,7 +229,7 @@ def test_asset_connectability_util(assets, task_name=None):
if
task_name
is
None
:
# task_name = _("Test assets connectability")
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
:
logger
.
info
(
"No hosts, passed"
)
return
{}
...
...
@@ -281,7 +281,7 @@ def test_system_user_connectability_util(system_user, task_name):
"""
from
ops.utils
import
update_or_create_ansible_task
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
if
not
hosts
:
logger
.
info
(
"No hosts, passed"
)
...
...
@@ -379,7 +379,7 @@ def push_system_user_util(system_users, assets, task_name):
logger
.
info
(
"Not tasks, passed"
)
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
:
logger
.
info
(
"Not hosts, passed"
)
return
{}
...
...
apps/assets/utils.py
View file @
2ac5786b
...
...
@@ -12,8 +12,8 @@ def get_assets_by_id_list(id_list):
return
Asset
.
objects
.
filter
(
id__in
=
id_list
)
def
get_assets_by_
host
name_list
(
hostname_list
):
return
Asset
.
objects
.
filter
(
hostname__in
=
hostname_list
)
def
get_assets_by_
full
name_list
(
hostname_list
):
return
Asset
.
objects
.
get_queryset_by_fullname_list
(
hostname_list
)
def
get_system_user_by_name
(
name
):
...
...
apps/ops/inventory.py
View file @
2ac5786b
...
...
@@ -2,7 +2,7 @@
#
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__
=
[
'JMSInventory'
...
...
@@ -44,7 +44,7 @@ class JMSInventory(BaseInventory):
super
()
.
__init__
(
host_list
=
host_list
)
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
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
from
django.forms
import
ModelForm
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
.models
import
Organization
...
...
@@ -39,6 +39,25 @@ class OrgManager(models.Manager):
tl
.
times
+=
1
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
):
if
not
current_org
:
msg
=
'You can `objects.set_current_org(org).all()` then run it'
...
...
@@ -57,11 +76,50 @@ class OrgModelMixin(models.Model):
org_id
=
models
.
CharField
(
max_length
=
36
,
null
=
True
,
blank
=
True
,
default
=
None
)
objects
=
OrgManager
()
sep
=
'@'
def
save
(
self
,
*
args
,
**
kwargs
):
if
current_org
and
current_org
.
is_real
():
self
.
org_id
=
current_org
.
id
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
:
abstract
=
True
...
...
apps/orgs/models.py
View file @
2ac5786b
...
...
@@ -4,6 +4,8 @@ from django.db import models
from
django.core.cache
import
cache
from
django.utils.translation
import
ugettext_lazy
as
_
from
common.utils
import
is_uuid
class
Organization
(
models
.
Model
):
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
...
...
@@ -15,19 +17,23 @@ class Organization(models.Model):
comment
=
models
.
TextField
(
max_length
=
128
,
default
=
''
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
CACHE_PREFIX
=
'JMS_ORG_{}'
ROOT_ID
=
'ROOT'
DEFAULT_ID
=
'DEFAULT'
ROOT_ID
_NAME
=
'ROOT'
DEFAULT_ID
_NAME
=
'DEFAULT'
def
__str__
(
self
):
return
self
.
name
def
set_to_cache
(
self
):
key
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
cache
.
set
(
key
,
self
,
3600
)
key_id
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
key_name
=
self
.
CACHE_PREFIX
.
format
(
self
.
name
)
cache
.
set
(
key_id
,
self
,
3600
)
cache
.
set
(
key_name
,
self
,
3600
)
def
expire_cache
(
self
):
key
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
cache
.
set
(
key
,
self
,
1
)
key_id
=
self
.
CACHE_PREFIX
.
format
(
self
.
id
)
key_name
=
self
.
CACHE_PREFIX
.
format
(
self
.
name
)
cache
.
delete
(
key_id
)
cache
.
delete
(
key_name
)
@classmethod
def
get_instance_from_cache
(
cls
,
oid
):
...
...
@@ -35,18 +41,23 @@ class Organization(models.Model):
return
cache
.
get
(
key
,
None
)
@classmethod
def
get_instance
(
cls
,
oid
,
default
=
True
):
cached
=
cls
.
get_instance_from_cache
(
oid
)
def
get_instance
(
cls
,
id_or_name
,
default
=
True
):
cached
=
cls
.
get_instance_from_cache
(
id_or_name
)
if
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
()
elif
oid
==
cls
.
ROOT_ID
:
elif
id_or_name
==
cls
.
ROOT_ID_NAME
:
return
cls
.
root
()
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
()
except
cls
.
DoesNotExist
:
org
=
cls
.
default
()
if
default
else
None
...
...
@@ -92,20 +103,20 @@ class Organization(models.Model):
@classmethod
def
default
(
cls
):
return
cls
(
id
=
cls
.
DEFAULT_ID
,
name
=
"Default"
)
return
cls
(
id
=
cls
.
DEFAULT_ID
_NAME
,
name
=
cls
.
DEFAULT_ID_NAME
)
@classmethod
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
):
if
self
.
id
is
self
.
ROOT_ID
:
if
self
.
id
is
self
.
ROOT_ID
_NAME
:
return
True
else
:
return
False
def
is_default
(
self
):
if
self
.
id
is
self
.
DEFAULT_ID
:
if
self
.
id
is
self
.
DEFAULT_ID
_NAME
:
return
True
else
:
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