├── .gitignore ├── INSTALL ├── LICENSE ├── README.md ├── api ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py ├── asset ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py ├── auths ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py ├── create_user.py ├── deploy ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py ├── utils.py └── views.py ├── discard.bak ├── manage.py ├── ops_system ├── .ropeproject │ ├── config.py │ ├── globalnames │ ├── history │ └── objectdb ├── __init__.py ├── auth.py ├── settings.py ├── static │ ├── bootstrap │ │ ├── css │ │ │ ├── bootstrap-datetimepicker.css │ │ │ ├── bootstrap-datetimepicker.min.css │ │ │ ├── bootstrap-theme.css │ │ │ ├── bootstrap-theme.css.map │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ └── bootstrap.min.css │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ ├── bootstrap-datetimepicker.js │ │ │ ├── bootstrap-datetimepicker.min.js │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.min.js │ │ │ ├── jquery-1.8.3.min.js │ │ │ ├── locales │ │ │ └── bootstrap-datetimepicker.zh-CN.js │ │ │ └── npm.js │ ├── css │ │ ├── component.css │ │ ├── demo.css │ │ ├── form-elements.css │ │ ├── normalize.css │ │ ├── sb-admin.css │ │ └── style.css │ ├── font-awesome │ │ ├── css │ │ │ ├── font-awesome.css │ │ │ └── font-awesome.min.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── less │ │ │ ├── animated.less │ │ │ ├── bordered-pulled.less │ │ │ ├── core.less │ │ │ ├── fixed-width.less │ │ │ ├── font-awesome.less │ │ │ ├── icons.less │ │ │ ├── larger.less │ │ │ ├── list.less │ │ │ ├── mixins.less │ │ │ ├── path.less │ │ │ ├── rotated-flipped.less │ │ │ ├── stacked.less │ │ │ └── variables.less │ │ └── scss │ │ │ ├── _animated.scss │ │ │ ├── _bordered-pulled.scss │ │ │ ├── _core.scss │ │ │ ├── _fixed-width.scss │ │ │ ├── _icons.scss │ │ │ ├── _larger.scss │ │ │ ├── _list.scss │ │ │ ├── _mixins.scss │ │ │ ├── _path.scss │ │ │ ├── _rotated-flipped.scss │ │ │ ├── _stacked.scss │ │ │ ├── _variables.scss │ │ │ └── font-awesome.scss │ ├── ico │ │ ├── apple-touch-icon-114-precomposed.png │ │ ├── apple-touch-icon-144-precomposed.png │ │ ├── apple-touch-icon-57-precomposed.png │ │ ├── apple-touch-icon-72-precomposed.png │ │ └── favicon.png │ ├── img │ │ ├── backgrounds │ │ │ ├── 1.jpg │ │ │ └── 1@2x.jpg │ │ ├── demo-1-bg.jpg │ │ ├── login_ico.png │ │ ├── meitianhui.png │ │ └── wait.gif │ └── js │ │ ├── EasePack.min.js │ │ ├── TweenLite.min.js │ │ ├── demo-1.js │ │ ├── echarts.js │ │ ├── html5.js │ │ ├── jquery-1.11.1.js │ │ ├── jquery-1.11.1.min.js │ │ ├── jquery.backstretch.js │ │ ├── jquery.backstretch.min.js │ │ ├── jquery.js │ │ ├── masklayer.min.js │ │ ├── minion.js │ │ ├── placeholder.js │ │ ├── rAF.js │ │ └── scripts.js ├── urls.py ├── utils.py ├── views.py └── wsgi.py ├── requirements ├── requirements.txt ├── salts ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── test.py ├── tests.py ├── urls.py ├── utils.py └── views.py ├── screenshots ├── 0.png ├── 1.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png ├── sls ├── epel │ ├── files │ │ └── epel-release-latest-6.noarch.rpm │ └── install.sls ├── memcached │ ├── files │ │ ├── libevent-2.0.21-stable.tar.gz │ │ └── memcached-1.4.25.tar.gz │ └── install.sls ├── mysql │ ├── files │ │ ├── my.cnf │ │ ├── mysql-5.6.10.tar.gz │ │ └── mysqld │ └── install.sls ├── nginx │ ├── files │ │ ├── jemalloc-4.0.4.tar.bz2 │ │ └── tengine-2.1.1.tar.gz │ └── install.sls ├── php │ ├── files │ │ ├── libevent-2.0.21-stable.tar.gz │ │ ├── libmemcached-1.0.18.tar.gz │ │ ├── memcache-3.0.5.tgz │ │ ├── php-5.6.16.tar.gz │ │ ├── php-fpm.conf │ │ ├── php-memcached.tar.gz │ │ ├── php.ini │ │ └── phpredis-2.2.4.tar.gz │ └── install.sls ├── redis │ ├── files │ │ ├── redis-3.2.0.tar.gz │ │ └── redis.conf │ └── install.sls ├── system │ └── install.sls ├── tomcat │ ├── files │ │ └── apache-tomcat-7.0.54.tar.gz │ └── install.sls ├── tools │ ├── files │ │ ├── agent.py │ │ ├── daemon.conf │ │ ├── getdaemon.py │ │ └── psutil-4.3.0.tar.gz │ └── install.sls ├── top.sls └── zabbix │ ├── files │ ├── zabbix.tar.gz │ ├── zabbix_agentd │ └── zabbix_agentd.conf │ ├── init.sls │ ├── install.sls │ ├── install_zabbix.sls │ ├── readme.md │ ├── start_zbx_install.sls │ ├── up.sls │ └── update_zbx_conf.sls ├── soft ├── Python-2.7.10.tgz ├── libmysqlclient.so.18 ├── pip-7.1.2.tar.gz └── setuptools-18.4.tar.gz ├── start.sh ├── static ├── admin │ ├── css │ │ ├── base.css │ │ ├── changelists.css │ │ ├── dashboard.css │ │ ├── fonts.css │ │ ├── forms.css │ │ ├── login.css │ │ ├── rtl.css │ │ └── widgets.css │ ├── fonts │ │ ├── LICENSE.txt │ │ ├── README.txt │ │ ├── Roboto-Bold-webfont.woff │ │ ├── Roboto-Light-webfont.woff │ │ └── Roboto-Regular-webfont.woff │ ├── img │ │ ├── LICENSE │ │ ├── README.txt │ │ ├── calendar-icons.svg │ │ ├── gis │ │ │ ├── move_vertex_off.svg │ │ │ └── move_vertex_on.svg │ │ ├── icon-addlink.svg │ │ ├── icon-alert.svg │ │ ├── icon-calendar.svg │ │ ├── icon-changelink.svg │ │ ├── icon-clock.svg │ │ ├── icon-deletelink.svg │ │ ├── icon-no.svg │ │ ├── icon-unknown-alt.svg │ │ ├── icon-unknown.svg │ │ ├── icon-yes.svg │ │ ├── inline-delete.svg │ │ ├── search.svg │ │ ├── selector-icons.svg │ │ ├── sorting-icons.svg │ │ ├── tooltag-add.svg │ │ └── tooltag-arrowright.svg │ └── js │ │ ├── SelectBox.js │ │ ├── SelectFilter2.js │ │ ├── actions.js │ │ ├── actions.min.js │ │ ├── admin │ │ ├── DateTimeShortcuts.js │ │ └── RelatedObjectLookups.js │ │ ├── calendar.js │ │ ├── collapse.js │ │ ├── collapse.min.js │ │ ├── core.js │ │ ├── inlines.js │ │ ├── inlines.min.js │ │ ├── jquery.init.js │ │ ├── prepopulate.js │ │ ├── prepopulate.min.js │ │ ├── timeparse.js │ │ ├── urlify.js │ │ └── vendor │ │ ├── jquery │ │ ├── LICENSE-JQUERY.txt │ │ ├── jquery.js │ │ └── jquery.min.js │ │ └── xregexp │ │ ├── LICENSE-XREGEXP.txt │ │ └── xregexp.min.js ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js ├── css │ ├── form-elements.css │ ├── sb-admin.css │ └── style.css ├── font-awesome │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── less │ │ ├── animated.less │ │ ├── bordered-pulled.less │ │ ├── core.less │ │ ├── fixed-width.less │ │ ├── font-awesome.less │ │ ├── icons.less │ │ ├── larger.less │ │ ├── list.less │ │ ├── mixins.less │ │ ├── path.less │ │ ├── rotated-flipped.less │ │ ├── stacked.less │ │ └── variables.less │ └── scss │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _icons.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _path.scss │ │ ├── _rotated-flipped.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ └── font-awesome.scss ├── ico │ ├── apple-touch-icon-114-precomposed.png │ ├── apple-touch-icon-144-precomposed.png │ ├── apple-touch-icon-57-precomposed.png │ ├── apple-touch-icon-72-precomposed.png │ └── favicon.png ├── img │ ├── backgrounds │ │ ├── 1.jpg │ │ └── 1@2x.jpg │ ├── meitianhui.png │ └── wait.gif └── js │ ├── echarts.js │ ├── jquery-1.11.1.js │ ├── jquery-1.11.1.min.js │ ├── jquery.backstretch.js │ ├── jquery.backstretch.min.js │ ├── jquery.js │ ├── masklayer.min.js │ ├── minion.js │ ├── placeholder.js │ └── scripts.js ├── templates ├── add_git_repo.html ├── add_svn_repo.html ├── asset_overview.html ├── base.html ├── code_deploy.html ├── db_info_list.html ├── deploy_project.html ├── download_file.html ├── host_list.html ├── index.html ├── list_app_deploy_info.html ├── list_cmd_opt_log.html ├── list_cmd_run_info.html ├── list_deploy_info.html ├── list_repo_info.html ├── login.html ├── login_new.html ├── query_host_cmd_log.html ├── rollback_project.html ├── salt_cmd_run.html ├── salt_deploy_application.html ├── salt_hosts.html ├── upload_file.html └── user_list.html ├── tools ├── agent.py ├── agent_new.py └── master.py ├── users ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py └── uwsgi_deploy.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | 2 | requiments: 3 | python2.7 centos6.x salt-master salt-minion salt-api mysql-devel mysql-server git subversion MySQL-python 4 | 5 | pip install -r ./requirements 6 | 7 | 8 | chkconfig --level 35 salt-master on && service salt-master start 9 | 10 | vim ./ops_system/settings 11 | 12 | # configure your database info 13 | 14 | 15 | python manage.py makemigrations 16 | 17 | python manage.py migrate 18 | 19 | python manage.py createsuperuser 20 | 21 | 22 | python manage.py runserver 0.0.0.0:8080 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ho_o 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpsSystem 2 | 运维管理发布系统 Demo 地址: http://demo.hujingguang.cn username: guest 管理系统 password: 123123 3 | 4 | 5 | #这是一个运维平台,使用bootstrap 和django 框架进行开发。目前实现了项目管理模块,发布Git和SVN代码库的php工程,回滚代码,以及集成Saltstack 进行应用批量部署模块和命令批量执行. 命令审计查询 6 | 7 | 8 | 前端模板下载地址: https://startbootstrap.com/ 9 | 10 | 11 | Docker Image 部署 12 | 13 | 14 | docker pull hooversa/ops_system:latest 15 | 16 | docker run --name ops_system --rm -p 80:81 -d hooversa/ops_system 17 | 18 | 浏览器打开 127.0.0.1 (用户名/密码: admin/helloworld) 19 | 20 | 21 | 22 | 23 | 24 | 服务器部署步骤, 25 | 26 | 1 :安装python2.7版本,CentOS6.x, django1.9框架 pexpect python模块,svn工具 git工具 Saltstack 自动化工具 27 | 28 | 2: pip install django==v1.9.0 && pip install pexpect && yum install git subversion -y && pip install salt==v2015.8.13 29 | 30 | 3: 进入工程根目录,配置好mysql数据库,执行python manage.py test 测试数据库连接 31 | 32 | 4: 初始化数据库表,python manage.py makemigrations && python manage.py migrate 33 | 34 | 5: 创建一个管理员账号, python manage.py createsuperuser ,(在该平台里,只有管理员才能发布工程到正式环境) 35 | 36 | 6: 第一次发布代码,需要初始化发布记录,直接在表ops_deploy_info 插入一条发布记录,版本号根据自己项目而定,发布到相应的环境需要初始换相应的target字段:如测试环境target为test,预生产环境为pre,正式环境target字段为online. 37 | 7: 如果发布到正式环境,需配置ssh秘钥登陆,发布密码为管理员密码。发布到测试环境或预发布环境,密码为机器的root密码 38 | 39 | 8: 运行平台 python manage.py runserver 0.0.0.0:80 40 | 41 | 9: 如果要进行应用部署,请将项目根目录下的sls目录里面的所有文件拷贝至salt的file_root 下面,一般为/srv/salt 下面。如果要部署tomcat应用,请自行下载jdk源码包,放在/srv/salt/tomcat/files下面,并修改install.sls文件. 42 | 43 | 10: 要进行应用部署,需要安装minion客户端,并配置好master 和id ,还有必须在grains 添加三个变量:group,area,usage。 这个三个变量信息会在主机信息中对应:组,地址,和用途三栏。否则刷新无法获取到主机信息 44 | 45 | 46 | 11: 命令审计模块需要在各个salt-minion端安装agent.py,该文件位于项目下tools文件夹中,在salt-master运行 master.py接受来自agent.py的数据。,master.py需要配置数据库连接信息。直接编辑文件添加即可. 47 | 48 | 49 | 50 | 51 | git clone https://github.com/hujingguang/OpsSystem.git 52 | 53 | cd OpsSystem && cat INSTALL 54 | 55 | 56 | -----Demo 地址: 57 | 58 | http://demo.hujingguang.cn 59 | 60 | username: guest 61 | 62 | password: 123123 63 | 64 | 65 | #### Screenshots 66 | ----------- 67 | 登陆界面 68 | 69 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/0.png) 70 | 71 | Dashboard 72 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/1.png) 73 | 74 | 用户管理 75 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/15.png) 76 | 77 | 用户添加 78 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/16.png) 79 | 80 | 添加SVN版本库项目 81 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/2.png) 82 | 83 | 添加Git版本库项目 84 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/3.png) 85 | 86 | 发布工程 87 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/4.png) 88 | 89 | 代码回滚 90 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/13.png) 91 | 92 | 主机信息 93 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/5.png) 94 | 95 | 应用部署 96 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/6.png) 97 | 98 | 命令执行 99 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/7.png) 100 | 101 | 应用部署记录 102 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/8.png) 103 | 104 | 命令执行记录 105 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/9.png) 106 | 107 | 云资产信息 108 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/10.png) 109 | 110 | 文件下载 111 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/11.png) 112 | 113 | 命令审计 114 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/12.png) 115 | 116 | 集成脚本代码发布 117 | ![](https://github.com/hujingguang/OpsSystem/blob/master/screenshots/14.png) 118 | -------------------------------------------------------------------------------- /api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/api/__init__.py -------------------------------------------------------------------------------- /api/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /api/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class ApiConfig(AppConfig): 7 | name = 'api' 8 | -------------------------------------------------------------------------------- /api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/api/migrations/__init__.py -------------------------------------------------------------------------------- /api/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | 5 | # Create your models here. 6 | -------------------------------------------------------------------------------- /api/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /api/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from views import * 3 | urlpatterns=[ 4 | url('^project/version/current/$',get_project_current_version,name='get_procurversion'), 5 | ] 6 | -------------------------------------------------------------------------------- /api/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from deploy.models import RepoModel,DeployInfoModel 3 | from django.http import HttpResponse 4 | import json 5 | def get_project_current_version(request): 6 | repos=[o.repoName for o in RepoModel.objects.all()] 7 | ret={} 8 | for repo in repos: 9 | try: 10 | test_cur_version=DeployInfoModel.objects.filter(repoName=repo).filter(target='test').order_by('-date').first() 11 | pre_cur_version=DeployInfoModel.objects.filter(repoName=repo).filter(target='pre').order_by('-date').first() 12 | online_cur_version=DeployInfoModel.objects.filter(repoName=repo).filter(target='online').order_by('-date').first() 13 | tmp_dict={} 14 | if test_cur_version: 15 | tmp_dict['test']=test_cur_version.revision 16 | else: 17 | tmp_dict['test']='' 18 | if pre_cur_version: 19 | tmp_dict['pre']=pre_cur_version.revision 20 | else: 21 | tmp_dict['pre']='' 22 | if online_cur_version: 23 | tmp_dict['online']=online_cur_version.revision 24 | else: 25 | tmp_dict['online']='' 26 | ret[repo]=tmp_dict 27 | except Exception as e: 28 | ret={'status':'falied','error':'database connect timeout'} 29 | ret=json.dumps(ret) 30 | return HttpResponse(ret,content_type='application/json') 31 | 32 | -------------------------------------------------------------------------------- /asset/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/asset/__init__.py -------------------------------------------------------------------------------- /asset/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /asset/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class AssetConfig(AppConfig): 7 | name = 'asset' 8 | -------------------------------------------------------------------------------- /asset/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django import forms 4 | from models import * 5 | class QueryCmdForm(forms.Form): 6 | hostname=forms.ChoiceField(label=u'主机名', 7 | choices=(), 8 | widget=forms.Select(attrs={'class':'form-control','style':'width:370px'})) 9 | begin=forms.DateTimeField(widget=forms.DateTimeInput(attrs={'class':'form-control','style':'width:340px','readonly':True})) 10 | end=forms.DateTimeField(widget=forms.DateTimeInput(attrs={'class':'form-control','style':'width:340px','readonly':True})) 11 | 12 | def __init__(self,*arg,**kwargs): 13 | super(QueryCmdForm,self).__init__(*arg,**kwargs) 14 | sql='select id,hostname from ops_cmd_opt_log GROUP BY hostname' 15 | self.fields['hostname'].choices=[(o.hostname,o.hostname) for o in CmdLogModel.objects.raw(sql)] 16 | -------------------------------------------------------------------------------- /asset/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/asset/migrations/__init__.py -------------------------------------------------------------------------------- /asset/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | 5 | # Create your models here. 6 | 7 | class CmdLogModel(models.Model): 8 | hostname=models.CharField(max_length=100) 9 | user=models.CharField(max_length=100) 10 | command=models.CharField(max_length=2000) 11 | login_ip=models.CharField(max_length=20) 12 | runtime=models.DateTimeField() 13 | 14 | class Meta: 15 | db_table='ops_cmd_opt_log' 16 | 17 | -------------------------------------------------------------------------------- /asset/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /asset/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from views import * 3 | 4 | 5 | urlpatterns=[url('^asset/overview$',overview,name='overview'), 6 | url('^asset/query_cmd_log$',query_cmd_log,name='query_cmd_log'), 7 | url('^asset/list_cmd_opt_log$',list_cmd_opt_log,name='list_cmd_opt_log'), 8 | ] 9 | -------------------------------------------------------------------------------- /asset/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.contrib.auth.decorators import login_required 3 | from django.shortcuts import render_to_response 4 | from django.template import RequestContext 5 | from forms import * 6 | from models import * 7 | from datetime import datetime 8 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 9 | from django.http import HttpResponseRedirect 10 | from django.core.urlresolvers import reverse 11 | Host=None 12 | Begin=None 13 | End=None 14 | 15 | 16 | @login_required(login_url='/') 17 | def overview(request): 18 | return render_to_response('asset_overview.html',RequestContext(request)) 19 | @login_required(login_url='/') 20 | def query_cmd_log(request): 21 | global Host,Begin,End 22 | form=QueryCmdForm() 23 | if request.method == 'POST': 24 | form=QueryCmdForm(request.POST) 25 | if form.is_valid(): 26 | Host=form.cleaned_data['hostname'] 27 | Begin=datetime.strftime(form.cleaned_data['begin'],'%Y-%m-%d %H:%M:%S') 28 | End=datetime.strftime(form.cleaned_data['end'],'%Y-%m-%d %H:%M:%S') 29 | return HttpResponseRedirect(reverse('asset:list_cmd_opt_log')) 30 | return render_to_response('query_host_cmd_log.html',RequestContext(request,{'form':form})) 31 | @login_required(login_url='/') 32 | def list_cmd_opt_log(request): 33 | global Host,Begin,End 34 | if not Host or not Begin or not End: 35 | return HttpResponseRedirect(reverse('asset:query_cmd_log')) 36 | query_set=CmdLogModel.objects.filter(hostname=Host).filter(runtime__range=(Begin,End)) 37 | for q in query_set: 38 | q.runtime=datetime.strftime(q.runtime,'%Y-%m-%d %H:%M:%S') 39 | paginator=Paginator(query_set,100) 40 | page=request.GET.get('page') 41 | try: 42 | query=paginator.page(page) 43 | except PageNotAnInteger: 44 | query=paginator.page(1) 45 | except EmptyPage: 46 | query=paginator.page(paginator.num_pages) 47 | return render_to_response('list_cmd_opt_log.html',RequestContext(request,{'cmd_set':query})) 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /auths/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/auths/__init__.py -------------------------------------------------------------------------------- /auths/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /auths/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class AuthConfig(AppConfig): 7 | name = 'auth' 8 | -------------------------------------------------------------------------------- /auths/forms.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | from django import forms 3 | 4 | 5 | class DbAuthForm(forms.Form): 6 | dbuser=forms.CharField(label=u'登陆用户名',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control'})) 7 | accesshost=forms.CharField(label=u'登陆主机',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control'})) 8 | accessdb=forms.CharField(label=u'数据库名',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control'})) 9 | accessauth=forms.CharField(label=u'库权限',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control'})) 10 | owner=forms.CharField(label=u'所有者',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control'})) 11 | envtype=forms.ChoiceField(label=u'使用环境',choices=(('test',u'测试环境'),('online',u'正式环境')),widget=forms.Select(attrs={'class':'form-control'})) 12 | useperson=forms.CharField(label=u'使用者',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control'})) 13 | comment=forms.CharField(label=u'备注',max_length=100,required=True,widget=forms.Textarea(attrs={'class':'form-control'})) 14 | createtime=forms.DateTimeField(label='',widget=forms.HiddenInput()) 15 | 16 | -------------------------------------------------------------------------------- /auths/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/auths/migrations/__init__.py -------------------------------------------------------------------------------- /auths/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | 5 | 6 | class DatabaseAuthInfoModel(models.Model): 7 | username=models.CharField(max_length=50) 8 | accesshost=models.CharField(max_length=100) 9 | accessdb=models.CharField(max_length=100) 10 | accessauth=models.CharField(max_length=200) 11 | owner=models.CharField(max_length=20) 12 | useperson=models.CharField(max_length=100) 13 | envtype=models.CharField(max_length=20) 14 | createtime=models.DateTimeField() 15 | comment=models.CharField(max_length=1000) 16 | class Meta: 17 | db_table='ops_db_auth_info' 18 | 19 | 20 | class CodeRepoAuthInfoModel(models.Model): 21 | username=models.CharField(max_length=50) 22 | reponame=models.CharField(max_length=50) 23 | accessauth=models.CharField(max_length=100) 24 | envtype=models.CharField(max_length=20) 25 | createtime=models.DateTimeField() 26 | comment=models.CharField(max_length=200) 27 | repotype=models.CharField(max_length=10) 28 | class Meta: 29 | db_table='ops_repo_auth_info' 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /auths/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /auths/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from views import * 3 | 4 | urlpatterns=[ 5 | url('^db/list',db_auth_info_list,name='db_info_list'), 6 | url('^db/add',db_auth_info_add,name='db_info_add'), 7 | url('^db/delete',db_auth_info_delete,name='db_info_delete'), 8 | url('^db/edit',db_auth_info_edit,name='db_info_edit'), 9 | url('^db/query',db_auth_info_query,name='db_info_query'), 10 | ] 11 | -------------------------------------------------------------------------------- /create_user.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import User 2 | 3 | def create_superuser(): 4 | user = User.objects.create_superuser("admin",'admin@gmail.com','helloworld') 5 | user.save() 6 | 7 | create_superuser() 8 | 9 | -------------------------------------------------------------------------------- /deploy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/deploy/__init__.py -------------------------------------------------------------------------------- /deploy/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /deploy/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class DeployConfig(AppConfig): 7 | name = 'deploy' 8 | -------------------------------------------------------------------------------- /deploy/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/deploy/migrations/__init__.py -------------------------------------------------------------------------------- /deploy/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | 5 | 6 | class RepoModel(models.Model): 7 | repo_type_choice=(('svn','svn repo type'),('git','git repo type')) 8 | repoName=models.CharField(max_length=100) 9 | repoAddress=models.CharField(max_length=200) 10 | repoUser=models.CharField(max_length=50,blank=False) 11 | repoPassword=models.CharField(max_length=50,blank=True) 12 | wwwDir=models.CharField(max_length=50) 13 | testDeployIP=models.CharField(max_length=50) 14 | preDeployIP=models.CharField(max_length=50) 15 | onlineDeployIP=models.CharField(max_length=500) 16 | localCheckoutDir=models.CharField(max_length=100) 17 | excludeDir=models.CharField(max_length=500) 18 | repoType=models.CharField(max_length=5,choices=repo_type_choice) 19 | addDate=models.DateTimeField() 20 | class Meta: 21 | db_table='ops_repo_info' 22 | 23 | class DeployInfoModel(models.Model): 24 | repoName=models.CharField(max_length=100) 25 | target=models.CharField(max_length=10) 26 | revision=models.CharField(max_length=100) 27 | person=models.CharField(max_length=50) 28 | date=models.DateTimeField() 29 | remark=models.CharField(max_length=80,default=None) 30 | log=models.TextField() 31 | class Meta: 32 | db_table='ops_deploy_info' 33 | 34 | 35 | class RollBackInfoModel(models.Model): 36 | repoName=models.CharField(max_length=100) 37 | curRevision=models.CharField(max_length=30) 38 | backRevision=models.CharField(max_length=30) 39 | status=models.CharField(max_length=10,choices=(('success','rollback success'),('failed','rollback failed'))) 40 | rollDate=models.DateTimeField() 41 | target=models.CharField(max_length=10) 42 | person=models.CharField(max_length=30) 43 | 44 | class Meta: 45 | db_table='ops_rollback_info' 46 | -------------------------------------------------------------------------------- /deploy/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /deploy/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from views import * 3 | urlpatterns=[ 4 | url(r'^add_svn_repo/$',add_svn_repo,name='add_svn_repo'), 5 | url(r'^add_git_repo/$',add_git_repo,name='add_git_repo'), 6 | url(r'^list_repo_info/$',list_repo_info,name='list_repo_info'), 7 | url(r'^list_deploy_info/$',list_deploy_info,name='list_deploy_info'), 8 | url(r'^deploy_project/$',deploy_project,name='deploy_project'), 9 | url(r'^rollback_project/$',rollback_project,name='rollback_project') 10 | ] 11 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ops_system.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /ops_system/.ropeproject/globalnames: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/.ropeproject/globalnames -------------------------------------------------------------------------------- /ops_system/.ropeproject/history: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/.ropeproject/history -------------------------------------------------------------------------------- /ops_system/.ropeproject/objectdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/.ropeproject/objectdb -------------------------------------------------------------------------------- /ops_system/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/__init__.py -------------------------------------------------------------------------------- /ops_system/auth.py: -------------------------------------------------------------------------------- 1 | from modles import Account 2 | 3 | class MyAuth: 4 | def authenticate(self, username=None, password=None): 5 | try: 6 | user = Account.object.get(username=username) 7 | except Account.DoesNotExist: 8 | pass 9 | else: 10 | if user.check_password(password): 11 | return user 12 | return None 13 | def get_user(self, user_id): 14 | try: 15 | return Account.object.get(pk=user_id) 16 | except Account.DoesNotExist: 17 | return None 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ops_system/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 3 | SECRET_KEY = 'a-nxu(3p^q8g_l=ka3l%7x(gm6#gf559%k2299-8b_11d+ysdl' 4 | DEBUG = True 5 | ALLOWED_HOSTS = ['*'] 6 | INSTALLED_APPS = [ 7 | 'django.contrib.admin', 8 | 'django.contrib.auth', 9 | 'django.contrib.contenttypes', 10 | 'django.contrib.sessions', 11 | 'django.contrib.messages', 12 | 'django.contrib.staticfiles', 13 | 'ops_system', 14 | 'deploy', 15 | 'asset', 16 | 'salts', 17 | 'api', 18 | 'auths', 19 | ] 20 | MIDDLEWARE_CLASSES = [ 21 | 'django.middleware.security.SecurityMiddleware', 22 | 'django.contrib.sessions.middleware.SessionMiddleware', 23 | 'django.middleware.common.CommonMiddleware', 24 | # 'django.middleware.csrf.CsrfViewMiddleware', 25 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 26 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 27 | 'django.contrib.messages.middleware.MessageMiddleware', 28 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 29 | ] 30 | ROOT_URLCONF = 'ops_system.urls' 31 | STATIC_ROOT = os.path.join(BASE_DIR, 'static') 32 | 33 | 34 | TEMPLATES = [ 35 | { 36 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 37 | 'DIRS': [os.path.join(BASE_DIR, 'templates'), ], 38 | 'APP_DIRS': True, 39 | 'OPTIONS': { 40 | 'context_processors': [ 41 | 'django.template.context_processors.debug', 42 | 'django.template.context_processors.request', 43 | 'django.contrib.auth.context_processors.auth', 44 | 'django.contrib.messages.context_processors.messages', 45 | ], 46 | }, 47 | }, 48 | ] 49 | WSGI_APPLICATION = 'ops_system.wsgi.application' 50 | DATABASES = { 51 | 'default': { 52 | 'ENGINE': 'django.db.backends.mysql', 53 | 'NAME': 'ops', 54 | 'HOST': '127.0.0.1', 55 | 'USER': 'root', 56 | 'PORT': 3306, 57 | 'PASSWORD': '123123', 58 | } 59 | } 60 | AUTH_PASSWORD_VALIDATORS = [ 61 | { 62 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 63 | }, 64 | { 65 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 66 | }, 67 | { 68 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 69 | }, 70 | { 71 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 72 | }, 73 | ] 74 | #LANGUAGE_CODE = 'en-US' 75 | LANGUAGE_CODE = 'zh-Hans' 76 | TIME_ZONE = 'Asia/Shanghai' 77 | USE_I18N = True 78 | USE_L10N = True 79 | USE_TZ = False 80 | STATIC_URL = '/static/' 81 | STATICFILE_DIRS = (os.path.join(BASE_DIR, 'static') ,) 82 | -------------------------------------------------------------------------------- /ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /ops_system/static/bootstrap/js/locales/bootstrap-datetimepicker.zh-CN.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simplified Chinese translation for bootstrap-datetimepicker 3 | * Yuan Cheung 4 | */ 5 | ;(function($){ 6 | $.fn.datetimepicker.dates['zh-CN'] = { 7 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 8 | daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], 9 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 10 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 11 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | today: "今天", 13 | suffix: [], 14 | meridiem: ["上午", "下午"] 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /ops_system/static/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /ops_system/static/css/component.css: -------------------------------------------------------------------------------- 1 | /* Header */ 2 | .large-header { 3 | position: relative; 4 | width: 100%; 5 | background: #333; 6 | overflow: hidden; 7 | background-size: cover; 8 | background-position: center center; 9 | z-index: 1; 10 | } 11 | 12 | .demo-1 .large-header { 13 | background-image: url('../img/demo-1-bg.jpg'); 14 | } 15 | .logo_box{ 16 | width: 400px; 17 | height: 500px; 18 | padding: 35px; 19 | color: #EEE; 20 | position: absolute; 21 | left: 50%; 22 | top:50%; 23 | margin-left: -200px; 24 | margin-top: -250px; 25 | } 26 | .logo_box h3{ 27 | text-align: center; 28 | height: 20px; 29 | font: 20px "microsoft yahei",Helvetica,Tahoma,Arial,"Microsoft jhengHei",sans-serif; 30 | color: #FFFFFF; 31 | height: 20px; 32 | line-height: 20px; 33 | padding:0 0 35px 0; 34 | } 35 | .forms{ 36 | width: 280px; 37 | height: 485px; 38 | } 39 | .logon_inof{ 40 | width: 100%; 41 | min-height: 450px; 42 | padding-top: 35px; 43 | position: relative; 44 | } 45 | .input_outer{ 46 | height: 46px; 47 | padding: 0 5px; 48 | margin-bottom: 30px; 49 | border-radius: 50px; 50 | position: relative; 51 | border: rgba(255,255,255,0.2) 2px solid !important; 52 | } 53 | .u_user{ 54 | width: 25px; 55 | height: 25px; 56 | background: url(../img/login_ico.png); 57 | background-position: -125px 0; 58 | position: absolute; 59 | margin: 10px 13px; 60 | } 61 | .us_uer{ 62 | width: 25px; 63 | height: 25px; 64 | background-image: url(../img/login_ico.png); 65 | background-position: -125px -34px; 66 | position: absolute; 67 | margin: 10px 13px; 68 | } 69 | .l-login{ 70 | position: absolute; 71 | z-index: 1; 72 | left: 50px; 73 | top: 0; 74 | height: 46px; 75 | font: 14px "microsoft yahei",Helvetica,Tahoma,Arial,"Microsoft jhengHei"; 76 | line-height: 46px; 77 | } 78 | .text{ 79 | width: 220px; 80 | height: 46px; 81 | outline: none; 82 | display: inline-block; 83 | font: 14px "microsoft yahei",Helvetica,Tahoma,Arial,"Microsoft jhengHei"; 84 | margin-left: 50px; 85 | border: none; 86 | background: none; 87 | line-height: 46px; 88 | } 89 | /*///*/ 90 | .mb2{ 91 | margin-bottom: 20px 92 | } 93 | .mb2 a{ 94 | text-decoration: none; 95 | outline: none; 96 | } 97 | .submit { 98 | padding: 15px; 99 | margin-top: 20px; 100 | display: block; 101 | } 102 | .act-but{ 103 | line-height: 20px; 104 | text-align: center; 105 | font-size: 20px; 106 | border-radius: 50px; 107 | background: #0096e6; 108 | } -------------------------------------------------------------------------------- /ops_system/static/css/demo.css: -------------------------------------------------------------------------------- 1 | *, *:after, *:before { -webkit-box-sizing: border-box; box-sizing: border-box; } 2 | .clearfix:before, .clearfix:after { content: ''; display: table; } 3 | .clearfix:after { clear: both; } 4 | 5 | body { 6 | background: #fff; 7 | color: #383a3c; 8 | font-weight: 400; 9 | font-size: 1em; 10 | line-height: 1.25; 11 | font-family: 'Raleway', Calibri, Arial, sans-serif; 12 | } 13 | 14 | a, button { 15 | outline: none; 16 | } 17 | 18 | a { 19 | color: #566473; 20 | text-decoration: none; 21 | } 22 | 23 | a:hover, a:focus { 24 | color: #34495e; 25 | } 26 | 27 | section { 28 | padding: 1em; 29 | text-align: center; 30 | } 31 | 32 | p.ref { 33 | text-align: center; 34 | padding: 2em 1em; 35 | } -------------------------------------------------------------------------------- /ops_system/static/css/form-elements.css: -------------------------------------------------------------------------------- 1 | 2 | input[type="text"], 3 | input[type="password"], 4 | textarea, 5 | textarea.form-control { 6 | height: 50px; 7 | margin: 0; 8 | padding: 0 20px; 9 | vertical-align: middle; 10 | background: #fff; 11 | border: 3px solid #fff; 12 | font-family: 'Roboto', sans-serif; 13 | font-size: 16px; 14 | font-weight: 300; 15 | line-height: 50px; 16 | color: #888; 17 | -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; 18 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 19 | -o-transition: all .3s; -moz-transition: all .3s; -webkit-transition: all .3s; -ms-transition: all .3s; transition: all .3s; 20 | } 21 | 22 | textarea, 23 | textarea.form-control { 24 | padding-top: 10px; 25 | padding-bottom: 10px; 26 | line-height: 30px; 27 | } 28 | 29 | input[type="text"]:focus, 30 | input[type="password"]:focus, 31 | textarea:focus, 32 | textarea.form-control:focus { 33 | outline: 0; 34 | background: #fff; 35 | border: 3px solid #fff; 36 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 37 | } 38 | 39 | input[type="text"]:-moz-placeholder, input[type="password"]:-moz-placeholder, 40 | textarea:-moz-placeholder, textarea.form-control:-moz-placeholder { color: #888; } 41 | 42 | input[type="text"]:-ms-input-placeholder, input[type="password"]:-ms-input-placeholder, 43 | textarea:-ms-input-placeholder, textarea.form-control:-ms-input-placeholder { color: #888; } 44 | 45 | input[type="text"]::-webkit-input-placeholder, input[type="password"]::-webkit-input-placeholder, 46 | textarea::-webkit-input-placeholder, textarea.form-control::-webkit-input-placeholder { color: #888; } 47 | 48 | 49 | 50 | button.btn { 51 | height: 50px; 52 | margin: 0; 53 | padding: 0 20px; 54 | vertical-align: middle; 55 | background: #de615e; 56 | border: 0; 57 | font-family: 'Roboto', sans-serif; 58 | font-size: 16px; 59 | font-weight: 300; 60 | line-height: 50px; 61 | color: #fff; 62 | -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; 63 | text-shadow: none; 64 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 65 | -o-transition: all .3s; -moz-transition: all .3s; -webkit-transition: all .3s; -ms-transition: all .3s; transition: all .3s; 66 | } 67 | 68 | button.btn:hover { opacity: 0.6; color: #fff; } 69 | 70 | button.btn:active { outline: 0; opacity: 0.6; color: #fff; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } 71 | 72 | button.btn:focus { outline: 0; opacity: 0.6; background: #de615e; color: #fff; } 73 | 74 | button.btn:active:focus, button.btn.active:focus { outline: 0; opacity: 0.6; background: #de615e; color: #fff; } 75 | -------------------------------------------------------------------------------- /ops_system/static/css/normalize.css: -------------------------------------------------------------------------------- 1 | article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;} -------------------------------------------------------------------------------- /ops_system/static/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /ops_system/static/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /ops_system/static/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /ops_system/static/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /ops_system/static/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .@{fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | 15 | .fa-icon-rotate(@degrees, @rotation) { 16 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); 17 | -webkit-transform: rotate(@degrees); 18 | -ms-transform: rotate(@degrees); 19 | transform: rotate(@degrees); 20 | } 21 | 22 | .fa-icon-flip(@horiz, @vert, @rotation) { 23 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); 24 | -webkit-transform: scale(@horiz, @vert); 25 | -ms-transform: scale(@horiz, @vert); 26 | transform: scale(@horiz, @vert); 27 | } 28 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | 15 | @mixin fa-icon-rotate($degrees, $rotation) { 16 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 17 | -webkit-transform: rotate($degrees); 18 | -ms-transform: rotate($degrees); 19 | transform: rotate($degrees); 20 | } 21 | 22 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 23 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 24 | -webkit-transform: scale($horiz, $vert); 25 | -ms-transform: scale($horiz, $vert); 26 | transform: scale($horiz, $vert); 27 | } 28 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /ops_system/static/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | -------------------------------------------------------------------------------- /ops_system/static/ico/apple-touch-icon-114-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/ico/apple-touch-icon-114-precomposed.png -------------------------------------------------------------------------------- /ops_system/static/ico/apple-touch-icon-144-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/ico/apple-touch-icon-144-precomposed.png -------------------------------------------------------------------------------- /ops_system/static/ico/apple-touch-icon-57-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/ico/apple-touch-icon-57-precomposed.png -------------------------------------------------------------------------------- /ops_system/static/ico/apple-touch-icon-72-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/ico/apple-touch-icon-72-precomposed.png -------------------------------------------------------------------------------- /ops_system/static/ico/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/ico/favicon.png -------------------------------------------------------------------------------- /ops_system/static/img/backgrounds/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/img/backgrounds/1.jpg -------------------------------------------------------------------------------- /ops_system/static/img/backgrounds/1@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/img/backgrounds/1@2x.jpg -------------------------------------------------------------------------------- /ops_system/static/img/demo-1-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/img/demo-1-bg.jpg -------------------------------------------------------------------------------- /ops_system/static/img/login_ico.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/img/login_ico.png -------------------------------------------------------------------------------- /ops_system/static/img/meitianhui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/img/meitianhui.png -------------------------------------------------------------------------------- /ops_system/static/img/wait.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/ops_system/static/img/wait.gif -------------------------------------------------------------------------------- /ops_system/static/js/html5.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f); 8 | if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d{b}: {c} ({d}%)" 9 | }, 10 | legend: { 11 | orient: 'vertical', 12 | x: 'left', 13 | data:['accept','reject','unaccept'] 14 | }, 15 | series: [ 16 | { 17 | type:'pie', 18 | radius: ['50%', '70%'], 19 | avoidLabelOverlap: false, 20 | label: { 21 | normal: { 22 | show: false, 23 | position: 'center' 24 | }, 25 | emphasis: { 26 | show: true, 27 | textStyle: { 28 | fontSize: '30', 29 | fontWeight: 'bold' 30 | } 31 | } 32 | }, 33 | labelLine: { 34 | normal: { 35 | show: false 36 | } 37 | }, 38 | data:[ 39 | {value:{{ accept_num }}, name:'accept', itemStyle:{ 40 | normal:{color:'green'} 41 | }}, 42 | 43 | {value:{{ reject_num }}, name:'reject', itemStyle:{ 44 | normal:{color:'red'} 45 | }}, 46 | {value:{{ unaccept_num }}, name:'unaccept', itemStyle:{ 47 | normal:{color:'yellow'} 48 | }}, 49 | ] 50 | } 51 | ] 52 | }; 53 | myChart.setOption(option); 54 | -------------------------------------------------------------------------------- /ops_system/static/js/placeholder.js: -------------------------------------------------------------------------------- 1 | 2 | $(document).ready(function(){ 3 | 4 | $(".form-username").val("Username..."); 5 | $(".form-password").val("Password..."); 6 | 7 | }); -------------------------------------------------------------------------------- /ops_system/static/js/rAF.js: -------------------------------------------------------------------------------- 1 | // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 2 | // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 3 | 4 | // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel 5 | 6 | // MIT license 7 | 8 | (function() { 9 | var lastTime = 0; 10 | var vendors = ['ms', 'moz', 'webkit', 'o']; 11 | for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 12 | window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; 13 | window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 14 | || window[vendors[x]+'CancelRequestAnimationFrame']; 15 | } 16 | 17 | if (!window.requestAnimationFrame) 18 | window.requestAnimationFrame = function(callback, element) { 19 | var currTime = new Date().getTime(); 20 | var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 21 | var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 22 | timeToCall); 23 | lastTime = currTime + timeToCall; 24 | return id; 25 | }; 26 | 27 | if (!window.cancelAnimationFrame) 28 | window.cancelAnimationFrame = function(id) { 29 | clearTimeout(id); 30 | }; 31 | }()); -------------------------------------------------------------------------------- /ops_system/static/js/scripts.js: -------------------------------------------------------------------------------- 1 | 2 | jQuery(document).ready(function() { 3 | 4 | /* 5 | Fullscreen background 6 | */ 7 | $.backstretch("/static/img/backgrounds/1.jpg"); 8 | 9 | /* 10 | Form validation 11 | */ 12 | $('.login-form input[type="text"], .login-form input[type="password"], .login-form textarea').on('focus', function() { 13 | $(this).removeClass('input-error'); 14 | }); 15 | 16 | $('.login-form').on('submit', function(e) { 17 | 18 | $(this).find('input[type="text"], input[type="password"], textarea').each(function(){ 19 | if( $(this).val() == "" ) { 20 | e.preventDefault(); 21 | $(this).addClass('input-error'); 22 | } 23 | else { 24 | $(this).removeClass('input-error'); 25 | } 26 | }); 27 | 28 | }); 29 | 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /ops_system/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url,include 2 | from django.contrib import admin 3 | from ops_system.views import index 4 | from ops_system.views import login_view,logout_view,change_password 5 | urlpatterns = [ 6 | url(r'^$',login_view,name='login'), 7 | url(r'^changePasswd$',change_password,name='changePassword'), 8 | url(r'^admin/', admin.site.urls), 9 | url(r'^index/$',index,name='index'), 10 | url(r'^asset/', include('asset.urls',namespace='asset',app_name='asset')), 11 | url(r'^deploy-manage/',include('deploy.urls',namespace='deploy-manage',app_name='deploy')), 12 | url(r'^saltstack/',include('salts.urls',namespace='saltstack',app_name='salts')), 13 | url(r'^logout/$',logout_view,name='logout'), 14 | url(r'^api/',include('api.urls',namespace='api',app_name='api')), 15 | url(r'^user/',include('users.urls',namespace='users',app_name='users')), 16 | url(r'^auths/',include('auths.urls',namespace='auths',app_name='auths')), 17 | ] 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ops_system/utils.py: -------------------------------------------------------------------------------- 1 | import commands 2 | import os 3 | 4 | 5 | 6 | def get_system_info(): 7 | cmd_get_cpu_sockect=r"lscpu|grep Socket|awk '{print $NF}'" 8 | cmd_get_cpu_cores=r"cat /proc/cpuinfo|grep processor|wc -l" 9 | cmd_get_mem_total=r"free -m |head -n 2|tail -n 1|awk '{print $2}'" 10 | cmd_get_mem_used=r"free -m |tail -n 2|head -n 1|awk '{print $3}'" 11 | cmd_get_users_num=r"w -h |wc -l" 12 | cmd_get_uptime=r"uptime |awk -F',' '{print $1}'" 13 | cpu_sockets=commands.getoutput(cmd_get_cpu_sockect) 14 | res=os.system('lscpu &>/dev/null') 15 | if res != 0: 16 | cpu_sockets=1 17 | cpu_cores=commands.getoutput(cmd_get_cpu_cores) 18 | mem_total=commands.getoutput(cmd_get_mem_total) 19 | mem_used=commands.getoutput(cmd_get_mem_used) 20 | users=commands.getoutput(cmd_get_users_num) 21 | uptime=commands.getoutput(cmd_get_uptime) 22 | mem_percentage=round(float(mem_used)/float(mem_total)*100,2) 23 | mem_left_percentage=100-mem_percentage 24 | info_dict={'cpu_sockets':cpu_sockets,'cpu_cores':cpu_cores,'mem_total':mem_total,'mem_used':mem_used,'mem_percentage':mem_percentage,'users':users,'uptime':uptime,'mem_left_percentage':mem_left_percentage} 25 | return info_dict 26 | 27 | 28 | 29 | 30 | if __name__=='__main__': 31 | print get_system_info() 32 | -------------------------------------------------------------------------------- /ops_system/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django.shortcuts import render_to_response 3 | from django.core.urlresolvers import reverse 4 | from django.contrib.auth.decorators import login_required 5 | from django.contrib.auth import authenticate,login,logout 6 | from django.template import RequestContext 7 | from django.http import HttpResponseRedirect,HttpResponseNotAllowed,HttpResponse 8 | from utils import * 9 | import json 10 | from salts.utils import SaltByLocalApi 11 | @login_required(login_url='/') 12 | def index(request): 13 | if request.method=='POST': 14 | return HttpResponseNotAllowed(request) 15 | local=SaltByLocalApi('/etc/salt/master') 16 | res=local.get_minions_key_status() 17 | key_status={'a_n':res[0],'r_n':res[1],'u_n':res[2]} 18 | minion_status=local.get_minions_status() 19 | minion_status=json.dumps(minion_status) 20 | key_status=json.dumps(key_status) 21 | sys_info_dict=get_system_info() 22 | return render_to_response('index.html', RequestContext(request,{'Dict': key_status,'info':minion_status,'info_dict':sys_info_dict})) 23 | 24 | def login_view(request): 25 | if request.user.is_authenticated(): 26 | return HttpResponseRedirect(reverse('index')) 27 | if request.method == 'POST': 28 | user = authenticate(username=request.POST['username'], password=request.POST['password']) 29 | if user is not None and user.is_active: 30 | login(request, user) 31 | #return render_to_response('index.html',RequestContext(request)) 32 | return HttpResponseRedirect(reverse('index')) 33 | else: 34 | return render_to_response('login_new.html',RequestContext(request,{'error':'Bad Username or Password'})) 35 | else: 36 | return render_to_response('login_new.html',RequestContext(request,{'error':''})) 37 | 38 | @login_required(login_url='/') 39 | def logout_view(request): 40 | logout(request) 41 | return HttpResponseRedirect('/') 42 | 43 | @login_required(login_url='/') 44 | def change_password(request): 45 | if request.method=='POST': 46 | old_pwd=request.POST.get('old_pwd','') 47 | new_pwd=request.POST.get('new_pwd','') 48 | again_pwd=request.POST.get('again_pwd','') 49 | print old_pwd,new_pwd,again_pwd 50 | if new_pwd.replace(' ','') == '' or again_pwd.replace(' ','')=='' or old_pwd.replace(' ','')=='': 51 | return HttpResponse(json.dumps({'code':400,'info':u'请输入所有选项'})) 52 | user=authenticate(username=request.user.username,password=old_pwd) 53 | if user is not None and user.is_active: 54 | print user.is_active,user 55 | user.set_password(again_pwd) 56 | try: 57 | user.save() 58 | except Exception as e: 59 | return HttpResponse(json.dumps({'code':400,'info':u'修改失败'})) 60 | else: 61 | return HttpResponse(json.dumps({'code':200,'info':u'修改成功'})) 62 | else: 63 | return HttpResponse(json.dumps({'code':400,'info':u'原密码错误!'})) 64 | 65 | -------------------------------------------------------------------------------- /ops_system/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for ops_system project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ops_system.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /requirements: -------------------------------------------------------------------------------- 1 | django==v1.9 2 | pexpect 3 | zmq 4 | tornado 5 | pyaml 6 | MySQL-python 7 | msgpack-python 8 | salt==v2015.8.13 9 | uwsgi 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | 2 | 1, 环境 : python2.7 mysql,svn ,git ,salt-master,salt 3 | 4 | 2, python模块 pexpect, django,salt,msgpack-python,MySQL-python,pyaml,tornado,zmq 5 | -------------------------------------------------------------------------------- /salts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/salts/__init__.py -------------------------------------------------------------------------------- /salts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /salts/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class SaltConfig(AppConfig): 7 | name = 'salt' 8 | -------------------------------------------------------------------------------- /salts/forms.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | from django import forms 3 | Choice=(('list','List'),('grain','Grain'),('pcre','Regex'),('nodegroup','NodeGroup'),('glob','Hostname')) 4 | class CmdInputForm(forms.Form): 5 | target=forms.CharField(error_messages={'required':u'请输入目标主机!'}, 6 | label=u'Target', 7 | max_length=100, 8 | required=True, 9 | widget=forms.TextInput(attrs={'class':'form-control'})) 10 | mapping=forms.ChoiceField(required=True, 11 | choices=(('list','List'),('grain','Grain'),('pcre','Regex'),('nodegroup','NodeGroup'),('glob','Hostname')), 12 | widget=forms.RadioSelect(attrs={'checked':None})) 13 | cmdline=forms.CharField(error_messages={'required':u'请输入命令!'}, 14 | label=u'Command', 15 | max_length=1000, 16 | required=True, 17 | widget=forms.TextInput(attrs={'class':'form-control'})) 18 | 19 | 20 | 21 | 22 | class UploadFileForm(forms.Form): 23 | global Choice 24 | target=forms.CharField(error_messages={'required':u'请输入目标主机'}, 25 | label=u'分发主机', 26 | max_length=200, 27 | required=True, 28 | widget=forms.TextInput(attrs={'class':'form-control'})) 29 | mapping=forms.ChoiceField(required=True,choices=Choice, 30 | widget=forms.RadioSelect(attrs={'checked':None})) 31 | upload_path=forms.RegexField(error_messages={'invalid':u'分发路径书写不正确,请以/开头'}, 32 | label=u'分发路径', 33 | max_length=500, 34 | regex=r'^/', 35 | required=True, 36 | widget=forms.TextInput(attrs={'class':'form-control','placeholder':'中文名命名文件无法分发'})) 37 | upload_file=forms.FileField(label=u'上传文件',required=True, 38 | widget=forms.FileInput(attrs={'style':'margin-left:100px'})) 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | class DownloadFileForm(forms.Form): 47 | target=forms.CharField(error_messages={'required':u'请输入目标主机!'}, 48 | label=u'Target', 49 | max_length=100, 50 | required=True, 51 | widget=forms.TextInput(attrs={'class':'form-control'})) 52 | file_path=forms.RegexField(regex=r'^/', 53 | error_messages={'required':u'请输入文件绝对路径!','invalid':u'无效的路径,必须以/开头'}, 54 | label=u'FilePath', 55 | max_length=1000, 56 | required=True, 57 | widget=forms.TextInput(attrs={'class':'form-control'})) 58 | 59 | class ProjectRecord(forms.Form): 60 | type=forms.CharField(label=u'类型',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control','placeholder':'可选类型为: mps,appportal'})) 61 | version=forms.CharField(label=u'版本号',max_length=100,required=True,widget=forms.TextInput(attrs={'class':'form-control'})) 62 | projects=forms.CharField(label=u'工程名',max_length=1000,required=True,widget=forms.TextInput(attrs={'class':'form-control','placeholder':'多个工程以空格相隔'})) 63 | sql=forms.CharField(label=u'Sql文件名',max_length=1000,required=False,widget=forms.TextInput(attrs={'class':'form-control','placeholder':'若无则不填'})) 64 | comment=forms.CharField(label=u'版本说明',max_length=2000,required=True,widget=forms.Textarea(attrs={'class':'form-control'})) 65 | #comment=forms.Textarea() 66 | 67 | -------------------------------------------------------------------------------- /salts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/salts/migrations/__init__.py -------------------------------------------------------------------------------- /salts/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | 5 | 6 | class HostInfoModel(models.Model): 7 | hostname=models.CharField(max_length=100) 8 | ipaddress=models.CharField(max_length=200) 9 | cpuinfo=models.CharField(max_length=50) 10 | meminfo=models.CharField(max_length=50) 11 | group=models.CharField(max_length=50) 12 | osinfo=models.CharField(max_length=20) 13 | area=models.CharField(max_length=100) 14 | usage=models.CharField(max_length=200) 15 | class Meta: 16 | db_table='ops_host_info' 17 | 18 | class AppDeployLogModel(models.Model): 19 | user=models.CharField(max_length=50) 20 | time=models.DateTimeField() 21 | target=models.CharField(max_length=100) 22 | application=models.CharField(max_length=100) 23 | mapping=models.CharField(max_length=20) 24 | success_hosts=models.CharField(max_length=500) 25 | failed_hosts=models.CharField(max_length=500) 26 | total=models.IntegerField() 27 | log=models.TextField() 28 | duration=models.CharField(max_length=500) 29 | class Meta: 30 | db_table='ops_app_deploy_log' 31 | 32 | class CmdRunLogModel(models.Model): 33 | user=models.CharField(max_length=30) 34 | time=models.DateTimeField() 35 | target=models.CharField(max_length=100) 36 | mapping=models.CharField(max_length=50) 37 | cmd=models.CharField(max_length=500) 38 | hosts=models.CharField(max_length=500) 39 | total=models.IntegerField() 40 | class Meta: 41 | db_table='ops_cmd_run_log' 42 | 43 | 44 | 45 | class OnlineDeployModel(models.Model): 46 | type=models.CharField(max_length=50) 47 | version=models.CharField(max_length=50) 48 | project=models.CharField(max_length=1000) 49 | sql_name=models.CharField(max_length=1000,null=True) 50 | create_time=models.DateTimeField() 51 | modify_time=models.DateTimeField() 52 | audit_time=models.DateTimeField(null=True) 53 | publish_time=models.DateTimeField(null=True) 54 | proposer=models.CharField(max_length=100) 55 | auditor=models.CharField(max_length=100,null=True) 56 | publisher=models.CharField(max_length=100,null=True) 57 | status=models.CharField(max_length=100) 58 | deploy_status=models.CharField(max_length=20,null=True) 59 | active=models.CharField(max_length=10) 60 | comment=models.CharField(max_length=2000) 61 | command=models.CharField(max_length=1000,null=True) 62 | class Meta: 63 | db_table='ops_publish_record' 64 | 65 | 66 | class DistributeFileRecordModel(models.Model): 67 | user=models.CharField(max_length=100) 68 | hostname=models.CharField(max_length=100) 69 | pattern=models.CharField(max_length=100) 70 | opttime=models.DateTimeField() 71 | path=models.CharField(max_length=200) 72 | filename=models.CharField(max_length=100) 73 | class Meta: 74 | db_table='ops_upload_file_record' 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /salts/test.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | from salt.client import LocalClient 3 | from salt.config import client_config 4 | from utils import SaltByLocalApi 5 | def test1(): 6 | client=LocalClient() 7 | result=client.cmd('self','oss:centos',['ls /root'],'grain') 8 | print result 9 | # for k,v in result.iteritems(): 10 | # print k 11 | # print '----' 12 | # for i,j in v.iteritems(): 13 | # print i 14 | # print j 15 | # 16 | 17 | def parse_target_params(target,match): 18 | saltapi=SaltByLocalApi('/etc/salt/master') 19 | active_minion_list=saltapi.connected_minions_list 20 | nodegroup_list=[] 21 | t_list=[] 22 | target=target.replace(' ','') 23 | for key in saltapi.get_master_config()['nodegroups'].iterkeys(): 24 | nodegroup_list.append(key) 25 | if match == 'list': 26 | L=target.split(',') 27 | t_list=[x for x in L if x !=''] 28 | for v in t_list: 29 | if v not in active_minion_list: 30 | return None,'do not exists the minion: %s' %v 31 | return True,','.join(t_list) 32 | elif match == 'glob': 33 | if target == '*': 34 | pass 35 | elif target not in active_minion_list: 36 | return None,'illegal hostname: %s ' %target 37 | elif match == 'grain': 38 | grains=saltapi.get_grains().values()[0] 39 | if grains is None: 40 | return None,'do not exists online monions' 41 | var_list=target.split(':') 42 | length=len(var_list) 43 | if length<2: 44 | return None,'illegal grains' 45 | g_var=var_list[length-1] 46 | g_key=var_list[:length-1] 47 | for k in g_key: 48 | if k not in grains: 49 | return None,'bad grains key : %s' %k 50 | grains=grains[k] 51 | elif match == 'nodegroup': 52 | if target not in nodegroup_list: 53 | return None,'do not exist nodegroup: %s' %target 54 | return True,target 55 | 56 | 57 | if __name__=='__main__': 58 | print parse_target_params('supply_webss','nodegroup') 59 | -------------------------------------------------------------------------------- /salts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /salts/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from views import * 3 | 4 | 5 | urlpatterns=[ 6 | url('^hosts/host_info$',list_host_info,name='host_info'), 7 | url('^hosts/deploy/application$',deploy_application,name='deploy'), 8 | url('^hosts/refresh_host_info$',refresh_host_info,name='refresh_host_info'), 9 | url('^hosts/list_app_deploy_info$',list_app_deploy_info,name='list_app_deploy_info'), 10 | url('^hosts/list_cmd_run_info$',list_cmd_run_info,name='list_cmd_run_info'), 11 | url('^hosts/cmd_run$',cmd_run,name='cmd_run'), 12 | url('^hosts/download_file$',download_file,name='download_file'), 13 | url('^hosts/upload_file$',upload_file,name='upload_file'), 14 | url('^hosts/code_deploy$',code_deploy,name='code_deploy'), 15 | url('^hosts/record/info$',get_record_from_id,name='record'), 16 | url('^hosts/record/delete$',delete_record_from_id,name='record_delete'), 17 | url('^hosts/record/modify$',modify_record_from_id,name='record_modify'), 18 | url('^hosts/record/audit$',audit_record_from_id,name='record_audit'), 19 | url('^hosts/record/deploy$',deploy_record_from_id,name='record_deploy'), 20 | ] 21 | 22 | -------------------------------------------------------------------------------- /screenshots/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/0.png -------------------------------------------------------------------------------- /screenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/1.png -------------------------------------------------------------------------------- /screenshots/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/10.png -------------------------------------------------------------------------------- /screenshots/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/11.png -------------------------------------------------------------------------------- /screenshots/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/12.png -------------------------------------------------------------------------------- /screenshots/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/13.png -------------------------------------------------------------------------------- /screenshots/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/14.png -------------------------------------------------------------------------------- /screenshots/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/15.png -------------------------------------------------------------------------------- /screenshots/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/16.png -------------------------------------------------------------------------------- /screenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/2.png -------------------------------------------------------------------------------- /screenshots/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/3.png -------------------------------------------------------------------------------- /screenshots/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/4.png -------------------------------------------------------------------------------- /screenshots/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/5.png -------------------------------------------------------------------------------- /screenshots/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/6.png -------------------------------------------------------------------------------- /screenshots/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/7.png -------------------------------------------------------------------------------- /screenshots/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/8.png -------------------------------------------------------------------------------- /screenshots/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/screenshots/9.png -------------------------------------------------------------------------------- /sls/epel/files/epel-release-latest-6.noarch.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/epel/files/epel-release-latest-6.noarch.rpm -------------------------------------------------------------------------------- /sls/epel/install.sls: -------------------------------------------------------------------------------- 1 | 2 | /tmp/epel-release-latest-6.noarch.rpm: 3 | file.managed: 4 | - source: salt://epel/files/epel-release-latest-6.noarch.rpm 5 | - mode: 755 6 | - user: root 7 | 8 | install_epel: 9 | cmd.run: 10 | - name: cd /tmp && rpm -ih epel-release-latest-6.noarch.rpm 11 | - required: 12 | - file: /tmp/epel-release-latest-6.noarch.rpm 13 | - unless: rpm -qa|grep epel 14 | 15 | install_gcc: 16 | cmd.run: 17 | - name: yum install gcc make gcc-c++ -y &>/dev/null 18 | - required: 19 | - cmd: install_epel 20 | -------------------------------------------------------------------------------- /sls/memcached/files/libevent-2.0.21-stable.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/memcached/files/libevent-2.0.21-stable.tar.gz -------------------------------------------------------------------------------- /sls/memcached/files/memcached-1.4.25.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/memcached/files/memcached-1.4.25.tar.gz -------------------------------------------------------------------------------- /sls/memcached/install.sls: -------------------------------------------------------------------------------- 1 | {% set memcached_install_dir='/webdata/opt/local' %} 2 | include: 3 | - epel.install 4 | 5 | 6 | install_compile_env: 7 | cmd.run: 8 | - name: yum install gcc make -y &>/dev/null 9 | 10 | /tmp/libevent-2.0.21-stable.tar.gz: 11 | file.managed: 12 | - source: salt://memcached/files/libevent-2.0.21-stable.tar.gz 13 | - mode: 755 14 | - user: root 15 | - unless: test -e /tmp/libevent-2.0.21-stable.tar.gz 16 | 17 | /tmp/memcached-1.4.25.tar.gz: 18 | file.managed: 19 | - source: salt://memcached/files/memcached-1.4.25.tar.gz 20 | - mode: 755 21 | - user: root 22 | - unless: test -e /tmp/memcached-1.4.25.tar.gz 23 | 24 | 25 | install_libevent: 26 | cmd.run: 27 | - name: cd /tmp && rm -rf libevent-2.0.21-stable && tar -xzf libevent-2.0.21-stable.tar.gz && cd libevent-2.0.21-stable && ./configure --prefix=/usr/local/libevent &>/dev/null && make &>/dev/null && make install &>/dev/null 28 | - required: 29 | - file: /tmp/libevent-2.0.21-stable.tar.gz 30 | - cmd: install_compile_env 31 | - unless: test -d /usr/local/libevent 32 | 33 | install_memcached: 34 | cmd.run: 35 | - name: cd /tmp/ && rm -rf memcached-1.4.25 && tar -zxf memcached-1.4.25.tar.gz && cd memcached-1.4.25 && mkdir -p {{memcached_install_dir}} && ./configure --prefix={{memcached_install_dir}}/memcached --with-libevent=/usr/local/libevent &>/dev/null && make &>/dev/null && make install &>/dev/null 36 | - required: 37 | - file: /tmp/memcached-1.4.25.tar.gz 38 | - cmd: install_libevent 39 | - cmd: install_compile_env 40 | - unless: test -d {{ memcached_install_dir }}/memcached/bin 41 | -------------------------------------------------------------------------------- /sls/mysql/files/my.cnf: -------------------------------------------------------------------------------- 1 | # For advice on how to change settings please see 2 | # http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html 3 | 4 | [mysqld] 5 | 6 | # Remove leading # and set to the amount of RAM for the most important data 7 | # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. 8 | # innodb_buffer_pool_size = 128M 9 | 10 | # Remove leading # to turn on a very important data integrity option: logging 11 | # changes to the binary log between backups. 12 | # log_bin 13 | 14 | # These are commonly set, remove the # and set as required. 15 | basedir = {{basedir}} 16 | datadir = {{datadir}} 17 | port = 3306 18 | # server_id = ..... 19 | socket =/tmp/mysql.sock 20 | bind_address=127.0.0.1 21 | 22 | # Remove leading # to set options mainly useful for reporting servers. 23 | # The server defaults are faster for transactions and fast SELECTs. 24 | # Adjust sizes as needed, experiment to find the optimal values. 25 | # join_buffer_size = 128M 26 | # sort_buffer_size = 2M 27 | # read_rnd_buffer_size = 2M 28 | 29 | sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 30 | -------------------------------------------------------------------------------- /sls/mysql/files/mysql-5.6.10.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/mysql/files/mysql-5.6.10.tar.gz -------------------------------------------------------------------------------- /sls/mysql/install.sls: -------------------------------------------------------------------------------- 1 | {% set mysql_install_dir = '/webdata/opt/local' %} 2 | {% set configure_args= '-DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_MEMORY_STORAGE_ENGINE=1 -DWITH_MYISAM_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_READLINE=1 -DENABLED_LOCAL_INFILE=1 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DEXTRA_CHARSET=utf8 -DWITH_USER=mysql -DWITH_EMBEDDED_SERVER=OFF' %} 3 | 4 | include: 5 | - epel.install 6 | 7 | /tmp/mysql-5.6.10.tar.gz: 8 | file.managed: 9 | - source: salt://mysql/files/mysql-5.6.10.tar.gz 10 | - mode: 755 11 | - user: root 12 | - unless: test -e /tmp/mysql-5.6.10.tar.gz 13 | 14 | install_dep_pkg: 15 | cmd.run: 16 | - name: yum install ncurses-devel zlib-devel perl-DBI perl-DBD-mysql perl-Time-HiRes perl-IO-Socket-SSL perl-Term-ReadKey cmake -y &>/dev/null 17 | 18 | install_mysql_source: 19 | cmd.run: 20 | - name: cd /tmp && rm -rf mysql-5.6.10 && tar -zxf mysql-5.6.10.tar.gz && cd mysql-5.6.10 && mkdir -p {{mysql_install_dir}} && cmake -DCMAKE_INSTALL_PREFIX={{mysql_install_dir}}/mysql -DMYSQL_DATADIR={{mysql_install_dir}}/mysql/data {{configure_args}} &>/dev/null && make &>/dev/null && make install &>/dev/null 21 | - required: 22 | - file: /tmp/mysql-5.6.10.tar.gz 23 | - unless: test -e {{mysql_install_dir}}/mysql/bin/mysqld 24 | 25 | add_mysql_user: 26 | user.present: 27 | - name: mysql 28 | - system: Ture 29 | - shell: /sbin/nologin 30 | - gid_from_name: Ture 31 | - createhome: False 32 | 33 | /etc/my.cnf: 34 | file.managed: 35 | - source: salt://mysql/files/my.cnf 36 | - mode: 755 37 | - user: root 38 | - template: jinja 39 | - defaults: 40 | datadir: {{mysql_install_dir}}/mysql/data 41 | basedir: {{mysql_install_dir}}/mysql 42 | 43 | /etc/init.d/mysqld: 44 | file.managed: 45 | - source: salt://mysql/files/mysqld 46 | - template: jinja 47 | - defaults: 48 | datadir: {{mysql_install_dir}}/mysql/data 49 | basedir: {{mysql_install_dir}}/mysql 50 | - mode: 755 51 | - user: root 52 | 53 | init_mysql_data: 54 | cmd.run: 55 | - name: cd {{mysql_install_dir}}/mysql && ./scripts/mysql_install_db --user=mysql --datadir={{mysql_install_dir}}/mysql/data --basedir={{mysql_install_dir}}/mysql &>/dev/null 56 | - required: 57 | - cmd: install_mysql_source 58 | - unless: test -e {{mysql_install_dir}}/mysql/data/mysql/user.frm 59 | 60 | add_chkconfig: 61 | cmd.run: 62 | - name: chkconfig --level 35 mysqld on 63 | - required: 64 | - file: /etc/init.d/mysqld 65 | - unless: chkconfig --list|grep mysqld &>/dev/null 66 | 67 | 68 | chown_mysql_dir: 69 | cmd.run: 70 | - name: chown -R mysql.mysql {{mysql_install_dir }}/mysql && chown -R mysql.mysql {{mysql_install_dir}}/mysql/data 71 | - required: 72 | - cmd: install_mysql_source 73 | - user: add_mysql_user 74 | 75 | -------------------------------------------------------------------------------- /sls/nginx/files/jemalloc-4.0.4.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/nginx/files/jemalloc-4.0.4.tar.bz2 -------------------------------------------------------------------------------- /sls/nginx/files/tengine-2.1.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/nginx/files/tengine-2.1.1.tar.gz -------------------------------------------------------------------------------- /sls/nginx/install.sls: -------------------------------------------------------------------------------- 1 | {%set nginx_install_dir= '/webdata/opt/local' %} 2 | {%set configure_args=' --user=www --group=www --with-pcre --with-http_upstream_session_sticky_module=shared --with-http_upstream_ip_hash_module=shared --with-http_sub_module --with-http_spdy_module' %} 3 | include: 4 | - epel.install 5 | 6 | 7 | /tmp/jemalloc-4.0.4.tar.bz2: 8 | file.managed: 9 | - source: salt://nginx/files/jemalloc-4.0.4.tar.bz2 10 | - mode: 755 11 | - user: root 12 | - unless: test -e /tmp/jemalloc-4.0.4.tar.bz2 13 | 14 | /tmp/tengine-2.1.1.tar.gz: 15 | file.managed: 16 | - source: salt://nginx/files/tengine-2.1.1.tar.gz 17 | - mode: 755 18 | - user: root 19 | - unless: test -e /tmp/tengine-2.1.1.tar.gz 20 | 21 | install_dep_pkgs: 22 | cmd.run: 23 | - name: yum install gcc gcc-c++ cmake make pcre-devel openssl-devel ncurses-devel openssl -y &>/dev/null 24 | 25 | install_tengine: 26 | cmd.run: 27 | - name: cd /tmp && tar -jxf jemalloc-4.0.4.tar.bz2 &>/dev/null && tar -zxf tengine-2.1.1.tar.gz && mkdir -p {{ nginx_install_dir}} && cd tengine-2.1.1 && ./configure --prefix={{nginx_install_dir}}/nginx --with-jemalloc --with-jemalloc=/tmp/jemalloc-4.0.4 {{ configure_args }} &>/dev/null && make &>/dev/null && make install &>/dev/null 28 | - required: 29 | - file: /tmp/tengine-2.1.1.tar.gz 30 | - file: /tmp/jemalloc-4.0.4.tar.bz2 31 | - cmd: install_dep_pkgs 32 | - unless: test -e {{nginx_install_dir}}/nginx/sbin/nginx 33 | 34 | add_run_user: 35 | user.present: 36 | - shell: /sbin/nologin 37 | - name: www 38 | - gid_from_name: Ture 39 | - createhome: False 40 | - system: Ture 41 | 42 | -------------------------------------------------------------------------------- /sls/php/files/libevent-2.0.21-stable.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/php/files/libevent-2.0.21-stable.tar.gz -------------------------------------------------------------------------------- /sls/php/files/libmemcached-1.0.18.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/php/files/libmemcached-1.0.18.tar.gz -------------------------------------------------------------------------------- /sls/php/files/memcache-3.0.5.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/php/files/memcache-3.0.5.tgz -------------------------------------------------------------------------------- /sls/php/files/php-5.6.16.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/php/files/php-5.6.16.tar.gz -------------------------------------------------------------------------------- /sls/php/files/php-memcached.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/php/files/php-memcached.tar.gz -------------------------------------------------------------------------------- /sls/php/files/phpredis-2.2.4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/php/files/phpredis-2.2.4.tar.gz -------------------------------------------------------------------------------- /sls/redis/files/redis-3.2.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/redis/files/redis-3.2.0.tar.gz -------------------------------------------------------------------------------- /sls/redis/install.sls: -------------------------------------------------------------------------------- 1 | {% set redis_install_dir = '/webdata/opt/local' %} 2 | 3 | /tmp/redis-3.2.0.tar.gz: 4 | file.managed: 5 | - source: salt://redis/files/redis-3.2.0.tar.gz 6 | - mode: 755 7 | - user: root 8 | - unless: test -e /tmp/redis-3.2.0.tar.gz 9 | 10 | 11 | install_redis: 12 | cmd.run: 13 | - name: cd /tmp && rm -rf redis-3.2.0 && tar -zxf redis-3.2.0.tar.gz && cd redis-3.2.0/src && make &>/dev/null && mkdir -p {{ redis_install_dir }}/redis/{bin,etc,db} && \cp redis-server redis-cli {{redis_install_dir}}/redis/bin 14 | - required: 15 | - file: /tmp/redis-3.2.0.tar.gz 16 | - unless: test -e {{redis_install_dir}}/redis/bin/redis-server 17 | 18 | up_conf: 19 | file.managed: 20 | - name: {{redis_install_dir}}/redis/etc/redis.conf 21 | - source: salt://redis/files/redis.conf 22 | - mode: 755 23 | - user: root 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /sls/system/install.sls: -------------------------------------------------------------------------------- 1 | 2 | /etc/profile: 3 | cmd.run: 4 | - name: echo 'HISTTIMEFORMAT="%F %T `whoami`"' >>/etc/profile 5 | - unless: grep HISTTIMEFORMAT /etc/profile &>/dev/null 6 | 7 | install_lrzsz: 8 | cmd.run: 9 | - name: yum install lrzsz -y &>/dev/null 10 | - unless: rpm -qa|grep lrzsz 11 | 12 | net.ipv4.conf.default.accept_source_route: 13 | sysctl.present: 14 | - value: 0 15 | kernel.core_uses_pid: 16 | sysctl.present: 17 | - value: 1 18 | vm.swappiness: 19 | sysctl.present: 20 | - value: 0 21 | net.ipv4.tcp_tw_reuse: 22 | sysctl.present: 23 | - value: 1 24 | net.ipv4.tcp_tw_recycle: 25 | sysctl.present: 26 | - value: 1 27 | net.ipv4.tcp_fin_timeout: 28 | sysctl.present: 29 | - value: 15 30 | net.ipv4.tcp_keepalive_time: 31 | sysctl.present: 32 | - value: 1200 33 | net.ipv4.ip_local_port_range: 34 | sysctl.present: 35 | - value: 1024 65532 36 | net.core.netdev_max_backlog: 37 | sysctl.present: 38 | - value: 30000 39 | net.ipv4.tcp_timestamps: 40 | sysctl.present: 41 | - value: 0 42 | 43 | 44 | -------------------------------------------------------------------------------- /sls/tomcat/files/apache-tomcat-7.0.54.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/tomcat/files/apache-tomcat-7.0.54.tar.gz -------------------------------------------------------------------------------- /sls/tomcat/install.sls: -------------------------------------------------------------------------------- 1 | {%set jdk_install_dir= '/webdata/opt/local' %} 2 | {%set tomcat_install_dir= '/webdata/opt/local' %} 3 | 4 | include: 5 | - epel.install 6 | /tmp/apache-tomcat-7.0.54.tar.gz: 7 | file.managed: 8 | - source: salt://tomcat/files/apache-tomcat-7.0.54.tar.gz 9 | - mode: 755 10 | - user: root 11 | - unless: ls -l /tmp/apache-tomcat-7.0.54.tar.gz 12 | 13 | /tmp/jdk-7u71-linux-i586.tar.gz: 14 | file.managed: 15 | - source: salt://tomcat/files/jdk-7u71-linux-i586.tar.gz 16 | - mode: 755 17 | - root: root 18 | - unless: ls -l /tmp/jdk-7u71-linux-i586.tar.gz 19 | 20 | install_jdk: 21 | cmd.run: 22 | - name: cd /tmp && rm -rf jdk1.7.0_71 && tar -zxf jdk-7u71-linux-i586.tar.gz &>/dev/null && mkdir -p {{ jdk_install_dir }} && mv jdk1.7.0_71 {{ jdk_install_dir }}/jdk7 23 | - required: 24 | file: /tmp/jdk-7u71-linux-i586.tar.gz 25 | - unless: test -e {{jdk_install_dir}}/jdk7/bin/java 26 | 27 | install_tomcat: 28 | cmd.run: 29 | - name: cd /tmp && rm -rf apache-tomcat-7.0.54 && tar -zxf apache-tomcat-7.0.54.tar.gz &>/dev/null && mkdir -p {{ tomcat_install_dir }} && mv apache-tomcat-7.0.54 {{ tomcat_install_dir }}/tomcat7 30 | - required: 31 | file: /tmp/apache-tomcat-7.0.54.tar.gz 32 | - unless: test -d {{tomcat_install_dir}}/tomcat7/bin 33 | 34 | init_env_var: 35 | cmd.run: 36 | - name: echo "JAVA_HOME={{ jdk_install_dir }}/jdk7" >>/etc/profile && echo "JRE_HOME={{ jdk_install_dir }}/jdk7/jre" >>/etc/profile && echo 'CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib' >>/etc/profile && echo 'PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin' >>/etc/profile 37 | - required: 38 | - file: /tmp/jdk-7u71-linux-i586.tar.gz 39 | - file: /tmp/apache-tomcat-7.0.54.tar.gz 40 | - unless: grep 'JAVA_HOME' /etc/profile &>/dev/null && grep 'JRE_HOME' /etc/profile &>/dev/null && grep 'CLASSPATH' /etc/profile &>/dev/null 41 | 42 | install_dep_pkg: 43 | cmd.run: 44 | - name: yum install glibc glibc-devel glibc-static glibc-common glibc-headers glibc*.i686 -y &>/dev/null 45 | -------------------------------------------------------------------------------- /sls/tools/files/daemon.conf: -------------------------------------------------------------------------------- 1 | AliHids 2 | AliYunDun 3 | AliYunDunUpdate 4 | aliyun-service 5 | crond 6 | gshelld 7 | haproxy 8 | java 9 | login 10 | master 11 | memcached 12 | mingetty 13 | mongod 14 | mysqld_safe 15 | mysql-proxy 16 | nginx 17 | node 18 | nscd 19 | ntpd 20 | php 21 | php-fpm 22 | python 23 | redis-server 24 | rpcbind 25 | rpc.idmapd 26 | rpc.mountd 27 | rpc.rquotad 28 | rpc.statd 29 | rsync 30 | rsyslogd 31 | ruby 32 | runsvdir 33 | salt-master 34 | salt-minion 35 | sersync2 36 | snmpd 37 | ssh 38 | sshd 39 | svnserve 40 | tcpdump.sh 41 | udevd 42 | vsftpd 43 | zabbix_agentd 44 | zabbix_server 45 | -------------------------------------------------------------------------------- /sls/tools/files/getdaemon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import psutil 4 | import urllib2,urllib 5 | import json 6 | import random 7 | import commands 8 | import time 9 | def get_daemon(): 10 | sleep_time=5 11 | res,hostname=commands.getstatusoutput('hostname') 12 | daemon_list=[] 13 | tmp_list=[] 14 | illegal_daemon_list=[] 15 | p=psutil.Process(1) 16 | for pp in p.children(): 17 | tmp_list.append(pp.name()) 18 | for i in tmp_list: 19 | if i not in daemon_list: 20 | daemon_list.append(i) 21 | all_daemon_list=[] 22 | try: 23 | with open('/etc/daemon.conf','r') as f: 24 | for i in f.readlines(): 25 | all_daemon_list.append(i.replace('\n','')) 26 | except Exception as e: 27 | print e 28 | for daemon in daemon_list: 29 | if daemon not in all_daemon_list: 30 | illegal_daemon_list.append(daemon) 31 | if illegal_daemon_list != []: 32 | prefix='illegal daemon on %s running: ' %hostname 33 | for d in illegal_daemon_list: 34 | prefix=prefix+'*'+d 35 | sendsms(prefix) 36 | time.sleep(sleep_time) 37 | 38 | 39 | def sendsms(mess): 40 | app_id='375f0089-6ae1-0b10-a41d-6fa882086341' 41 | ID=str(random.randint(134234,876355)) 42 | url='http://api.110monitor.com/alert/api/event' 43 | data={'app':app_id, 44 | 'priority':'3', 45 | 'eventType':'trigger', 46 | 'alarmName':mess, 47 | 'alarmContent':mess, 48 | 'eventId':ID, 49 | 'entityId':ID 50 | } 51 | data=json.dumps(data) 52 | header={'Content-type':'application/json'} 53 | request=urllib2.Request(url,data,header) 54 | response=urllib2.urlopen(request) 55 | 56 | 57 | if __name__ == '__main__': 58 | get_daemon() 59 | -------------------------------------------------------------------------------- /sls/tools/files/psutil-4.3.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/tools/files/psutil-4.3.0.tar.gz -------------------------------------------------------------------------------- /sls/tools/install.sls: -------------------------------------------------------------------------------- 1 | /etc/init.d/agent.py: 2 | file.managed: 3 | - source: salt://tools/files/agent.py 4 | - mode: 755 5 | 6 | /tmp/psutil-4.3.0.tar.gz: 7 | file.managed: 8 | - source: salt://tools/files/psutil-4.3.0.tar.gz 9 | 10 | install_gcc: 11 | cmd.run: 12 | - name: yum install python-devel gcc -y &>/dev/null 13 | 14 | 15 | install_psutil: 16 | cmd.run: 17 | - name: cd /tmp && tar -zxf psutil-4.3.0.tar.gz && cd psutil-4.3.0 && python setup.py install &>/dev/null 18 | - required: 19 | - file: /tmp/psutil-4.3.0.tar.gz 20 | 21 | /etc/daemon.conf: 22 | file.managed: 23 | - source: salt://tools/files/daemon.conf 24 | - mode: 700 25 | 26 | run: 27 | cmd.run: 28 | - name: /etc/init.d/agent.py -d -s 72000 -m 10.117.74.247 29 | - unless: ps aux|grep python|grep agent.py|egrep -v 'grep' 30 | -------------------------------------------------------------------------------- /sls/top.sls: -------------------------------------------------------------------------------- 1 | base: 2 | '*': 3 | - zabbix.install 4 | -------------------------------------------------------------------------------- /sls/zabbix/files/zabbix.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/sls/zabbix/files/zabbix.tar.gz -------------------------------------------------------------------------------- /sls/zabbix/files/zabbix_agentd: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # chkconfig: - 90 10 4 | # description: Starts and stops Zabbix Agent using chkconfig 5 | # Tested on Fedora Core 2 - 5 6 | # Should work on all Fedora Core versions 7 | # 8 | # @name: zabbix_agentd 9 | # @author: Alexander Hagenah 10 | # @created: 18.04.2006 11 | # 12 | # Modified for Zabbix 2.0.0 13 | # May 2012, Zabbix SIA 14 | # 15 | # Source function library. 16 | . /etc/init.d/functions 17 | 18 | # Variables 19 | # Edit these to match your system settings 20 | 21 | # Zabbix-Directory 22 | BASEDIR={{install_dir}}/zabbix 23 | 24 | # Binary File 25 | BINARY_NAME=zabbix_agentd 26 | 27 | # Full Binary File Call 28 | FULLPATH=$BASEDIR/sbin/$BINARY_NAME 29 | 30 | # PID file 31 | PIDFILE=/tmp/$BINARY_NAME.pid 32 | 33 | # Establish args 34 | ERROR=0 35 | STOPPING=0 36 | 37 | # 38 | # No need to edit the things below 39 | # 40 | 41 | # application checking status 42 | if [ -f $PIDFILE ] && [ -s $PIDFILE ] 43 | then 44 | PID=`cat $PIDFILE` 45 | 46 | if [ "x$PID" != "x" ] && kill -0 $PID 2>/dev/null && [ $BINARY_NAME == `ps -e | grep $PID | awk '{print $4}'` ] 47 | then 48 | STATUS="$BINARY_NAME (pid `pidof $APP`) running.." 49 | RUNNING=1 50 | else 51 | rm -f $PIDFILE 52 | STATUS="$BINARY_NAME (pid file existed ($PID) and now removed) not running.." 53 | RUNNING=0 54 | fi 55 | else 56 | if [ `ps -e | grep $BINARY_NAME | head -1 | awk '{ print $1 }'` ] 57 | then 58 | STATUS="$BINARY_NAME (pid `pidof $APP`, but no pid file) running.." 59 | else 60 | STATUS="$BINARY_NAME (no pid file) not running" 61 | fi 62 | RUNNING=0 63 | fi 64 | 65 | # functions 66 | start() { 67 | if [ $RUNNING -eq 1 ] 68 | then 69 | echo "$0 $ARG: $BINARY_NAME (pid $PID) already running" 70 | else 71 | action $"Starting $BINARY_NAME: " $FULLPATH 72 | touch /var/lock/subsys/$BINARY_NAME 73 | fi 74 | } 75 | 76 | stop() { 77 | echo -n $"Shutting down $BINARY_NAME: " 78 | killproc $BINARY_NAME 79 | RETVAL=$? 80 | echo 81 | [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$BINARY_NAME 82 | RUNNING=0 83 | } 84 | 85 | 86 | # logic 87 | case "$1" in 88 | start) 89 | start 90 | ;; 91 | stop) 92 | stop 93 | ;; 94 | status) 95 | status $BINARY_NAME 96 | ;; 97 | restart) 98 | stop 99 | sleep 10 100 | start 101 | ;; 102 | help|*) 103 | echo $"Usage: $0 {start|stop|status|restart|help}" 104 | cat </dev/null 40 | -------------------------------------------------------------------------------- /sls/zabbix/readme.md: -------------------------------------------------------------------------------- 1 | begain install zabbix_agentd command for all host: 2 | salt '*' state.sls zabbix.init 3 | -------------------------------------------------------------------------------- /sls/zabbix/start_zbx_install.sls: -------------------------------------------------------------------------------- 1 | include: 2 | - zabbix.install_zabbix 3 | - zabbix.update_zbx_conf 4 | 5 | start_zbx_agentd: 6 | cmd.run: 7 | - name: service zabbix_agentd start 8 | - unless: pstree|grep zabbix_agentd 9 | 10 | chkconfig: 11 | cmd.run: 12 | - name: chkconfig --level 35 zabbix_agentd on 13 | -------------------------------------------------------------------------------- /sls/zabbix/up.sls: -------------------------------------------------------------------------------- 1 | {%set install_path= '/soft' %} 2 | 3 | /soft/zabbix/monitor_scripts: 4 | file.recurse: 5 | - source: salt://zabbix/files/zabbix/monitor_scripts 6 | - include_empty: True 7 | - file_mode: 755 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /sls/zabbix/update_zbx_conf.sls: -------------------------------------------------------------------------------- 1 | {% set server_ip = '10.175.198.38' %} 2 | {% set base_dir = '/soft' %} 3 | up_conf: 4 | file.managed: 5 | - name: /soft/zabbix/etc/zabbix_agentd.conf 6 | - source: salt://zabbix/files/zabbix_agentd.conf 7 | - template: jinja 8 | - user: zabbix 9 | - group: zabbix 10 | - defaults: 11 | Server: {{ server_ip }} 12 | ServerActive: {{ server_ip }} 13 | host: {{ grains['ip4_interfaces']['eth0'][0] }} 14 | install_dir: {{ base_dir }} 15 | 16 | modify: 17 | file.managed: 18 | - name: /etc/init.d/zabbix_agentd 19 | - source: salt://zabbix/files/zabbix_agentd 20 | - template: jinja 21 | - defaults: 22 | install_dir: {{ base_dir }} 23 | -------------------------------------------------------------------------------- /soft/Python-2.7.10.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/soft/Python-2.7.10.tgz -------------------------------------------------------------------------------- /soft/libmysqlclient.so.18: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/soft/libmysqlclient.so.18 -------------------------------------------------------------------------------- /soft/pip-7.1.2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/soft/pip-7.1.2.tar.gz -------------------------------------------------------------------------------- /soft/setuptools-18.4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/soft/setuptools-18.4.tar.gz -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash - 2 | #=============================================================================== 3 | # 4 | # FILE: start.sh 5 | # 6 | # USAGE: ./start.sh 7 | # 8 | # DESCRIPTION: 9 | # 10 | # OPTIONS: --- 11 | # REQUIREMENTS: --- 12 | # BUGS: --- 13 | # NOTES: --- 14 | # AUTHOR: YOUR NAME (), 15 | # ORGANIZATION: 16 | # CREATED: 07/15/2016 17:12 17 | # REVISION: --- 18 | #=============================================================================== 19 | 20 | nohup python ./manage.py runserver 0.0.0.0:80 & 21 | 22 | -------------------------------------------------------------------------------- /static/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | } 25 | 26 | ul.actionlist li { 27 | overflow: hidden; 28 | text-overflow: ellipsis; 29 | -o-text-overflow: ellipsis; 30 | } 31 | -------------------------------------------------------------------------------- /static/admin/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Roboto'; 3 | src: url('../fonts/Roboto-Bold-webfont.woff'); 4 | font-weight: 700; 5 | font-style: normal; 6 | } 7 | 8 | @font-face { 9 | font-family: 'Roboto'; 10 | src: url('../fonts/Roboto-Regular-webfont.woff'); 11 | font-weight: 400; 12 | font-style: normal; 13 | } 14 | 15 | @font-face { 16 | font-family: 'Roboto'; 17 | src: url('../fonts/Roboto-Light-webfont.woff'); 18 | font-weight: 300; 19 | font-style: normal; 20 | } 21 | -------------------------------------------------------------------------------- /static/admin/css/login.css: -------------------------------------------------------------------------------- 1 | /* LOGIN FORM */ 2 | 3 | body.login { 4 | background: #f8f8f8; 5 | } 6 | 7 | .login #header { 8 | height: auto; 9 | padding: 5px 16px; 10 | } 11 | 12 | .login #header h1 { 13 | font-size: 18px; 14 | } 15 | 16 | .login #header h1 a { 17 | color: #fff; 18 | } 19 | 20 | .login #content { 21 | padding: 20px 20px 0; 22 | } 23 | 24 | .login #container { 25 | background: #fff; 26 | border: 1px solid #eaeaea; 27 | border-radius: 4px; 28 | overflow: hidden; 29 | width: 28em; 30 | min-width: 300px; 31 | margin: 100px auto; 32 | } 33 | 34 | .login #content-main { 35 | width: 100%; 36 | } 37 | 38 | .login .form-row { 39 | padding: 4px 0; 40 | float: left; 41 | width: 100%; 42 | border-bottom: none; 43 | } 44 | 45 | .login .form-row label { 46 | padding-right: 0.5em; 47 | line-height: 2em; 48 | font-size: 1em; 49 | clear: both; 50 | color: #333; 51 | } 52 | 53 | .login .form-row #id_username, .login .form-row #id_password { 54 | clear: both; 55 | padding: 8px; 56 | width: 100%; 57 | -webkit-box-sizing: border-box; 58 | -moz-box-sizing: border-box; 59 | box-sizing: border-box; 60 | } 61 | 62 | .login span.help { 63 | font-size: 10px; 64 | display: block; 65 | } 66 | 67 | .login .submit-row { 68 | clear: both; 69 | padding: 1em 0 0 9.4em; 70 | margin: 0; 71 | border: none; 72 | background: none; 73 | text-align: left; 74 | } 75 | 76 | .login .password-reset-link { 77 | text-align: center; 78 | } 79 | -------------------------------------------------------------------------------- /static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | Weights used in this project: Light (300), Regular (400), Bold (700) 3 | -------------------------------------------------------------------------------- /static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /static/admin/img/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Code Charm Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - http://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /static/admin/img/calendar-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /static/admin/img/gis/move_vertex_off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/admin/img/gis/move_vertex_on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-alert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-calendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-unknown-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/inline-delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/selector-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /static/admin/img/sorting-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static/admin/js/actions.min.js: -------------------------------------------------------------------------------- 1 | (function(a){var f;a.fn.actions=function(q){var b=a.extend({},a.fn.actions.defaults,q),g=a(this),e=!1,k=function(){a(b.acrossClears).hide();a(b.acrossQuestions).show();a(b.allContainer).hide()},l=function(){a(b.acrossClears).show();a(b.acrossQuestions).hide();a(b.actionContainer).toggleClass(b.selectedClass);a(b.allContainer).show();a(b.counterContainer).hide()},m=function(){a(b.acrossClears).hide();a(b.acrossQuestions).hide();a(b.allContainer).hide();a(b.counterContainer).show()},n=function(){m(); 2 | a(b.acrossInput).val(0);a(b.actionContainer).removeClass(b.selectedClass)},p=function(c){c?k():m();a(g).prop("checked",c).parent().parent().toggleClass(b.selectedClass,c)},h=function(){var c=a(g).filter(":checked").length;a(b.counterContainer).html(interpolate(ngettext("%(sel)s of %(cnt)s selected","%(sel)s of %(cnt)s selected",c),{sel:c,cnt:_actions_icnt},!0));a(b.allToggle).prop("checked",function(){var a;c===g.length?(a=!0,k()):(a=!1,n());return a})};a(b.counterContainer).show();a(this).filter(":checked").each(function(c){a(this).parent().parent().toggleClass(b.selectedClass); 3 | h();1===a(b.acrossInput).val()&&l()});a(b.allToggle).show().click(function(){p(a(this).prop("checked"));h()});a("a",b.acrossQuestions).click(function(c){c.preventDefault();a(b.acrossInput).val(1);l()});a("a",b.acrossClears).click(function(c){c.preventDefault();a(b.allToggle).prop("checked",!1);n();p(0);h()});f=null;a(g).click(function(c){c||(c=window.event);var d=c.target?c.target:c.srcElement;if(f&&a.data(f)!==a.data(d)&&!0===c.shiftKey){var e=!1;a(f).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass, 4 | d.checked);a(g).each(function(){if(a.data(this)===a.data(f)||a.data(this)===a.data(d))e=e?!1:!0;e&&a(this).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked)})}a(d).parent().parent().toggleClass(b.selectedClass,d.checked);f=d;h()});a("form#changelist-form table#result_list tr").find("td:gt(0) :input").change(function(){e=!0});a('form#changelist-form button[name="index"]').click(function(a){if(e)return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."))}); 5 | a('form#changelist-form input[name="_save"]').click(function(c){var d=!1;a("select option:selected",b.actionContainer).each(function(){a(this).val()&&(d=!0)});if(d)return e?confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")):confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."))})}; 6 | a.fn.actions.defaults={actionContainer:"div.actions",counterContainer:"span.action-counter",allContainer:"div.actions span.all",acrossInput:"div.actions input.select-across",acrossQuestions:"div.actions span.question",acrossClears:"div.actions span.clear",allToggle:"#action-toggle",selectedClass:"selected"}})(django.jQuery); 7 | -------------------------------------------------------------------------------- /static/admin/js/collapse.js: -------------------------------------------------------------------------------- 1 | /*global gettext*/ 2 | (function($) { 3 | 'use strict'; 4 | $(document).ready(function() { 5 | // Add anchor tag for Show/Hide link 6 | $("fieldset.collapse").each(function(i, elem) { 7 | // Don't hide if fields in this fieldset have errors 8 | if ($(elem).find("div.errors").length === 0) { 9 | $(elem).addClass("collapsed").find("h2").first().append(' (' + gettext("Show") + 11 | ')'); 12 | } 13 | }); 14 | // Add toggle to anchor tag 15 | $("fieldset.collapse a.collapse-toggle").click(function(ev) { 16 | if ($(this).closest("fieldset").hasClass("collapsed")) { 17 | // Show 18 | $(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset", [$(this).attr("id")]); 19 | } else { 20 | // Hide 21 | $(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", [$(this).attr("id")]); 22 | } 23 | return false; 24 | }); 25 | }); 26 | })(django.jQuery); 27 | -------------------------------------------------------------------------------- /static/admin/js/collapse.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a(document).ready(function(){a("fieldset.collapse").each(function(b,c){0===a(c).find("div.errors").length&&a(c).addClass("collapsed").find("h2").first().append(' ('+gettext("Show")+")")});a("fieldset.collapse a.collapse-toggle").click(function(b){a(this).closest("fieldset").hasClass("collapsed")?a(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset",[a(this).attr("id")]):a(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", 2 | [a(this).attr("id")]);return!1})})})(django.jQuery); 3 | -------------------------------------------------------------------------------- /static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /*global django:true, jQuery:false*/ 2 | /* Puts the included jQuery into our own namespace using noConflict and passing 3 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 4 | * namespace (i.e. this preserves pre-existing values for both window.$ and 5 | * window.jQuery). 6 | */ 7 | var django = django || {}; 8 | django.jQuery = jQuery.noConflict(true); 9 | -------------------------------------------------------------------------------- /static/admin/js/prepopulate.js: -------------------------------------------------------------------------------- 1 | /*global URLify*/ 2 | (function($) { 3 | 'use strict'; 4 | $.fn.prepopulate = function(dependencies, maxLength, allowUnicode) { 5 | /* 6 | Depends on urlify.js 7 | Populates a selected field with the values of the dependent fields, 8 | URLifies and shortens the string. 9 | dependencies - array of dependent fields ids 10 | maxLength - maximum length of the URLify'd string 11 | allowUnicode - Unicode support of the URLify'd string 12 | */ 13 | return this.each(function() { 14 | var prepopulatedField = $(this); 15 | 16 | var populate = function() { 17 | // Bail if the field's value has been changed by the user 18 | if (prepopulatedField.data('_changed')) { 19 | return; 20 | } 21 | 22 | var values = []; 23 | $.each(dependencies, function(i, field) { 24 | field = $(field); 25 | if (field.val().length > 0) { 26 | values.push(field.val()); 27 | } 28 | }); 29 | prepopulatedField.val(URLify(values.join(' '), maxLength, allowUnicode)); 30 | }; 31 | 32 | prepopulatedField.data('_changed', false); 33 | prepopulatedField.change(function() { 34 | prepopulatedField.data('_changed', true); 35 | }); 36 | 37 | if (!prepopulatedField.val()) { 38 | $(dependencies.join(',')).keyup(populate).change(populate).focus(populate); 39 | } 40 | }); 41 | }; 42 | })(django.jQuery); 43 | -------------------------------------------------------------------------------- /static/admin/js/prepopulate.min.js: -------------------------------------------------------------------------------- 1 | (function(c){c.fn.prepopulate=function(e,f,g){return this.each(function(){var a=c(this),b=function(){if(!a.data("_changed")){var b=[];c.each(e,function(a,d){d=c(d);0 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /static/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /static/css/form-elements.css: -------------------------------------------------------------------------------- 1 | 2 | input[type="text"], 3 | input[type="password"], 4 | textarea, 5 | textarea.form-control { 6 | height: 50px; 7 | margin: 0; 8 | padding: 0 20px; 9 | vertical-align: middle; 10 | background: #fff; 11 | border: 3px solid #fff; 12 | font-family: 'Roboto', sans-serif; 13 | font-size: 16px; 14 | font-weight: 300; 15 | line-height: 50px; 16 | color: #888; 17 | -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; 18 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 19 | -o-transition: all .3s; -moz-transition: all .3s; -webkit-transition: all .3s; -ms-transition: all .3s; transition: all .3s; 20 | } 21 | 22 | textarea, 23 | textarea.form-control { 24 | padding-top: 10px; 25 | padding-bottom: 10px; 26 | line-height: 30px; 27 | } 28 | 29 | input[type="text"]:focus, 30 | input[type="password"]:focus, 31 | textarea:focus, 32 | textarea.form-control:focus { 33 | outline: 0; 34 | background: #fff; 35 | border: 3px solid #fff; 36 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 37 | } 38 | 39 | input[type="text"]:-moz-placeholder, input[type="password"]:-moz-placeholder, 40 | textarea:-moz-placeholder, textarea.form-control:-moz-placeholder { color: #888; } 41 | 42 | input[type="text"]:-ms-input-placeholder, input[type="password"]:-ms-input-placeholder, 43 | textarea:-ms-input-placeholder, textarea.form-control:-ms-input-placeholder { color: #888; } 44 | 45 | input[type="text"]::-webkit-input-placeholder, input[type="password"]::-webkit-input-placeholder, 46 | textarea::-webkit-input-placeholder, textarea.form-control::-webkit-input-placeholder { color: #888; } 47 | 48 | 49 | 50 | button.btn { 51 | height: 50px; 52 | margin: 0; 53 | padding: 0 20px; 54 | vertical-align: middle; 55 | background: #de615e; 56 | border: 0; 57 | font-family: 'Roboto', sans-serif; 58 | font-size: 16px; 59 | font-weight: 300; 60 | line-height: 50px; 61 | color: #fff; 62 | -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; 63 | text-shadow: none; 64 | -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; 65 | -o-transition: all .3s; -moz-transition: all .3s; -webkit-transition: all .3s; -ms-transition: all .3s; transition: all .3s; 66 | } 67 | 68 | button.btn:hover { opacity: 0.6; color: #fff; } 69 | 70 | button.btn:active { outline: 0; opacity: 0.6; color: #fff; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } 71 | 72 | button.btn:focus { outline: 0; opacity: 0.6; background: #de615e; color: #fff; } 73 | 74 | button.btn:active:focus, button.btn.active:focus { outline: 0; opacity: 0.6; background: #de615e; color: #fff; } 75 | -------------------------------------------------------------------------------- /static/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /static/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /static/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /static/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /static/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /static/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /static/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .@{fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /static/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | -------------------------------------------------------------------------------- /static/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /static/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | -------------------------------------------------------------------------------- /static/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /static/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /static/font-awesome/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | 15 | .fa-icon-rotate(@degrees, @rotation) { 16 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); 17 | -webkit-transform: rotate(@degrees); 18 | -ms-transform: rotate(@degrees); 19 | transform: rotate(@degrees); 20 | } 21 | 22 | .fa-icon-flip(@horiz, @vert, @rotation) { 23 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); 24 | -webkit-transform: scale(@horiz, @vert); 25 | -ms-transform: scale(@horiz, @vert); 26 | transform: scale(@horiz, @vert); 27 | } 28 | -------------------------------------------------------------------------------- /static/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /static/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /static/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | transform: translate(0, 0); // ensures no half-pixel rendering in firefox 12 | 13 | } 14 | 15 | @mixin fa-icon-rotate($degrees, $rotation) { 16 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 17 | -webkit-transform: rotate($degrees); 18 | -ms-transform: rotate($degrees); 19 | transform: rotate($degrees); 20 | } 21 | 22 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 23 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 24 | -webkit-transform: scale($horiz, $vert); 25 | -ms-transform: scale($horiz, $vert); 26 | transform: scale($horiz, $vert); 27 | } 28 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /static/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.3.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | -------------------------------------------------------------------------------- /static/ico/apple-touch-icon-114-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/ico/apple-touch-icon-114-precomposed.png -------------------------------------------------------------------------------- /static/ico/apple-touch-icon-144-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/ico/apple-touch-icon-144-precomposed.png -------------------------------------------------------------------------------- /static/ico/apple-touch-icon-57-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/ico/apple-touch-icon-57-precomposed.png -------------------------------------------------------------------------------- /static/ico/apple-touch-icon-72-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/ico/apple-touch-icon-72-precomposed.png -------------------------------------------------------------------------------- /static/ico/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/ico/favicon.png -------------------------------------------------------------------------------- /static/img/backgrounds/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/img/backgrounds/1.jpg -------------------------------------------------------------------------------- /static/img/backgrounds/1@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/img/backgrounds/1@2x.jpg -------------------------------------------------------------------------------- /static/img/meitianhui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/img/meitianhui.png -------------------------------------------------------------------------------- /static/img/wait.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/static/img/wait.gif -------------------------------------------------------------------------------- /static/js/minion.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | var myChart=echarts.init(document.getElementById('status')); 4 | 5 | option = { 6 | tooltip: { 7 | trigger: 'item', 8 | formatter: "{a}
{b}: {c} ({d}%)" 9 | }, 10 | legend: { 11 | orient: 'vertical', 12 | x: 'left', 13 | data:['accept','reject','unaccept'] 14 | }, 15 | series: [ 16 | { 17 | type:'pie', 18 | radius: ['50%', '70%'], 19 | avoidLabelOverlap: false, 20 | label: { 21 | normal: { 22 | show: false, 23 | position: 'center' 24 | }, 25 | emphasis: { 26 | show: true, 27 | textStyle: { 28 | fontSize: '30', 29 | fontWeight: 'bold' 30 | } 31 | } 32 | }, 33 | labelLine: { 34 | normal: { 35 | show: false 36 | } 37 | }, 38 | data:[ 39 | {value:{{ accept_num }}, name:'accept', itemStyle:{ 40 | normal:{color:'green'} 41 | }}, 42 | 43 | {value:{{ reject_num }}, name:'reject', itemStyle:{ 44 | normal:{color:'red'} 45 | }}, 46 | {value:{{ unaccept_num }}, name:'unaccept', itemStyle:{ 47 | normal:{color:'yellow'} 48 | }}, 49 | ] 50 | } 51 | ] 52 | }; 53 | myChart.setOption(option); 54 | -------------------------------------------------------------------------------- /static/js/placeholder.js: -------------------------------------------------------------------------------- 1 | 2 | $(document).ready(function(){ 3 | 4 | $(".form-username").val("Username..."); 5 | $(".form-password").val("Password..."); 6 | 7 | }); -------------------------------------------------------------------------------- /static/js/scripts.js: -------------------------------------------------------------------------------- 1 | 2 | jQuery(document).ready(function() { 3 | 4 | /* 5 | Fullscreen background 6 | */ 7 | $.backstretch("/static/img/backgrounds/1.jpg"); 8 | 9 | /* 10 | Form validation 11 | */ 12 | $('.login-form input[type="text"], .login-form input[type="password"], .login-form textarea').on('focus', function() { 13 | $(this).removeClass('input-error'); 14 | }); 15 | 16 | $('.login-form').on('submit', function(e) { 17 | 18 | $(this).find('input[type="text"], input[type="password"], textarea').each(function(){ 19 | if( $(this).val() == "" ) { 20 | e.preventDefault(); 21 | $(this).addClass('input-error'); 22 | } 23 | else { 24 | $(this).removeClass('input-error'); 25 | } 26 | }); 27 | 28 | }); 29 | 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /templates/add_git_repo.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   项目管理 9 |
  • 10 |
  • 11 |   添加版本库 12 |
  • 13 |
  • 14 | Git 15 |
  • 16 | {%endblock%} 17 | 18 | {%block page_content%} 19 | 20 |
    21 |
    22 |
    23 |

      添加Git库信息

    24 |

    25 |
    26 |
    27 |
    28 |
    29 | {% csrf_token %} 30 | {%for f in form %} 31 |
    32 | 33 | {{f}} 34 |
    35 | {%if f.errors %} 36 |
    {{f.errors}}
    37 | {%endif%} 38 | {%endfor%} 39 |

    40 |

    41 |
    42 |
    43 |
    44 | 45 | 46 |

    47 |
    48 |
    49 |
    50 |
    51 | 52 |
    53 |
    54 | 55 | 56 | {%endblock%} 57 | -------------------------------------------------------------------------------- /templates/add_svn_repo.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | 3 | {%load static %} 4 | {%block head%} 5 |
  • 6 |   Dashboard 7 |
  • 8 |
  • 9 |   项目管理 10 |
  • 11 |
  • 12 |   添加版本库 13 |
  • 14 |
  • 15 | SVN 16 |
  • 17 | {%endblock%} 18 | 19 | {%block page_content%} 20 | 21 |
    22 |
    23 |
    24 |

      添加SVN库信息

    25 |

    26 |
    27 |
    28 |
    29 |
    30 | {% csrf_token %} 31 | {%if form %} 32 | {%for f in form %} 33 |
    34 | 35 | {{f}} 36 |
    37 | {%if f.errors %} 38 |
    {{f.errors}}
    39 | {%endif%} 40 | {%endfor%} 41 | {%endif%} 42 |

    43 |

    44 |
    45 |
    46 |
    47 | 48 | 49 |

    50 |
    51 |
    52 |
    53 |
    54 | 55 |
    56 |
    57 | 58 | 59 | {%endblock%} 60 | -------------------------------------------------------------------------------- /templates/deploy_project.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   项目管理 9 |
  • 10 |
  • 11 |   发布工程 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      Deploy Project

    21 |

    22 |
    23 |
    24 |
    25 | {%csrf_token %} 26 | {%for f in form %} 27 |
    28 | {{f}} 29 |
    30 | {%if f.errors%} 31 | {%if res %} 32 |
    33 | {{f.errors}} 34 |
    35 |
    36 |
    37 | {%else%} 38 |
    39 | {{f.errors}} 40 |
    41 |
    42 |
    43 | {%endif%} 44 | {%endif%} 45 |
    46 |
    47 |
    48 |
    49 |
    50 |
    51 |
    52 |
    53 |
    54 |
    55 |
    56 |
    57 | {%endfor%} 58 |
    59 |
    60 | 61 | 63 |
    64 | 81 |
    82 |
    83 |
    84 |
    85 | 86 | {%if log %} 87 |
    88 |
    89 |
    90 |
    91 |
    92 | 96 |
    97 |
    98 |
    99 |
    100 |
    101 | {%endif%} 102 | {%endblock%} 103 | -------------------------------------------------------------------------------- /templates/download_file.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   SaltStack 9 |
  • 10 |
  • 11 |  文件下载 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      Download File

    21 |

    22 |
    23 |
    24 |
    25 |
    26 |
    27 | {%csrf_token%} 28 |
    29 |
    30 |
    31 | 32 | 35 | 36 | {{form.target}} 37 |
    38 | {% if form.target.errors %} 39 |
    40 |
    {{form.target.errors}}
    41 |
    42 | {%endif%} 43 |
    44 | 45 | 48 | 49 | {{form.file_path}} 50 |
    51 | {% if form.file_path.errors %} 52 |
    53 |
    {{form.file_path.errors}}
    54 |
    55 | {%endif%} 56 | 57 | 58 |
    59 | 60 | 61 |
    62 | 78 |
    79 | 80 | {{file}} 81 |
    82 |
    83 |
    84 |
    85 |
    86 |
    87 | {%if result %} 88 |
    89 |
    90 |
    91 |
    92 |
    93 | 97 |
    98 |
    99 |
    100 |
    101 |
    102 | {%endif%} 103 | {%endblock%} 104 | -------------------------------------------------------------------------------- /templates/host_list.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 | Dashboard 6 |
  • 7 |
  • 8 | 主机列表 9 |
  • 10 | {%endblock %} 11 | 12 | 13 | -------------------------------------------------------------------------------- /templates/list_app_deploy_info.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   SaltStack 9 |
  • 10 |
  • 11 |   部署记录 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      部署记录

    21 |

    22 |
    23 |
    24 |
    25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {%for info in app_info %} 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {%endfor%} 51 | 52 |
    操作用户部署时间匹配目标部署应用部署成功主机部署失败主机影响主机数总耗时
    {{info.user}}{{info.time}}{{info.target}}{{info.application}}{{info.success_hosts}}{{info.failed_hosts}}{{info.total}}{{info.duration}}
    53 |
    54 |
    55 |
    56 |
    57 | 58 | {%if app_info.has_previous %} 59 |
  • ←Previous
  • 60 | {%endif%} 61 | Page {{app_info.number}} of {{app_info.paginator.num_pages}} 62 | {%if app_info.has_next%} 63 |
  • Next →
  • 64 | {%endif%} 65 |
    66 |
    67 | 68 |
    69 |
    70 | {%endblock%} 71 | -------------------------------------------------------------------------------- /templates/list_cmd_opt_log.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   资产管理 9 |
  • 10 |
  • 11 |   命令审计 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      命令审计

    21 |

    22 |
    23 |
    24 |
    25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {%for cmd in cmd_set %} 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | {%endfor%} 45 | 46 |
    登陆主机登陆用户执行命令登陆IP执行时间
    {{cmd.hostname}}{{cmd.user}}{{cmd.command}}{{cmd.login_ip}}{{cmd.runtime}}
    47 |
    48 |
    49 |
    50 | 51 | {%if cmd_set.has_previous %} 52 |
  • ←Previous
  • 53 | {%endif%} 54 | Page {{ cmd_set.number }} of {{ cmd_set.paginator.num_pages }}. 55 | {%if cmd_set.has_next %} 56 |
  • Next →
  • 57 | {%endif%} 58 |
    59 |
    60 |
    61 |
    62 |
    63 | {%endblock%} 64 | -------------------------------------------------------------------------------- /templates/list_cmd_run_info.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   SaltStack 9 |
  • 10 |
  • 11 |   命令记录 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      命令执行记录

    21 |

    22 |
    23 |
    24 |
    25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | {%for info in cmd_info %} 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | {%endfor%} 47 | 48 |
    用户目标机器匹配规则执行命令受影响主机执行日期
    {{info.user}}{{info.target}}{{info.mapping}}{{info.cmd}}{{info.hosts}}{{info.time}}
    49 |
    50 |
    51 |
    52 |
    53 | 54 | {%if cmd_info.has_previous %} 55 |
  • ←Previous
  • 56 | {%endif%} 57 | Page {{cmd_info.number}} of {{cmd_info.paginator.num_pages}} 58 | {%if cmd_info.has_next%} 59 |
  • Next →
  • 60 | {%endif%} 61 |
    62 |
    63 |
    64 |
    65 | {%endblock%} 66 | -------------------------------------------------------------------------------- /templates/list_deploy_info.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   项目管理 9 |
  • 10 |
  • 11 |   发布日志 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      发布日志

    21 |

    22 |
    23 |
    24 |
    25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | {%for deploy in deploy_list %} 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | {%endfor%} 47 | 48 |
    版本库名发布环境版本号发布时间发布用户备注
    {{deploy.repoName}}{{deploy.target}}{{deploy.revision}}{{deploy.date}}{{deploy.person}}{{deploy.remark}}
    49 |
    50 |
    51 |
    52 | 53 | {%if deploy_list.has_previous %} 54 |
  • ←Previous
  • 55 | {%endif%} 56 | Page {{ deploy_list.number }} of {{ deploy_list.paginator.num_pages }}. 57 | {%if deploy_list.has_next %} 58 |
  • Next →
  • 59 | {%endif%} 60 |
    61 |
    62 |
    63 |
    64 |
    65 | {%endblock%} 66 | -------------------------------------------------------------------------------- /templates/list_repo_info.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   项目管理 9 |
  • 10 |
  • 11 |   版本库列表 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      版本库信息浏览

    21 |

    22 |
    23 |
    24 |
    25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {%for repo in repos_list %} 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {%endfor%} 49 | 50 |
    版本库名库地址测试环境地址预生产环境地址生产环境地址网站根目录排除文件
    {{repo.repoName}}{{repo.repoAddress}}{{repo.testDeployIP}}{{repo.preDeployIP}}{{repo.onlineDeployIP}}{{repo.wwwDir}}{{repo.excludeDir}}
    51 |
    52 |
    53 |
    54 |
    55 |
    56 | {%endblock%} 57 | -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | {%load static%} 3 | 4 | 5 | 6 | 7 | 8 | Login 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
    27 |
    28 |
    29 |
    30 |
    31 |
    32 |
    33 |

    欢迎登陆运维平台

    34 |

    Enter your username and password to log on:

    35 |
    36 |
    37 | 38 |
    39 |
    40 |
    41 | {% if error %} 42 |

    {{ error }}

    43 | {%endif%} 44 | 56 |
    57 |
    58 |
    59 | 60 |
    61 |
    62 |
    63 | 64 | 65 | -------------------------------------------------------------------------------- /templates/login_new.html: -------------------------------------------------------------------------------- 1 | 2 | {%load static%} 3 | 4 | 5 | 6 | 7 | 8 | login 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 |
    19 |
    20 |
    21 | 22 |
    23 |

    欢迎登陆运维平台

    24 |
    25 | {%csrf_token%} 26 | {%if error%} 27 |
    {{error}}
    28 | {%endif%} 29 |
    30 | 31 | 32 |
    33 |
    34 | 35 | 36 |
    37 |
    38 | 登录 39 |
    40 |
    41 |
    42 |
    43 |
    44 |
    45 | 46 | 47 | 48 | 49 | 50 | 55 | 56 | -------------------------------------------------------------------------------- /templates/query_host_cmd_log.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   资产管理 9 |
  • 10 |
  • 11 |   命令审计 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      命令审计

    21 |

    22 |
    23 |
    24 |
    25 | {%csrf_token %} 26 | {%for f in form %} 27 | {%if f.label = "Begin" or f.label = "End" %} 28 |
    29 | 30 | 37 | 38 | {{f}} 39 | 40 | 41 | 42 |
    43 | {%else%} 44 |
    45 | 46 | 49 | 50 | {{f}} 51 |
    52 | {%endif%} 53 | {%endfor%} 54 |
    55 | 56 |
    57 |
    58 | 59 | 64 | 69 | 70 |
    71 |
    72 |
    73 |
    74 | {%endblock%} 75 | -------------------------------------------------------------------------------- /templates/salt_hosts.html: -------------------------------------------------------------------------------- 1 | {%extends 'base.html' %} 2 | {%load static %} 3 | {%block head%} 4 |
  • 5 |   Dashboard 6 |
  • 7 |
  • 8 |   SaltStack 9 |
  • 10 |
  • 11 |   Minions信息 12 |
  • 13 | {%endblock%} 14 | 15 | {%block page_content%} 16 | 17 |
    18 |
    19 |
    20 |

      主机信息

    21 |

    22 |
    23 |
    24 |
    25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | {%for host in hosts%} 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {%endfor%} 51 | 52 |
    主机名IP地址CPU信息内存信息所属组系统版本主机区域用途
    {{host.hostname }}{{host.ipaddress }}{{host.cpuinfo }}{{host.meminfo }}{{host.group }}{{host.osinfo }}{{host.area }}{{host.usage }}
    53 |
    54 |
    55 |
    56 |
    57 | 58 | {%if hosts.has_previous %} 59 |
  • ←Previous
  • 60 | {%endif%} 61 | Page {{hosts.number}} of {{hosts.paginator.num_pages}}    total: {{total}} 62 | {%if hosts.has_next%} 63 |
  • Next →
  • 64 | {%endif%} 65 |
    66 |
    67 |
    68 |
    69 | 刷新 70 | 71 | 81 |
    82 |
    83 | {%endblock%} 84 | -------------------------------------------------------------------------------- /users/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/users/__init__.py -------------------------------------------------------------------------------- /users/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /users/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class UsersConfig(AppConfig): 7 | name = 'users' 8 | -------------------------------------------------------------------------------- /users/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujingguang/OpsSystem/1c9de0fbc4eb11a5e35d0fc4784c207b6d8495e7/users/migrations/__init__.py -------------------------------------------------------------------------------- /users/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | 5 | # Create your models here. 6 | -------------------------------------------------------------------------------- /users/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /users/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from views import * 3 | 4 | 5 | urlpatterns=[ 6 | url(r'^userList/$',list_all_users,name='userList'), 7 | url(r'^userAdd/$',add_user,name='userAdd'), 8 | url(r'^changeUser/$',change_user_api,name='changeUser'), 9 | ] 10 | -------------------------------------------------------------------------------- /users/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render,render_to_response 2 | from django.contrib.auth.decorators import login_required 3 | from django.template import RequestContext 4 | from django.http import HttpResponse 5 | from django.contrib.auth.models import User 6 | from datetime import datetime 7 | import json 8 | 9 | 10 | @login_required(login_url='/') 11 | def list_all_users(request): 12 | users=User.objects.all() 13 | for u in users: 14 | if u.last_login: 15 | u.last_login=datetime.strftime(u.last_login,'%Y-%m-%d %H:%M:%S') 16 | else: 17 | u.last_login='' 18 | if u.date_joined: 19 | u.date_joined=datetime.strftime(u.date_joined,'%Y-%m-%d %H:%M:%S') 20 | else: 21 | u.date_joined='' 22 | return render_to_response('user_list.html',RequestContext(request,{'users':users})) 23 | 24 | @login_required(login_url='/') 25 | def add_user(request): 26 | if request.method=='POST': 27 | username=request.POST.get('username','').replace(' ','') 28 | password=request.POST.get('password','').replace(' ','') 29 | email=request.POST.get('email','').replace(' ','') 30 | isadmin=request.POST.get('isadmin','').replace(' ','') 31 | if not request.user.is_superuser: 32 | return HttpResponse(json.dumps({'code':400,'info':'No Permission'})) 33 | if username == '' or password == '' or email== '' or isadmin == '': 34 | return HttpResponse(json.dumps({'code':400,'info':'Error Form Params'})) 35 | if isadmin == 'Y': 36 | user=User.objects.create_superuser(username=username,email=email,password=password) 37 | else: 38 | user=User.objects.create_user(username=username,email=email,password=password) 39 | try: 40 | user.save() 41 | except Exception as e: 42 | return HttpResponse(json.dumps({'code':400,'info':'add user failed'})) 43 | return HttpResponse(json.dumps({'code':200,'info':'add user success'})) 44 | return HttpResponse(json.dumps({'code':400,'info':'error http method'})) 45 | 46 | 47 | 48 | 49 | @login_required(login_url='/') 50 | def change_user_api(request): 51 | if request.method=='POST': 52 | if not request.user.is_superuser: 53 | return HttpResponse(json.dumps({'code':400,'info':'No Permission !'})) 54 | userid=request.POST.get('userid','').replace(' ','') 55 | opt=request.POST.get('opt','').replace(' ','') 56 | if not userid or not opt: 57 | return HttpResponse(json.dumps({'code':400,'info':'Error Params !'})) 58 | u=User.objects.get(id=userid) 59 | if not u: 60 | return HttpResponse(json.dumps({'code':400,'info':'User do not exist !'})) 61 | print dir(u) 62 | if opt == 'delete': 63 | try: 64 | u.delete() 65 | except Exception as e: 66 | return HttpResponse(json.dumps({'code':400,'info':'Delete Failed'})) 67 | elif opt == 'active': 68 | if not u.is_active: 69 | u.is_active=1 70 | try: 71 | u.save() 72 | except Exception as e: 73 | return HttpResponse(json.dumps({'code':400,'info':'Active Failed'})) 74 | elif opt == 'freeze': 75 | if u.is_active: 76 | u.is_active=0 77 | try: 78 | u.save() 79 | except Exception as e: 80 | return HttpResponse(json.dumps({'code':400,'info':'Freeze Failed'})) 81 | else: 82 | return HttpResponse(json.dumps({'code':400,'info':'Error Params'})) 83 | return HttpResponse(json.dumps({'code':200,'info':'Change User Status Success'})) 84 | else: 85 | return HttpResponse(json.dumps({'code':400,'info':'Error Http Method'})) 86 | -------------------------------------------------------------------------------- /uwsgi_deploy.txt: -------------------------------------------------------------------------------- 1 | 2 | 1: vim ./uwsgi.ini 3 | 4 | [uwsgi] 5 | chdir=/webdata/webdir/ops/ops_new/pro 6 | module=ops_system.wsgi:application 7 | pidfile=/tmp/ops.pid 8 | vacuum=True 9 | max-requests=10000 10 | daemonize=/tmp/ops.log 11 | socket=0.0.0.0:8888 12 | master=True 13 | 14 | 2: python manage.py collectstatic 15 | 16 | 17 | 3: vim nginx.conf 18 | 19 | server { 20 | listen 9988; 21 | server_name 127.0.0.1; 22 | index index.html index.htm; 23 | 24 | location /static { 25 | alias /webdata/webdir/ops/ops_new/pro/static; 26 | } 27 | location / { 28 | uwsgi_pass 127.0.0.1:8888; 29 | include uwsgi_params; 30 | } 31 | access_log /tmp/ops_nginx.log; 32 | } 33 | 34 | 35 | 4: pip install uwsgi 36 | 37 | 38 | 5: uwsgi --ini ./uwsgi.ini 39 | --------------------------------------------------------------------------------