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
1b9c9c48
Commit
1b9c9c48
authored
Sep 04, 2016
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'cmdb'
parents
22e20d29
0604f76f
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
1250 additions
and
439 deletions
+1250
-439
__init__.py
apps/__init__.py
+7
-7
api.py
apps/assets/api.py
+4
-1
forms.py
apps/assets/forms.py
+7
-2
0001_initial.py
apps/assets/migrations/0001_initial.py
+111
-0
0002_auto_20160821_1757.py
apps/assets/migrations/0002_auto_20160821_1757.py
+20
-0
0003_auto_20160821_1759.py
apps/assets/migrations/0003_auto_20160821_1759.py
+20
-0
models.py
apps/assets/models.py
+113
-46
asset_add.html
apps/assets/templates/assets/asset_add.html
+57
-134
asset_detail.html
apps/assets/templates/assets/asset_detail.html
+375
-0
asset_list.html
apps/assets/templates/assets/asset_list.html
+19
-19
assetgroup_add.html
apps/assets/templates/assets/assetgroup_add.html
+67
-0
assetgroup_list.html
apps/assets/templates/assets/assetgroup_list.html
+59
-0
urls.py
apps/assets/urls.py
+22
-15
utils.py
apps/assets/utils.py
+21
-0
views.py
apps/assets/views.py
+58
-22
common_tags.py
apps/common/templatetags/common_tags.py
+36
-39
utils.py
apps/common/utils.py
+23
-24
settings.py
apps/jumpserver/settings.py
+2
-2
django.po
apps/locale/zh_CN/LC_MESSAGES/django.po
+143
-37
_header_bar.html
apps/templates/_header_bar.html
+1
-1
_nav.html
apps/templates/_nav.html
+2
-2
django.po
apps/users/locale/zh_CN/LC_MESSAGES/django.po
+6
-6
models.py
apps/users/models.py
+1
-1
serializers.py
apps/users/serializers.py
+31
-33
_user.html
apps/users/templates/users/_user.html
+1
-1
forget_password.html
apps/users/templates/users/forget_password.html
+1
-1
user_list.html
apps/users/templates/users/user_list.html
+1
-1
users_tags.py
apps/users/templatetags/users_tags.py
+38
-41
views.py
apps/users/views.py
+3
-3
run_server.py
run_server.py
+1
-1
No files found.
apps/__init__.py
View file @
1b9c9c48
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
if
__name__
==
'__main__'
:
pass
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
if
__name__
==
'__main__'
:
pass
apps/assets/api.py
View file @
1b9c9c48
...
...
@@ -22,7 +22,8 @@ class IDCSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
IDC
#fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
class
AssetGroupViewSet
(
viewsets
.
ModelViewSet
):
"""
API endpoint that allows AssetGroup to be viewed or edited.
...
...
@@ -30,6 +31,7 @@ class AssetGroupViewSet(viewsets.ModelViewSet):
queryset
=
AssetGroup
.
objects
.
all
()
serializer_class
=
AssetGroupSerializer
class
AssetViewSet
(
viewsets
.
ModelViewSet
):
"""
API endpoint that allows Asset to be viewed or edited.
...
...
@@ -37,6 +39,7 @@ class AssetViewSet(viewsets.ModelViewSet):
queryset
=
Asset
.
objects
.
all
()
serializer_class
=
AssetSerializer
class
IDCViewSet
(
viewsets
.
ModelViewSet
):
"""
API endpoint that allows IDC to be viewed or edited.
...
...
apps/assets/forms.py
View file @
1b9c9c48
...
...
@@ -2,6 +2,7 @@
from
django
import
forms
from
.models
import
IDC
,
Asset
,
AssetGroup
from
django.utils.translation
import
gettext_lazy
as
_
class
AssetForm
(
forms
.
ModelForm
):
...
...
@@ -10,11 +11,15 @@ class AssetForm(forms.ModelForm):
model
=
Asset
fields
=
[
"ip"
,
"other_ip"
,
"
hostname"
,
"port"
,
"group"
,
"username"
,
"password"
,
"idc"
,
"mac_addr
"
,
"
remote_card_ip
"
,
"brand"
,
"cpu"
,
"memory"
,
"disk"
,
"os"
,
"cabinet_no"
,
"cabinet_pos"
,
"ip"
,
"other_ip"
,
"
remote_card_ip"
,
"hostname"
,
"port"
,
"groups"
,
"username"
,
"password
"
,
"
idc"
,
"mac_addr
"
,
"brand"
,
"cpu"
,
"memory"
,
"disk"
,
"os"
,
"cabinet_no"
,
"cabinet_pos"
,
"number"
,
"status"
,
"type"
,
"env"
,
"sn"
,
"is_active"
,
"comment"
]
widgets
=
{
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
'data-placeholder'
:
_
(
'Join assetgroups'
)}),
}
class
AssetGroupForm
(
forms
.
ModelForm
):
class
Meta
:
...
...
apps/assets/migrations/0001_initial.py
0 → 100644
View file @
1b9c9c48
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-09-03 14:30
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
initial
=
True
dependencies
=
[
]
operations
=
[
migrations
.
CreateModel
(
name
=
'Asset'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'ip'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u8d44\u4ea7
IP'
)),
(
'other_ip'
,
models
.
CharField
(
blank
=
True
,
max_length
=
255
,
verbose_name
=
'
\u5176\u4ed6
IP'
)),
(
'remote_card_ip'
,
models
.
CharField
(
blank
=
True
,
max_length
=
16
,
verbose_name
=
'
\u8fdc\u63a7\u5361
IP'
)),
(
'hostname'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
unique
=
True
,
verbose_name
=
'
\u4e3b\u673a\u540d
'
)),
(
'port'
,
models
.
IntegerField
(
blank
=
True
,
verbose_name
=
'
\u7aef\u53e3
'
)),
(
'username'
,
models
.
CharField
(
blank
=
True
,
max_length
=
16
,
verbose_name
=
'
\u7ba1\u7406\u7528\u6237\u540d
'
)),
(
'password'
,
models
.
CharField
(
blank
=
True
,
max_length
=
256
,
verbose_name
=
'
\u5bc6\u7801
'
)),
(
'mac_addr'
,
models
.
CharField
(
blank
=
True
,
max_length
=
20
,
unique
=
True
,
verbose_name
=
'MAC
\u5730\u5740
'
)),
(
'brand'
,
models
.
CharField
(
blank
=
True
,
max_length
=
64
,
verbose_name
=
'
\u786c\u4ef6\u5382\u5546\u578b\u53f7
'
)),
(
'cpu'
,
models
.
CharField
(
blank
=
True
,
max_length
=
64
,
verbose_name
=
'CPU'
)),
(
'memory'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
verbose_name
=
'
\u5185\u5b58
'
)),
(
'disk'
,
models
.
CharField
(
blank
=
True
,
max_length
=
1024
,
verbose_name
=
'
\u786c\u76d8
'
)),
(
'os'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
verbose_name
=
'
\u7cfb\u7edf\u4fe1\u606f
'
)),
(
'cabinet_no'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u673a\u67dc\u53f7
'
)),
(
'cabinet_pos'
,
models
.
IntegerField
(
blank
=
True
,
null
=
True
,
verbose_name
=
'
\u8d44\u4ea7\u4f4d\u7f6e
'
)),
(
'number'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
unique
=
True
,
verbose_name
=
'
\u8d44\u4ea7\u7f16\u53f7
'
)),
(
'sn'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
unique
=
True
,
verbose_name
=
'SN
\u7f16\u53f7
'
)),
(
'created_by'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u521b\u5efa\u8005
'
)),
(
'is_active'
,
models
.
BooleanField
(
default
=
True
,
verbose_name
=
'
\u662f\u5426\u6fc0\u6d3b
'
)),
(
'date_added'
,
models
.
DateTimeField
(
auto_now
=
True
,
null
=
True
)),
(
'comment'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
verbose_name
=
'
\u5907\u6ce8
'
)),
],
options
=
{
'db_table'
:
'asset'
,
},
),
migrations
.
CreateModel
(
name
=
'AssetExtend'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
],
),
migrations
.
CreateModel
(
name
=
'AssetGroup'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'name'
,
models
.
CharField
(
max_length
=
64
,
unique
=
True
)),
(
'created_by'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u521b\u5efa\u8005
'
)),
(
'comment'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
null
=
True
)),
],
options
=
{
'db_table'
:
'assetgroup'
,
},
),
migrations
.
CreateModel
(
name
=
'IDC'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
auto_created
=
True
,
primary_key
=
True
,
serialize
=
False
,
verbose_name
=
'ID'
)),
(
'name'
,
models
.
CharField
(
max_length
=
32
,
verbose_name
=
'
\u673a\u623f\u540d\u79f0
'
)),
(
'bandwidth'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u673a\u623f\u5e26\u5bbd
'
)),
(
'contact'
,
models
.
CharField
(
blank
=
True
,
max_length
=
16
,
verbose_name
=
'
\u8054\u7cfb\u4eba
'
)),
(
'phone'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u8054\u7cfb\u7535\u8bdd
'
)),
(
'address'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
verbose_name
=
'
\u673a\u623f\u5730\u5740
'
)),
(
'network'
,
models
.
TextField
(
blank
=
True
,
verbose_name
=
'IP
\u5730\u5740\u6bb5
'
)),
(
'date_added'
,
models
.
DateField
(
auto_now
=
True
,
null
=
True
)),
(
'operator'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u8fd0\u8425\u5546
'
)),
(
'created_by'
,
models
.
CharField
(
blank
=
True
,
max_length
=
32
,
verbose_name
=
'
\u521b\u5efa\u8005
'
)),
(
'comment'
,
models
.
CharField
(
blank
=
True
,
max_length
=
128
,
verbose_name
=
'
\u5907\u6ce8
'
)),
],
options
=
{
'db_table'
:
'idc'
,
'verbose_name'
:
'IDC
\u673a\u623f
'
,
'verbose_name_plural'
:
'IDC
\u673a\u623f
'
,
},
),
migrations
.
AddField
(
model_name
=
'asset'
,
name
=
'env'
,
field
=
models
.
ManyToManyField
(
blank
=
True
,
related_name
=
'asset_env_extend'
,
to
=
'assets.AssetExtend'
,
verbose_name
=
'
\u6240\u5c5e\u4e3b\u673a\u7ec4\u73af\u5883
'
),
),
migrations
.
AddField
(
model_name
=
'asset'
,
name
=
'group'
,
field
=
models
.
ManyToManyField
(
blank
=
True
,
to
=
'assets.AssetGroup'
,
verbose_name
=
'
\u6240\u5c5e\u4e3b\u673a\u7ec4
'
),
),
migrations
.
AddField
(
model_name
=
'asset'
,
name
=
'idc'
,
field
=
models
.
ForeignKey
(
blank
=
True
,
null
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
to
=
'assets.IDC'
,
verbose_name
=
'
\u673a\u623f
'
),
),
migrations
.
AddField
(
model_name
=
'asset'
,
name
=
'status'
,
field
=
models
.
ManyToManyField
(
blank
=
True
,
related_name
=
'asset_status_extend'
,
to
=
'assets.AssetExtend'
,
verbose_name
=
'
\u8d44\u4ea7\u72b6\u6001
'
),
),
migrations
.
AddField
(
model_name
=
'asset'
,
name
=
'type'
,
field
=
models
.
ManyToManyField
(
blank
=
True
,
related_name
=
'asset_type_extend'
,
to
=
'assets.AssetExtend'
,
verbose_name
=
'
\u8d44\u4ea7\u7c7b\u578b
'
),
),
]
apps/assets/migrations/0002_auto_20160821_1757.py
0 → 100644
View file @
1b9c9c48
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-08-21 09:57
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'assets'
,
'0001_initial'
),
]
operations
=
[
migrations
.
AlterField
(
model_name
=
'asset'
,
name
=
'cabinet_pos'
,
field
=
models
.
IntegerField
(
blank
=
True
,
max_length
=
4
,
verbose_name
=
'
\u673a\u5668\u4f4d\u7f6e
'
),
),
]
apps/assets/migrations/0003_auto_20160821_1759.py
0 → 100644
View file @
1b9c9c48
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-08-21 09:59
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'assets'
,
'0002_auto_20160821_1757'
),
]
operations
=
[
migrations
.
AlterField
(
model_name
=
'asset'
,
name
=
'cabinet_pos'
,
field
=
models
.
IntegerField
(
blank
=
True
,
max_length
=
4
,
null
=
True
,
verbose_name
=
'
\u673a\u5668\u4f4d\u7f6e
'
),
),
]
apps/assets/models.py
View file @
1b9c9c48
# coding:utf-8
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
,
absolute_import
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
class
AssetGroup
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
64
,
unique
=
True
)
created_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"创建者"
)
comment
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
)
name
=
models
.
CharField
(
max_length
=
64
,
unique
=
True
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Name'
)
)
created_by
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
)
)
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
)
)
def
__unicode__
(
self
):
return
self
.
name
...
...
@@ -17,71 +18,137 @@ class AssetGroup(models.Model):
class
IDC
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
u'机房名称'
)
bandwidth
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
default
=
''
,
verbose_name
=
u'机房带宽'
)
contact
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
null
=
True
,
default
=
''
,
verbose_name
=
u'联系人'
)
phone
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
default
=
''
,
verbose_name
=
u'联系电话'
)
address
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
default
=
''
,
verbose_name
=
u"机房地址"
)
network
=
models
.
TextField
(
blank
=
True
,
null
=
True
,
default
=
''
,
verbose_name
=
u"IP地址段"
)
date_added
=
models
.
DateField
(
auto_now
=
True
,
null
=
True
)
operator
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
default
=
''
,
null
=
True
,
verbose_name
=
u"运营商"
)
created_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"创建者"
)
comment
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
default
=
''
,
null
=
True
,
verbose_name
=
u"备注"
)
name
=
models
.
CharField
(
max_length
=
32
,
verbose_name
=
_
(
'Name'
)
)
bandwidth
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Bandwidth'
)
)
contact
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
verbose_name
=
_
(
'Contact'
)
)
phone
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Phone'
)
)
address
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
"Address"
)
)
network
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Network'
)
)
date_added
=
models
.
DateField
(
auto_now
=
True
,
null
=
True
,
verbose_name
=
_
(
'Date added'
)
)
operator
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Operator'
)
)
created_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
)
)
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
)
)
def
__unicode__
(
self
):
return
self
.
name
class
Meta
:
db_table
=
'idc'
verbose_name
=
u"IDC机房"
verbose_name_plural
=
verbose_name
class
AssetExtend
(
models
.
Model
):
pass
key
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'KEY'
))
value
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'VALUE'
))
created_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
"Created by"
))
date_added
=
models
.
DateTimeField
(
auto_now
=
True
,
null
=
True
,
blank
=
True
)
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
def
__unicode__
(
self
):
return
self
.
name
class
Meta
:
db_table
=
'assetextend'
class
Asset
(
models
.
Model
):
ip
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
"主机IP"
)
other_ip
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
,
null
=
True
,
verbose_name
=
"其他IP"
)
remote_card_ip
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'远控卡IP'
)
hostname
=
models
.
CharField
(
unique
=
True
,
max_length
=
128
,
verbose_name
=
u"主机名"
)
port
=
models
.
IntegerField
(
blank
=
True
,
null
=
True
,
verbose_name
=
u"端口号"
)
group
=
models
.
ManyToManyField
(
AssetGroup
,
blank
=
True
,
verbose_name
=
u"所属主机组"
)
username
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"管理用户名"
)
password
=
models
.
CharField
(
max_length
=
256
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"密码"
)
idc
=
models
.
ForeignKey
(
IDC
,
blank
=
True
,
null
=
True
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
u'机房'
)
mac_addr
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"MAC地址"
)
brand
=
models
.
CharField
(
max_length
=
64
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'硬件厂商型号'
)
cpu
=
models
.
CharField
(
max_length
=
64
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'CPU'
)
memory
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'内存'
)
disk
=
models
.
CharField
(
max_length
=
1024
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'硬盘'
)
os
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'系统信息'
)
cabinet_no
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'机柜号'
)
cabinet_pos
=
models
.
IntegerField
(
blank
=
True
,
null
=
True
,
verbose_name
=
u'机器位置'
)
number
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
u'资产编号'
)
status
=
models
.
ManyToManyField
(
AssetExtend
,
blank
=
True
,
related_name
=
"asset_status_extend"
,
verbose_name
=
"机器状态"
)
type
=
models
.
ManyToManyField
(
AssetExtend
,
blank
=
True
,
related_name
=
"asset_type_extend"
,
verbose_name
=
"机器类型"
)
env
=
models
.
ManyToManyField
(
AssetExtend
,
blank
=
True
,
related_name
=
"asset_env_extend"
,
verbose_name
=
"所属主机组环境"
)
sn
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"SN编号"
)
created_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"创建者"
)
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
u"是否激活"
)
date_added
=
models
.
DateTimeField
(
auto_now
=
True
,
null
=
True
)
comment
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
,
verbose_name
=
u"备注"
)
class
AdminUser
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Name'
))
username
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Username'
))
password
=
models
.
CharField
(
max_length
=
256
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Password'
))
private_key
=
models
.
CharField
(
max_length
=
4096
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'SSH private key'
))
is_default
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'As default'
))
auto_update
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Auto update pass/key'
))
date_added
=
models
.
DateTimeField
(
auto_now
=
True
,
null
=
True
,
blank
=
True
)
create_by
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
comment
=
models
.
TextField
(
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
def
__unicode__
(
self
):
return
self
.
ip
return
self
.
name
class
Meta
:
db_table
=
'asset'
db_table
=
'adminuser'
class
SysUser
(
models
.
Model
):
PROTOCOL_CHOICES
=
(
(
'ssh'
,
'ssh'
),
(
'telnet'
,
'telnet'
),
)
name
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Name'
))
username
=
models
.
CharField
(
max_length
=
16
,
blank
=
True
,
verbose_name
=
_
(
'Username'
))
password
=
models
.
CharField
(
max_length
=
256
,
blank
=
True
,
verbose_name
=
_
(
'Password'
))
protocol
=
models
.
CharField
(
max_length
=
16
,
default
=
'ssh'
,
verbose_name
=
_
(
'Protocol'
))
private_key
=
models
.
CharField
(
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'SSH private key'
))
public_key
=
models
.
CharField
(
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'SSH public key'
))
is_default
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'As default'
))
auto_push
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Auto push'
))
auto_update
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Auto update pass/key'
))
sudo
=
models
.
TextField
(
max_length
=
4096
,
blank
=
True
,
verbose_name
=
_
(
'Sudo'
))
shell
=
models
.
CharField
(
max_length
=
64
,
blank
=
True
,
verbose_name
=
_
(
'Shell'
))
home
=
models
.
CharField
(
max_length
=
64
,
blank
=
True
,
verbose_name
=
_
(
'Home'
))
uid
=
models
.
IntegerField
(
blank
=
True
,
verbose_name
=
_
(
'Uid'
))
date_added
=
models
.
DateTimeField
(
auto_now
=
True
,
null
=
True
)
create_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
comment
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
def
__unicode__
(
self
):
return
self
.
name
class
Meta
:
db_table
=
'sysuser'
class
Asset
(
models
.
Model
):
ip
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'IP'
))
other_ip
=
models
.
CharField
(
max_length
=
255
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Other IP'
))
remote_card_ip
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Remote card IP'
))
hostname
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Hostname'
))
port
=
models
.
IntegerField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Port'
))
groups
=
models
.
ManyToManyField
(
AssetGroup
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Asset groups'
))
username
=
models
.
CharField
(
max_length
=
16
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Admin user'
))
password
=
models
.
CharField
(
max_length
=
256
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
"Admin password"
))
admin_user
=
models
.
ForeignKey
(
AdminUser
,
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
"Admin User"
))
sys_user
=
models
.
ManyToManyField
(
SysUser
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
"Sys User"
))
idc
=
models
.
ForeignKey
(
IDC
,
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
'IDC'
))
mac_addr
=
models
.
CharField
(
max_length
=
20
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
"Mac address"
))
brand
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Brand'
))
cpu
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'CPU'
))
memory
=
models
.
CharField
(
max_length
=
128
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Memory'
))
disk
=
models
.
CharField
(
max_length
=
1024
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Disk'
))
os
=
models
.
CharField
(
max_length
=
128
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'OS'
))
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'
))
number
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
unique
=
True
,
verbose_name
=
_
(
'Asset number'
))
status
=
models
.
ManyToManyField
(
AssetExtend
,
related_name
=
"asset_status_extend"
,
verbose_name
=
_
(
'Asset status'
))
type
=
models
.
ManyToManyField
(
AssetExtend
,
related_name
=
"asset_type_extend"
,
verbose_name
=
_
(
'Asset type'
))
env
=
models
.
ManyToManyField
(
AssetExtend
,
related_name
=
"asset_env_extend"
,
verbose_name
=
_
(
'Asset environment'
))
sn
=
models
.
CharField
(
max_length
=
128
,
null
=
True
,
blank
=
True
,
unique
=
True
,
verbose_name
=
_
(
'Serial number'
))
created_by
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
date_added
=
models
.
DateTimeField
(
auto_now
=
True
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Date added'
))
comment
=
models
.
CharField
(
max_length
=
128
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
def
__unicode__
(
self
):
return
self
.
ip
def
initial
(
self
):
pass
class
Meta
:
db_table
=
'asset'
index_together
=
(
'ip'
,
'port'
)
class
Label
(
models
.
Model
):
key
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'KEY'
))
value
=
models
.
CharField
(
max_length
=
64
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'VALUE'
))
asset
=
models
.
ForeignKey
(
Asset
,
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
,
verbose_name
=
_
(
'Asset'
))
created_by
=
models
.
CharField
(
max_length
=
32
,
blank
=
True
,
verbose_name
=
_
(
"Created by"
))
date_added
=
models
.
DateTimeField
(
auto_now
=
True
,
null
=
True
)
comment
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
def
__unicode__
(
self
):
return
self
.
name
class
Meta
:
db_table
=
'label'
apps/assets/templates/assets/asset_add.html
View file @
1b9c9c48
{% extends 'base.html' %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-10"
>
<div
class=
"ibox float-e-margins"
>
<div
id=
"ibox-content"
class=
"ibox-title"
>
<h5>
填写资产基本信息
</h5>
<h5>
添加资产
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
...
...
@@ -22,81 +27,73 @@
<div
class=
"ibox-content"
>
<div
class=
"panel blank-panel"
>
<div
class=
"panel-options"
>
<ul
class=
"nav nav-tabs"
>
<li
class=
"active"
><a
href=
"{% url 'assets:asset-add' %}"
class=
"text-center"
><i
class=
"fa fa-laptop"
></i>
单台添加
</a></li>
{#
<li><a
href=
"{% url 'asset_add_batch' %}"
class=
"text-center"
><i
class=
"fa fa-bar-chart-o"
></i>
批量添加
</a></li>
#}
</ul>
</div>
<div
class=
"panel-body"
>
<div
class=
"tab-content"
>
<div
id=
"tab-1"
class=
"ibox float-e-margins tab-pane active"
>
{% if error %}
<div
class=
"alert alert-warning text-center"
>
{{ error }}
</div>
{% endif %}
{% if msg %}
<div
class=
"alert alert-success text-center"
>
{{ msg }}
</div>
{% endif %}
<div
id=
"tab-1"
class=
"ibox float-e-margins tab-pane active"
></div>
<form
id=
"assetForm"
method=
"post"
class=
"form-horizontal"
>
{% csrf_token %}
<h3
class=
"widget-head-color-box"
>
基本信息
</h3>
{{ form.hostname|bootstrap_horizontal }}
<div
class=
"hr-line-dashed"
></div>
{{ form.ip|bootstrap_horizontal }}
<p
class=
"col-sm-offset-2"
>
Tips: 如果IP地址不填写, IP默认会设置与主机名一致
</p>
{#
<div
class=
"hr-line-dashed"
></div>
#}
{#
<div
class=
"form-group"
>
#}
{#
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
管理用户
<span
class=
"red-fonts"
>
*
</span></label>
#}
{#
<div
class=
"col-sm-2"
>
#}
{#
<div
class=
"radio i-checks"
>
#}
{#
<label
style=
"padding-left: 0"
>
#}
{#
<input
type=
"checkbox"
checked=
"checked"
id=
"id_use_default_auth"
name=
"use_default_auth"
><span>
使用默认
</span>
#}
{#
</label>
#}
{#
</div>
#}
{#
</div>
#}
{#
</div>
#}
{#
<p
class=
"col-sm-offset-2"
>
Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户
</p>
#}
{#
<div
class=
"form-group"
id=
"admin_account"
style=
"display: none"
>
#}
{#
<label
class=
"col-sm-2 control-label"
>
<span
class=
"red-fonts"
></span>
</label>
#}
{#
<div
class=
"col-sm-3"
>
#}
{#
<input
type=
"text"
placeholder=
"Username"
name=
"username"
class=
"form-control"
>
#}
{#
</div>
#}
{##}
{#
<label
class=
"col-sm-1 control-label"
>
<span
class=
"red-fonts"
></span>
</label>
#}
{#
<div
class=
"col-sm-4"
>
#}
{#
<input
type=
"password"
placeholder=
"Password"
name=
"password"
class=
"form-control"
>
#}
{#
</div>
#}
{#
</div>
#}
<div
class=
"form-group"
id=
"id_port"
>
<div
class=
"hr-line-dashed"
></div>
<label
class=
"col-sm-2 control-label"
>
端口
<span
class=
"red-fonts"
>
*
</span>
</label>
<div
class=
"col-sm-8"
>
<input
type=
"text"
placeholder=
"Port"
name=
"port"
class=
"form-control"
value=
"{{ default_port }}"
>
<label
class=
"col-sm-2 control-label"
>
端口
</label>
<div
class=
"col-sm-9"
>
<input
type=
"text"
placeholder=
""
name=
"port"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
{{ form.group|bootstrap_horizontal }}
{#
<div
class=
"form-group"
id=
"id_type"
>
#}
{#
<label
class=
"col-sm-2 control-label"
>
资产类型
</label>
#}
{#
<div
class=
"col-sm-9"
>
#}
{#
<input
type=
"text"
placeholder=
""
name=
"type"
class=
"form-control"
>
#}
{#
</div>
#}
{#
</div>
#}
{{ form.type|bootstrap_horizontal }}
{# {{ af.is_active|bootstrap_horizontal }}#
}
{{ form.comment|bootstrap_horizontal }
}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
><label
class=
"col-sm-2 control-label"
>
是否激活
<span
class=
"red-fonts"
>
*
</span>
</label>
<div
class=
"col-sm-8"
>
<h3>
关联资产用户
</h3>
<div
class=
"form-group"
>
<label
for=
"j_group"
class=
"col-sm-2 control-label"
>
管理用户
</label>
<div
class=
"col-sm-9"
>
<div
class=
"radio i-checks"
>
<label>
<input
type=
"radio"
checked=
""
value=
"1"
name=
"is_active"
>
激活
</label>
<label>
<input
type=
"radio"
value=
"0"
name=
"is_active"
>
禁用
</label>
<label><input
type=
"radio"
checked=
"checked"
id=
"id_use_default_auth"
name=
"use_default_auth"
><span>
使用预定义管理用户
</span>
</label>
<label><input
type=
"radio"
id=
"id_use_default_auth"
name=
"use_default_auth"
><span>
自定义
</span>
</label>
</div>
</div>
</div>
<div
class=
"form-group"
id=
"id_manager_user"
>
<div
class=
"col-sm-offset-2 col-sm-9"
>
<input
type=
"text"
placeholder=
"请选择管理用户"
name=
"manager_user"
class=
"form-control"
>
</div>
</div>
<p
class=
"col-sm-offset-2"
>
Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户
</p>
<div
class=
"form-group"
>
<label
for=
"system_user"
class=
"col-sm-2 control-label"
>
系统用户
</label>
<div
class=
"col-sm-9"
>
<input
type=
"text"
placeholder=
""
name=
"system_user"
class=
"form-control"
>
</div>
</div>
<div
class=
"hr-line-dashed"
></div>
<h3>
所属
</h3>
{{ form.idc|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div
class=
"hr-line-dashed"
></div>
<h3>
标签
</h3>
<div
class=
"hr-line-dashed"
></div>
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-
2
"
>
<div
class=
"col-sm-4 col-sm-offset-
5
"
>
<button
class=
"btn btn-white"
type=
"reset"
>
重置
</button>
<button
class=
"btn btn-primary"
type=
"submit"
>
提交
</button>
</div>
...
...
@@ -113,85 +110,10 @@
</div>
{% endblock %}
{% block self_footer_js %}
<script>
$
(
'document'
).
ready
(
function
(){
var
check_default
=
"{{ default_setting.name }}"
;
console
.
log
(
check_default
);
if
(
check_default
!=
'default'
){
$
(
'#id_use_default_auth'
).
attr
(
'disabled'
,
true
);
$
(
'#id_use_default_auth'
).
attr
(
'checked'
,
false
);
$
(
'#admin_account'
).
css
(
'display'
,
'block'
);
}
else
{
$
(
'#id_use_default_auth'
).
click
(
function
(){
if
(
$
(
this
).
is
(
':checked'
)){
$
(
'#admin_account'
).
css
(
'display'
,
'none'
);
}
else
{
$
(
'#admin_account'
).
css
(
'display'
,
'block'
);
}
})
}
});
var
required_fields
=
[
"id_hostname"
,
"id_port"
];
required_fields
.
forEach
(
function
(
field
)
{
$
(
'label[for="'
+
field
+
'"]'
).
parent
().
addClass
(
"required"
);
});
$
(
'#assetForm'
).
validator
({
timely
:
2
,
theme
:
"yellow_right_effect"
,
rules
:
{
check_ip
:
[
/^
(\d{1,2}
|1
\d\d
|2
[
0-4
]\d
|25
[
0-5
])(\.(\d{1,2}
|1
\d\d
|2
[
0-4
]\d
|25
[
0-5
])){3}
$/
,
'ip地址不正确'
],
check_port
:
[
/^
\d{1,5}
$/
,
'端口号不正确'
],
use_default_auth
:
function
()
{
var
str1
=
$
(
"#id_use_default_auth"
).
is
(
":checked"
);
if
(
str1
==
true
){
var
decide
=
false
;
}
else
{
var
decide
=
true
;
}
return
decide
}
},
fields
:
{
"ip"
:
{
rule
:
"check_ip;"
,
tip
:
"输入IP"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
},
"hostname"
:
{
rule
:
"required;length[0~53]"
,
tip
:
"填写主机名"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
},
"port"
:
{
rule
:
"required"
,
tip
:
"输入端口号"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
},
"username"
:
{
rule
:
"required(use_default_auth)"
,
tip
:
"输入用户名"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
},
"password"
:
{
rule
:
"required(use_default_auth);length[0~64]"
,
tip
:
"输入密码"
,
ok
:
""
,
msg
:
{
required
:
"必须填写!"
}
}
},
valid
:
function
(
form
)
{
form
.
submit
();
}
});
</script>
{% block custom_foot_js %}
<script>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
})
</script>
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/asset_detail.html
0 → 100644
View file @
1b9c9c48
{% extends 'base.html' %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-4"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<span
class=
"text text-primary"
><b>
{{ asset.ip }}
</b></span>
<div
class=
"ibox-tools"
>
{#
<a
class=
""
href=
"{% url 'assets:asset-update' %}"
>
#}
<i
class=
"fa fa-refresh"
></i>
</a>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<ul
class=
"dropdown-menu dropdown-user"
>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content ibox-heading"
>
<h3>
主机详细信息
</h3>
<small><i
class=
"fa fa-map-marker"
></i>
此主机详细信息.
</small>
</div>
<div
class=
"ibox-content"
>
<div>
<div
class=
"text-left"
>
<table
class=
"table"
>
<tr>
<td
class=
"text-navy"
>
主机名
</td>
<td>
{{ asset.hostname|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
IP
</td>
<td>
{{ asset.ip|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
其他IP
</td>
<td>
<table
class=
"table"
>
{% if asset.other_ip %}
{% for ip in asset.other_ip %}
<tr>
<td>
{{ ip }}
</td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
远控IP
</td>
<td>
{{ asset.remote_ip|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
端口
</td>
<td>
{{ asset.port|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
主机组
</td>
<td>
<table
class=
"table"
>
{% for asset_group in asset.group.all %}
<tr>
<td>
{{ asset_group.name|default_if_none:"" }}
</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
使用默认管理账号
</td>
{#
<td>
{{ asset.use_default_auth|bool2str }}
</td>
#}
{#
<td>
{{ asset.use_default_auth|bool2str }} {% if not asset.use_default_auth %}
<span
class=
"text-info"
>
{{ asset.username }}
</span>
{% endif %}
</td>
#}
</tr>
<tr>
<td
class=
"text-navy"
>
机房
</td>
<td>
{{ asset.idc.name|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
硬件厂商型号
</td>
<td>
{{ asset.brand|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
CPU
</td>
<td>
{{ asset.cpu|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
内存
</td>
<td>
{{ asset.memory|default_if_none:"" }}{% if asset.memory %}G{% endif %}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
硬盘
</td>
<td>
<table
class=
"table"
>
{% if asset.disk %}
{% for disk, value in asset.disk %}
<tr>
<td><span
class=
"text-navy"
>
{{ disk|default_if_none:"" }}
</span>
&
nbsp
&
nbsp
&
nbsp {{ value|default_if_none:"" }}
</td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
资产编号
</td>
<td>
{{ asset.number|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
SN
</td>
<td>
{{ asset.sn|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
主机类型
</td>
<td>
{{ asset.get_asset_type_display|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
系统版本
</td>
<td>
{{ asset.system_type|default_if_none:"" }} {{ asset.system_version|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
系统平台
</td>
<td>
{{ asset.system_arch|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
运行环境
</td>
<td>
{{ asset.get_env_display|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
机器状态
</td>
<td>
{{ asset.get_status_display|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
机柜号
</td>
<td>
{{ asset.cabinet|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
机柜位置
</td>
<td>
{{ asset.position|default_if_none:"" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
激活
</td>
<td>
{{ asset.is_active }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
添加日期
</td>
<td>
{{ asset.date_added|date:"Y-m-d H:i:s" }}
</td>
</tr>
<tr>
<td
class=
"text-navy"
>
备注
</td>
<td>
{{ asset.comment|default_if_none:"" }}
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div
class=
"col-sm-4"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<h5>
拥有权限的用户
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<ul
class=
"dropdown-menu dropdown-user"
>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content ibox-heading"
>
<h3>
主机所有授权的信息
</h3>
<small><i
class=
"fa fa-map-marker"
></i>
包含了此主机所有授权的信息.
</small>
</div>
<div
class=
"ibox-content"
>
<div>
<div
class=
"text-left"
>
{% if perm_info %}
{% if user_perm %}
<table
class=
"table"
>
<p>
授权用户信息
</p>
<td
class=
"text-navy"
>
授权用户
</td>
<td
class=
"text-navy"
>
关联用户
</td>
{% for perm in user_perm %}
<tr>
<td
class=
"text-navy"
><a
href=
"{% url 'user_detail' %}?id={{ perm.0.id }}"
>
{{ perm.0 }}
</a></td>
<td>
<table
class=
"table"
>
{% if perm.1 %}
{% for role in perm.1 %}
<tr>
<td
class=
"text-navy"
><a
href=
"{% url 'role_detail' %}?id={{ role.id }}"
>
{{ role }}
</a></td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if user_group_perm %}
<table
class=
"table"
>
<p>
授权用户组信息
</p>
<td
class=
"text-navy"
>
授权用户组
</td>
<td
class=
"text-navy"
>
组详情
</td>
{% for user_group in user_group_perm %}
<tr>
<td
class=
"text-navy"
>
{{ user_group }}
</td>
<td
class=
"text-navy"
><a
href=
"{% url 'user_group_list' %}?gid={{ user_group.id }}"
>
详情
</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if user_rule_perm %}
<table
class=
"table"
>
<p>
授权规则信息
</p>
<td
class=
"text-navy"
>
授权规则
</td>
<td
class=
"text-navy"
>
详情
</td>
{% for rule in user_rule_perm %}
<tr>
<td
class=
"text-navy"
>
{{ rule }}
</td>
<td
class=
"text-navy"
><a
href=
"{% url 'rule_detail' %}?id={{ rule.id }}"
>
详情
</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
{% else %}
<p
class=
"text-center"
>
(暂无)
</p>
{% endif %}
</div>
</div>
</div>
<div
class=
"ibox-title"
>
<h5>
主机修改记录
</h5>
{#
<a
href=
"{% url 'asset_edit' %}?id={{ asset.id }}"
data-toggle=
"tooltip"
class=
"text-success pull-center"
data-placement=
"bottom"
title=
"修改"
>
&
nbsp
&
nbsp
&
nbsp
&
nbsp点击修改
</a>
#}
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<ul
class=
"dropdown-menu dropdown-user"
>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content ibox-heading"
>
<h3>
主机修改记录
</h3>
<small><i
class=
"fa fa-map-marker"
></i>
包含了此主机所有历史修改记录.
</small>
</div>
<div
class=
"ibox-content"
>
<div
class=
"feed-activity-list"
>
{% if asset_record %}
{# {% for r in asset_record %}#}
{#
<div
class=
"feed-element"
>
#}
{#
<div>
#}
{#
<small
class=
"pull-right"
>
{{ r.alert_time|naturaltime }}
</small>
#}
{#
<strong
class=
"text-navy"
>
{{ r.username }}
</strong>
#}
{# {% for i in r.content|str_to_list %}#}
{#
<div>
{{ i.0 }} 由
<span
class=
"text-success"
>
{{ i.1|str_to_code }}
</span>
改为
<span
class=
"text-warning"
>
{{ i.2|str_to_code }}
</span></div>
#}
{# {% endfor %}#}
{#
<small
class=
"text-success"
>
{{ r.alert_time }}
</small>
#}
{#
</div>
#}
{#
</div>
#}
{# {% endfor %}#}
{% else %}
<p
class=
"text-center"
>
(暂无)
</p>
{% endif %}
</div>
</div>
</div>
</div>
<div
class=
"col-sm-4"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<h5>
最近一周登录记录
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<ul
class=
"dropdown-menu dropdown-user"
>
</ul>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content ibox-heading"
>
<h3>
最近一周登录记录
</h3>
<small><i
class=
"fa fa-map-marker"
></i>
此主机最近一周用户登录信息.
</small>
</div>
<div
class=
"ibox-content inspinia-timeline"
>
{% if log %}
{% for l in log %}
<div
class=
"timeline-item"
>
<div
class=
"row"
>
<div
class=
"col-xs-5 date"
>
<i
class=
"fa fa-info-circle"
></i>
<small
class=
"text-navy"
>
{{ l.user }}
</small>
<br/>
</div>
<div
class=
"col-xs-7 content no-top-border"
>
<p
class=
"m-b-xs"
><strong>
详细信息
</strong></p>
<p>
来源IP: {{ l.remote_ip }}
</p>
<p>
开始: {{ l.start_time |date:"Y-m-d H:i:s" }}
</p>
<p>
结束: {{ l.end_time |date:"Y-m-d H:i:s" }}
</p>
</div>
</div>
</div>
{% endfor %}
<button
id=
"show"
class=
"btn btn-primary btn-block m-t"
><i
class=
"fa fa-arrow-down"
></i>
所有
</button>
<div
id=
'more'
style=
"display: none"
>
<br/>
{% for l in log_more %}
<div
class=
"timeline-item"
>
<div
class=
"row"
>
<div
class=
"col-xs-5 date"
>
<i
class=
"fa fa-info-circle"
></i>
<small
class=
"text-navy"
>
{{ l.user }}
</small>
<br/>
</div>
<div
class=
"col-xs-7 content no-top-border"
>
<p
class=
"m-b-xs"
><strong>
详细信息
</strong></p>
<p>
来源IP: {{ l.remote_ip }}
</p>
<p>
开始: {{ l.start_time |date:"Y-m-d H:i:s" }}
</p>
<p>
结束: {{ l.end_time |date:"Y-m-d H:i:s" }}
</p>
</div>
</div>
</div>
{% endfor %}
{% else %}
<p
class=
"text-center"
>
(暂无)
</p>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$
(
document
).
ready
(
function
(){
$
(
'#show'
).
click
(
function
(){
$
(
'#show'
).
css
(
'display'
,
'none'
);
$
(
'#more'
).
css
(
'display'
,
'block'
);
})
})
</script>
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/asset_list.html
View file @
1b9c9c48
...
...
@@ -6,7 +6,7 @@
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
id=
"all"
>
<div
class=
"ibox-title"
>
<h5>
主机详细信息
列表
</h5>
<h5>
资产
列表
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
...
...
@@ -102,14 +102,11 @@
<input
id=
"checkall"
type=
"checkbox"
class=
"i-checks"
name=
"checkall"
value=
"checkall"
data-editable=
'false'
onclick=
"check_all('asset_form')"
>
</th>
<th
class=
"text-center"
>
主机名
</th>
<th
class=
"text-center"
name=
"ip"
>
IP地址
</th>
<th
class=
"text-center"
>
IDC
</th>
<th
class=
"text-center"
>
所属主机组
</th>
{#
<th
class=
"text-center"
>
配置信息
</th>
#}
<th
class=
"text-center"
>
操作系统
</th>
<th
class=
"text-center"
>
cpu核数
</th>
<th
class=
"text-center"
>
内存
</th>
<th
class=
"text-center"
>
硬盘
</th>
<th
class=
"text-center"
name=
"ip"
>
IP
</th>
<th
class=
"text-center"
>
类型
</th>
<th
class=
"text-center"
>
配置
</th>
<th
class=
"text-center"
>
资产组
</th>
<th
class=
"text-center"
>
状态
</th>
<th
class=
"text-center"
>
操作
</th>
</tr>
</thead>
...
...
@@ -119,15 +116,18 @@
<td
class=
"text-center"
name=
"id"
value=
"{{ asset.id }}"
data-editable=
'false'
>
<input
name=
"id"
value=
"{{ asset.id }}"
type=
"checkbox"
class=
"i-checks"
>
</td>
<td
class=
"text-center hostname"
>
<a
href=
"{% url 'assets:asset-detail' %}?id={{ asset.id }}"
>
{{ asset.hostname|default_if_none:"" }}
</a></td>
<td
class=
"text-center"
>
{{ asset.ip|default_if_none:"" }}
</td>
<td
class=
"text-center"
>
{{ asset.idc.name|default_if_none:"" }}
</td>
{#
<td
class=
"text-center"
>
{{ asset.group.all|group_str2 }}
</td>
#}
{#
<td
class=
"text-center"
>
{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}
</td>
#}
<td
class=
"text-center"
>
{{ asset.system_type|default_if_none:"" }}{{ asset.system_version|default_if_none:"" }}
</td>
<td
class=
"text-center"
>
{{ asset.cpu|default_if_none:"" }}
</td>
<td
class=
"text-center"
>
{{ asset.memory|default_if_none:"" }}{% if asset.memory %}G{% endif %}
</td>
<td
class=
"text-center"
>
{{ asset.disk }}{% if asset.disk %}G{% endif %}
</td>
<td
class=
"text-center"
>
{{ asset.hostname }}
</td>
<td
class=
"text-center"
>
{{ asset.ip }}
</td>
<td
class=
"text-center"
>
{{ asset.system_type }}
</td>
<td
class=
"text-center"
>
{{ asset.cpu }} | {{ asset.memory }} | {{ asset.disk }}
</td>
<td
class=
"text-center"
>
{% for group in asset.group.all %} {{ group.name }} {% endfor %}
</td>
<td
class=
"text-center"
>
{% if asset.is_active %}
<i
class=
"fa fa-circle text-navy"
></i>
{% else %}
<i
class=
"fa fa-circle text-danger"
></i>
{% endif %}
</td>
<td
class=
"text-center"
data-editable=
'false'
>
{#
<a
href=
"{% url 'asset_edit' %}?id={{ asset.id }}"
class=
"btn btn-xs btn-info"
>
编辑
</a>
#}
<a
value=
"{{ asset.id }}"
class=
"conn btn btn-xs btn-warning"
>
连接
</a>
...
...
@@ -145,7 +145,7 @@
{#
<input
type=
"button"
id=
"asset_update_all"
class=
"btn btn-primary btn-sm"
name=
"update_button"
value=
"更新全部"
/>
#}
<input
type=
"button"
id=
"exec_cmd"
class=
"btn btn-sm btn-primary"
name=
"exec_cmd"
value=
"执行命令"
/>
</div>
{# {% include 'paginator.html' %}#
}
{% include '_pagination.html' %
}
</div>
</form>
</div>
...
...
apps/assets/templates/assets/assetgroup_add.html
0 → 100644
View file @
1b9c9c48
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link
href=
"{% static "
css
/
plugins
/
select2
/
select2
.
min
.
css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
plugins
/
select2
/
select2
.
full
.
min
.
js
"
%}"
></script>
{% endblock %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-title"
>
<h5>
{% trans 'Create asset group' %}
</h5>
<div
class=
"ibox-tools"
>
<a
class=
"collapse-link"
>
<i
class=
"fa fa-chevron-up"
></i>
</a>
<a
class=
"dropdown-toggle"
data-toggle=
"dropdown"
href=
"#"
>
<i
class=
"fa fa-wrench"
></i>
</a>
<a
class=
"close-link"
>
<i
class=
"fa fa-times"
></i>
</a>
</div>
</div>
<div
class=
"ibox-content"
>
<form
method=
"post"
id=
"userForm"
class=
"form-horizontal"
action=
""
>
{% csrf_token %}
{{ form.name|bootstrap_horizontal }}
<div
class=
"form-group"
>
<label
for=
"users"
class=
"col-sm-2 control-label"
>
{% trans 'Asset' %}
</label>
<div
class=
"col-sm-9"
>
<select
name=
"assets"
id=
"assets"
data-placeholder=
"{% trans 'Select asset' %}"
class=
"select2 form-control m-b"
multiple
tabindex=
"2"
>
{% for asset in assets %}
<option
value=
"{{ asset.id }}"
>
{{ asset.ip }}:{{ asset.port }}
</option>
{% endfor %}
</select>
</div>
</div>
{{ form.comment|bootstrap_horizontal }}
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
})
</script>
{% endblock %}
\ No newline at end of file
apps/assets/templates/assets/assetgroup_list.html
0 → 100644
View file @
1b9c9c48
{% extends '_list_base.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
<a
href=
"{% url 'assets:assetgroup-add' %}"
class=
"btn btn-sm btn-primary "
>
{% trans "Create asset group" %}
</a>
{% endblock %}
{% block table_head %}
<th
class=
"text-center"
>
<input
type=
"checkbox"
id=
"check_all"
onclick=
"checkAll('check_all', 'checked')"
>
</th>
<th
class=
"text-center"
><a
href=
"{% url 'assets:assetgroup-list' %}?sort=name"
>
{% trans 'Name' %}
</a></th>
<th
class=
"text-center"
>
{% trans 'Asset num' %}
</th>
<th
class=
"text-center"
><a
href=
"{% url 'assets:assetgroup-list' %}?sort=date_expired"
>
{% trans 'Comment' %}
</a></th>
<th
class=
"text-center"
></th>
{% endblock %}
{% block table_body %}
{% for assetgroup in assetgroups %}
<tr
class=
"gradeX"
>
<td
class=
"text-center"
>
<input
type=
"checkbox"
name=
"checked"
value=
"{{ assetgroup.id }}"
>
</td>
<td
class=
"text-center"
>
<a
href=
"{% url 'assets:assetgroup-detail' pk=assetgroup.id %}"
>
{{ assetgroup.name }}
</a>
</td>
<td
class=
"text-center"
>
{{ assetgroup.asset_set.count }}
</td>
<td
class=
"text-center"
>
{{ assetgroup.comment }}
</td>
<td
class=
"text-center"
>
<a
href=
"{% url 'assets:assetgroup-edit' pk=assetgroup.id %}"
class=
"btn btn-xs btn-info"
>
{% trans 'Edit' %}
</a>
<a
href=
"{% url 'assets:assetgroup-delete' pk=assetgroup.id %}"
class=
"btn btn-xs btn-danger del"
>
{% trans 'Delete' %}
</a>
</td>
</tr>
{% endfor %}
{% endblock %}
{% block content_bottom_left %}
<form
id=
""
method=
"get"
action=
""
class=
" mail-search"
>
<div
class=
"input-group"
>
<select
class=
"form-control m-b"
style=
"width: auto"
>
<option>
{% trans 'Delete selected' %}
</option>
<option>
{% trans 'Update selected' %}
</option>
<option>
{% trans 'Deactive selected' %}
</option>
<option>
{% trans 'Export selected' %}
</option>
</select>
<div
class=
"input-group-btn pull-left"
style=
"padding-left: 5px;"
>
<button
id=
'search_btn'
type=
"submit"
style=
"height: 32px;"
class=
"btn btn-sm btn-primary"
>
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
{% endblock %}
apps/assets/urls.py
View file @
1b9c9c48
# coding:utf-8
from
django.conf.urls
import
url
,
include
from
.views
import
*
from
.api
import
(
AssetGroupViewSet
,
AssetViewSet
,
IDCViewSet
)
from
rest_framework
import
routers
router
=
routers
.
DefaultRouter
()
router
.
register
(
r'assetgroup'
,
AssetGroupViewSet
)
router
.
register
(
r'asset'
,
AssetViewSet
)
router
.
register
(
r'idc'
,
IDCViewSet
)
from
django.conf.urls
import
url
,
include
import
views
#
from .api import (
# AssetGroupViewSet, AssetViewSet,
IDCViewSet
#
)
#
from rest_framework import routers
#
router = routers.DefaultRouter()
#
router.register(r'assetgroup', AssetGroupViewSet)
#
router.register(r'asset', AssetViewSet)
#
router.register(r'idc', IDCViewSet)
app_name
=
'assets'
urlpatterns
=
[
url
(
r'^add/$'
,
AssetAddView
.
as_view
(),
name
=
'asset-add'
),
url
(
r'^list/$'
,
AssetListView
.
as_view
(),
name
=
'asset-list'
),
url
(
r'^(?P<pk>[0-9]+)/delete/$'
,
AssetDeleteView
.
as_view
(),
name
=
'asset-list'
),
url
(
r'^(?P<pk>[0-9]+)/detail/$'
,
AssetDetailView
.
as_view
(),
name
=
'asset-detail'
),
url
(
r'^api/v1.0/'
,
include
(
router
.
urls
)),
url
(
r'^$'
,
views
.
AssetListView
.
as_view
(),
name
=
'asset-index'
),
url
(
r'^asset$'
,
views
.
AssetListView
.
as_view
(),
name
=
'asset-list'
),
url
(
r'^asset/add$'
,
views
.
AssetAddView
.
as_view
(),
name
=
'asset-add'
),
url
(
r'^asset/(?P<pk>[0-9]+)$'
,
views
.
AssetDetailView
.
as_view
(),
name
=
'asset-detail'
),
url
(
r'^asset/(?P<pk>[0-9]+)$/edit'
,
views
.
AssetEditView
.
as_view
(),
name
=
'asset-edit'
),
url
(
r'^asset/(?P<pk>[0-9]+)/delete$'
,
views
.
AssetDeleteView
.
as_view
(),
name
=
'asset-delete'
),
url
(
r'^assetgroup$'
,
views
.
AssetGroupListView
.
as_view
(),
name
=
'assetgroup-list'
),
url
(
r'^assetgroup/add$'
,
views
.
AssetGroupAddView
.
as_view
(),
name
=
'assetgroup-add'
),
url
(
r'^assetgroup/(?P<pk>[0-9]+)$'
,
views
.
AssetGroupDetailView
.
as_view
(),
name
=
'assetgroup-detail'
),
url
(
r'^assetgroup/(?P<pk>[0-9]+)/edit$'
,
views
.
AssetGroupEditView
.
as_view
(),
name
=
'assetgroup-edit'
),
url
(
r'^assetgroup/(?P<pk>[0-9]+)/delete$'
,
views
.
AssetGroupDeleteView
.
as_view
(),
name
=
'assetgroup-delete'
),
# url(r'^api/v1.0/', include(router.urls)),
]
apps/assets/utils.py
View file @
1b9c9c48
# ~*~ coding: utf-8 ~*~
#
from
django.contrib.auth.mixins
import
UserPassesTestMixin
from
django.urls
import
reverse_lazy
from
common.tasks
import
send_mail_async
from
common.utils
import
reverse
from
users.models
import
User
try
:
import
cStringIO
as
StringIO
except
ImportError
:
import
StringIO
class
AdminUserRequiredMixin
(
UserPassesTestMixin
):
login_url
=
reverse_lazy
(
'users:login'
)
def
test_func
(
self
):
return
self
.
request
.
user
.
is_staff
apps/assets/views.py
View file @
1b9c9c48
from
django.views.generic
import
(
TemplateView
,
ListView
)
# coding:utf-8
from
__future__
import
absolute_import
,
unicode_literals
from
django.utils.translation
import
ugettext
as
_
from
django.views.generic
import
TemplateView
,
ListView
from
django.urls
import
reverse_lazy
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
FormView
,
UpdateView
from
django.views.generic
import
TemplateView
,
ListView
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
FormView
,
UpdateView
from
django.urls
import
reverse_lazy
from
django.views.generic.detail
import
DetailView
from
.models
import
Asset
,
AssetGroup
,
IDC
,
AssetExtend
from
.forms
import
AssetForm
,
AssetGroupForm
from
django.views.generic.edit
import
(
CreateView
,
DeleteView
,
FormView
,
UpdateView
)
from
django.views.generic.detail
import
(
DetailView
)
from
.models
import
(
Asset
,
AssetGroup
,
IDC
,
AssetExtend
)
from
.forms
import
(
AssetForm
,
)
from
.utils
import
AdminUserRequiredMixin
class
AssetAddView
(
CreateView
):
...
...
@@ -31,8 +22,12 @@ class AssetAddView(CreateView):
template_name
=
'assets/asset_add.html'
success_url
=
reverse_lazy
(
'assets:asset-list'
)
def
form_invalid
(
self
,
form
):
print
(
form
.
errors
)
return
super
(
AssetAddView
,
self
)
.
form_invalid
(
form
)
class
AssetEdit
(
):
class
AssetEdit
View
(
UpdateView
):
pass
...
...
@@ -52,3 +47,44 @@ class AssetDetailView(DetailView):
context_object_name
=
'asset'
template_name
=
'assets/asset_detail.html'
class
AssetGroupAddView
(
CreateView
):
model
=
AssetGroup
form_class
=
AssetGroupForm
template_name
=
'assets/assetgroup_add.html'
success_url
=
reverse_lazy
(
'assets:assetgroup-list'
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Create asset group'
),
'assets'
:
Asset
.
objects
.
all
(),
}
kwargs
.
update
(
context
)
return
super
(
AssetGroupAddView
,
self
)
.
get_context_data
(
**
kwargs
)
class
AssetGroupListView
(
ListView
):
model
=
AssetGroup
context_object_name
=
'assetgroups'
template_name
=
'assets/assetgroup_list.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'app'
:
_
(
'Assets'
),
'action'
:
_
(
'Asset group list'
)
}
kwargs
.
update
(
context
)
return
super
(
AssetGroupListView
,
self
)
.
get_context_data
(
**
kwargs
)
class
AssetGroupDetailView
(
DetailView
):
pass
class
AssetGroupEditView
(
UpdateView
):
pass
class
AssetGroupDeleteView
(
DeleteView
):
pass
apps/common/templatetags/common_tags.py
View file @
1b9c9c48
# ~*~ coding: utf-8 ~*~
from
django
import
template
from
django.utils
import
timezone
from
django.conf
import
settings
register
=
template
.
Library
()
@register.filter
def
join_queryset_attr
(
queryset
,
attr
,
delimiter
=
', '
):
return
delimiter
.
join
([
getattr
(
obj
,
attr
,
''
)
for
obj
in
queryset
])
@register.filter
def
pagination_range
(
total_page
,
current_num
=
1
,
display
=
5
):
"""Return Page range
:param total_page: Total numbers of paginator
:param current_num: current display page num
:param display: Display as many as [:display:] page
In order to display many page num on web like:
< 1 2 3 4 5 >
"""
try
:
current_num
=
int
(
current_num
)
except
ValueError
:
current_num
=
1
start
=
current_num
-
display
/
2
if
current_num
>
display
/
2
else
1
end
=
start
+
display
if
start
+
display
<=
total_page
else
total_page
+
1
return
range
(
start
,
end
)
# ~*~ coding: utf-8 ~*~
from
django
import
template
from
django.utils
import
timezone
from
django.conf
import
settings
register
=
template
.
Library
()
@register.filter
def
join_queryset_attr
(
queryset
,
attr
,
delimiter
=
', '
):
return
delimiter
.
join
([
getattr
(
obj
,
attr
,
''
)
for
obj
in
queryset
])
@register.filter
def
pagination_range
(
total_page
,
current_num
=
1
,
display
=
5
):
"""Return Page range
:param total_page: Total numbers of paginator
:param current_num: current display page num
:param display: Display as many as [:display:] page
In order to display many page num on web like:
< 1 2 3 4 5 >
"""
try
:
current_num
=
int
(
current_num
)
except
ValueError
:
current_num
=
1
start
=
current_num
-
display
/
2
if
current_num
>
display
/
2
else
1
end
=
start
+
display
if
start
+
display
<=
total_page
else
total_page
+
1
return
range
(
start
,
end
)
\ No newline at end of file
apps/common/utils.py
View file @
1b9c9c48
# -*- coding: utf-8 -*-
#
from
__future__
import
unicode_literals
from
django.shortcuts
import
reverse
as
dj_reverse
from
django.conf
import
settings
def
reverse
(
viewname
,
urlconf
=
None
,
args
=
None
,
kwargs
=
None
,
current_app
=
None
,
external
=
False
):
url
=
dj_reverse
(
viewname
,
urlconf
=
urlconf
,
args
=
args
,
kwargs
=
kwargs
,
current_app
=
current_app
)
if
external
:
url
=
settings
.
SITE_URL
.
strip
(
'/'
)
+
url
return
url
def
get_object_or_none
(
model
,
**
kwargs
):
try
:
obj
=
model
.
objects
.
get
(
**
kwargs
)
except
model
.
DoesNotExist
:
obj
=
None
return
obj
# -*- coding: utf-8 -*-
#
from
__future__
import
unicode_literals
from
django.shortcuts
import
reverse
as
dj_reverse
from
django.conf
import
settings
def
reverse
(
viewname
,
urlconf
=
None
,
args
=
None
,
kwargs
=
None
,
current_app
=
None
,
external
=
False
):
url
=
dj_reverse
(
viewname
,
urlconf
=
urlconf
,
args
=
args
,
kwargs
=
kwargs
,
current_app
=
current_app
)
if
external
:
url
=
settings
.
SITE_URL
.
strip
(
'/'
)
+
url
return
url
def
get_object_or_none
(
model
,
**
kwargs
):
try
:
obj
=
model
.
objects
.
get
(
**
kwargs
)
except
model
.
DoesNotExist
:
obj
=
None
return
obj
apps/jumpserver/settings.py
View file @
1b9c9c48
...
...
@@ -132,7 +132,7 @@ else:
# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
#
AUTH_PASSWORD_VALIDATORS
=
[
{
'NAME'
:
'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'
,
...
...
@@ -215,7 +215,7 @@ LOGGING = {
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE
=
'
zh_CN
'
LANGUAGE_CODE
=
'
en_US
'
TIME_ZONE
=
'Asia/Shanghai'
...
...
apps/locale/zh_CN/LC_MESSAGES/django.po
View file @
1b9c9c48
...
...
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-04 1
2:20
+0800\n"
"POT-Creation-Date: 2016-09-04 1
7:31
+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
...
...
@@ -17,6 +17,140 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: assets/models.py:9 assets/models.py:21
msgid "Name"
msgstr "名称"
#: assets/models.py:10 assets/models.py:29 assets/models.py:71
msgid "Created by"
msgstr "创建者"
#: assets/models.py:11 assets/models.py:30 assets/models.py:74
msgid "Comment"
msgstr "备注"
#: assets/models.py:22
msgid "Bandwidth"
msgstr "带宽"
#: assets/models.py:23
msgid "Contact"
msgstr "联系人"
#: assets/models.py:24
msgid "Phone"
msgstr "手机"
#: assets/models.py:25
msgid "Address"
msgstr "地址"
#: assets/models.py:26
msgid "Network"
msgstr "网络"
#: assets/models.py:27 assets/models.py:73
msgid "Date added"
msgstr "加入日期"
#: assets/models.py:28
msgid "Operator"
msgstr "运营商"
#: assets/models.py:37 assets/models.py:54 templates/_nav.html:23
msgid "IDC"
msgstr "机房"
#: assets/models.py:46
msgid "IP"
msgstr ""
#: assets/models.py:47
msgid "Other IP"
msgstr ""
#: assets/models.py:48
msgid "Remote card IP"
msgstr ""
#: assets/models.py:49
msgid "Hostname"
msgstr "用户名"
#: assets/models.py:50
msgid "Port"
msgstr "端口"
#: assets/models.py:51
msgid "Asset groups"
msgstr "用户组"
#: assets/models.py:52
#, fuzzy
#| msgid "Edit user"
msgid "Admin user"
msgstr "编辑用户"
#: assets/models.py:53
msgid "Admin password"
msgstr "管理员密码"
#: assets/models.py:55
msgid "Mac address"
msgstr "Mac地址"
#: assets/models.py:56
msgid "Brand"
msgstr "品牌"
#: assets/models.py:57
msgid "CPU"
msgstr "CPU"
#: assets/models.py:58
msgid "Memory"
msgstr "内存"
#: assets/models.py:59
msgid "Disk"
msgstr "硬盘"
#: assets/models.py:60
msgid "OS"
msgstr "操作系统"
#: assets/models.py:61
msgid "Cabinet number"
msgstr "机柜编号"
#: assets/models.py:62
msgid "Cabinet position"
msgstr "机柜层号"
#: assets/models.py:63
msgid "Asset number"
msgstr "资产编号"
#: assets/models.py:65
msgid "Asset status"
msgstr "资产状态"
#: assets/models.py:67
msgid "Asset type"
msgstr "系统类型"
#: assets/models.py:69
msgid "Asset environment"
msgstr "资产环境"
#: assets/models.py:70
msgid "Serial number"
msgstr "序列号"
#: assets/models.py:72
msgid "Is active"
msgstr "是否激活"
#: templates/_header_bar.html:8
msgid "Search"
msgstr "搜索"
...
...
@@ -57,16 +191,16 @@ msgstr "资产"
msgid "Assetgroup"
msgstr "用户组"
#: templates/_nav.html:23
msgid "IDC"
msgstr "机房"
#: templates/_nav.html:24
msgid "Asset admin"
#, fuzzy
#| msgid "Asset admin"
msgid "Assetadmin"
msgstr "管理用户"
#: templates/_nav.html:25
msgid "Asset user"
#, fuzzy
#| msgid "Asset user"
msgid "Assetuser"
msgstr "系统用户"
#: templates/_nav.html:26
...
...
@@ -121,22 +255,15 @@ msgstr "注销登录"
msgid "Play CAPTCHA as audio file"
msgstr ""
#~ msgid "
Username
"
#~ msgstr "
用户名
"
#~ msgid "
Asset user
"
#~ msgstr "
系统用户
"
#~ msgid "Password"
#~ msgstr "密码"
#, fuzzy
#~ msgid "Join usergroups"
#~ msgstr "添加到用户组"
#~ msgid "Name"
#~ msgstr "名称"
#~ msgid "Comment"
#~ msgstr "备注"
#~ msgid "Administrator"
#~ msgstr "管理员"
...
...
@@ -152,9 +279,6 @@ msgstr ""
#~ msgid "Wechat"
#~ msgstr "微信"
#~ msgid "Phone"
#~ msgstr "手机"
#~ msgid "Enable OTP"
#~ msgstr "二次验证"
...
...
@@ -200,9 +324,6 @@ msgstr ""
#~ msgid "Captcha invalid"
#~ msgstr "验证码错误"
#~ msgid "Reset password"
#~ msgstr "重置密码"
#~ msgid "Password again"
#~ msgstr "再次输入密码"
...
...
@@ -224,12 +345,6 @@ msgstr ""
#~ msgid "User log"
#~ msgstr "登录日志"
#~ msgid "Created by"
#~ msgstr "创建者"
#~ msgid "Date joined"
#~ msgstr "加入日期"
#~ msgid "Last login"
#~ msgstr "最后登录"
...
...
@@ -245,12 +360,6 @@ msgstr ""
#~ msgid "Add"
#~ msgstr "添加"
#~ msgid "Asset num"
#~ msgstr "资产数量"
#~ msgid "Active"
#~ msgstr "有效"
#~ msgid "Edit"
#~ msgstr "编辑"
...
...
@@ -377,9 +486,6 @@ msgstr ""
#~ msgid "Create user<a href=\"%s\">%s</a> success."
#~ msgstr "创建用户<a href=\"%s\">%s</a> 成功"
#~ msgid "Edit user"
#~ msgstr "编辑用户"
#~ msgid "Usergroup list"
#~ msgstr "用户组列表"
...
...
apps/templates/_header_bar.html
View file @
1b9c9c48
...
...
@@ -11,7 +11,7 @@
</div>
<ul
class=
"nav navbar-top-links navbar-right"
>
<li>
<span
class=
"m-r-sm text-muted welcome-message"
>
{% trans 'Welcome use Jumpserver system' %}
</span>
<span
class=
"m-r-sm text-muted welcome-message"
>
{% trans 'Welcome
to
use Jumpserver system' %}
</span>
</li>
<li
class=
"dropdown"
>
<a
class=
"dropdown-toggle count-info"
data-toggle=
"dropdown"
href=
"#"
>
...
...
apps/templates/_nav.html
View file @
1b9c9c48
...
...
@@ -18,8 +18,8 @@
<i
class=
"fa fa-inbox"
></i>
<span
class=
"nav-label"
>
{% trans 'Assets' %}
</span><span
class=
"fa arrow"
></span>
</a>
<ul
class=
"nav nav-second-level"
>
<li
class=
""
><a
href=
""
>
{% trans 'Asset' %}
</a></li>
<li
class=
""
><a
href=
""
>
{% trans 'Assetgroup' %}
</a></li>
<li
class=
"
{% url 'assets:asset-list' %}
"
><a
href=
""
>
{% trans 'Asset' %}
</a></li>
<li
class=
""
><a
href=
"
{% url 'assets:assetgroup-list' %}
"
>
{% trans 'Assetgroup' %}
</a></li>
<li
class=
""
><a
href=
""
>
{% trans 'IDC' %}
</a></li>
<li
class=
""
><a
href=
""
>
{% trans 'Assetadmin' %}
</a></li>
<li
class=
""
><a
href=
""
>
{% trans 'Assetuser' %}
</a></li>
...
...
apps/users/locale/zh_CN/LC_MESSAGES/django.po
View file @
1b9c9c48
...
...
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-04 1
2:20
+0800\n"
"POT-Creation-Date: 2016-09-04 1
7:31
+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
...
...
@@ -97,6 +97,10 @@ msgstr ""
msgid "Date expired"
msgstr ""
#: users/models.py:122 users/templates/users/user_detail.html:101
msgid "Created by"
msgstr ""
#: users/models.py:228
msgid "Administrator is the super user of system"
msgstr ""
...
...
@@ -131,7 +135,7 @@ msgstr ""
#: users/templates/users/_user.html:70
#: users/templates/users/forget_password.html:44
#: users/templates/users/user_list.html:63
msgid "
Com
mit"
msgid "
Sub
mit"
msgstr ""
#: users/templates/users/forget_password.html:26
...
...
@@ -187,10 +191,6 @@ msgstr ""
msgid "Search"
msgstr ""
#: users/templates/users/user_detail.html:101
msgid "Created by"
msgstr ""
#: users/templates/users/user_detail.html:105
msgid "Date joined"
msgstr ""
...
...
apps/users/models.py
View file @
1b9c9c48
...
...
@@ -119,7 +119,7 @@ class User(AbstractUser):
is_first_login
=
models
.
BooleanField
(
default
=
False
)
date_expired
=
models
.
DateTimeField
(
default
=
date_expired_default
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Date expired'
))
created_by
=
models
.
CharField
(
max_length
=
30
,
default
=
''
)
created_by
=
models
.
CharField
(
max_length
=
30
,
default
=
''
,
verbose_name
=
_
(
'Created by'
)
)
@property
def
password_raw
(
self
):
...
...
apps/users/serializers.py
View file @
1b9c9c48
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
.models
import
User
,
UserGroup
class
UserSerializer
(
serializers
.
ModelSerializer
):
groups
=
serializers
.
HyperlinkedRelatedField
(
many
=
True
,
read_only
=
True
,
view_name
=
'users:usergroup-detail-api'
)
class
Meta
:
model
=
User
exclude
=
[
'password'
,
'first_name'
,
'last_name'
,
'secret_key_otp'
,
'private_key'
,
'public_key'
,
'avatar'
,
]
class
UserActiveSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
User
fields
=
[
'is_active'
]
class
UserGroupSerializer
(
serializers
.
ModelSerializer
):
users
=
serializers
.
HyperlinkedRelatedField
(
many
=
True
,
read_only
=
True
,
view_name
=
'users:user-detail-api'
)
class
Meta
:
model
=
UserGroup
fields
=
'__all__'
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
.models
import
User
,
UserGroup
class
UserSerializer
(
serializers
.
ModelSerializer
):
groups
=
serializers
.
HyperlinkedRelatedField
(
many
=
True
,
read_only
=
True
,
view_name
=
'users:usergroup-detail-api'
)
class
Meta
:
model
=
User
exclude
=
[
'password'
,
'first_name'
,
'last_name'
,
'secret_key_otp'
,
'private_key'
,
'public_key'
,
'avatar'
,
]
class
UserActiveSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
User
fields
=
[
'is_active'
]
class
UserGroupSerializer
(
serializers
.
ModelSerializer
):
users
=
serializers
.
HyperlinkedRelatedField
(
many
=
True
,
read_only
=
True
,
view_name
=
'users:user-detail-api'
)
class
Meta
:
model
=
UserGroup
fields
=
'__all__'
apps/users/templates/users/_user.html
View file @
1b9c9c48
...
...
@@ -67,7 +67,7 @@
<div
class=
"form-group"
>
<div
class=
"col-sm-4 col-sm-offset-2"
>
<button
class=
"btn btn-white"
type=
"reset"
>
{% trans 'Reset' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans '
Com
mit' %}
</button>
<button
id=
"submit_button"
class=
"btn btn-primary"
type=
"submit"
>
{% trans '
Sub
mit' %}
</button>
</div>
</div>
</form>
...
...
apps/users/templates/users/forget_password.html
View file @
1b9c9c48
...
...
@@ -41,7 +41,7 @@
<input
type=
"email"
name=
"email"
class=
"form-control"
placeholder=
"Email address"
required=
""
>
</div>
<button
type=
"submit"
class=
"btn btn-primary block full-width m-b"
>
{% trans '
Com
mit' %}
</button>
<button
type=
"submit"
class=
"btn btn-primary block full-width m-b"
>
{% trans '
Sub
mit' %}
</button>
</form>
</div>
...
...
apps/users/templates/users/user_list.html
View file @
1b9c9c48
...
...
@@ -60,7 +60,7 @@
<div
class=
"input-group-btn pull-left"
style=
"padding-left: 5px;"
>
<button
id=
'search_btn'
type=
"submit"
style=
"height: 32px;"
class=
"btn btn-sm btn-primary"
>
{% trans '
Com
mit' %}
{% trans '
Sub
mit' %}
</button>
</div>
...
...
apps/users/templatetags/users_tags.py
View file @
1b9c9c48
# ~*~ coding: utf-8 ~*~
import
os
import
urllib
import
hashlib
from
django
import
template
from
django.utils
import
timezone
from
django.conf
import
settings
register
=
template
.
Library
()
@register.filter
def
join_queryset_attr
(
queryset
,
attr
,
delimiter
=
', '
):
return
delimiter
.
join
([
getattr
(
obj
,
attr
,
''
)
for
obj
in
queryset
])
@register.filter
def
is_expired
(
datetime
):
if
datetime
>
timezone
.
now
():
return
False
else
:
return
True
@register.filter
def
user_avatar_url
(
user
):
if
user
.
avatar
:
return
user
.
avatar
.
url
else
:
default_dir
=
os
.
path
.
join
(
settings
.
MEDIA_ROOT
,
'avatar'
,
'default'
)
if
os
.
path
.
isdir
(
default_dir
):
default_avatar_list
=
os
.
listdir
(
default_dir
)
default_avatar
=
default_avatar_list
[
len
(
user
.
username
)
%
len
(
default_avatar_list
)]
return
os
.
path
.
join
(
settings
.
MEDIA_URL
,
'avatar'
,
'default'
,
default_avatar
)
return
'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
# ~*~ coding: utf-8 ~*~
import
os
import
urllib
import
hashlib
from
django
import
template
from
django.utils
import
timezone
from
django.conf
import
settings
register
=
template
.
Library
()
@register.filter
def
join_queryset_attr
(
queryset
,
attr
,
delimiter
=
', '
):
return
delimiter
.
join
([
getattr
(
obj
,
attr
,
''
)
for
obj
in
queryset
])
@register.filter
def
is_expired
(
datetime
):
if
datetime
>
timezone
.
now
():
return
False
else
:
return
True
@register.filter
def
user_avatar_url
(
user
):
if
user
.
avatar
:
return
user
.
avatar
.
url
else
:
default_dir
=
os
.
path
.
join
(
settings
.
MEDIA_ROOT
,
'avatar'
,
'default'
)
if
os
.
path
.
isdir
(
default_dir
):
default_avatar_list
=
os
.
listdir
(
default_dir
)
default_avatar
=
default_avatar_list
[
len
(
user
.
username
)
%
len
(
default_avatar_list
)]
return
os
.
path
.
join
(
settings
.
MEDIA_URL
,
'avatar'
,
'default'
,
default_avatar
)
return
'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
apps/users/views.py
View file @
1b9c9c48
...
...
@@ -168,10 +168,10 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
context_object_name
=
"user"
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
UserDetailView
,
self
)
.
get_context_data
(
**
kwargs
)
groups
=
[
group
for
group
in
UserGroup
.
objects
.
iterator
()
if
group
not
in
self
.
object
.
groups
.
iterator
()]
context
.
update
({
'app'
:
_
(
'Users'
),
'action'
:
_
(
'User detail'
),
'groups'
:
groups
})
return
context
context
=
{
'app'
:
_
(
'Users'
),
'action'
:
_
(
'User detail'
),
'groups'
:
groups
}
kwargs
.
update
(
context
)
return
super
(
UserDetailView
,
self
)
.
get_context_data
(
**
kwargs
)
class
UserGroupListView
(
AdminUserRequiredMixin
,
ListView
):
...
...
run_server.py
View file @
1b9c9c48
...
...
@@ -19,7 +19,7 @@ apps_dir = os.path.join(BASE_DIR, 'apps')
def
start_django
():
http_host
=
CONFIG
.
HTTP_LISTEN_HOST
or
'
locahost
'
http_host
=
CONFIG
.
HTTP_LISTEN_HOST
or
'
127.0.0.1
'
http_port
=
CONFIG
.
HTTP_LISTEN_PORT
or
'8080'
os
.
chdir
(
apps_dir
)
print
(
'start django'
)
...
...
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