Showing preview only (5,189K chars total). Download the full file or copy to clipboard to get everything.
Repository: roddyofchina/SimpletourDevops
Branch: master
Commit: 8248e430355a
Files: 559
Total size: 4.8 MB
Directory structure:
gitextract_gajczjdw/
├── .idea/
│ ├── SimpletourDevops.iml
│ ├── inspectionProfiles/
│ │ ├── Project_Default.xml
│ │ └── profiles_settings.xml
│ ├── misc.xml
│ ├── modules.xml
│ └── vcs.xml
├── Publicapi/
│ ├── __init__.py
│ ├── dnspod/
│ │ ├── __init__.py
│ │ └── apicn.py
│ ├── dockerapi/
│ │ ├── Manager.py
│ │ └── __init__.py
│ └── saltstackapi/
│ ├── Assets_Module.py
│ ├── SaltConApi.py
│ └── __init__.py
├── README.md
├── SimpletourDevops/
│ ├── __init__.py
│ ├── apps.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── dockermanager/
│ ├── Docker_Controller.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── domainmanager/
│ └── urls.py
├── manage.py
├── requirements.txt
├── run_eventlet.py
├── saltadmin/
│ ├── Minions_Controller.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ ├── utils.py
│ └── views.py
├── servermanager/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations/
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20161121_1740.py
│ │ ├── 0003_auto_20161128_1031.py
│ │ ├── 0004_auto_20161128_1032.py
│ │ ├── 0005_auto_20161128_1032.py
│ │ ├── 0006_auto_20161128_1034.py
│ │ ├── 0007_auto_20161128_1038.py
│ │ ├── 0008_auto_20161128_1109.py
│ │ ├── 0009_auto_20161128_1112.py
│ │ ├── 0010_auto_20161128_1113.py
│ │ ├── 0011_auto_20161202_1049.py
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── static/
│ └── assets/
│ ├── css/
│ │ ├── _variables.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap.css
│ │ ├── components.css
│ │ ├── core.css
│ │ ├── elements.css
│ │ ├── icons.css
│ │ ├── pages.css
│ │ ├── responsive.css
│ │ ├── statusecho.css
│ │ ├── style.css
│ │ ├── variables.css
│ │ └── xterm.css
│ ├── js/
│ │ ├── bootstrap.js
│ │ ├── detect.js
│ │ ├── fastclick.js
│ │ ├── jquery.app.js
│ │ ├── jquery.blockUI.js
│ │ ├── jquery.core.js
│ │ ├── jquery.nicescroll.js
│ │ ├── jquery.slimscroll.js
│ │ ├── json.js
│ │ ├── json2yaml.js
│ │ ├── npm.js
│ │ ├── spin.js
│ │ ├── waves.js
│ │ └── xterm.js
│ ├── pages/
│ │ ├── chartjs.init.js
│ │ ├── datatables.editable.init.js
│ │ ├── easy-pie-chart.init.js
│ │ ├── jquery.bs-table.js
│ │ ├── jquery.dashboard.js
│ │ ├── jquery.flot.init.js
│ │ ├── jquery.footable.js
│ │ └── jquery.sweet-alert.init.js
│ └── plugins/
│ ├── Chart.js/
│ │ ├── Chart.js
│ │ └── src/
│ │ ├── Chart.Bar.js
│ │ ├── Chart.Core.js
│ │ ├── Chart.Doughnut.js
│ │ ├── Chart.Line.js
│ │ ├── Chart.PolarArea.js
│ │ └── Chart.Radar.js
│ ├── bootstrap-datepicker/
│ │ └── dist/
│ │ ├── css/
│ │ │ ├── bootstrap-datepicker.css
│ │ │ ├── bootstrap-datepicker.standalone.css
│ │ │ ├── bootstrap-datepicker3.css
│ │ │ └── bootstrap-datepicker3.standalone.css
│ │ └── js/
│ │ └── bootstrap-datepicker.js
│ ├── bootstrap-select/
│ │ ├── css/
│ │ │ ├── bootstrap-select.css
│ │ │ └── variables.css
│ │ ├── dist/
│ │ │ ├── css/
│ │ │ │ └── bootstrap-select.css
│ │ │ └── js/
│ │ │ ├── bootstrap-select.js
│ │ │ └── i18n/
│ │ │ ├── defaults-bg_BG.js
│ │ │ ├── defaults-cs_CZ.js
│ │ │ ├── defaults-da_DK.js
│ │ │ ├── defaults-de_DE.js
│ │ │ ├── defaults-en_US.js
│ │ │ ├── defaults-es_CL.js
│ │ │ ├── defaults-eu.js
│ │ │ ├── defaults-fa_IR.js
│ │ │ ├── defaults-fr_FR.js
│ │ │ ├── defaults-hu_HU.js
│ │ │ ├── defaults-it_IT.js
│ │ │ ├── defaults-ko_KR.js
│ │ │ ├── defaults-nl_NL.js
│ │ │ ├── defaults-pl_PL.js
│ │ │ ├── defaults-pt_BR.js
│ │ │ ├── defaults-pt_PT.js
│ │ │ ├── defaults-ro_RO.js
│ │ │ ├── defaults-ru_RU.js
│ │ │ ├── defaults-sk_SK.js
│ │ │ ├── defaults-sl_SI.js
│ │ │ ├── defaults-sv_SE.js
│ │ │ ├── defaults-tr_TR.js
│ │ │ ├── defaults-ua_UA.js
│ │ │ ├── defaults-zh_CN.js
│ │ │ └── defaults-zh_TW.js
│ │ └── js/
│ │ ├── .jshintrc
│ │ ├── bootstrap-select.js
│ │ └── i18n/
│ │ ├── defaults-bg_BG.js
│ │ ├── defaults-cs_CZ.js
│ │ ├── defaults-da_DK.js
│ │ ├── defaults-de_DE.js
│ │ ├── defaults-en_US.js
│ │ ├── defaults-es_CL.js
│ │ ├── defaults-eu.js
│ │ ├── defaults-fa_IR.js
│ │ ├── defaults-fr_FR.js
│ │ ├── defaults-hu_HU.js
│ │ ├── defaults-it_IT.js
│ │ ├── defaults-ko_KR.js
│ │ ├── defaults-nl_NL.js
│ │ ├── defaults-pl_PL.js
│ │ ├── defaults-pt_BR.js
│ │ ├── defaults-pt_PT.js
│ │ ├── defaults-ro_RO.js
│ │ ├── defaults-ru_RU.js
│ │ ├── defaults-sk_SK.js
│ │ ├── defaults-sl_SI.js
│ │ ├── defaults-sv_SE.js
│ │ ├── defaults-tr_TR.js
│ │ ├── defaults-ua_UA.js
│ │ ├── defaults-zh_CN.js
│ │ └── defaults-zh_TW.js
│ ├── bootstrap-table/
│ │ ├── dist/
│ │ │ ├── bootstrap-table-all.js
│ │ │ ├── bootstrap-table-locale-all.js
│ │ │ ├── bootstrap-table.css
│ │ │ ├── bootstrap-table.js
│ │ │ ├── extensions/
│ │ │ │ ├── cookie/
│ │ │ │ │ └── bootstrap-table-cookie.js
│ │ │ │ ├── editable/
│ │ │ │ │ └── bootstrap-table-editable.js
│ │ │ │ ├── export/
│ │ │ │ │ └── bootstrap-table-export.js
│ │ │ │ ├── filter/
│ │ │ │ │ └── bootstrap-table-filter.js
│ │ │ │ ├── filter-control/
│ │ │ │ │ └── bootstrap-table-filter-control.js
│ │ │ │ ├── flat-json/
│ │ │ │ │ └── bootstrap-table-flat-json.js
│ │ │ │ ├── key-events/
│ │ │ │ │ └── bootstrap-table-key-events.js
│ │ │ │ ├── mobile/
│ │ │ │ │ └── bootstrap-table-mobile.js
│ │ │ │ ├── multiple-sort/
│ │ │ │ │ └── bootstrap-table-multiple-sort.js
│ │ │ │ ├── natural-sorting/
│ │ │ │ │ └── bootstrap-table-natural-sorting.js
│ │ │ │ ├── reorder-columns/
│ │ │ │ │ └── bootstrap-table-reorder-columns.js
│ │ │ │ ├── reorder-rows/
│ │ │ │ │ ├── bootstrap-table-reorder-rows.css
│ │ │ │ │ └── bootstrap-table-reorder-rows.js
│ │ │ │ ├── resizable/
│ │ │ │ │ └── bootstrap-table-resizable.js
│ │ │ │ └── toolbar/
│ │ │ │ └── bootstrap-table-toolbar.js
│ │ │ └── locale/
│ │ │ ├── bootstrap-table-ar-SA.js
│ │ │ ├── bootstrap-table-cs-CZ.js
│ │ │ ├── bootstrap-table-da-DK.js
│ │ │ ├── bootstrap-table-de-DE.js
│ │ │ ├── bootstrap-table-el-GR.js
│ │ │ ├── bootstrap-table-en-US.js
│ │ │ ├── bootstrap-table-es-AR.js
│ │ │ ├── bootstrap-table-es-CR.js
│ │ │ ├── bootstrap-table-es-MX.js
│ │ │ ├── bootstrap-table-es-NI.js
│ │ │ ├── bootstrap-table-es-SP.js
│ │ │ ├── bootstrap-table-fr-BE.js
│ │ │ ├── bootstrap-table-fr-FR.js
│ │ │ ├── bootstrap-table-hu-HU.js
│ │ │ ├── bootstrap-table-it-IT.js
│ │ │ ├── bootstrap-table-ja-JP.js
│ │ │ ├── bootstrap-table-ka-GE.js
│ │ │ ├── bootstrap-table-ko-KR.js
│ │ │ ├── bootstrap-table-ms-MY.js
│ │ │ ├── bootstrap-table-nb-NO.js
│ │ │ ├── bootstrap-table-nl-NL.js
│ │ │ ├── bootstrap-table-pl-PL.js
│ │ │ ├── bootstrap-table-pt-BR.js
│ │ │ ├── bootstrap-table-pt-PT.js
│ │ │ ├── bootstrap-table-ro-RO.js
│ │ │ ├── bootstrap-table-ru-RU.js
│ │ │ ├── bootstrap-table-sk-SK.js
│ │ │ ├── bootstrap-table-sv-SE.js
│ │ │ ├── bootstrap-table-th-TH.js
│ │ │ ├── bootstrap-table-tr-TR.js
│ │ │ ├── bootstrap-table-uk-UA.js
│ │ │ ├── bootstrap-table-ur-PK.js
│ │ │ ├── bootstrap-table-vi-VN.js
│ │ │ ├── bootstrap-table-zh-CN.js
│ │ │ └── bootstrap-table-zh-TW.js
│ │ └── src/
│ │ ├── bootstrap-table.css
│ │ ├── bootstrap-table.js
│ │ ├── extensions/
│ │ │ ├── cookie/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-cookie.js
│ │ │ ├── editable/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-editable.js
│ │ │ ├── export/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-export.js
│ │ │ ├── filter/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-filter.js
│ │ │ ├── filter-control/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-filter-control.js
│ │ │ ├── flat-json/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-flat-json.js
│ │ │ ├── key-events/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-key-events.js
│ │ │ ├── mobile/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-mobile.js
│ │ │ ├── multiple-sort/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-multiple-sort.js
│ │ │ ├── natural-sorting/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-natural-sorting.js
│ │ │ ├── reorder-columns/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-reorder-columns.js
│ │ │ ├── reorder-rows/
│ │ │ │ ├── README.md
│ │ │ │ ├── bootstrap-table-reorder-rows.css
│ │ │ │ └── bootstrap-table-reorder-rows.js
│ │ │ ├── resizable/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-resizable.js
│ │ │ └── toolbar/
│ │ │ ├── README.md
│ │ │ └── bootstrap-table-toolbar.js
│ │ └── locale/
│ │ ├── README.md
│ │ ├── bootstrap-table-ar-SA.js
│ │ ├── bootstrap-table-cs-CZ.js
│ │ ├── bootstrap-table-da-DK.js
│ │ ├── bootstrap-table-de-DE.js
│ │ ├── bootstrap-table-el-GR.js
│ │ ├── bootstrap-table-en-US.js
│ │ ├── bootstrap-table-en-US.js.template
│ │ ├── bootstrap-table-es-AR.js
│ │ ├── bootstrap-table-es-CR.js
│ │ ├── bootstrap-table-es-MX.js
│ │ ├── bootstrap-table-es-NI.js
│ │ ├── bootstrap-table-es-SP.js
│ │ ├── bootstrap-table-fr-BE.js
│ │ ├── bootstrap-table-fr-FR.js
│ │ ├── bootstrap-table-hu-HU.js
│ │ ├── bootstrap-table-it-IT.js
│ │ ├── bootstrap-table-ja-JP.js
│ │ ├── bootstrap-table-ka-GE.js
│ │ ├── bootstrap-table-ko-KR.js
│ │ ├── bootstrap-table-ms-MY.js
│ │ ├── bootstrap-table-nb-NO.js
│ │ ├── bootstrap-table-nl-NL.js
│ │ ├── bootstrap-table-pl-PL.js
│ │ ├── bootstrap-table-pt-BR.js
│ │ ├── bootstrap-table-pt-PT.js
│ │ ├── bootstrap-table-ro-RO.js
│ │ ├── bootstrap-table-ru-RU.js
│ │ ├── bootstrap-table-sk-SK.js
│ │ ├── bootstrap-table-sv-SE.js
│ │ ├── bootstrap-table-th-TH.js
│ │ ├── bootstrap-table-tr-TR.js
│ │ ├── bootstrap-table-uk-UA.js
│ │ ├── bootstrap-table-ur-PK.js
│ │ ├── bootstrap-table-vi-VN.js
│ │ ├── bootstrap-table-zh-CN.js
│ │ └── bootstrap-table-zh-TW.js
│ ├── bootstrap-touchspin/
│ │ ├── dist/
│ │ │ ├── jquery.bootstrap-touchspin.css
│ │ │ └── jquery.bootstrap-touchspin.js
│ │ └── src/
│ │ ├── jquery.bootstrap-touchspin.css
│ │ └── jquery.bootstrap-touchspin.js
│ ├── custombox/
│ │ └── src/
│ │ ├── css/
│ │ │ └── custombox.css
│ │ └── js/
│ │ ├── custombox.js
│ │ └── legacy.js
│ ├── datatables/
│ │ └── dataTables.bootstrap.js
│ ├── flot-chart/
│ │ ├── jquery.flot.crosshair.js
│ │ ├── jquery.flot.js
│ │ ├── jquery.flot.pie.js
│ │ ├── jquery.flot.resize.js
│ │ ├── jquery.flot.selection.js
│ │ ├── jquery.flot.stack.js
│ │ └── jquery.flot.time.js
│ ├── footable/
│ │ └── css/
│ │ └── footable.core.css
│ ├── jquery-datatables-editable/
│ │ ├── dataTables.bootstrap.js
│ │ ├── datatables.css
│ │ └── jquery.dataTables.js
│ ├── jquery-knob/
│ │ ├── excanvas.js
│ │ └── jquery.knob.js
│ ├── jquery.easy-pie-chart/
│ │ ├── dist/
│ │ │ ├── angular.easypiechart.js
│ │ │ ├── easypiechart.js
│ │ │ └── jquery.easypiechart.js
│ │ └── src/
│ │ ├── angular.directive.js
│ │ ├── easypiechart.js
│ │ ├── jquery.plugin.js
│ │ └── renderer/
│ │ └── canvas.js
│ ├── magnific-popup/
│ │ ├── dist/
│ │ │ ├── jquery.magnific-popup.js
│ │ │ └── magnific-popup.css
│ │ └── src/
│ │ ├── css/
│ │ │ ├── _settings.scss
│ │ │ └── main.scss
│ │ └── js/
│ │ ├── ajax.js
│ │ ├── core.js
│ │ ├── fastclick.js
│ │ ├── gallery.js
│ │ ├── iframe.js
│ │ ├── image.js
│ │ ├── inline.js
│ │ ├── retina.js
│ │ └── zoom.js
│ ├── morris/
│ │ ├── morris.css
│ │ └── morris.js
│ ├── multiselect/
│ │ ├── css/
│ │ │ └── multi-select.css
│ │ └── js/
│ │ └── jquery.multi-select.js
│ ├── notifications/
│ │ ├── notification.css
│ │ └── notify-metro.js
│ ├── notifyjs/
│ │ ├── dist/
│ │ │ ├── notify-combined.js
│ │ │ ├── notify.js
│ │ │ └── styles/
│ │ │ ├── bootstrap/
│ │ │ │ └── notify-bootstrap.js
│ │ │ └── metro/
│ │ │ ├── notify-metro.css
│ │ │ └── notify-metro.js
│ │ └── src/
│ │ ├── notify.coffee
│ │ └── styles/
│ │ ├── STYLES-README.md
│ │ └── bootstrap/
│ │ └── notify-bootstrap.coffee
│ ├── peity/
│ │ └── jquery.peity.js
│ ├── raphael/
│ │ └── raphael-min.js
│ ├── select2/
│ │ ├── .bower.json
│ │ ├── .gitignore
│ │ ├── CONTRIBUTING.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bower.json
│ │ ├── component.json
│ │ ├── composer.json
│ │ ├── package.json
│ │ ├── release.sh
│ │ ├── select2-bootstrap.css
│ │ ├── select2.css
│ │ ├── select2.jquery.json
│ │ ├── select2.js
│ │ ├── select2_locale_ar.js
│ │ ├── select2_locale_az.js
│ │ ├── select2_locale_bg.js
│ │ ├── select2_locale_ca.js
│ │ ├── select2_locale_cs.js
│ │ ├── select2_locale_da.js
│ │ ├── select2_locale_de.js
│ │ ├── select2_locale_el.js
│ │ ├── select2_locale_en.js.template
│ │ ├── select2_locale_es.js
│ │ ├── select2_locale_et.js
│ │ ├── select2_locale_eu.js
│ │ ├── select2_locale_fa.js
│ │ ├── select2_locale_fi.js
│ │ ├── select2_locale_fr.js
│ │ ├── select2_locale_gl.js
│ │ ├── select2_locale_he.js
│ │ ├── select2_locale_hr.js
│ │ ├── select2_locale_hu.js
│ │ ├── select2_locale_id.js
│ │ ├── select2_locale_is.js
│ │ ├── select2_locale_it.js
│ │ ├── select2_locale_ja.js
│ │ ├── select2_locale_ka.js
│ │ ├── select2_locale_ko.js
│ │ ├── select2_locale_lt.js
│ │ ├── select2_locale_lv.js
│ │ ├── select2_locale_mk.js
│ │ ├── select2_locale_ms.js
│ │ ├── select2_locale_nb.js
│ │ ├── select2_locale_nl.js
│ │ ├── select2_locale_pl.js
│ │ ├── select2_locale_pt-BR.js
│ │ ├── select2_locale_pt-PT.js
│ │ ├── select2_locale_ro.js
│ │ ├── select2_locale_rs.js
│ │ ├── select2_locale_ru.js
│ │ ├── select2_locale_sk.js
│ │ ├── select2_locale_sv.js
│ │ ├── select2_locale_th.js
│ │ ├── select2_locale_tr.js
│ │ ├── select2_locale_ug-CN.js
│ │ ├── select2_locale_uk.js
│ │ ├── select2_locale_vi.js
│ │ ├── select2_locale_zh-CN.js
│ │ └── select2_locale_zh-TW.js
│ ├── summernote/
│ │ ├── dist/
│ │ │ ├── summernote-bs3.css
│ │ │ ├── summernote.css
│ │ │ └── summernote.js
│ │ ├── lang/
│ │ │ ├── summernote-ar-AR.js
│ │ │ ├── summernote-bg-BG.js
│ │ │ ├── summernote-ca-ES.js
│ │ │ ├── summernote-cs-CZ.js
│ │ │ ├── summernote-da-DK.js
│ │ │ ├── summernote-de-DE.js
│ │ │ ├── summernote-es-ES.js
│ │ │ ├── summernote-es-EU.js
│ │ │ ├── summernote-fa-IR.js
│ │ │ ├── summernote-fi-FI.js
│ │ │ ├── summernote-fr-FR.js
│ │ │ ├── summernote-he-IL.js
│ │ │ ├── summernote-hu-HU.js
│ │ │ ├── summernote-id-ID.js
│ │ │ ├── summernote-it-IT.js
│ │ │ ├── summernote-ja-JP.js
│ │ │ ├── summernote-ko-KR.js
│ │ │ ├── summernote-lt-LT.js
│ │ │ ├── summernote-nb-NO.js
│ │ │ ├── summernote-nl-NL.js
│ │ │ ├── summernote-pl-PL.js
│ │ │ ├── summernote-pt-BR.js
│ │ │ ├── summernote-pt-PT.js
│ │ │ ├── summernote-ro-RO.js
│ │ │ ├── summernote-ru-RU.js
│ │ │ ├── summernote-sk-SK.js
│ │ │ ├── summernote-sl-SI.js
│ │ │ ├── summernote-sr-RS-Latin.js
│ │ │ ├── summernote-sr-RS.js
│ │ │ ├── summernote-sv-SE.js
│ │ │ ├── summernote-th-TH.js
│ │ │ ├── summernote-tr-TR.js
│ │ │ ├── summernote-uk-UA.js
│ │ │ ├── summernote-vi-VN.js
│ │ │ ├── summernote-zh-CN.js
│ │ │ └── summernote-zh-TW.js
│ │ ├── meteor/
│ │ │ ├── README.md
│ │ │ ├── package-standalone.js
│ │ │ ├── package.js
│ │ │ ├── publish.sh
│ │ │ ├── runtests.sh
│ │ │ └── test.js
│ │ ├── plugin/
│ │ │ ├── summernote-ext-hello.js
│ │ │ ├── summernote-ext-hint.js
│ │ │ └── summernote-ext-video.js
│ │ └── src/
│ │ ├── css/
│ │ │ ├── elements.css
│ │ │ └── summernote.css
│ │ ├── js/
│ │ │ ├── EventHandler.js
│ │ │ ├── Renderer.js
│ │ │ ├── app.js
│ │ │ ├── core/
│ │ │ │ ├── agent.js
│ │ │ │ ├── async.js
│ │ │ │ ├── dom.js
│ │ │ │ ├── func.js
│ │ │ │ ├── key.js
│ │ │ │ ├── list.js
│ │ │ │ └── range.js
│ │ │ ├── defaults.js
│ │ │ ├── editing/
│ │ │ │ ├── Bullet.js
│ │ │ │ ├── History.js
│ │ │ │ ├── Style.js
│ │ │ │ ├── Table.js
│ │ │ │ └── Typing.js
│ │ │ ├── intro.js
│ │ │ ├── module/
│ │ │ │ ├── Button.js
│ │ │ │ ├── Clipboard.js
│ │ │ │ ├── Codeview.js
│ │ │ │ ├── DragAndDrop.js
│ │ │ │ ├── Editor.js
│ │ │ │ ├── Fullscreen.js
│ │ │ │ ├── Handle.js
│ │ │ │ ├── HelpDialog.js
│ │ │ │ ├── ImageDialog.js
│ │ │ │ ├── LinkDialog.js
│ │ │ │ ├── Popover.js
│ │ │ │ ├── Statusbar.js
│ │ │ │ └── Toolbar.js
│ │ │ ├── outro.js
│ │ │ └── summernote.js
│ │ ├── less/
│ │ │ ├── elements.less
│ │ │ └── summernote.less
│ │ └── sass/
│ │ └── summernote.scss
│ ├── sweetalert/
│ │ └── dist/
│ │ ├── sweetalert-dev.js
│ │ └── sweetalert.css
│ ├── switchery/
│ │ ├── dist/
│ │ │ ├── switchery.css
│ │ │ └── switchery.js
│ │ ├── meteor/
│ │ │ ├── export.js
│ │ │ └── tests.js
│ │ ├── switchery.css
│ │ └── switchery.js
│ ├── tiny-editable/
│ │ ├── mindmup-editabletable.js
│ │ └── numeric-input-example.js
│ └── waypoints/
│ └── lib/
│ ├── jquery.waypoints.js
│ ├── noframework.waypoints.js
│ ├── shortcuts/
│ │ ├── infinite.js
│ │ ├── inview.js
│ │ └── sticky.js
│ ├── waypoints.debug.js
│ └── zepto.waypoints.js
├── supervisord.conf
├── templates/
│ ├── 403.html
│ ├── 404.html
│ ├── 500.html
│ ├── base.html
│ ├── dockermanager/
│ │ ├── containers_list.html
│ │ ├── dockerhosts_add.html
│ │ ├── dockerhosts_edit.html
│ │ ├── dockerhosts_list.html
│ │ ├── dockerhosts_logs.html
│ │ ├── images_list.html
│ │ └── websocket.html
│ ├── domainmanager/
│ │ ├── domain_list.html
│ │ └── domain_records.html
│ ├── saltadmin/
│ │ ├── key_list.html
│ │ ├── minion_status.html
│ │ ├── salt_cmd.html
│ │ ├── saltjob_detail.html
│ │ ├── saltjob_list.html
│ │ ├── saltmaster_list.html
│ │ └── saltmodule_deploy.html
│ ├── servermanager/
│ │ ├── assets_list.html
│ │ ├── assetschange.html
│ │ ├── assetsdetail.html
│ │ ├── hosts.html
│ │ ├── servers_change.html
│ │ ├── servers_detail.html
│ │ └── servers_list.html
│ ├── tempdir/
│ │ ├── foot_script.html
│ │ ├── head_css.html
│ │ └── head_script.html
│ └── webapp/
│ ├── index.html
│ ├── login.html
│ ├── register.html
│ ├── resetpass.html
│ ├── sendresetpw.html
│ ├── sysrestuserpassword.html
│ └── userinfo.html
├── uwsgi.ini
└── webapp/
├── Extends/
│ ├── PageList.py
│ └── __init__.py
├── __init__.py
├── admin.py
├── apps.py
├── forms.py
├── migrations/
│ └── __init__.py
├── models.py
├── tasks.py
├── tests.py
├── urls.py
└── views.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .idea/SimpletourDevops.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 2.7.6 (C:\Python27\python.exe)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="docker_module" />
<orderEntry type="module" module-name="zxpython" />
</component>
</module>
================================================
FILE: .idea/inspectionProfiles/Project_Default.xml
================================================
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="9">
<item index="0" class="java.lang.String" itemvalue="django" />
<item index="1" class="java.lang.String" itemvalue="django-celery-email" />
<item index="2" class="java.lang.String" itemvalue="django-suit" />
<item index="3" class="java.lang.String" itemvalue="django-import-export" />
<item index="4" class="java.lang.String" itemvalue="itsdangerous" />
<item index="5" class="java.lang.String" itemvalue="v2-vertical" />
<item index="6" class="java.lang.String" itemvalue="uwsgi" />
<item index="7" class="java.lang.String" itemvalue="supervisor" />
<item index="8" class="java.lang.String" itemvalue="eventlet" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>
================================================
FILE: .idea/inspectionProfiles/profiles_settings.xml
================================================
<component name="InspectionProjectProfileManager">
<settings>
<option name="PROJECT_PROFILE" value="Project Default" />
<option name="USE_PROJECT_PROFILE" value="true" />
<version value="1.0" />
</settings>
</component>
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7.6 (C:\Python27\python.exe)" project-jdk-type="Python SDK" />
<component name="masterDetails">
<states>
<state key="ScopeChooserConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>
================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/SimpletourDevops.iml" filepath="$PROJECT_DIR$/.idea/SimpletourDevops.iml" />
<module fileurl="file://D:/简途运维平台/docker_module/.idea/docker_module.iml" filepath="D:/简途运维平台/docker_module/.idea/docker_module.iml" />
<module fileurl="file://D:/zxpython/.idea/zxpython.iml" filepath="D:/zxpython/.idea/zxpython.iml" />
</modules>
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
================================================
FILE: Publicapi/__init__.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
================================================
FILE: Publicapi/dnspod/__init__.py
================================================
================================================
FILE: Publicapi/dnspod/apicn.py
================================================
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import httplib, urllib
try: import json
except: import simplejson as json
import socket
import re
class ApiCn:
def __init__(self, email, password, **kw):
self.base_url = "dnsapi.cn"
self.params = dict(
login_email=email,
login_password=password,
format="json",
)
self.params.update(kw)
self.path = None
def request(self, **kw):
self.params.update(kw)
if not self.path:
"""Class UserInfo will auto request path /User.Info."""
name = re.sub(r'([A-Z])', r'.\1', self.__class__.__name__)
self.path = "/" + name[1:]
conn = httplib.HTTPSConnection(self.base_url)
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/json", "User-Agent": "dnspod-python/0.01 (im@chuangbo.li; DNSPod.CN API v2.8)"}
conn.request("POST", self.path, urllib.urlencode(self.params), headers)
response = conn.getresponse()
data = response.read()
conn.close()
ret = json.loads(data)
if ret.get("status", {}).get("code") == "1":
return ret
else:
raise Exception(ret)
__call__ = request
class InfoVersion(ApiCn):
pass
class UserDetail(ApiCn):
pass
class UserInfo(ApiCn):
pass
class UserLog(ApiCn):
pass
class DomainCreate(ApiCn):
def __init__(self, domain, **kw):
kw.update(dict(domain=domain))
ApiCn.__init__(self, **kw)
class DomainId(ApiCn):
def __init__(self, domain, **kw):
kw.update(dict(domain=domain))
ApiCn.__init__(self, **kw)
class DomainList(ApiCn):
pass
class _DomainApiBase(ApiCn):
def __init__(self, domain_id, **kw):
kw.update(dict(domain_id=domain_id))
ApiCn.__init__(self, **kw)
class DomainRemove(_DomainApiBase):
pass
class DomainStatus(_DomainApiBase):
def __init__(self, status, **kw):
kw.update(dict(status=status))
_DomainApiBase.__init__(self, **kw)
class DomainInfo(_DomainApiBase):
pass
class DomainLog(_DomainApiBase):
pass
class RecordType(ApiCn):
def __init__(self, domain_grade, **kw):
kw.update(dict(domain_grade=domain_grade))
ApiCn.__init__(self, **kw)
class RecordLine(ApiCn):
def __init__(self, domain_grade, **kw):
kw.update(dict(domain_grade=domain_grade))
ApiCn.__init__(self, **kw)
class RecordCreate(_DomainApiBase):
def __init__(self, sub_domain, record_type, record_line, value, ttl, mx=None, **kw):
kw.update(dict(
sub_domain=sub_domain,
record_type=record_type,
record_line=record_line,
value=value,
ttl=ttl,
))
if mx:
kw.update(dict(mx=mx))
_DomainApiBase.__init__(self, **kw)
class RecordModify(RecordCreate):
def __init__(self, record_id, **kw):
kw.update(dict(record_id=record_id))
RecordCreate.__init__(self, **kw)
class RecordList(_DomainApiBase):
pass
class _RecordBase(_DomainApiBase):
def __init__(self, record_id, **kw):
kw.update(dict(record_id=record_id))
_DomainApiBase.__init__(self, **kw)
class RecordRemove(_RecordBase):
pass
class RecordDdns(_DomainApiBase):
def __init__(self, record_id, sub_domain, record_line, **kw):
kw.update(dict(
record_id=record_id,
sub_domain=sub_domain,
record_type=record_type,
record_line=record_line,
))
_DomainApiBase.__init__(self, **kw)
class RecordStatus(_RecordBase):
def __init__(self, status, **kw):
kw.update(dict(status=status))
_RecordBase.__init__(self, **kw)
class RecordInfo(_RecordBase):
pass
================================================
FILE: Publicapi/dockerapi/Manager.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
import docker
'''
Docker 容器API公共模块,可进行容器及镜像管理
'''
class Dockerapi(object):
def __init__(self, host, port):
self.dockerConnect = docker.Client(base_url='tcp://%s:%s' %(host,port), timeout=60, version='1.22')
def GetallContainers(self):
Containers = self.dockerConnect.containers(all=1)
return Containers
def SearchContainers(self, Searchparameter):
SearchContainer = self.dockerConnect.containers(all=1,filters={'name':[Searchparameter]})
return SearchContainer
def ContainerStatus(self, Status):
StatusContainer = self.dockerConnect.containers(all=1,filters={'status':[Status]})
return StatusContainer
def InspectContainer(self,name):
inspect = self.dockerConnect.inspect_container(container=name)
return inspect
def Dockerversion(self):
Version = self.dockerConnect.version()
return Version
def StartContainer(self, name):
StartContainer = self.dockerConnect.start(container=name)
return StartContainer
def StopContainer(self, name):
StopContainer = self.dockerConnect.stop(container=name)
return StopContainer
def DelayedstopContainer(self, name, timeout):
delayedstop = self.dockerConnect.stop(container=name, timeout=timeout)
return delayedstop
def Dockerinfo(self):
dockerinfo = self.dockerConnect.info()
return dockerinfo
def RestartContainer(self, name):
restart = self.dockerConnect.restart(container=name)
return restart
def DelayedRestart(self, name, timeout):
delayedrestart = self.dockerConnect.restart(container=name, timeout=timeout)
return delayedrestart
def RenameDocker(self, name, newname):
rename = self.dockerConnect.rename(container=name, name=newname)
return rename
def TopContainer(self, name):
topinfo = self.dockerConnect.top(container=name, ps_args=aux)
return topinfo
def killContainer(self, name):
kill = self.dockerConnect.kill(container=name)
return kill
def PauseContainer(self, name):
pause = self.dockerConnect.pause(container=name)
return pause
def UnpauseContainer(self, name):
unpause = self.dockerConnect.unpause(container=name)
return unpause
def removeContainer(self, name, v=False, link=False, force=False):
remove = self.dockerConnect.remove_container(container=name, v=v, link=link, force=force)
return remove
def LogContainer(self,name,timestamps=False,tail=all):
logs = self.dockerConnect.logs(container=name,stdout=True,stderr=True,timestamps=timestamps,tail=tail)
return logs
def AllImages(self):
images=self.dockerConnect.images(all=1)
return images
def DeleteImages(self,imagename):
data=self.dockerConnect.remove_image(image=imagename,force=False)
return u"删除镜像成功!!"
if __name__ == '__main__':
test=Dockerapi('192.168.2.232','2375')
#a=test.DeleteImages('docker.io/centos/v1:latest')
#print a
# search=test.SearchContainers('simpletou')
# status=test.ContainerStatus('exited')
# version=test.Dockerversion()
# stop=test.StopContainer('nostalgic_albattani')
#tart=test.StartContainer('nostalgic_albattani')
#stopd=test.DelayedstopContainer('nostalgic_albattani',10)
#print stopd
#rename=test.RenameDocker('nostalgic_albattani','aaa')
#inspect = test.InspectContainer('aaa')
#print all
================================================
FILE: Publicapi/dockerapi/__init__.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
================================================
FILE: Publicapi/saltstackapi/Assets_Module.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
class ServerBaseInfo(object):
def __init__(self,data,minion):
self.ServerHardInfo = {}
self.serverbaseinfo={}
self.data = data
self.minion = minion
self.serverbaseinfo['sn'] = self.data[self.minion]['serialnumber']
self.serverbaseinfo['hostname'] = self.data[self.minion]['nodename']
self.serverbaseinfo['cpu_count'] = self.data[self.minion]['CPU_COUNT']
self.serverbaseinfo['cpu_core_count'] = self.data[self.minion]['CPU_Info']['cpu processor']
self.serverbaseinfo['saltid'] = self.data[self.minion]['id']
self.serverbaseinfo['mem'] = self.data[self.minion]['Mem_Total']
self.serverbaseinfo['swap'] = self.data[self.minion]['Swap_Total']
self.serverbaseinfo['platform'] = self.data[self.minion]['osarch']
self.serverbaseinfo['system'] = self.data[self.minion]['oscodename']
self.serverbaseinfo['version'] = self.data[self.minion]['osrelease']
self.ServerHardInfo['Serverbaseinfo']=self.serverbaseinfo
class ServerCPUInfo(ServerBaseInfo):
def __init__(self,data,minion):
super(ServerCPUInfo,self).__init__(data,minion)
def ServerCPU(self):
servercpuinfo ={}
servercpuinfo['uuid'] = self.data[self.minion]['cpu_uuid']
servercpuinfo['parent_sn'] = self.data[self.minion]['serialnumber']
servercpuinfo['architecture'] = self.data[self.minion]['cpuarch']
servercpuinfo['model'] = self.data[self.minion]['cpu_model']
servercpuinfo['cpu_mhz'] = self.data[self.minion]['cpu MHz']
servercpuinfo['L1cache'] = self.data[self.minion]['CPU_Info']['L1 cache']
servercpuinfo['L2cache'] = self.data[self.minion]['CPU_Info']['L2 cache']
servercpuinfo['L3cache'] = self.data[self.minion]['CPU_Info']['L3 cache']
servercpuinfo['thread'] = self.data[self.minion]['CPU_Info']['cpu processor']
self.ServerHardInfo['servercpuinfo'] = servercpuinfo
return self.ServerHardInfo
class ServerNICInfo(ServerBaseInfo):
def __init__(self,data,minion):
super(ServerNICInfo,self).__init__(data,minion)
def ServerNIC(self):
servernicinfo={}
servernicinfo['nicinfo'] = self.data[self.minion]['nicinfo']
self.ServerHardInfo['servernicinfo'] = servernicinfo
return self.ServerHardInfo
class ServerDiskInfo(ServerBaseInfo):
def __init__(self,data,minion):
super(ServerDiskInfo,self).__init__(data,minion)
def ServerDISK(self):
serverdiskinfo={}
serverdiskinfo['diskinfo'] = self.data[self.minion]['disk']
self.ServerHardInfo['serverdiskinfo'] = serverdiskinfo
return self.ServerHardInfo
================================================
FILE: Publicapi/saltstackapi/SaltConApi.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
import urllib,urllib2
import json
import requests
import yaml
from Assets_Module import ServerBaseInfo,ServerCPUInfo,ServerNICInfo,ServerDiskInfo
class SaltApi(object):
__token = ''
def __init__(self,url,user,password):
self.__url = url.rstrip('/')
self.__user= user
self.__pass = password
params = {'eauth': 'pam','username':self.__user,'password': self.__pass}
req = requests.post(url+'/login', data=params,allow_redirects=False)
try:
self.__token = req.headers['x-auth-token']
except KeyError:
raise KeyError
def PostRequest(self,obj,parurl='/'):
url = self.__url + parurl
headers = {'X-Auth-Token': self.__token,'Accept': 'application/json'}
req = requests.post(url, data=obj, headers=headers,verify=False)
content = req.json()
return content
def grains(self,tgt,args):
params={'client':'local','tgt': tgt, 'fun': 'grains.item','arg': args}
content = self.PostRequest(params)
ret = content['return'][0]
return ret
def grainsall(self,tgt):
params={'client':'local','tgt': tgt, 'fun': 'grains.items'}
content = self.PostRequest(params)
ret = content['return'][0]
return ret
def pillarall(self,tgt):
params = {'client': 'local', 'tgt': tgt, 'fun': 'pillar.items'}
content = self.PostRequest(params)
ret = content['return'][0]
return ret
def List_all_keys(self):
params={'client':'wheel', 'fun':'key.list_all'}
content=self.PostRequest(params)
minions = content['return'][0]['data']['return']['minions']
minions_pre = content['return'][0]['data']['return']['minions_pre']
minions_rej = content['return'][0]['data']['return']['minions_rejected']
minions_deny = content['return'][0]['data']['return']['minions_denied']
return minions, minions_pre, minions_rej, minions_deny
def shell_remote_execution(self,tgt,arg):
''' Shell command execution with parameters '''
params = {'client': 'local_async', 'tgt': tgt, 'fun': 'cmd.run', 'arg': arg, 'expr_form': 'list'}
content = self.PostRequest(params)
jid = content['return'][0]['jid']
return jid
def Softwarete_deploy(self,tgt,arg):
'''执行salt.sls 远程部署程序'''
params = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls','arg':arg, 'expr_form': 'list'}
content = self.PostRequest(params)
jid = content['return'][0]['jid']
return jid
'''saltstack key管理 action需要进行传入,方法有,accept,delete,reject'''
def actionKeys(self,keystrings,action):
func = 'key.' + action
params = {'client': 'wheel', 'fun': func, 'match': keystrings}
content = self.PostRequest(params)
ret = content['return'][0]['data']['success']
return ret
'''saltstack key 批量管理传入值必须为一个字典'''
def dictActionKeys(self,keydict,action):
func = 'key.' + action + '_dict'
params = {'client':'wheel','fun':func,'match':keydict}
content = self.PostRequest(params)
return content['return'][0]
def cpFiletoMinions(self,tgt):
params={'client':'local','tgt': tgt, 'fun': 'cp.get'}
content = self.PostRequest(params)
ret = content['return'][0]
return ret
#获取JOB ID的详细执行结果
def runner(self,arg):
''' Return minion status '''
params = {'client': 'runner', 'fun': arg }
content = self.PostRequest(params)
jid = content['return'][0]
return jid
def salt_runner(self, jid):
'''
通过jid获取执行结果
'''
params = {'client': 'runner', 'fun': 'jobs.lookup_jid', 'jid': jid}
print params
content = self.PostRequest(params)
print content
return content['return'][0]
#获取events
def SaltEvents(self):
parurl = '/events'
res = self.PostRequest(None,parurl)
return res
#接受KEY
def AcceptKey(self, key_id):
params = {'client': 'wheel', 'fun': 'key.accept', 'match': key_id, 'include_rejected': True, 'include_denied': True}
content = self.PostRequest(params)
ret = content['return'][0]['data']['success']
return ret
#删除KEY
def DeleteKey(self, key_id):
params = {'client': 'wheel', 'fun': 'key.delete', 'match': key_id}
content = self.PostRequest(params)
ret = content['return'][0]['data']['success']
return ret
# 拒绝KEY
def RejectKey(self, key_id):
params = {'client': 'wheel', 'fun': 'key.reject', 'match': key_id, 'include_accepted': True, 'include_denied': True}
content = self.PostRequest(params)
ret = content['return'][0]['data']['success']
return ret
def Saltalive(self,tgt):
'''
salt主机存活检测
'''
params = {'client': 'local', 'tgt': tgt, 'fun': 'test.ping'}
content = self.PostRequest(params)
return content['return'][0]
def format(data):
print data
if __name__ == '__main__':
salt=SaltApi('http://192.168.2.150:8000','roddy','roudy_123456')
#a=salt.Softwarete_deploy('192.168.2.147,',arg=['saltenv="prod"','nginx.install,zabbix-client.install','test=True'])
#a=salt.Softwarete_deploy('192.168.2.147',kwarg={'mods':'redis.install,nginx.install','test':True,'saltenv':'prod'})
#print a
#a = salt.SaltRun('192.168.2.147','state.sls','nginx.install,redis.install',saltenv='prod','test=True')
#data=salt.Saltalive('192.168.2.147')
#print data
#host='192.168.2.147,192.168.2.148,'
#data=salt.shell_remote_execution(host, 'df -i')
#print data
data = salt.salt_runner(20161215192828817118)
print data
format(data)
#print salt.SaltRun(client='runner', fun='fileserver.envs')
#a=sorted(salt.SaltRun(client='runner',fun='fileserver.envs')['return'][0])
#print a
#jids = salt.runner("jobs.list_jobs")
#print jids
#for i,v in jids.items:
# print i,v
#a,b,c,d =salt.List_all_keys()
#print a,b,c,d
#salt.shell_remote_execution
#funs = ['doc.runner', 'doc.wheel', 'doc.execution']
#for fun in funs:
# result = salt.SaltRun(fun=fun, client='runner')
# cs = result['return'][0]
# for c in cs:
# print fun.split('.')[1], c.split('.')[0]
#server=ServerDiskInfo(data, u'192.168.2.147')
#server=ServerCPUInfo(data,u'192.168.2.147')
#print server.ServerCPU()
#data=salt.grainsall('192.168.2.147')
#print data
#clientkey=salt.List_all_keys()['minions']
# Servers={}
# for i in clientkey:
# data=salt.grainsall(i)
# server=ServerNICInfo(data,i)
# serverinfo=server.ServerNIC()
# print serverinfo
================================================
FILE: Publicapi/saltstackapi/__init__.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
================================================
FILE: README.md
================================================
# SimpletourDevops
django+python+celery+saltstack+docker实现的运维管理后台
作者QQ:923401910
v1.0:完成资产信息录入及使用saltstack自动采集更新
完成单机版docker主机的基本管理,日志实时刷新
##部署步骤
* 安装环境
```
pip install requirements.txt
```
* 安装nginx
```
yum install nginx -y
```
* 安装saltstack
```
yum install salt-master -y
yum install salt-minion -y
```
* 配置docker
```
[root@localhost ~]# vim /etc/sysconfig/docker
# /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--selinux-enabled -H 0.0.0.0:2375 -H unix:///var/run/docker.sock '
DOCKER_CERT_PATH=/etc/docker
```
* 部署流程
以下为部署流程
修改 settings.py中db连接
```
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'SimpletourDevops',
'HOST': '192.168.2.232',
'USER': 'root',
'PORT': 3306,
'PASSWORD': 'redhat',
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB',
},
}
}
```
部署程序到/data
```
[root@localhost ~]# mv /root/SimpletourDevops /data/
[root@localhost ~]# cd /data/SimpletourDevops
[root@localhost SimpletourDevops]#python manage.py makemigrations
[root@localhost SimpletourDevops]#python manage.py migrate
```
复制supervisor配置
```
[root@localhost SimpletourDevops]# cp supervisord.conf /etc/
[root@localhost supervisord.d]# supervisord -c /etc/supervisord.conf <--启动supervisor,如果启动用户非www,请自行修改
```
修改配置文件
```
在settings.py中添加STATIC_ROOT
STATIC_ROOT = '/data/SimpletourDevops/static/suit'
```
```
python manage.py collectstatic <--生成静态文件
```
配置nginx
```
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/devops.simpletour.com.access.log main;
error_log /var/log/nginx/devops.simpletour.com.error.log error;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8098;
uwsgi_read_timeout 600;
uwsgi_connect_timeout 60;
uwsgi_send_timeout 600;
client_max_body_size 35m;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
uwsgi_ignore_client_abort on;
}
location ^~ /docker/getSocket{
proxy_pass http://127.0.0.1:8099;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
uwsgi_ignore_client_abort on;
}
location /static {
alias /data/SimpletourDevops/static/suit;
}
}
```
启动访问
### 首页及docker







### saltstack




### 后台

================================================
FILE: SimpletourDevops/__init__.py
================================================
#coding:utf-8
from django.core import signals
from django.db import close_old_connections
# 取消信号关联,实现数据库长连接
signals.request_finished.disconnect(close_old_connections)
================================================
FILE: SimpletourDevops/apps.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
from suit.apps import DjangoSuitConfig
from suit.menu import ParentItem, ChildItem
class SuitConfig(DjangoSuitConfig):
layout = 'vertical'
menu = (
ParentItem(u'资产组件', children=[
ChildItem(model='servermanager.server'),
ChildItem(model='servermanager.assets'),
ChildItem(model='servermanager.idc'),
ChildItem(model='servermanager.cpu'),
ChildItem(model='servermanager.nic'),
ChildItem(model='servermanager.disk'),
ChildItem(model='servermanager.software'),
ChildItem(model='servermanager.business'),
ChildItem(model='servermanager.devicetype'),
ChildItem(model='servermanager.provider'),
], icon='fa fa-leaf'),
ParentItem(u'容器管理', children=[
ChildItem(model='dockermanager.dockerhost'),
ChildItem(model='dockermanager.dockercontainer'),
ChildItem(model='dockermanager.dockerimage'),
], icon='fa fa-magnet'),
ParentItem(u'Salt管理', children=[
ChildItem(model='saltadmin.saltjobs'),
ChildItem(model='saltadmin.cmdrunlog'),
ChildItem(model='saltadmin.miniongroup'),
ChildItem(model='saltadmin.modules'),
], icon='fa fa-magnet'),
ParentItem(u'用户管理', children=[
ChildItem(u'用 户','webapp.suser'),
ChildItem(u'用户组', 'auth.group'),
], icon='fa fa-users'),
)
================================================
FILE: SimpletourDevops/settings.py
================================================
#coding:utf8
"""
Django settings for SimpletourDevops project.
Generated by 'django-admin startproject' using Django 1.9.9.
For more information on this file, see
https://docs.djangoproject.com/en/1.9/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.9/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '7yk*v@pp1dxi+9fdg-=_3_&!hh4=4tiukajl1^-m$(_2q=gw=9'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
#'suit',
'SimpletourDevops.apps.SuitConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'webapp',
'servermanager',
'dockermanager',
'saltadmin',
#'domainmanager',
'import_export',
]
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'SimpletourDevops.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ["%s/%s" %(BASE_DIR,'templates'),],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'SimpletourDevops.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'SimpletourDevops',
'HOST': '192.168.2.232',
'USER': 'root',
'PORT': 3306,
'PASSWORD': 'redhat',
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB',
},
}
}
# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
AUTH_USER_MODEL = 'webapp.Suser'
LOGIN_URL='/web/login/'
# Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = False
USE_TZ = False
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.qq.com'
EMAIL_PORT = 25
EMAIL_HOST_USER = '923401910@qq.com'
EMAIL_HOST_PASSWORD = 'utzvxwccfxhkbcdc'
DEFAULT_FROM_EMAIL = '923401910@qq.com'
SESSION_COOKIE_AGE = 60*180
================================================
FILE: SimpletourDevops/urls.py
================================================
"""SimpletourDevops URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin
from webapp.views import index
from django.conf import settings
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', index, name='index'),
url(r'^web/', include('webapp.urls')),
url(r'^docker/',include('dockermanager.urls')),
url(r'^server/',include('servermanager.urls')),
# url(r'^domain/', include('domainmanager.urls')),
url(r'^salt/',include('saltadmin.urls')),
]
================================================
FILE: SimpletourDevops/wsgi.py
================================================
"""
WSGI config for SimpletourDevops project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "SimpletourDevops.settings")
application = get_wsgi_application()
================================================
FILE: dockermanager/Docker_Controller.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "SimpletourDevops.settings")
import django
django.setup()
from dockermanager.models import DockerHost,Dockerimage,DockerContainer
from Publicapi.dockerapi.Manager import Dockerapi
import time
'''获取数据'''
def GetDockerServerinfo():
DockerServerList = DockerHost.objects.filter(enabled=1)
for server in DockerServerList:
try:
docker=Dockerapi(server.hostip,server.port)
Dockerdata=docker.GetallContainers()
for container in Dockerdata:
'''获取容器最新状态进行修改'''
if DockerContainer.objects.filter(containerID=container['Id']):
status=container['Status']
if 'Up' in status:
status= 'running'
else:
status = 'Exited'
OldContainer = DockerContainer.objects.get(containerID=container['Id'])
OldContainer.Name=container['Names'][0].lstrip('/')
OldContainer.command=container['Command']
OldContainer.status=status
OldContainer.image=container['Image']
OldContainer.hostip=server.hostip
OldContainer.Created=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(container['Created']))
OldContainer.save()
else:
'''如果没有容器就添加'''
status = container['Status']
if 'Up' in status:
status = 'running'
else:
status = 'Exited'
NewContainer=DockerContainer(containerID=container['Id'],
Name=container['Names'][0].lstrip('/'),
command=container['Command'],
status=status,
image=container['Image'],
hostip=server.hostip,
Created=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(container['Created'])))
NewContainer.save()
except:
print "sssssss"
return u"Connect Docker host is Error!!!"
return u"OK"
def GetDockerImages():
DockerServerList = DockerHost.objects.filter(enabled=1)
for server in DockerServerList:
try:
docker=Dockerapi(server.hostip,server.port)
DockerImagesdata=docker.AllImages()
except:
return u"Connect Docker host is Error!!!"
else:
for image in DockerImagesdata:
if image['RepoTags'][0] == '<none>:<none>':
continue
imageid=image['Id'].split(':')[-1]
for repo in image['RepoTags']:
if Dockerimage.objects.filter(repository=repo):
Oldimage = Dockerimage.objects.get(repository=repo)
Oldimage.repository = repo
Oldimage.imagesId=imageid
Oldimage.tag = repo.split(':')[-1]
Oldimage.imagehost = server.hostip
Oldimage.size = image['Size']
Oldimage.save()
else:
Newimage=Dockerimage(imagesId=imageid,
repository=repo,
tag = repo.split(':')[-1],
imagehost = server.hostip,
size=image['Size'],
)
Newimage.save()
return "Get all imgeas is oK!!"
if __name__ == '__main__':
GetDockerImages()
================================================
FILE: dockermanager/__init__.py
================================================
================================================
FILE: dockermanager/admin.py
================================================
#coding:utf8
from django.contrib import admin
from dockermanager.models import *
class DockerHostModels(admin.ModelAdmin):
list_display = ('host','containers','images','port','enabled')
class DockerContainerModels(admin.ModelAdmin):
list_display = ('Name','status','ip','host','uptime')
admin.site.register(DockerHost,DockerHostModels)
admin.site.register(DockerContainer)
admin.site.register(Dockerimage)
================================================
FILE: dockermanager/apps.py
================================================
from __future__ import unicode_literals
from django.apps import AppConfig
class DockermanagerConfig(AppConfig):
name = 'dockermanager'
================================================
FILE: dockermanager/forms.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
from django import forms
from servermanager.models import Server
from dockermanager.models import DockerHost
from django.forms import ModelForm
class DockerServerAdd(forms.Form):
DockerServer=forms.ModelChoiceField(required=True,
error_messages={'required': u'选择主机'},
queryset=Server.objects.all(),widget=forms.Select(attrs={'class':'form-control'}))
ServerStatus = forms.ChoiceField(choices=[(0,u'禁用'),(1,u'启用')],widget=forms.Select(attrs={'class':'form-control'}))
dockerip = forms.GenericIPAddressField(required=True,
error_messages={'required': u'请输入dockerhost ip', 'invalid':u'ip地址错误'},
widget=forms.TextInput(attrs={'class': 'form-control','placeholder': '宿主机IP',
}),)
dockerport = forms.IntegerField(required=True,
error_messages={'required': u'请输入dockerhost port', 'invalid':u'port输入错误'},
widget=forms.TextInput(attrs={'class': 'form-control','placeholder': '宿主机端口',
}),)
class DockerServerEdit(ModelForm):
class Meta:
model = DockerHost
fields = ('host', 'hostip','port','enabled')
================================================
FILE: dockermanager/migrations/__init__.py
================================================
================================================
FILE: dockermanager/models.py
================================================
#coding:utf8
from __future__ import unicode_literals
from django.db import models
from servermanager.models import Server
class Dockerimage(models.Model):
imagesId = models.CharField(u'镜像ID', max_length=64)
repository = models.CharField(u'仓库', max_length=64,blank=True)
tag = models.CharField(u'Tag', max_length=32,blank=True)
imagehost = models.GenericIPAddressField(u'主机IP')
size = models.CharField(u'大小', max_length=32,blank=True)
update_at = models.DateTimeField(blank=True, auto_now=True,null=True)
def __unicode__(self):
return self.imagesId
class Meta:
verbose_name = u'Docker镜像'
verbose_name_plural = u"Docker镜像"
class DockerHost(models.Model):
host = models.OneToOneField(Server,verbose_name=u'主机')
hostip = models.GenericIPAddressField(max_length=128,null=False,default='',verbose_name=u'docker IP地址')
containers = models.IntegerField(u'容器数',blank=True,null=True)
images = models.IntegerField(verbose_name=u'镜像数',blank=True,null=True)
port = models.IntegerField(u'端口',blank=True)
enabled = models.IntegerField(u'状态',blank=True)
serverversion = models.CharField(u'docker版本', max_length=32,blank=True)
datatotal = models.CharField(u'总共空间', max_length=32,blank=True)
datause = models.CharField(u'已使用空间', max_length=32,blank=True)
dataAvailable = models.CharField(u'剩余空间', max_length=32,blank=True)
storageDriver = models.CharField(u'存储驱动', max_length=32,blank=True)
create_at = models.DateTimeField(blank=True, auto_now_add=True)
update_at = models.DateTimeField(blank=True, auto_now=True)
def __unicode__(self):
return self.hostip
class Meta:
verbose_name = u'Docker主机'
verbose_name_plural = u"Docker主机"
class DockerContainer(models.Model):
hostip = models.GenericIPAddressField(u'宿主机IP地址',max_length=128,blank=True,null=True)
containerID = models.CharField(u'容器ID', max_length=64)
Name = models.CharField(u'容器名', max_length=255,blank=True)
command = models.CharField(u'执行命令', max_length=255,blank=True)
status = models.CharField(u'状态', max_length=32,blank=True)
image= models.CharField(verbose_name=u'镜像', blank=True,max_length=64)
Created = models.DateTimeField(u'创建时间',blank=True,)
update_at = models.DateTimeField(blank=True, auto_now=True,null=True)
def __unicode__(self):
return self.Name
class Meta:
verbose_name = u'Docker容器'
verbose_name_plural = u"Docker容器"
permissions = (
("docker_index_view", "Can view %s" % verbose_name),
)
class DockerContainerInfo(models.Model):
containerid = models.CharField(u'容器ID', max_length=48) #与上表进行关联
State = models.CharField(u'状态', max_length=48)
Driver = models.CharField(u'磁盘设备', max_length=48,blank=True,null=True)
net = models.CharField(u'网络模式', max_length=48,blank=True)
cpu = models.CharField(u'CPU', max_length=32,blank=True)
mem =models.CharField(u'内存', max_length=32,blank=True)
ip = models.GenericIPAddressField(u'IP')
dns = models.CharField(u'DNS', max_length=32,blank=True)
host = models.CharField(u'主机', max_length=32,blank=True)
MacAddress = models.CharField(u'网卡mac地址', max_length=64)
uptime = models.CharField(u'运行时间', max_length=32,blank=True)
gateway = models.GenericIPAddressField(u'网关')
class ContainerPorts(models.Model):
containerid = models.CharField(u'容器ID', max_length=48) #与上表进行关联
container_port = models.IntegerField(u'容器端口',blank=True)
protocol = models.CharField(u'协议',max_length=32,blank=True)
hostip = models.GenericIPAddressField(u'映射IP')
hostport = models.CharField(u'主机端口',max_length=32,blank=True)
def __unicode__(self):
return self.containerid
class Meta:
verbose_name = u'端口管理'
verbose_name_plural = u"端口管理"
================================================
FILE: dockermanager/tests.py
================================================
from django.test import TestCase
# Create your tests here.
================================================
FILE: dockermanager/urls.py
================================================
from django.conf.urls import url
from dockermanager.views import (Dockercontainerlist,DockerHosts,DockerImages,DockercontainerSearch,
DockerHostAdd,DockerHostDel,DockerHostEdit,DockerContainerDel,
DockerContainerStop,DockerContainerStart,DockerContainerRestart,
DockerImageDelete,DockerLogOutput,StartCeleryStatus,StopCeleryStatus,
RestartCeleryStatus,DeleteCeleryStatus,webSocket,getsocket)
urlpatterns = [
url(r'container/list/(\d+)$', Dockercontainerlist, name='Dockercontainerlist'),
url(r'container/search/(?P<page>\d+)$',DockercontainerSearch,name='DockercontainerSearch'),
url(r'container/restart/(\w+)$',DockerContainerRestart,name='DockerContainerRestart'),
url(r'container/stop/(\w+)$', DockerContainerStop,name='DockerContainerStop'),
url(r'container/start/(\w+)$', DockerContainerStart, name='DockerContainerStart'),
url(r'container/logs/(\w+)$',DockerLogOutput,name='DockerLogOutput'),
url(r'container/delete/(\w+)$',DockerContainerDel,name='DockerContainerDel'),
url(r'container/start/task/(\w+\-\w+\-\w+\-\w+\-\w+)$',StartCeleryStatus,name='StartCeleryStatus'),
url(r'container/restart/task/(\w+\-\w+\-\w+\-\w+\-\w+)$',RestartCeleryStatus,name='RestartCeleryStatus'),
url(r'container/stop/task/(\w+\-\w+\-\w+\-\w+\-\w+)$',StopCeleryStatus,name='StopCeleryStatus'),
url(r'container/delete/task/(\w+\-\w+\-\w+\-\w+\-\w+)$',DeleteCeleryStatus,name='DeleteCeleryStatus'),
url(r'server/list/$', DockerHosts, name='DockerHosts'),
url(r'images/list/(\d+)$',DockerImages, name='DockerImages'),
url(r'images/del/(\d+)$', DockerImageDelete, name='DockerImageDelete'),
url(r'server/add/$', DockerHostAdd, name='DockerHostAdd'),
url(r'server/del/(\d+)$',DockerHostDel,name='DockerHostDel'),
url(r'server/edit/(\d+)$',DockerHostEdit,name='DockerHostEdit'),
url(r'webSocket/(\w+)$',webSocket,name='webSocket'),
url(r'getSocket/(\w+)$',getsocket,name='getsocket'),
]
================================================
FILE: dockermanager/views.py
================================================
#coding:utf8
from django.shortcuts import render,render_to_response
from django.http import HttpResponse,HttpResponseRedirect
from django.http import StreamingHttpResponse
from dwebsocket import accept_websocket,require_websocket
import threading
from django.http import HttpResponse
from django.db.models import Q
from django.contrib.auth.decorators import login_required
from dockermanager.models import DockerHost,Dockerimage,DockerContainer
from django.contrib.auth.decorators import permission_required
# Create your views here.
from webapp.Extends import PageList
from servermanager.models import Server
from dockermanager import forms
from Publicapi.dockerapi.Manager import Dockerapi
from webapp.tasks import StopContainer,StartContainer,RestartContainer,DeleteContainer
import json
import docker
from webapp.models import *
@login_required()
@permission_required('dockermanger.docker_index_view',raise_exception=True)
def Dockercontainerlist(request,page):
usersession=request.session.get('user_id')
if request.method == 'POST':
searchdata = request.POST.get('search')
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count = DockerContainer.objects.filter(Q(containerID__contains=searchdata) | Q(Name__contains=searchdata)).count()
result = DockerContainer.objects.filter(Q(containerID__contains=searchdata) | Q(Name__contains=searchdata)).order_by('-id')[start:end]
url = "/docker/container/list"
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count)
ret = {'Containerdata': result,
'count': count,
'page': page,
'usersession':usersession}
return render(request,'dockermanager/containers_list.html',ret)
else:
DockerHostData= DockerHost.objects.all()
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count = DockerContainer.objects.all().count()
result = DockerContainer.objects.all().order_by('-id')[start:end]
url = "/docker/container/list"
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count)
ret = {'Containerdata': result,
'count': count,
'DockerHostData':DockerHostData,
'page': page,
'usersession':usersession}
return render(request,'dockermanager/containers_list.html',ret)
@login_required()
def DockercontainerSearch(request,page):
usersession=request.session.get('user_id')
if request.method == 'GET':
searchdata = request.GET.get('search')
ipData = request.GET.get('ipList')
status = request.GET.get('status')
DockerHostData = DockerHost.objects.all()
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count=DockerContainer.objects.filter(Q(hostip__contains=ipData) & Q(status__contains=status),
Q(containerID__contains=searchdata) | Q(Name__contains=searchdata)).count()
result=DockerContainer.objects.filter(Q(hostip__contains=ipData) & Q(status__contains=status),
Q(containerID__contains=searchdata) | Q(Name__contains=searchdata)).order_by('-id')[start:end]
#count = DockerContainer.objects.filter(Q(containerID__contains=searchdata) | Q(Name__contains=searchdata)).count()
#result = DockerContainer.objects.filter(Q(containerID__contains=searchdata) | Q(Name__contains=searchdata)).order_by('-id')[start:end]
url = "/docker/container/search"
print url
search=u"?search=%s&status=%s&ipList=%s" %(searchdata,status,ipData)
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count,search)
ret = {'Containerdata': result,
'count': count,
'DockerHostData': DockerHostData,
'page': page,
'usersession':usersession}
return render(request,'dockermanager/containers_list.html',ret)
@login_required()
def DockerHosts(request):
usersession=request.session.get('user_id')
if request.method == 'POST':
id = request.POST['id']
status= request.POST['checkboxValue']
if status == 'true':
status=1
else:
status=0
dockerhostdata = DockerHost.objects.get(id=id)
dockerhostdata.enabled = status
dockerhostdata.save()
msg={'msginfo':u'主机状态修改成功!!!!!!'}
return HttpResponse(json.dumps(msg))
else:
Hostadata=DockerHost.objects.all()
ret={'usersession':usersession,'Hostadata':Hostadata}
return render(request,'dockermanager/dockerhosts_list.html',ret)
@login_required()
@permission_required('dockermanger.add_dockerhost',raise_exception=True)
def DockerHostAdd(request):
username = request.session.get('user_name')
restdata = {'data':'','regerror':'','usersession': request.session.get('user_id')}
registerobj=forms.DockerServerAdd()
restdata['data'] = registerobj
listdata=[]
[listdata.append(int(i.host.id)) for i in DockerHost.objects.all()]
ServerData=Server.objects.exclude(id__in=listdata)
restdata['ServerData']=ServerData
if request.method == 'POST':
form = forms.DockerServerAdd(request.POST)
if form.is_valid():
ServerData = request.POST['DockerServer']
ServerData = Server.objects.get(id=ServerData)
dockerip = request.POST['dockerip']
dockerport = request.POST['dockerport']
ServerStatus = int(request.POST['ServerStatus'])
NewDockerHost=DockerHost(host=ServerData,hostip=dockerip,port=dockerport,enabled=ServerStatus)
NewDockerHost.save()
Operation.objects.create(Opuser=username,Opaction=u'添加Docker宿主机')
return HttpResponseRedirect('/docker/server/list/')
else:
restdata['data'] = form
return render(request,'dockermanager/dockerhosts_add.html', restdata)
@login_required()
def DockerImages(request,page):
usersession=request.session.get('user_id')
if request.method == 'POST':
pass
else:
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count = Dockerimage.objects.all().count()
result = Dockerimage.objects.all().order_by('-id')[start:end]
url = "/docker/images/list"
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count)
ret = {'Imagedata': result,
'count': count,
'page': page,
'usersession':usersession}
return render(request,'dockermanager/images_list.html',ret)
@login_required()
@permission_required('dockermanger.delete_dockerimage',raise_exception=True)
def DockerImageDelete(request, imageid):
username = request.session.get('user_name')
if request.method == 'GET':
Image=Dockerimage.objects.get(id=imageid)
if Image:
repo=Image.repository
#查询DOCKER主机IP及端口
ip = Image.imagehost
port = DockerHost.objects.get(hostip=ip).port
dockerapi = Dockerapi(ip,port)
a=dockerapi.DeleteImages(repo)
Image.delete()
Operation.objects.create(Opuser=username,Opaction=u'删除Docker镜像 %s' %repo)
return HttpResponse(a)
else:
return HttpResponse(u"没有该镜像!!")
@login_required()
@permission_required('dockermanger.delete_dockerhost',raise_exception=True)
def DockerHostDel(request,hostid):
username = request.session.get('user_name')
if request.method == 'GET':
DockerHost.objects.get(id=hostid).delete()
Operation.objects.create(Opuser=username,Opaction=u'删除Docker宿主机%s' %hostid)
msg={'msginfo':u'DockerHost 删除成功!!!'}
return HttpResponse(json.dumps(msg))
@login_required()
@permission_required('dockermanger.change_dockerhost',raise_exception=True)
def DockerHostEdit(request,hostid):
usersession=request.session.get('user_id')
username = request.session.get('user_name')
HostData=DockerHost.objects.get(id=hostid)
if request.method == 'POST':
pass
Operation.objects.create(Opuser=username,Opaction=u'修改Docker宿主机%s' %hostid)
else:
listdata=[]
[listdata.append(int(i.host.id)) for i in DockerHost.objects.all()]
hostid=HostData.host.id
listdata.remove(hostid)
ServerData=Server.objects.exclude(id__in=listdata)
ret={'usersession':usersession,'HostData':HostData,'hostid':hostid,'ServerData':ServerData}
return render(request,'dockermanager/dockerhosts_edit.html', ret)
@login_required()
def DockerContainerStop(request,containerid):
username = request.session.get('user_name')
if request.method == 'GET':
IP=DockerContainer.objects.get(containerID=containerid).hostip
port = DockerHost.objects.get(hostip=IP).port
a=StopContainer.delay(dict(host=IP,port=port,container=containerid))
Operation.objects.create(Opuser=username,Opaction=u'停止容器%s' %containerid[0:12])
msg={'celeryId':a.id}
return HttpResponse(json.dumps(msg))
@login_required()
def DockerContainerRestart(request,containerId):
username = request.session.get('user_name')
if request.method == 'GET':
IP=DockerContainer.objects.get(containerID=containerId).hostip
port = DockerHost.objects.get(hostip=IP).port
a=RestartContainer.apply_async((IP, port, containerId))
Operation.objects.create(Opuser=username,Opaction=u'重启容器%s' %containerId[0:12])
msg={'celeryId':a.id}
return HttpResponse(json.dumps(msg))
@login_required()
@permission_required('dockermanger.delete_dockercontainerinfo',raise_exception=True)
def DockerContainerDel(request,containerId):
username = request.session.get('user_name')
if request.method == 'GET':
print "sdsdsds"
IP=DockerContainer.objects.get(containerID=containerId).hostip
port = DockerHost.objects.get(hostip=IP).port
print "ssssssss"
print IP,port,containerId
a=DeleteContainer.apply_async((IP, port, containerId))
Operation.objects.create(Opuser=username,Opaction=u'删除容器%s' %containerId[0:12])
msg={'celeryId': a.id}
return HttpResponse(json.dumps(msg))
@login_required()
def DockerContainerStart(request, containerId):
username = request.session.get('user_name')
if request.method == 'GET':
IP=DockerContainer.objects.get(containerID=containerId).hostip
port = DockerHost.objects.get(hostip=IP).port
a=StartContainer.apply_async((IP, port, containerId))
Operation.objects.create(Opuser=username,Opaction=u'启动容器%s' %containerId[0:12])
msg={'celeryId': a.id}
return HttpResponse(json.dumps(msg))
@login_required()
def DockerLogOutput(request,containerid):
usersession=request.session.get('user_id')
if request.method == 'GET':
IP=DockerContainer.objects.get(containerID=containerid).hostip
port = DockerHost.objects.get(hostip=IP).port
try:
dockerserver = Dockerapi(IP,port)
data=dockerserver.LogContainer(containerid,tail=30)
data=data.split('\n')
except docker.errors.NotFound:
return HttpResponse('没有该容器')
ret = {'usersession': usersession,'dockerlogsdata':data,'containerid':containerid}
return render(request,'dockermanager/dockerhosts_logs.html',ret)
else:
IP=DockerContainer.objects.get(containerID=containerid).hostip
port = DockerHost.objects.get(hostip=IP).port
try:
dockerserver = Dockerapi(IP,port)
data=dockerserver.LogContainer(containerid,tail=30)
data=data.split('\n')
except docker.errors.NotFound:
return HttpResponse('没有该容器')
ret={'dockerlogsdata':data}
return HttpResponse(json.dumps(ret))
@login_required()
def StartCeleryStatus(request,celeryid):
if request.method == 'GET':
task=StartContainer.AsyncResult(str(celeryid))
if task.state == 'PENDING':
response = {
'state': task.state,
'status': 'Pending...'
}
elif task.state != 'FAILURE':
response = {
'state': task.state,
'status': task.status,
}
if 'result' in task.info:
response['result'] = task.info['result']
else:
response = {
'state': task.state,
'current': 1,
'total': 1,
'status': str(task.info), # this is the exception raised
}
return HttpResponse(json.dumps(response))
@login_required()
def StopCeleryStatus(request,celeryid):
if request.method == 'GET':
task=StopContainer.AsyncResult(str(celeryid))
if task.state == 'PENDING':
response = {
'state': task.state,
'status': 'Pending...'
}
elif task.state != 'FAILURE':
response = {
'state': task.state,
'status': task.status,
}
if 'result' in task.info:
response['result'] = task.info['result']
else:
response = {
'state': task.state,
'current': 1,
'total': 1,
'status': str(task.info), # this is the exception raised
}
return HttpResponse(json.dumps(response))
@login_required()
def RestartCeleryStatus(request,celeryid):
if request.method == 'GET':
task=RestartContainer.AsyncResult(str(celeryid))
if task.state == 'PENDING':
response = {
'state': task.state,
'status': 'Pending...'
}
elif task.state != 'FAILURE':
response = {
'state': task.state,
'status': task.status,
}
if 'result' in task.info:
response['result'] = task.info['result']
else:
response = {
'state': task.state,
'status': str(task.info), # this is the exception raised
}
return HttpResponse(json.dumps(response))
@login_required()
def DeleteCeleryStatus(request,celeryid):
if request.method == 'GET':
task=DeleteContainer.AsyncResult(str(celeryid))
containerID=request.GET['containerid']
if task.state == 'PENDING':
response = {
'state': task.state,
'status': 'Pending...'
}
elif task.state != 'FAILURE':
DockerContainer.objects.filter(containerID=containerID).delete()
response = {
'state': task.state,
'status': task.status,
}
if 'result' in task.info:
response['result'] = task.info['result']
else:
response = {
'state': task.state,
'status': str(task.info), # this is the exception raised
}
return HttpResponse(json.dumps(response))
@login_required()
def webSocket(request,containerId):
usersession = request.session.get('user_id')
IP = DockerContainer.objects.get(containerID=containerId).hostip
PORT = DockerHost.objects.get(hostip=IP).port
containerId = containerId
return render(request,'dockermanager/websocket.html',locals())
@accept_websocket
def getsocket(request,containerId):
if request.is_websocket:
request.websocket.send('Welcome to Simpletour DevOps!!')
IP = DockerContainer.objects.get(containerID=containerId).hostip
PORT = DockerHost.objects.get(hostip=IP).port
docker_api = Dockerapi(IP, PORT)
try:
container = docker_api.dockerConnect.exec_create(container=containerId, cmd="/bin/bash", user='root',
tty=True,stdout=True,stderr=True,stdin=True,)
a = docker_api.dockerConnect.exec_start(container['Id'], stream=True, tty=True, detach=False,socket=True)
docker_api.dockerConnect.exec_resize(container['Id'], height=40, width=80)
for message in request.websocket:
if not message:
break
a.send(message.encode('utf-8'))
request.websocket.send(a.recv(65535))
except:
request.websocket.send('主机无法连接!!')
================================================
FILE: domainmanager/urls.py
================================================
from django.conf.urls import url
from domainmanager.views import (SimpletourDomainLists,SimpletourGetdomainApi,Simpletourrecord,SimpletourGetRecords)
urlpatterns = [
url(r'list/$', SimpletourDomainLists, name='SimpletourDomainLists'),
url(r'dnspodapi/$',SimpletourGetdomainApi,name='SimpletourGetdomainApi'),
url(r'records/$',SimpletourGetRecords,name='SimpletourGetRecords'),
url(r'record/search/(?P<id>\d+)$',Simpletourrecord,name='Simpletourrecord'),
]
================================================
FILE: manage.py
================================================
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "SimpletourDevops.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
================================================
FILE: requirements.txt
================================================
django==1.9.9
django-import-export==0.5.1
itsdangerous==0.24
celery
https://github.com/darklow/django-suit/tarball/v2
MySQL-python
docker-py
supervisor
uwsgi
redis
dwebsocket
eventlet==0.19.0
pyyaml
================================================
FILE: run_eventlet.py
================================================
from eventlet import wsgi, patcher
patcher.monkey_patch()
import sys
import getopt
import eventlet
from SimpletourDevops.wsgi import application
addr, port = '127.0.0.1', 8099
opts, _ = getopt.getopt(sys.argv[1:], "b:")
for opt, value in opts:
if opt == '-b':
addr, port = value.split(":")
wsgi.server(eventlet.listen((addr, int(port))), application)
================================================
FILE: saltadmin/Minions_Controller.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "SimpletourDevops.settings")
import django
django.setup()
import datetime
from saltadmin.models import *
from Publicapi.saltstackapi.SaltConApi import SaltApi
import threading
import json
def GetALLkeys():
saltmaster = SaltServer.objects.all()
for server in saltmaster:
salt=SaltApi(server.url,server.username,server.password)
minions,minions_pre,minions_rej,minions_deny =salt.List_all_keys()
for i in minions:
try:
Minions.objects.create(minion=i, saltserver=server, status="Accepted")
except:
minion = Minions.objects.get(minion=i)
minion.status = 'Accepted'
minion.save()
for pre in minions_pre:
try:
Minions.objects.create(minion=pre, saltserver=server, status="Unaccepted")
except:
minion = Minions.objects.get(minion=pre)
minion.status = 'Unaccepted'
minion.save()
for rej in minions_rej:
try:
Minions.objects.create(minion=rej, saltserver=server, status="Rejected")
except:
minion = Minions.objects.get(minion=rej)
minion.status = 'Rejected'
minion.save()
for deny in minions_deny:
try:
Minions.objects.create(minion=deny, saltserver=server, status="Denied")
except:
minion = Minions.objects.get(minion=deny)
minion.status = 'Denied'
minion.save()
def UpdateMinionInfo(mininboj,minions,url,username,password):
salt = SaltApi(url, username, password)
alive_minions = salt.Saltalive(minions)
print alive_minions
if minions in alive_minions:
minion_status = True
else:
minion_status = False
try:
MinionStatus.objects.create(minion=mininboj, minion_status=minion_status)
except:
saltminion = MinionStatus.objects.get(minion=mininboj)
alive_old = MinionStatus.objects.get(minion=mininboj).minion_status
if minion_status != alive_old:
saltminion.alive_time_last = datetime.datetime.now()
saltminion.minion_status = minion_status
print "-------------------------------%s" %(minion_status,)
saltminion.alive_time_now = datetime.datetime.now()
saltminion.save()
def GetMinionConf():
GetALLkeys()
MinionsData=Minions.objects.filter(status='Accepted')
for minion in MinionsData:
t=threading.Thread(target=UpdateMinionInfo,args=(minion,
minion.minion,
minion.saltserver.url,
minion.saltserver.username,
minion.saltserver.password))
t.start()
return "GET minion conf is Ok!!"
def GetJobs(url,username,password):
salt = SaltApi(url,username,password)
data = salt.runner("jobs.list_jobs")
for j,info in data.items():
if SaltJobs.objects.filter(jid=j):
pass
else:
SaltJobs.objects.create(jid=j,args=info['Arguments'],function=info['Function'],
startTime=info['StartTime'],target=info['Target'],user=info['User'],saltserver=url)
def GetSaltJobs():
SaltMaster_data = SaltServer.objects.all()
for salt in SaltMaster_data:
t = threading.Thread(target=GetJobs,args=(salt.url,salt.username,salt.password))
t.start()
def JobResultFromat(data):
result=[]
for resultkey,resultdata in data.items():
list = []
errors_count = []
for task,taskresult in resultdata.items():
taskLinedict ={}
taskLinedict['ID'] = task.split('|')[1].strip('_').lstrip('-')
taskLinedict['Name'] = task.split('|')[2].strip('_').lstrip('-')
if taskresult['result'] == False:
errors_count.append(taskresult)
taskLinedict['Result'] =taskresult['result']
taskLinedict['Comment'] = taskresult['comment']
if not taskresult.has_key('start_time'):
taskresult['Started'] = ''
else:
taskresult['Started'] = taskresult['start_time']
if not taskresult.has_key('duration'):
taskresult['Duration'] = ''
else:
taskresult['Duration'] = taskresult['duration']
taskLinedict['Changes'] = taskresult['changes']
list.append(taskLinedict)
result_dict_list = {'url':resultkey,'result': list,'error':len(errors_count),'success':len(list) - len(errors_count)}
result.append(result_dict_list)
# for formatkey,formatresult in result.items():
# print formatkey
# for line in formatresult:
# print "---------------------------------"
# for k,v in line.items():
# if isinstance(v,dict):
# if len(v) == 0:
# v = None
# print k+":",v
#
# #result[k] = v
return result
if __name__ == '__main__':
#GetMinionConf()
#GetSaltJobs()
#a={u'192.168.2.148': {u'user_|-zabbix-user-group_|-zabbix_|-present': {u'comment': u'User zabbix set to be added', u'name': u'zabbix', u'start_time': u'10:41:43.381761', u'result': None, u'duration': 16.003, u'__run_num__': 1, u'changes': {}, u'__id__': u'zabbix-user-group'}, u'file_|-start-file_|-/etc/rc.local_|-append': {u'comment': u'File /etc/rc.local is set to be updated', u'pchanges': {}, u'name': u'/etc/rc.local', u'start_time': u'10:41:43.439903', u'result': None, u'duration': 1.483, u'__run_num__': 7, u'changes': {u'diff': u'--- \n\n+++ \n\n@@ -13,3 +13,4 @@\n\n touch /var/lock/subsys/local\n mount /home/data /data --bind\n mount /data/docker /var/lib/docker --bind\n+/etc/init.d/zabbix_agentd start'}, u'__id__': u'start-file'}, u'file_|-zabbix-client-transport_|-/usr/local/src/zabbix-3.0.5-client.tar.gz_|-managed': {u'comment': u'The file /usr/local/src/zabbix-3.0.5-client.tar.gz is set to be changed', u'pchanges': {u'newfile': u'/usr/local/src/zabbix-3.0.5-client.tar.gz'}, u'name': u'/usr/local/src/zabbix-3.0.5-client.tar.gz', u'start_time': u'10:41:43.399380', u'result': None, u'duration': 9.981, u'__run_num__': 2, u'changes': {}, u'__id__': u'zabbix-client-transport'}, u'cmd_|-zabbix-start-sh_|-/etc/init.d/zabbix_agentd start_|-run': {u'comment': u'Command "/etc/init.d/zabbix_agentd start" would have been executed', u'name': u'/etc/init.d/zabbix_agentd start', u'start_time': u'10:41:43.439464', u'result': None, u'duration': 0.355, u'__run_num__': 6, u'changes': {}, u'__id__': u'zabbix-start-sh'}, u'group_|-zabbix-user-group_|-zabbix_|-present': {u'comment': u'Group zabbix set to be added', u'name': u'zabbix', u'start_time': u'10:41:43.380688', u'result': None, u'duration': 0.683, u'__run_num__': 0, u'changes': {}, u'__id__': u'zabbix-user-group'}, u'file_|-zabbix-file-copy_|-/usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf_|-managed': {u'comment': u'The file /usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf is set to be changed', u'pchanges': {u'newfile': u'/usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf'}, u'name': u'/usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf', u'start_time': u'10:41:43.410485', u'result': None, u'duration': 24.638, u'__run_num__': 4, u'changes': {}, u'__id__': u'zabbix-file-copy'}, u'cmd_|-zabbix-client-transport_|-cd /usr/local/src/ && tar -zxf zabbix-3.0.5-client.tar.gz -C /usr/local/_|-run': {u'comment': u'Command "cd /usr/local/src/ && tar -zxf zabbix-3.0.5-client.tar.gz -C /usr/local/" would have been executed', u'name': u'cd /usr/local/src/ && tar -zxf zabbix-3.0.5-client.tar.gz -C /usr/local/', u'start_time': u'10:41:43.410143', u'result': None, u'duration': 0.276, u'__run_num__': 3, u'changes': {}, u'__id__': u'zabbix-client-transport'}, u'file_|-zabbix-start-sh_|-/etc/init.d/zabbix_agentd_|-managed': {u'comment': u'The file /etc/init.d/zabbix_agentd is set to be changed', u'pchanges': {u'newfile': u'/etc/init.d/zabbix_agentd'}, u'name': u'/etc/init.d/zabbix_agentd', u'start_time': u'10:41:43.435245', u'result': None, u'duration': 3.886, u'__run_num__': 5, u'changes': {}, u'__id__': u'zabbix-start-sh'}}, u'192.168.2.147': {u'user_|-zabbix-user-group_|-zabbix_|-present': {u'comment': u'User zabbix set to be added', u'name': u'zabbix', u'start_time': u'10:41:43.649409', u'result': None, u'duration': 16.626, u'__run_num__': 1, u'changes': {}, u'__id__': u'zabbix-user-group'}, u'file_|-start-file_|-/etc/rc.local_|-append': {u'comment': u'File /etc/rc.local is set to be updated', u'pchanges': {}, u'name': u'/etc/rc.local', u'start_time': u'10:41:43.759598', u'result': None, u'duration': 2.015, u'__run_num__': 7, u'changes': {u'diff': u'--- \n\n+++ \n\n@@ -13,3 +13,4 @@\n\n touch /var/lock/subsys/local\n mount /home/data /data --bind\n mount /data/docker /var/lib/docker --bind\n+/etc/init.d/zabbix_agentd start'}, u'__id__': u'start-file'}, u'file_|-zabbix-client-transport_|-/usr/local/src/zabbix-3.0.5-client.tar.gz_|-managed': {u'comment': u'The file /usr/local/src/zabbix-3.0.5-client.tar.gz is set to be changed', u'pchanges': {u'newfile': u'/usr/local/src/zabbix-3.0.5-client.tar.gz'}, u'name': u'/usr/local/src/zabbix-3.0.5-client.tar.gz', u'start_time': u'10:41:43.667990', u'result': None, u'duration': 20.692, u'__run_num__': 2, u'changes': {}, u'__id__': u'zabbix-client-transport'}, u'cmd_|-zabbix-start-sh_|-/etc/init.d/zabbix_agentd start_|-run': {u'comment': u'Command "/etc/init.d/zabbix_agentd start" would have been executed', u'name': u'/etc/init.d/zabbix_agentd start', u'start_time': u'10:41:43.758629', u'result': None, u'duration': 0.728, u'__run_num__': 6, u'changes': {}, u'__id__': u'zabbix-start-sh'}, u'group_|-zabbix-user-group_|-zabbix_|-present': {u'comment': u'Group zabbix set to be added', u'name': u'zabbix', u'start_time': u'10:41:43.647126', u'result': None, u'duration': 1.619, u'__run_num__': 0, u'changes': {}, u'__id__': u'zabbix-user-group'}, u'file_|-zabbix-file-copy_|-/usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf_|-managed': {u'comment': u'The file /usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf is set to be changed', u'pchanges': {u'newfile': u'/usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf'}, u'name': u'/usr/local/zabbix-3.0.5/etc/zabbix_agentd.conf', u'start_time': u'10:41:43.690624', u'result': None, u'duration': 56.148, u'__run_num__': 4, u'changes': {}, u'__id__': u'zabbix-file-copy'}, u'cmd_|-zabbix-client-transport_|-cd /usr/local/src/ && tar -zxf zabbix-3.0.5-client.tar.gz -C /usr/local/_|-run': {u'comment': u'Command "cd /usr/local/src/ && tar -zxf zabbix-3.0.5-client.tar.gz -C /usr/local/" would have been executed', u'name': u'cd /usr/local/src/ && tar -zxf zabbix-3.0.5-client.tar.gz -C /usr/local/', u'start_time': u'10:41:43.689750', u'result': None, u'duration': 0.66, u'__run_num__': 3, u'changes': {}, u'__id__': u'zabbix-client-transport'}, u'file_|-zabbix-start-sh_|-/etc/init.d/zabbix_agentd_|-managed': {u'comment': u'The file /etc/init.d/zabbix_agentd is set to be changed', u'pchanges': {u'newfile': u'/etc/init.d/zabbix_agentd'}, u'name': u'/etc/init.d/zabbix_agentd', u'start_time': u'10:41:43.746988', u'result': None, u'duration': 11.198, u'__run_num__': 5, u'changes': {}, u'__id__': u'zabbix-start-sh'}}}
a={u'192.168.2.147': {u'file_|-nginx-config_|-/usr/local/nginx/conf/nginx.conf_|-managed': {u'comment': u'The file /usr/local/nginx/conf/nginx.conf is set to be changed', u'pchanges': {u'newfile': u'/usr/local/nginx/conf/nginx.conf'}, u'retcode': 2, u'start_time': u'12:00:11.704011', u'__id__': u'nginx-config', u'result': None, u'duration': 62.022, u'__run_num__': 6, u'changes': {}, u'name': u'/usr/local/nginx/conf/nginx.conf'}, u'file_|-/usr/local/nginx/conf/vhosts/_|-/usr/local/nginx/conf/vhosts/_|-directory': {u'comment': u'The following files will be changed:\n/usr/local/nginx/conf/vhosts: directory - new\n', u'pchanges': {u'/usr/local/nginx/conf/vhosts': {u'directory': u'new'}}, u'retcode': 2, u'start_time': u'12:00:11.766317', u'__id__': u'/usr/local/nginx/conf/vhosts/', u'result': None, u'duration': 0.813, u'__run_num__': 7, u'changes': {}, u'name': u'/usr/local/nginx/conf/vhosts/'}, u'file_|-nginx-install_|-/usr/local/src/nginx-1.2.0.tar.gz_|-managed': {u'comment': u'Source file salt://nginx/files/nginx-1.2.0.tar.gz not found', u'_stamp': u'2016-12-15T12:02:16.749601', u'pchanges': [False, u'Source file salt://nginx/files/nginx-1.2.0.tar.gz not found'], u'return': u'Error: file.managed', u'retcode': 2, u'success': False, u'start_time': u'12:00:11.690524', u'jid': u'20161215200215675300', u'duration': 12.813, u'result': False, u'__id__': u'nginx-install', u'fun': u'state.sls', u'__run_num__': 4, u'changes': {}, u'id': u'192.168.2.147', u'name': u'/usr/local/src/nginx-1.2.0.tar.gz'}, u'user_|-www-user-group_|-www_|-present': {u'comment': u'User www set to be added', u'retcode': 2, u'start_time': u'12:00:11.674525', u'__id__': u'www-user-group', u'result': None, u'duration': 15.774, u'__run_num__': 3, u'changes': {}, u'name': u'www'}, u'file_|-pcre-install_|-/usr/local/src/pcre-8.37.tar.gz_|-managed': {u'comment': u'The file /usr/local/src/pcre-8.37.tar.gz is set to be changed', u'pchanges': {u'newfile': u'/usr/local/src/pcre-8.37.tar.gz'}, u'retcode': 2, u'start_time': u'12:00:11.641509', u'__id__': u'pcre-install', u'result': None, u'duration': 22.872, u'__run_num__': 0, u'changes': {}, u'name': u'/usr/local/src/pcre-8.37.tar.gz'}, u'file_|-/usr/local/nginx/conf/vhosts/www.test.com.conf_|-/usr/local/nginx/conf/vhosts/www.test.com.conf_|-managed': {u'comment': u'The file /usr/local/nginx/conf/vhosts/www.test.com.conf is set to be changed', u'pchanges': {u'newfile': u'/usr/local/nginx/conf/vhosts/www.test.com.conf'}, u'retcode': 2, u'start_time': u'12:00:11.767427', u'__id__': u'/usr/local/nginx/conf/vhosts/www.test.com.conf', u'result': None, u'duration': 431.954, u'__run_num__': 8, u'changes': {}, u'name': u'/usr/local/nginx/conf/vhosts/www.test.com.conf'}, u'cmd_|-nginx-install_|-cd /usr/local/src/ && tar zxf nginx-1.8.0.tar.gz && cd nginx-1.8.0 && ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --with-file-aio --with-http_dav_module --with-pcre=/usr/local/src/pcre-8.37 && make && make install && chown -R www. /usr/local/nginx_|-run': {u'comment': u'One or more requisite failed: nginx.install.nginx-install', u'__run_num__': 5, u'__sls__': u'nginx.install', u'changes': {}, u'result': False}, u'file_|-nginx-service_|-/usr/lib/systemd/system/nginx.service_|-managed': {u'comment': u'The file /usr/lib/systemd/system/nginx.service is set to be changed', u'pchanges': {u'newfile': u'/usr/lib/systemd/system/nginx.service'}, u'retcode': 2, u'start_time': u'12:00:12.199726', u'__id__': u'nginx-service', u'result': None, u'duration': 13.078, u'__run_num__': 9, u'changes': {}, u'name': u'/usr/lib/systemd/system/nginx.service'}, u'file_|-log_logrotate_|-/etc/logrotate.d/logrotate_nginx_|-managed': {u'comment': u'The file /etc/logrotate.d/logrotate_nginx is set to be changed', u'pchanges': {u'newfile': u'/etc/logrotate.d/logrotate_nginx'}, u'retcode': 2, u'start_time': u'12:00:12.229231', u'__id__': u'log_logrotate', u'result': None, u'duration': 13.148, u'__run_num__': 11, u'changes': {}, u'name': u'/etc/logrotate.d/logrotate_nginx'}, u'cmd_|-pcre-install_|-cd /usr/local/src/ && tar zxf pcre-8.37.tar.gz && cd pcre-8.37 && ./configure --prefix=/usr/local/pcre && make && make install_|-run': {u'comment': u'Command "cd /usr/local/src/ && tar zxf pcre-8.37.tar.gz && cd pcre-8.37 && ./configure --prefix=/usr/local/pcre && make && make install" would have been executed', u'retcode': 2, u'start_time': u'12:00:11.665282', u'__id__': u'pcre-install', u'result': None, u'duration': 6.168, u'__run_num__': 1, u'changes': {}, u'name': u'cd /usr/local/src/ && tar zxf pcre-8.37.tar.gz && cd pcre-8.37 && ./configure --prefix=/usr/local/pcre && make && make install'}, u'cmd_|-nginx-service_|-chmod +x /usr/lib/systemd/system/nginx.service && systemctl enable nginx.service && systemctl start nginx.service_|-run': {u'comment': u'Command "chmod +x /usr/lib/systemd/system/nginx.service && systemctl enable nginx.service && systemctl start nginx.service" would have been executed', u'retcode': 2, u'start_time': u'12:00:12.213134', u'__id__': u'nginx-service', u'result': None, u'duration': 15.835, u'__run_num__': 10, u'changes': {}, u'name': u'chmod +x /usr/lib/systemd/system/nginx.service && systemctl enable nginx.service && systemctl start nginx.service'}, u'group_|-www-user-group_|-www_|-present': {u'comment': u'Group www set to be added', u'name': u'www', u'start_time': u'12:00:11.672088', u'result': None, u'duration': 1.803, u'__run_num__': 2, u'changes': {}, u'__id__': u'www-user-group'}}}
JobResultFromat(a)
================================================
FILE: saltadmin/__init__.py
================================================
================================================
FILE: saltadmin/admin.py
================================================
from django.contrib import admin
from saltadmin.models import *
class SaltJobsModels(admin.ModelAdmin):
list_display = ('jid','args','function','target','startTime','saltserver','user')
search_fields = ('function','jid')
class CmdRunLogModels(admin.ModelAdmin):
list_display = ('user','time','target','cmd','total','runsuccess','runerror')
search_fields = ('user','cmd')
class MinionGroupModels(admin.ModelAdmin):
list_display = ('groupname',)
filter_horizontal = ('minions', )
admin.site.register(SaltJobs,SaltJobsModels)
admin.site.register(CmdRunLog,CmdRunLogModels)
admin.site.register(MinionGroup,MinionGroupModels)
admin.site.register(Modules)
================================================
FILE: saltadmin/apps.py
================================================
from __future__ import unicode_literals
from django.apps import AppConfig
class SaltadminConfig(AppConfig):
name = 'saltadmin'
================================================
FILE: saltadmin/forms.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
from django import forms
from saltadmin.models import SaltServer,Minions
class KeyManager(forms.Form):
status = forms.ChoiceField(choices=Minions.Status,widget=forms.Select(attrs={'class':'form-control'}))
class CheckSaltServer(forms.ModelForm):
url=forms.URLField(required=True,error_messages={'required': u'请输入一个URL格式'},
widget=forms.TextInput(attrs={'class':'form-control','placeholder': 'http://127.0.0.1',}))
username = forms.CharField(required=True,error_messages={'required':u'请输入API用户名'},
widget=forms.TextInput(attrs={'class':'form-control','placeholder': 'username',}))
password = forms.CharField(required=True, error_messages={'required': u'请输入API验证密码'},
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'password', }))
# def clean(self):
# cleaned_data = sum(CheckSaltServer,self).clean()
# value = cleaned_data.get('url')
# try:
# SaltServer.objects.get(url=value)
# self._errors['url'] = self.error_class(["%s url 信息已存在" % value])
# except SaltServer.DoesNotExist:
# pass
# return cleaned_data
class Meta:
model = SaltServer
exclude= ('id',)
widgets = {
'role': forms.Select(attrs={'class': 'form-control'}),
}
================================================
FILE: saltadmin/migrations/__init__.py
================================================
================================================
FILE: saltadmin/models.py
================================================
#coding:utf8
from __future__ import unicode_literals
from django.db import models
class SaltServer(models.Model):
Role = (
('Master', 'Master'),
('Backend', 'Backend'),
)
url = models.URLField(max_length=100,verbose_name=u'URL地址')
username = models.CharField(max_length=50, verbose_name=u'用户名')
password = models.CharField(max_length=50,verbose_name=u'密码')
role = models.CharField(choices=Role,max_length=20,default='Master',verbose_name=u'角色')
def __unicode__(self):
return u"%s - %s" %(self.url,self.role)
class Meta:
verbose_name = u'Salt服务器'
verbose_name_plural = u'Salt服务器列表'
permissions = (
("salt_index_view", "Can view %s" % verbose_name),
)
class Modules(models.Model):
name = models.CharField(max_length=20,verbose_name=u'Salt模块名称')
models_site = models.CharField(max_length=50,null=True,blank=True,verbose_name=u'Salt模块参数')
def __unicode__(self):
return self.name
class Meta:
verbose_name = u'Salt软件'
verbose_name_plural = u'Salt软件'
'''
class Command(models.Model):
cmd = models.CharField(max_length=100,verbose_name=u'Salt命令')
doc = models.TextField(max_length=2000,blank=True,verbose_name=u'帮助文档')
module = models.ForeignKey(Module,verbose_name=u'所属模块')
def __unicode__(self):
return u"%s - %s"%(self.module,self.cmd)
class Meta:
verbose_name = u'Salt命令'
verbose_name_plural = u'Salt命令列表'
unique_together = ("module", "cmd")
'''
class Minions(models.Model):
Status = (
('Accepted', 'Accepted'),
('Unaccepted', 'Unaccepted'),
('Rejected', 'Rejected'),
)
minion = models.CharField(max_length=50,verbose_name=u'客户端',unique=True)
saltserver = models.ForeignKey(SaltServer,verbose_name=u'所属Salt服务器')
status = models.CharField(choices=Status,max_length=20,default='Unknown',verbose_name=u'Key状态')
create_date=models.DateTimeField(auto_now_add=True,verbose_name=u'创建时间')
def __unicode__(self):
return self.minion
class Meta:
verbose_name = u'Salt客户端'
verbose_name_plural = u'Salt客户端列表'
class MinionStatus(models.Model):
minion = models.OneToOneField(Minions)
minion_status = models.CharField(max_length=20,verbose_name=u'在线状态')
# 上次检测时间
alive_time_last = models.DateTimeField(auto_now=True,null=True)
# 当前检测时间
alive_time_now = models.DateTimeField(auto_now=True,null=True)
class MinionGroup(models.Model):
groupname = models.CharField(u'Minion组',max_length=50,default='default')
minions = models.ManyToManyField(Minions,verbose_name=u'Minions',blank=True)
def __unicode__(self):
return self.groupname
class Meta:
verbose_name = u'Minion组'
verbose_name_plural = u'Minion组'
class CmdRunLog(models.Model):
user=models.CharField(max_length=30)
time=models.DateTimeField(auto_now_add=True,null=True)
target=models.CharField(max_length=500)
cmd=models.CharField(max_length=500)
total=models.IntegerField()
runsuccess = models.IntegerField(default=0)
runerror = models.IntegerField(default=0)
runresult = models.TextField(max_length=65535,null=True,blank=True)
class Meta:
verbose_name = u'命令执行日志'
verbose_name_plural = u'命令执行日志'
class SaltJobs(models.Model):
jid = models.CharField(max_length=50,unique=True)
args = models.CharField(max_length=50,null=True,blank=True)
function = models.CharField(max_length=50)
startTime = models.CharField(max_length=100)
target = models.CharField(max_length=500)
user = models.CharField(max_length=50)
saltserver = models.CharField(max_length=100,null=True,blank=True)
class Meta:
verbose_name = u'Jobs列表'
verbose_name_plural = u'Jobs列表'
class ModuleDeployLog(models.Model):
user=models.CharField(max_length=50)
time=models.DateTimeField()
target=models.CharField(max_length=100)
application=models.CharField(max_length=100)
#成功的主机
success_hosts=models.CharField(max_length=500)
#失败的主机
failed_hosts=models.CharField(max_length=500)
#执行总共结果
total=models.IntegerField()
#执行过程
log=models.TextField()
#持续时间
duration=models.CharField(max_length=500)
class Meta:
verbose_name = u'软件部署'
verbose_name_plural = u'软件部署'
================================================
FILE: saltadmin/tests.py
================================================
from django.test import TestCase
# Create your tests here.
================================================
FILE: saltadmin/urls.py
================================================
from django.conf.urls import url
from saltadmin.views import (KeyList,Minion_Status,SoftInstall,JobList,RemoteCmd,SaltMasterList,
SaltMinionGrains,CmdResult,jobdetail,DeployResult,SaltMasterDelete,
SalMasterChange
)
urlpatterns = [
url(r'keylist/', KeyList, name='KeyList'),
url(r'minion/status/',Minion_Status,name='Minion_Status'),
url(r'minion/softinstall/',SoftInstall,name='SoftInstall'),
url(r'job/list/(?P<page>\d+)',JobList,name='JobList'),
url(r'cmd/$',RemoteCmd,name='RemoteCmd'),
url(r'master/$',SaltMasterList,name='SaltMasterList'),
url(r'master/delete/(?P<masterid>\d+)$',SaltMasterDelete,name='SaltMasterDelete'),
url(r'master/change/(?P<masterid>\d+)$',SalMasterChange,name='SalMasterChange'),
url(r'grains/$',SaltMinionGrains,name='SaltMinionGrains'),
url(r'cmdresult/(?P<jid>\d+)$',CmdResult,name='CmdResult'),
url(r'deployresult/(?P<jid>\d+)$',DeployResult,name='DeployResult'),
url(r'job/detail/$',jobdetail,name='jobdetail'),
]
================================================
FILE: saltadmin/utils.py
================================================
#!/usr/bin/env python
#coding:utf-8
__author__ = 'Luodi'
import commands
import os
def get_system_info():
cmd_get_cpu_sockect=r"lscpu|grep Socket|awk '{print $NF}'"
cmd_get_cpu_cores=r"cat /proc/cpuinfo|grep processor|wc -l"
cmd_get_mem_total=r"free -m |head -n 2|tail -n 1|awk '{print $2}'"
cmd_get_mem_used=r"free -m |tail -n 2|head -n 1|awk '{print $3}'"
cmd_get_users_num=r"w -h |wc -l"
cmd_get_uptime=r"uptime |awk -F',' '{print $1}'"
cpu_sockets=commands.getoutput(cmd_get_cpu_sockect)
res=os.system('lscpu &>/dev/null')
if res != 0:
cpu_sockets=1 #如果没有lscpu命令,默认的CPU个数为1个
cpu_cores=commands.getoutput(cmd_get_cpu_cores)
mem_total=commands.getoutput(cmd_get_mem_total)
mem_used=commands.getoutput(cmd_get_mem_used)
users=commands.getoutput(cmd_get_users_num)
uptime=commands.getoutput(cmd_get_uptime)
mem_percentage=round(float(mem_used)/float(mem_total)*100,2)
mem_left_percentage=100-mem_percentage
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}
return info_dict
================================================
FILE: saltadmin/views.py
================================================
#coding:utf8
from django.shortcuts import render
from django.http import HttpResponse,HttpResponseRedirect
from django.core import serializers
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required
from saltadmin.models import *
from Publicapi.saltstackapi.SaltConApi import SaltApi
import json
from django.db.models import Q
from saltadmin.forms import CheckSaltServer,KeyManager
from webapp.Extends import PageList
import yaml
from saltadmin.Minions_Controller import JobResultFromat
from webapp.models import Operation
@login_required()
def SaltMasterList(request):
usersession = request.session.get('user_id')
form = CheckSaltServer()
if request.method == 'POST':
form = CheckSaltServer(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/salt/master/')
else:
form = form
SaltMasterData = SaltServer.objects.all()
Role=SaltServer.Role
return render(request, 'saltadmin/saltmaster_list.html', locals())
@login_required()
def SaltMasterDelete(request,masterid):
user_name = request.session.get('user_name')
if request.method == 'GET':
SaltServer.objects.get(id=masterid).delete()
Operation.objects.create(Opuser=user_name, Opaction=u'删除salt主机')
msg = {'msginfo': u'Salt主机及所有管理信息已经删除成功!!'}
return HttpResponse(json.dumps(msg))
@login_required()
def SalMasterChange(request,masterid):
user_name = request.session.get('user_name')
if request.method == 'POST':
url = request.POST.get('url')
username = request.POST.get('username')
password = request.POST.get('password')
role = request.POST.get('role')
Changeserver = SaltServer.objects.get(id=masterid)
Changeserver.url = url
Changeserver.username = username
Changeserver.password = password
Changeserver.role = role
Changeserver.save()
Operation.objects.create(Opuser=user_name, Opaction=u'修改salt主机信息')
msg = {'msginfo': u'Master修改成功!!!!',}
return HttpResponse(json.dumps(msg))
else:
Changeserver = SaltServer.objects.get(id=masterid)
data = {'url': Changeserver.url,'username':Changeserver.username,'password':Changeserver.password,'role':Changeserver.role }
return HttpResponse(json.dumps(data))
@login_required()
def KeyList(request):
usersession = request.session.get('user_id')
user_name = request.session.get('user_name')
if request.method == 'GET':
Accepted = Minions.objects.filter(status='Accepted')
Unaccepted = Minions.objects.filter(status='Unaccepted')
Rejected = Minions.objects.filter(status='Rejected')
froms=KeyManager()
return render(request,'saltadmin/key_list.html',locals())
if request.method == 'POST':
minion = request.POST.get('minion')
status = request.POST.get('status')
Minion_data=Minions.objects.get(minion=minion)
Minion_data.status = status
Minion_data.save()
Operation.objects.create(Opuser=user_name, Opaction=u'修改 minion Key状态 %s to %s' %(Minion_data.minion,status))
url = Minion_data.saltserver.url
username = Minion_data.saltserver.username
password = Minion_data.saltserver.password
salt = SaltApi(url, username, password)
if status == 'Accepted':
ret = salt.AcceptKey(minion)
elif status == 'Unaccepted':
ret = salt.DeleteKey(minion)
elif status == 'Rejected':
ret = salt.RejectKey(minion)
return HttpResponse('OK')
@login_required()
def Minion_Status(request):
usersession = request.session.get('user_id')
if request.method == 'GET':
SaltMinionData = MinionStatus.objects.filter(minion__status='Accepted')
return render(request,'saltadmin/minion_status.html',locals())
@login_required()
def SoftInstall(request):
usersession = request.session.get('user_id')
user_name = request.session.get('user_name')
if request.method == 'GET':
SoftModuleData = Modules.objects.all()
GroupData = MinionGroup.objects.all()
# hosts = """[ {type: 1, list: [{ text: 'yang', id: 1}, {text: 'asdasd',id: 4}]}, }]"""
groupall = []
for g in GroupData:
group = {}
list = []
for m in g.minions.all():
dir = {}
dir['text'] = m.minion
dir['id'] = m.minion
list.append(dir)
group['type'] = g.id
group['list'] = list
groupall.append(group)
groupall = json.dumps(groupall)
return render(request,'saltadmin/saltmodule_deploy.html',locals())
else:
if not request.POST.get('minion'):
minions_id = request.POST.get('minion_group')
minions_data=MinionGroup.objects.get(id=minions_id).minions.all()
else:
minions_data = request.POST.getlist('minion')
minions_list = ''
for m in minions_data:
minions_list += str(m) + ','
minions_list = minions_list.strip(',')
software = request.POST.getlist('software')
salt_env = request.POST.get('env')
soft=''
for i in software:
soft += i + ','
soft=soft.strip(',')
saltm = Minions.objects.get(minion=minions_list.split(',')[0])
url = saltm.saltserver.url
username = saltm.saltserver.username
password = saltm.saltserver.password
salt = SaltApi(url, username, password)
jid = salt.Softwarete_deploy(minions_list,arg=["saltenv=%s" %(salt_env), str(soft), 'test=True'])
Operation.objects.create(Opuser=user_name, Opaction=u'部署软件 %s' %soft)
#savelog = CmdRunLog.objects.create(user=user_name, target=minions_list, cmd=cmd, total=len(minions_list.split(',')))
ret={'jid':jid,'minion':minions_list,'savelogid':1}
return HttpResponse(json.dumps(ret))
@login_required()
def JobList(request,page):
usersession = request.session.get('user_id')
if request.method == 'GET':
# 分页代码
(page, start, end, per_item) = PageList.PageCount(page)
count = SaltJobs.objects.filter(~Q(function='test.ping')).count()
result = SaltJobs.objects.filter(~Q(function='test.ping')).order_by('-jid')[start:end]
url = "/salt/job/list"
if count % per_item == 0:
all_pages_count = count / per_item
else:
all_pages_count = count / per_item + 1
page = PageList.Page(page, url, all_pages_count)
ret = {'SaltMaster_data': result,
'count': count,
'page': page,
'usersession': usersession}
return render(request,'saltadmin/saltjob_list.html',ret)
@login_required()
def jobdetail(request):
if request.method == 'GET':
jid = request.GET.get('jid')
print jid
jiddata = SaltJobs.objects.get(jid=jid)
masterdata = SaltServer.objects.get(url=jiddata.saltserver)
url = masterdata.url
username =masterdata.username
password = masterdata.password
salt = SaltApi(url, username, password)
resultdata = salt.salt_runner(jid)
return HttpResponse(json.dumps(resultdata))
@login_required()
def RemoteCmd(request):
usersession = request.session.get('user_id')
user_name = request.session.get('user_name')
if request.method == 'GET':
GroupData = MinionGroup.objects.all()
#hosts = """[ {type: 1, list: [{ text: 'yang', id: 1}, {text: 'asdasd',id: 4}]}, }]"""
groupall=[]
for g in GroupData:
group={}
list = []
for m in g.minions.all():
dir = {}
dir['text'] = m.minion
dir['id'] = m.minion
list.append(dir)
group['type'] = g.id
group['list'] = list
groupall.append(group)
groupall=json.dumps(groupall)
return render(request,'saltadmin/salt_cmd.html',locals())
else:
if not request.POST.get('minion'):
minions_id = request.POST.get('minion_group')
minions_data=MinionGroup.objects.get(id=minions_id).minions.all()
else:
minions_data = request.POST.getlist('minion')
minions_list = ''
for m in minions_data:
minions_list += str(m) + ','
minions_list = minions_list.strip(',')
cmd =request.POST.get('cmd')
#必须是同一台master上的才能为一个组,这样只需要查询一个就可
saltm = Minions.objects.get(minion=minions_list.split(',')[0])
url = saltm.saltserver.url
username = saltm.saltserver.username
password = saltm.saltserver.password
salt = SaltApi(url, username, password)
jid = salt.shell_remote_execution(minions_list, cmd)
Operation.objects.create(Opuser=user_name, Opaction=u'执行命令 %s' %cmd)
savelog = CmdRunLog.objects.create(user=user_name, target=minions_list, cmd=cmd, total=len(minions_list.split(',')))
ret={'jid':jid,'minion':minions_list,'savelogid':savelog.id}
return HttpResponse(json.dumps(ret))
@login_required()
def CmdResult(request,jid):
if request.method == 'GET':
minions_list = request.GET.get('minion')
savelogid = request.GET.get('savelogid')
saltm = Minions.objects.get(minion=minions_list.split(',')[0])
url = saltm.saltserver.url
username = saltm.saltserver.username
password = saltm.saltserver.password
salt = SaltApi(url,username,password)
resultdata = salt.salt_runner(jid)
print savelogid
logs = CmdRunLog.objects.get(id=savelogid)
logs.runresult=resultdata
logs.runsuccess=len(resultdata)
logs.save()
ret={'minion':minions_list,'resultdata':resultdata}
return HttpResponse(json.dumps(ret))
@login_required()
def DeployResult(request,jid):
if request.method == 'GET':
minions_list = request.GET.get('minion')
savelogid = request.GET.get('savelogid')
saltm = Minions.objects.get(minion=minions_list.split(',')[0])
url = saltm.saltserver.url
username = saltm.saltserver.username
password = saltm.saltserver.password
salt = SaltApi(url,username,password)
resultdata = salt.salt_runner(jid)
resultdata=JobResultFromat(resultdata)
#print savelogid
#logs = CmdRunLog.objects.get(id=savelogid)
#logs.runresult=resultdata
#logs.runsuccess=len(resultdata)
#logs.save()
#print yaml.load_all(resultdata)
ret={'minion':minions_list,'resultdata':resultdata}
return HttpResponse(json.dumps(ret))
@login_required()
def SaltMinionGrains(request):
id = request.GET.get('minion')
action = request.GET.get('action')
Minion_data=MinionStatus.objects.get(id=id)
url = Minion_data.minion.saltserver.url
username = Minion_data.minion.saltserver.username
password = Minion_data.minion.saltserver.password
salt = SaltApi(url,username,password)
if str(action) == 'grains':
Data = salt.grainsall(str(Minion_data.minion))
elif str(action) == 'pillar':
Data = salt.pillarall(str(Minion_data.minion))
else:
Data={"msg": '无法查询'}
return HttpResponse(json.dumps(Data))
================================================
FILE: servermanager/__init__.py
================================================
================================================
FILE: servermanager/admin.py
================================================
#coding:utf8
from django.contrib import admin
from django.forms import ModelForm,TextInput,Textarea
from django.contrib.admin import ModelAdmin
#from suit.widgets import SuitDateWidget, SuitTimeWidget, SuitSplitDateTimeWidget
from servermanager.models import *
from import_export import resources
from django.forms import ModelForm
#导入和导出
from import_export.admin import ImportExportModelAdmin
#定义导出的内容
class ServerResource(resources.ModelResource):
class Meta:
model = Server
class AssetsResource(resources.ModelResource):
class Meta:
model = Assets
'''
class AssetsTimeForm(ModelForm):
class Meta:
widgets = {
'euse_time': SuitDateWidget,
'suse_time': SuitDateWidget,
}'''
# Register your models here.
class AssetsAdmin(ImportExportModelAdmin):
resource_class = AssetsResource
#form = AssetsTimeForm
list_display = ('id','host_name','device_type','device_number','IDC','status','business','buy_time','buy_type','price','admin')
list_filter = ('IDC','business','status','device_type')
search_fields = ['hostname','id']
fieldsets = (
('基本信息', {'fields': ('host_name', 'device_type', 'device_number','business','buy_type', 'IDC','status', 'admin','provider',)}),
('其它信息', {'fields': ('Warranty','buy_time', 'suse_time', 'euse_time','price','description')}),
)
class CpuModels(admin.ModelAdmin):
list_display = ('id','uuid','cpu_mhz','model','Architecture')
list_display_links = ('uuid',)
list_editable = ('cpu_mhz',)
class DiskModels(admin.ModelAdmin):
search_fields = ['parent_sn']
list_display = ('id','uuid', 'capacity','disk_type','Firm')
class NicModels(admin.ModelAdmin):
search_fields = ('ip',)
list_display = ('id','uuid','name','ip','model')
list_display_links = ('uuid',)
class SoftwareModels(admin.ModelAdmin):
list_display = ('id','name','version')
class DeviceTypeModels(admin.ModelAdmin):
search_fields = ('name',)
list_display = ('id','name',)
class BusinessModels(admin.ModelAdmin):
list_display = ('id','name',)
search_fields = ('name',)
list_editable = ('name',)
class ProviderModels(admin.ModelAdmin):
list_display = ('id','provider_name', 'address', 'contacts', 'phone')
class ServerModels(admin.ModelAdmin):
list_display = ('id','Assets','Firm','cpu','hostname','saltid','mem','swap','system','version','platform')
list_display_links = ('Assets',)
def get_idc(self, obj):
return obj.Assets.IDC
get_idc.short_description = '资产'
filter_horizontal = ('disk','nic','software')
class IdcModels(admin.ModelAdmin):
search_fields = ('idc_name',)
list_display = ('idc_name','address','floor','contacts','phone')
admin.site.register(Assets,AssetsAdmin)
admin.site.register(Server,ServerModels)
admin.site.register(DeviceType,DeviceTypeModels)
admin.site.register(Business,BusinessModels)
admin.site.register(Cpu,CpuModels)
admin.site.register(Disk,DiskModels)
admin.site.register(IDC,IdcModels)
admin.site.register(Software,SoftwareModels)
admin.site.register(NIC,NicModels)
admin.site.register(Provider,ProviderModels)
================================================
FILE: servermanager/apps.py
================================================
from __future__ import unicode_literals
from django.apps import AppConfig
class ServermanagerConfig(AppConfig):
name = 'servermanager'
================================================
FILE: servermanager/migrations/0001_initial.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-21 17:40
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Assets',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('host_name', models.CharField(max_length=128, null=True, unique=True, verbose_name='\u8bbe\u5907\u540d')),
('device_number', models.CharField(max_length=128, unique=True, verbose_name='\u8bbe\u5907\u7f16\u53f7')),
('Warranty', models.SmallIntegerField(verbose_name='\u4fdd\u4fee\u671f')),
('buy_time', models.CharField(blank=True, max_length=128, verbose_name='\u8d2d\u4e70\u65e5\u671f')),
('buy_type', models.SmallIntegerField(blank=True, choices=[(1, '\u516c\u53f8\u5185\u8d2d'), (2, '\u5458\u5de5\u81ea\u8d2d')], verbose_name='\u8d2d\u4e70\u65b9\u5f0f')),
('price', models.IntegerField(blank=True, verbose_name='\u8d2d\u4e70\u4ef7\u683c')),
('suse_time', models.DateField(max_length=128, null=True, verbose_name='\u5f00\u59cb\u4f7f\u7528\u65f6\u95f4')),
('euse_time', models.DateField(max_length=128, null=True, verbose_name='\u622a\u81f3\u4f7f\u7528\u65f6\u95f4')),
('status', models.SmallIntegerField(blank=True, choices=[(1, '\u6b63\u5728\u4f7f\u7528'), (2, '\u672a\u4f7f\u7528'), (3, '\u8bbe\u5907\u6545\u969c'), (4, '\u5e93\u5b58\u5907\u7528')], verbose_name='\u72b6\u6001')),
('create_time', models.DateTimeField(auto_now_add=True, null=True, verbose_name='\u8d44\u4ea7\u521b\u5efa\u65f6\u95f4')),
('devicetag', models.CharField(blank=True, max_length=255)),
('description', models.TextField(blank=True, max_length=255, verbose_name='\u5907\u6ce8')),
],
options={
'verbose_name': '\u8d44\u4ea7\u8868\u7ba1\u7406',
'verbose_name_plural': '\u8d44\u4ea7\u8868\u7ba1\u7406',
'permissions': (('cmdb_assets_view', 'Can view \u8d44\u4ea7\u8868\u7ba1\u7406'), ('assets_index_view', '\u8d44\u4ea7\u7ba1\u7406')),
},
),
migrations.CreateModel(
name='Business',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=128, unique=True, verbose_name='\u4e1a\u52a1\u540d')),
('memo', models.CharField(blank=True, max_length=64, verbose_name='\u5907\u6ce8')),
],
options={
'verbose_name': '\u4e1a\u52a1\u5217\u8868',
'verbose_name_plural': '\u4e1a\u52a1\u5217\u8868',
'permissions': (('cmdb_devicetype_view', 'Can view \u4e1a\u52a1\u5217\u8868'),),
},
),
migrations.CreateModel(
name='Cpu',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.CharField(blank=True, max_length=64, verbose_name='UUID\u53f7')),
('parent_sn', models.CharField(blank=True, max_length=128, verbose_name='\u670d\u52a1\u5668SN')),
('Architecture', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u67b6\u6784')),
('Vendor', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u5236\u9020\u5546')),
('model', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u578b\u53f7')),
('cpu_mhz', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u9891\u7387')),
('L1cache', models.CharField(blank=True, max_length=128, null=True)),
('L2cache', models.CharField(blank=True, max_length=128, null=True)),
('L3cache', models.CharField(blank=True, max_length=128, null=True)),
('Thread', models.SmallIntegerField(null=True, verbose_name='\u7ebf\u7a0b')),
('create_time', models.DateTimeField(auto_now_add=True)),
('update_time', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name': 'CPU',
'verbose_name_plural': 'CPU',
},
),
migrations.CreateModel(
name='DeviceType',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=128, verbose_name='\u8bbe\u5907\u7c7b\u578b')),
],
options={
'verbose_name': '\u8bbe\u5907\u7c7b\u578b',
'verbose_name_plural': '\u8bbe\u5907\u7c7b\u578b',
'permissions': (('cmdb_devicetype_view', 'Can view \u8bbe\u5907\u7c7b\u578b'),),
},
),
migrations.CreateModel(
name='Disk',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=128, verbose_name='\u786c\u76d8\u540d\u79f0')),
('uuid', models.CharField(blank=True, max_length=128, unique=True)),
('parent_sn', models.CharField(blank=True, max_length=128, verbose_name='\u670d\u52a1\u5668SN')),
('Firm', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u5236\u9020\u5546')),
('capacity', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u5bb9\u91cf')),
('disk_type', models.SmallIntegerField(blank=True, choices=[(1, 'SATA'), (2, 'SSD')], null=True, verbose_name='\u78c1\u76d8\u7c7b\u578b')),
('create_time', models.DateTimeField(auto_now_add=True)),
('update_time', models.DateTimeField(auto_now=True)),
('tag', models.CharField(blank=True, max_length=128, null=True)),
],
options={
'verbose_name': '\u786c\u76d8',
'verbose_name_plural': '\u786c\u76d8',
},
),
migrations.CreateModel(
name='IDC',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('idc_name', models.CharField(blank=True, max_length=128, unique=True)),
('address', models.CharField(blank=True, max_length=255, null=True)),
('floor', models.CharField(blank=True, max_length=20, null=True, verbose_name='\u697c\u5c42')),
('contacts', models.CharField(blank=True, max_length=128, null=True)),
('phone', models.CharField(blank=True, max_length=20, null=True)),
],
options={
'verbose_name': 'IDC',
'verbose_name_plural': 'IDC',
'permissions': (('cmdb_idc_view', 'Can view IDC'),),
},
),
migrations.CreateModel(
name='NIC',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.CharField(blank=True, max_length=128, verbose_name='UUID\u53f7')),
('parent_sn', models.CharField(blank=True, max_length=128, verbose_name='\u670d\u52a1\u5668SN')),
('name', models.CharField(max_length=128, verbose_name='\u7f51\u5361\u540d\u79f0')),
('model', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u578b\u53f7')),
('ip', models.GenericIPAddressField(default='', verbose_name='IP\u5730\u5740')),
('mac', models.CharField(max_length=64, verbose_name='mac\u5730\u5740')),
('netmask', models.CharField(blank=True, max_length=64, null=True, verbose_name='\u5b50\u7f51\u63a9\u7801')),
('nicstatus', models.CharField(blank=True, max_length=64, null=True, verbose_name='\u7f51\u5361\u72b6\u6001')),
('create_time', models.DateTimeField(auto_now_add=True)),
('update_time', models.DateTimeField(auto_now=True)),
('tag', models.CharField(blank=True, max_length=128, null=True)),
],
options={
'verbose_name': '\u7f51\u5361',
'verbose_name_plural': '\u7f51\u5361',
},
),
migrations.CreateModel(
name='Provider',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('provider_name', models.CharField(blank=True, max_length=128, unique=True, verbose_name='\u63d0\u4f9b\u5546')),
('address', models.CharField(blank=True, max_length=255, verbose_name='\u5730\u5740')),
('contacts', models.CharField(blank=True, max_length=128, verbose_name='\u8054\u7cfb\u4eba')),
('phone', models.CharField(blank=True, max_length=20, verbose_name='\u8054\u7cfb\u7535\u8bdd')),
('Fax', models.CharField(blank=True, max_length=20, verbose_name='\u4f20\u771f')),
],
options={
'verbose_name': '\u4f9b\u5e94\u5546',
'verbose_name_plural': '\u4f9b\u5e94\u5546',
'permissions': (('cmdb_provider_view', 'Can view \u4f9b\u5e94\u5546'),),
},
),
migrations.CreateModel(
name='Server',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('sn', models.CharField(max_length=128, unique=True, verbose_name='SN\u53f7')),
('hostname', models.CharField(max_length=128, verbose_name='\u4e3b\u673a\u540d')),
('mem', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u5185\u5b58\u603b\u5bb9\u91cf')),
('swap', models.CharField(blank=True, max_length=128, null=True, verbose_name='swap\u5bb9\u91cf')),
('platform', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u5e73\u53f0')),
('system', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u7cfb\u7edf')),
('version', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u7248\u672c')),
('Firm', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u5236\u9020\u5546')),
('cpu_count', models.SmallIntegerField(blank=True, verbose_name='cpu\u4e2a\u6570')),
('cpu_core_count', models.SmallIntegerField(blank=True, verbose_name='cpu\u6838\u6570')),
('raid', models.CharField(blank=True, max_length=128, null=True, verbose_name='RAID\u7ea7\u522b')),
('saltid', models.CharField(blank=True, max_length=128, null=True, verbose_name='SaltID\u540d')),
('create_time', models.DateTimeField(auto_now_add=True)),
('addtype', models.SmallIntegerField(blank=True, choices=[(1, '\u624b\u52a8\u6dfb\u52a0'), (2, '\u81ea\u52a8\u91c7\u96c6')], default=1, verbose_name='\u91c7\u96c6\u6a21\u5f0f')),
('update_time', models.DateTimeField(auto_now=True, null=True)),
('Assets', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pub', to='servermanager.Assets', verbose_name='\u8d44\u4ea7\u5173\u8054')),
('cpu', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='servermanager.Cpu')),
('disk', models.ManyToManyField(blank=True, to='servermanager.Disk', verbose_name='\u786c\u76d8')),
('nic', models.ManyToManyField(to='servermanager.NIC', verbose_name='\u7f51\u5361\u5217\u8868')),
],
options={
'verbose_name': '\u670d\u52a1\u5668\u7ba1\u7406',
'verbose_name_plural': '\u670d\u52a1\u5668\u7ba1\u7406',
'permissions': (('cmdb_server_view', 'Can view \u670d\u52a1\u5668\u7ba1\u7406'),),
},
),
migrations.CreateModel(
name='Software',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=128, verbose_name='\u8f6f\u4ef6\u540d\u79f0')),
('version', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u7248\u672c')),
('license', models.CharField(blank=True, max_length=128, null=True, verbose_name='\u5e8f\u5217\u53f7')),
],
options={
'verbose_name': '\u8f6f\u4ef6\u7ba1\u7406',
'verbose_name_plural': '\u8f6f\u4ef6\u7ba1\u7406',
'permissions': (('cmdb_software_view', 'Can view \u8f6f\u4ef6\u7ba1\u7406'),),
},
),
migrations.AddField(
model_name='server',
name='software',
field=models.ManyToManyField(blank=True, to='servermanager.Software', verbose_name='\u8f6f\u4ef6\u5217\u8868'),
),
migrations.AddField(
model_name='assets',
name='IDC',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='servermanager.IDC'),
),
]
================================================
FILE: servermanager/migrations/0002_auto_20161121_1740.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-21 17:40
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('servermanager', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='assets',
name='admin',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='\u7ba1\u7406\u5458\u90ae\u7bb1'),
),
migrations.AddField(
model_name='assets',
name='business',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='servermanager.Business', verbose_name='\u4e1a\u52a1'),
),
migrations.AddField(
model_name='assets',
name='device_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='servermanager.DeviceType', verbose_name='\u8bbe\u5907\u7c7b\u578b'),
),
migrations.AddField(
model_name='assets',
name='provider',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='servermanager.Provider', verbose_name='\u63d0\u4f9b\u5546'),
),
]
================================================
FILE: servermanager/migrations/0003_auto_20161128_1031.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 10:31
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0002_auto_20161121_1740'),
]
operations = [
migrations.AlterField(
model_name='cpu',
name='uuid',
field=models.CharField(max_length=64, verbose_name='UUID\u53f7'),
),
]
================================================
FILE: servermanager/migrations/0004_auto_20161128_1032.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 10:32
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0003_auto_20161128_1031'),
]
operations = [
migrations.AlterField(
model_name='cpu',
name='parent_sn',
field=models.CharField(max_length=128, verbose_name='\u670d\u52a1\u5668SN'),
),
]
================================================
FILE: servermanager/migrations/0005_auto_20161128_1032.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 10:32
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0004_auto_20161128_1032'),
]
operations = [
migrations.AlterField(
model_name='idc',
name='idc_name',
field=models.CharField(max_length=128, unique=True),
),
]
================================================
FILE: servermanager/migrations/0006_auto_20161128_1034.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 10:34
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0005_auto_20161128_1032'),
]
operations = [
migrations.AlterField(
model_name='business',
name='name',
field=models.CharField(max_length=128, unique=True, verbose_name='\u4e1a\u52a1\u540d'),
),
migrations.AlterField(
model_name='devicetype',
name='name',
field=models.CharField(max_length=128, verbose_name='\u8bbe\u5907\u7c7b\u578b'),
),
migrations.AlterField(
model_name='disk',
name='name',
field=models.CharField(max_length=128, verbose_name='\u786c\u76d8\u540d\u79f0'),
),
migrations.AlterField(
model_name='disk',
name='parent_sn',
field=models.CharField(max_length=128, verbose_name='\u670d\u52a1\u5668SN'),
),
migrations.AlterField(
model_name='disk',
name='uuid',
field=models.CharField(max_length=128, unique=True),
),
migrations.AlterField(
model_name='nic',
name='parent_sn',
field=models.CharField(max_length=128, verbose_name='\u670d\u52a1\u5668SN'),
),
migrations.AlterField(
model_name='nic',
name='uuid',
field=models.CharField(max_length=128, verbose_name='UUID\u53f7'),
),
migrations.AlterField(
model_name='provider',
name='provider_name',
field=models.CharField(max_length=128, unique=True, verbose_name='\u63d0\u4f9b\u5546'),
),
migrations.AlterField(
model_name='software',
name='name',
field=models.CharField(max_length=128, verbose_name='\u8f6f\u4ef6\u540d\u79f0'),
),
]
================================================
FILE: servermanager/migrations/0007_auto_20161128_1038.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 10:38
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0006_auto_20161128_1034'),
]
operations = [
migrations.AlterField(
model_name='idc',
name='address',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='\u5730\u5740'),
),
migrations.AlterField(
model_name='idc',
name='contacts',
field=models.CharField(blank=True, max_length=128, null=True, verbose_name='\u8054\u7cfb\u4eba'),
),
migrations.AlterField(
model_name='idc',
name='idc_name',
field=models.CharField(max_length=128, unique=True, verbose_name='IDC'),
),
migrations.AlterField(
model_name='idc',
name='phone',
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='\u8054\u7cfb\u7535\u8bdd'),
),
]
================================================
FILE: servermanager/migrations/0008_auto_20161128_1109.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 11:09
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0007_auto_20161128_1038'),
]
operations = [
migrations.AlterField(
model_name='server',
name='cpu_core_count',
field=models.SmallIntegerField(blank=True, default=0, verbose_name='cpu\u6838\u6570'),
),
migrations.AlterField(
model_name='server',
name='cpu_count',
field=models.SmallIntegerField(blank=True, default=0, verbose_name='cpu\u4e2a\u6570'),
),
]
================================================
FILE: servermanager/migrations/0009_auto_20161128_1112.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 11:12
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0008_auto_20161128_1109'),
]
operations = [
migrations.AlterField(
model_name='server',
name='saltid',
field=models.CharField(max_length=128, verbose_name='SaltID\u540d'),
),
]
================================================
FILE: servermanager/migrations/0010_auto_20161128_1113.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-11-28 11:13
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0009_auto_20161128_1112'),
]
operations = [
migrations.AlterField(
model_name='server',
name='nic',
field=models.ManyToManyField(blank=True, null=True, to='servermanager.NIC', verbose_name='\u7f51\u5361\u5217\u8868'),
),
]
================================================
FILE: servermanager/migrations/0011_auto_20161202_1049.py
================================================
# -*- coding: utf-8 -*-
# Generated by Django 1.9.9 on 2016-12-02 10:49
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('servermanager', '0010_auto_20161128_1113'),
]
operations = [
migrations.AlterField(
model_name='server',
name='nic',
field=models.ManyToManyField(blank=True, to='servermanager.NIC', verbose_name='\u7f51\u5361\u5217\u8868'),
),
]
================================================
FILE: servermanager/migrations/__init__.py
================================================
================================================
FILE: servermanager/models.py
================================================
#coding:utf8
from __future__ import unicode_literals
from django.db import models
from webapp.models import Suser
'''设备类型表'''
class DeviceType(models.Model):
name = models.CharField(max_length=128,verbose_name=u'设备类型')
def __unicode__(self):
return self.name
class Meta:
verbose_name = u'设备类型'
verbose_name_plural = u"设备类型"
permissions = (
("cmdb_devicetype_view", "Can view %s" %verbose_name),
)
'''IDC信息管理表'''
class IDC(models.Model):
idc_name = models.CharField(u'IDC',max_length=128, unique=True)
address = models.CharField(u'地址',max_length=255, null=True,blank=True)
floor = models.CharField(u'楼层',max_length=20,null=True,blank=True)
contacts = models.CharField(u'联系人',max_length=128, null=True,blank=True)
phone = models.CharField(u'联系电话',max_length=20,null=True,blank=True)
def __unicode__(self):
return self.idc_name
class Meta:
verbose_name = u'IDC'
verbose_name_plural = u'IDC'
permissions = (
("cmdb_idc_view", "Can view %s" %verbose_name),
)
'''业务表'''
class Business(models.Model):
name = models.CharField(max_length=128,unique=True,verbose_name=u'业务名')
memo = models.CharField(u'备注',max_length=64, blank=True)
def __unicode__(self):
return self.name
class Meta:
verbose_name = u'业务列表'
verbose_name_plural = u'业务列表'
permissions = (
("cmdb_devicetype_view", "Can view %s" %verbose_name),
)
'''提供商表'''
class Provider(models.Model):
provider_name = models.CharField(max_length=128, unique=True, verbose_name=u'提供商')
address = models.CharField(max_length=255, blank=True, verbose_name=u'地址')
contacts = models.CharField(max_length=128, blank=True, verbose_name=u'联系人')
phone = models.CharField(max_length=20,blank=True, verbose_name=u'联系电话')
Fax = models.CharField(max_length=20,blank=True, verbose_name=u'传真')
def __unicode__(self):
return self.provider_name
class Meta:
verbose_name = u'供应商'
verbose_name_plural = u'供应商'
permissions = (
("cmdb_provider_view", "Can view %s" %verbose_name),
)
'''资产表'''
class Assets(models.Model):
host_name = models.CharField(verbose_name=u'设备名',max_length=128,null=True, unique=True)
device_number = models.CharField(u'设备编号',max_length=128, unique=True)
device_type = models.ForeignKey('DeviceType',verbose_name=u'设备类型',null=True,blank=True)
#保修期
Warranty = models.SmallIntegerField(u'保修期')
IDC = models.ForeignKey('IDC', null=True,blank=True)
business = models.ForeignKey('Business',verbose_name=u'业务', null=True,blank=True)
buy_time = models.CharField(u'购买日期', max_length=128, blank=True)
buy_type_choice = (
(1, u'公司内购'),
(2, u'员工自购'),
)
buy_type = models.SmallIntegerField(u'购买方式',choices=buy_type_choice,blank=True)
price = models.IntegerField(u'购买价格',blank=True)
#管理员,可以是多个管理员进行维护
admin = models.ForeignKey(Suser, verbose_name=u'管理员邮箱',null=True,blank=True)
suse_time = models.DateField(u'开始使用时间', max_length=128, null=True)
euse_time = models.DateField(u'截至使用时间', max_length=128, null=True)
status_choice = (
(1, u'正在使用'),
(2, u'未使用'),
(3, u'设备故障'),
(4, u'库存备用'),
)
status =models.SmallIntegerField(u'状态',choices=status_choice,blank=True)
create_time = models.DateTimeField(u'资产创建时间', auto_now_add=True,null=True)
devicetag = models.CharField(max_length=255, blank=True)
#提供商
provider = models.ForeignKey('Provider',verbose_name=u'提供商', null=True,blank=True)
#其它备注
description = models.TextField(max_length=255,blank=True,verbose_name=u'备注')
def __unicode__(self):
return self.host_name
class Meta:
verbose_name = u'资产表管理'
verbose_name_plural = u'资产表管理'
permissions = (
("cmdb_assets_view", "Can view %s" %verbose_name),
("assets_index_view", "资产管理"),
)
'''软件版本'''
class Software(models.Model):
name = models.CharField(max_length=128, verbose_name=u'软件名称')
version = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'版本')
license = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'序列号')
def __unicode__(self):
return self.name
class Meta:
verbose_name = u'软件管理'
verbose_name_plural = u'软件管理'
permissions = (
("cmdb_software_view", "Can view %s" %verbose_name),
)
'''服务器主表'''
class Server(models.Model):
Assets = models.OneToOneField('Assets',verbose_name=u'资产关联',null=True,blank=True,related_name='pub')
sn = models.CharField(max_length=128,verbose_name=u'SN号',unique=True)
hostname = models.CharField(max_length=128,verbose_name=u'主机名')
mem = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'内存总容量')
swap = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'swap容量')
platform = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'平台')
system = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'系统')
version = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'版本')
#产商
Firm = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'制造商')
#软件安装列表
software = models.ManyToManyField('Software', blank=True,verbose_name=u'软件列表')
#CPU
cpu = models.ForeignKey('Cpu',blank=True,null=True)
cpu_count = models.SmallIntegerField(u'cpu个数',blank=True,default=0)
cpu_core_count = models.SmallIntegerField(u'cpu核数',blank=True,default=0)
#nic
nic = models.ManyToManyField('NIC', verbose_name=u'网卡列表',blank=True)
#磁盘
disk = models.ManyToManyField('Disk', verbose_name=u'硬盘',blank=True)
#raid
raid = models.CharField(max_length=128,null=True,blank=True,verbose_name=u'RAID级别')
saltid = models.CharField(max_length=128,verbose_name=u'SaltID名')
create_time = models.DateTimeField(blank=True, auto_now_add=True)
add_type_choice = (
(1,u'手动添加'),
(2,u'自动采集'),
)
addtype =models.SmallIntegerField(u'采集模式',choices=add_type_choice,blank=True,default=1)
#修改时间
update_time = models.DateTimeField(blank=True, auto_now=True, null=True)
def __unicode__(self):
return "%s %s" %(self.sn, self.Assets.host_name)
class Meta:
verbose_name = u'服务器管理'
verbose_name_plural = '服务器管理'
permissions = (
("cmdb_server_view", "Can view %s" %verbose_name),
)
class Cpu(models.Model):
uuid = models.CharField(u'UUID号',max_length=64)
parent_sn = models.CharField(max_length=128, verbose_name=u'服务器SN')
#cpu架构
Architecture = models.CharField(max_length=128,blank=True,null=True,verbose_name=u'架构')
#产商
Vendor = models.CharField(max_length=128,blank=True,null=True,verbose_name=u'制造商')
#型号
model = models.CharField(max_length=128,blank=True,null=True,verbose_name=u'型号')
cpu_mhz = models.CharField(max_length=128,blank=True,null=True,verbose_name=u'频率')
L1cache = models.CharField(max_length=128,blank=True,null=True)
L2cache = models.CharField(max_length=128,blank=True,null=True)
L3cache = models.CharField(max_length=128,blank=True,null=True)
Thread = models.SmallIntegerField(null=True,verbose_name=u'线程')
create_time = models.DateTimeField(blank=True, auto_now_add=True)
update_time = models.DateTimeField(blank=True, auto_now=True)
def __unicode__(self):
return self.parent_sn
class Meta:
verbose_name = u'CPU'
verbose_name_plural = u'CPU'
class Disk(models.Model):
name = models.CharField(max_length=128,verbose_name=u'硬盘名称')
uuid = models.CharField(max_length=128,unique=True)
parent_sn = models.CharField(max_length=128,verbose_name=u'服务器SN')
#产商
Firm = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'制造商')
#容量
capacity = models.CharField(max_length=128,null=True, blank=True,verbose_name=u'容量')
type_choice = (
(1, u'SATA'),
(2, u'SSD'),
)
#磁盘类型
disk_type = models.SmallIntegerField(choices=type_choice,null=True,blank=True,verbose_name='磁盘类型')
create_time = models.DateTimeField(blank=True, auto_now_add=True)
update_time = models.DateTimeField(blank=True, auto_now=True)
tag = models.CharField(max_length=128,blank=True,null=True)
def __unicode__(self):
return self.parent_sn
class Meta:
verbose_name = u'硬盘'
verbose_name_plural = u'硬盘'
class NIC(models.Model):
uuid = models.CharField(u'UUID号',max_length=128,)
parent_sn = models.CharField(max_length=128,verbose_name=u'服务器SN')
name = models.CharField(u'网卡名称', max_length=128,)
model = models.CharField(max_length=128,blank=True,null=True,verbose_name=u'型号')
ip = models.GenericIPAddressField(max_length=128,null=False,default='',verbose_name=u'IP地址')
mac = models.CharField(u'mac地址', max_length=64)
netmask = models.CharField(max_length=64,blank=True,null=True,verbose_name=u'子网掩码')
nicstatus = models.CharField(max_length=64,blank=True,null=True,verbose_name=u'网卡状态')
create_time = models.DateTimeField(blank=True, auto_now_add=True)
update_time = models.DateTimeField(blank=True, auto_now=True)
tag = models.CharField(max_length=128,blank=True,null=True)
def __unicode__(self):
return self.ip
class Meta:
verbose_name = u'网卡'
verbose_name_plural = u'网卡'
================================================
FILE: servermanager/tests.py
================================================
from django.test import TestCase
# Create your tests here.
================================================
FILE: servermanager/urls.py
================================================
from django.conf.urls import url
from servermanager.views import (HostLists,ServerDetail,ChangeServer,
AssetsLists,CeleryStatus,
AssetsDetail,
ServerList,
DeleteAsset,
DeleteServer,
UpdateServer,
ChangeAsset,)
urlpatterns = [
url(r'assets/(\d+)$', AssetsLists, name='AssetsLists'),
url(r'assets/detail/(\d+)$', AssetsDetail, name='AssetsDetail'),
url(r'assets/delete/(\d+)$', DeleteAsset, name='DeleteAsset'),
url(r'assets/change/(\d+)$', ChangeAsset, name='ChangeAsset'),
url(r'servers/detail/(\d+)$',ServerDetail,name='ServerDetail'),
url(r'servers/(\d+)$', ServerList, name='ServerList'),
url(r'servers/delete/(\d+)$', DeleteServer, name='DeleteServer'),
url(r'servers/update/(\d+)$',UpdateServer,name='UpdateServer'),
url(r'servers/change/(\d+)$',ChangeServer,name='ChangeServer'),
url(r'servers/task/(\w+\-\w+\-\w+\-\w+\-\w+)$',CeleryStatus,name='CeleryStatus'),
]
================================================
FILE: servermanager/views.py
================================================
#coding:utf8
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from servermanager.models import *
from webapp.models import *
from webapp.Extends import PageList
from webapp.tasks import SaltGrains,UpdateServerInfo
from django.db.models import Q
from django.contrib.auth.decorators import permission_required
import json
@login_required()
def HostLists(request):
return render(request,'servermanager/hosts.html')
@login_required()
@permission_required('servermanager.cmdb_assets_view',raise_exception=True)
def AssetsLists(request,page):
usersession=request.session.get('user_id')
if request.method == 'POST':
searchdata = request.POST.get('search')
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count = Assets.objects.filter(Q(host_name__contains=searchdata) | Q(device_number__contains=searchdata)).count()
result = Assets.objects.filter(Q(host_name__contains=searchdata) | Q(device_number__contains=searchdata)).order_by('-id')[start:end]
url = "/server/assets"
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count)
ret = {'Assetsdata': result,
'count': count,
'page': page,
'usersession':usersession}
return render(request,'servermanager/assets_list.html', ret)
else:
AssetsData=Assets.objects.all()
for asset in AssetsData:
if Server.objects.filter(Assets=asset):
asset.status = 1
asset.save()
else:
asset.status = 2
asset.save()
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count = Assets.objects.all().count()
result = Assets.objects.all().order_by('-id')[start:end]
url = "/server/assets"
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count)
ret = {'Assetsdata': result,
'count': count,
'page': page,
'usersession':usersession}
return render(request,'servermanager/assets_list.html', ret)
@login_required()
def AssetsDetail(request,id):
usersession=request.session.get('user_id')
if request.method == 'GET':
result = Assets.objects.get(id=id)
ret={'Assetsdata':result,'usersession':usersession}
return render(request,'servermanager/assetsdetail.html',ret)
@login_required()
@permission_required('servermanager.cmdb_server_view',raise_exception=True)
def ServerList(request,page):
usersession=request.session.get('user_id')
if request.method == 'POST':
searchdata = request.POST.get('search')
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count = Server.objects.filter(Q(Assets__host_name__contains=searchdata) | Q(hostname__contains=searchdata) | Q(sn__contains=searchdata)).count()
result = Server.objects.filter(Q(Assets__host_name__contains=searchdata) | Q(hostname__contains=searchdata) | Q(sn__contains=searchdata)).order_by('-id')[start:end]
url = "/server/servers"
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count)
ret = {'Serverdata': result,
'count': count,
'page': page,
'usersession':usersession}
return render(request,'servermanager/servers_list.html', ret)
else:
#分页代码
(page,start,end,per_item)=PageList.PageCount(page)
count = Server.objects.all().count()
result = Server.objects.all().order_by('-id')[start:end]
url = "/server/servers"
if count%per_item == 0:
all_pages_count = count/per_item
else:
all_pages_count = count/per_item+1
page=PageList.Page(page, url, all_pages_count)
ret = {'Serverdata': result,
'count': count,
'page': page,
'usersession':usersession}
return render(request, 'servermanager/servers_list.html', ret)
@login_required()
def ServerDetail(request,id):
usersession=request.session.get('user_id')
if request.method == 'GET':
ServerData = Server.objects.get(id=id)
Diskall=ServerData.disk.all()
colors = ["#5fbeaa","#ebeff2","#36404a","#5fbeaa","#ebeff2","#5d9cec"]
Diskhtml=[]
for i in range(Diskall.count()):
disk={}
disk['label']=Diskall[i].name.encode() #传给前端去掉unicode
disk['value']=Diskall[i].capacity.encode()
disk['color']=colors[i]
disk['highlight']=colors[i]
Diskhtml.append(disk)
ret = {'usersession':usersession,'ServerData':ServerData,'Diskhtml':json.dumps(Diskhtml)}
return render(request,'servermanager/servers_detail.html',ret)
@login_required()
@permission_required('servermanager.delete_assets',raise_exception=True)
def DeleteServer(request,id):
username = request.session.get('user_name')
if request.method == 'GET':
ServerData = Server.objects.get(id=id)
ServerData.delete()
msg=u'删除服务器信息 %s' %ServerData.hostname
Operation.objects.create(Opuser=username,Opaction=msg)
return HttpResponse(u'删除主机成功')
@login_required()
@permission_required('servermanager.delete_assets',raise_exception=True)
def DeleteAsset(request,id):
username = request.session.get('user_name')
if request.method == 'GET':
selectid=Assets.objects.filter(id=id)
if Server.objects.filter(Assets=selectid):
msg={'msgerror':u'请删除所关联的服务器!!'}
return HttpResponse(json.dumps(msg))
else:
AssetData = Assets.objects.get(id=id)
AssetData.delete()
msg=u'删除资产信息 %s' %AssetData.host_name
Operation.objects.create(Opuser=username,Opaction=msg)
msg={'msginfo':u'OK,资产信息删除成功!!!!'}
return HttpResponse(json.dumps(msg))
@login_required()
@permission_required('servermanager.change_assets',raise_exception=True)
def ChangeAsset(request,id):
usersession=request.session.get('user_id')
username = request.session.get('user_name')
if request.method == 'POST':
PostData=request.POST
AssetDsata=Assets.objects.get(id=id)
AssetDsata.status = PostData['status']
AssetDsata.Warranty =PostData['Warranty']
AssetDsata.device_number = PostData['device_number']
device_type=DeviceType.objects.get(id=PostData['device_type'])
AssetDsata.device_type = device_type
AssetDsata.host_name = PostData['host_name']
idc = IDC.objects.get(id=PostData['idc'])
AssetDsata.IDC = idc
business = Business.objects.get(id=PostData['business'])
AssetDsata.business = business
AssetDsata.buy_time = PostData['buytime']
AssetDsata.price = PostData['price']
admin = Suser.objects.get(id=PostData['admin'])
AssetDsata.admin = admin
AssetDsata.suse_time = PostData['start']
AssetDsata.euse_time = PostData['end']
provider = Provider.objects.get(id=PostData['provider'])
AssetDsata.provider = provider
AssetDsata.description = PostData['summernote']
AssetDsata.save()
Operation.objects.create(Opuser=username,Opaction=u'修改资产信息')
msg={'msginfo':u'恭喜您,资产修改成功!!!'}
return HttpResponse(json.dumps(msg))
else:
AssetsData=Assets.objects.get(id=id)
IdcData = IDC.objects.all()
BusinessData = Business.objects.all()
DeviceTypeData = DeviceType.objects.all()
AdminUser = Suser.objects.all()
ProviderData = Provider.objects.all()
ret = {
'usersession': usersession,
'AssetsData': AssetsData,
'IdcData': IdcData,
'BusinessData': BusinessData,
'DeviceTypeData': DeviceTypeData,
'AdminUser': AdminUser,
'ProviderData':ProviderData,
}
return render(request,'servermanager/assetschange.html',ret)
@login_required()
@permission_required('servermanager.change_assets',raise_exception=True)
def ChangeServer(request,id):
usersession=request.session.get('user_id')
username = request.session.get('user_name')
if request.method == 'POST':
software=request.POST.getlist('software')
disk=request.POST.getlist('disk')
nic=request.POST.getlist('nic')
Assetsid=request.POST['Assets']
AssetsInfo = Assets.objects.get(id=Assetsid)
ServerData=Server.objects.get(id=id)
ServerData.Assets=AssetsInfo
ServerData.mem = request.POST['mem']
ServerData.swap=request.POST['swap']
ServerData.platform = request.POST['platform']
ServerData.system = request.POST['system']
ServerData.version = request.POST['version']
ServerData.Firm = request.POST['firm']
ServerData.saltid = request.POST['saltid']
ServerData.hostname = request.POST['hostname']
ServerData.sn = request.POST['sn']
CPU = request.POST['CPU']
CPU = Cpu.objects.get(id=CPU)
ServerData.cpu=CPU
ServerData.cpu_count = request.POST['cpu_count']
ServerData.cpu_core_count = request.POST['cpu_core_count']
ServerData.raid = request.POST['raid']
ServerData.addtype = request.POST['addtype']
for n in ServerData.nic.all():
group_set = NIC.objects.get(id=n.id)
ServerData.nic.remove(group_set)
for d in ServerData.disk.all():
group_set = Disk.objects.get(id=d.id)
ServerData.disk.remove(group_set)
for s in ServerData.software.all():
group_set = Software.objects.get(id=s.id)
ServerData.software.remove(group_set)
for n in nic:
print n
group_set = NIC.objects.get(id=n)
ServerData.nic.add(group_set)
for d in disk:
group_set = Disk.objects.get(id=d)
ServerData.disk.add(group_set)
for s in software:
group_set = Software.objects.get(id=s)
ServerData.software.add(group_set)
ServerData.save()
Operation.objects.create(Opuser=username,Opaction=u'修改服务器信息')
return HttpResponse(u'Server 修改成功!!')
else:
listdata=[]
[listdata.append(int(i.Assets.id)) for i in Server.objects.all()]
hostid=Server.objects.get(id=id)
listdata.remove(hostid.Assets_id)
AssetsData=Assets.objects.exclude(id__in=listdata)
CpuData = Cpu.objects.all()
SoftwareData = Software.objects.all()
DiskData = Disk.objects.all()
NicData = NIC.objects.all()
ServerData = Server.objects.get(id=id)
ret={'usersession':usersession,
'AssetsData':AssetsData,
'ServerData':ServerData,
'SoftwareData':SoftwareData,
'DiskData':DiskData,
'NicData':NicData,
'CpuData':CpuData}
return render(request,'servermanager/servers_change.html',ret)
@login_required()
def UpdateServer(request,id):
username = request.session.get('user_name')
if request.method == 'GET':
a=UpdateServerInfo.apply_async((str(id),))
msg={'celeryId':a.id}
Operation.objects.create(Opuser=username,Opaction=u'Salt更新服务器信息 服务器 %s' %id)
return HttpResponse(json.dumps(msg))
@login_required()
def CeleryStatus(request,celeryid):
if request.method == 'GET':
task=UpdateServerInfo.AsyncResult(celeryid)
if task.state == 'PENDING':
response = {
'state': task.state,
'status': 'Pending...'
}
elif task.state != 'FAILURE':
response = {
'state': task.state,
'status': task.status,
}
if 'result' in task.info:
response['result'] = task.info['result']
else:
response = {
'state': task.state,
'current': 1,
'total': 1,
'status': str(task.info), # this is the exception raised
}
return HttpResponse(json.dumps(response))
================================================
FILE: static/assets/css/_variables.css
================================================
/*
Template Name: Moltran Dashboard
Author: CoderThemes
Email: coderthemes@gmail.com
File: Variables.less
*/
================================================
FILE: static/assets/css/bootstrap-theme.css
================================================
/*!
* Bootstrap v3.3.5 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.btn-default.disabled,
.btn-primary.disabled,
.btn-success.disabled,
.btn-info.disabled,
.btn-warning.disabled,
.btn-danger.disabled,
.btn-default[disabled],
.btn-primary[disabled],
.btn-success[disabled],
.btn-info[disabled],
.btn-warning[disabled],
.btn-danger[disabled],
fieldset[disabled] .btn-default,
fieldset[disabled] .btn-primary,
fieldset[disabled] .btn-success,
fieldset[disabled] .btn-info,
fieldset[disabled] .btn-warning,
fieldset[disabled] .btn-danger {
-webkit-box-shadow: none;
box-shadow: none;
}
.btn-default .badge,
.btn-primary .badge,
.btn-success .badge,
.btn-info .badge,
.btn-warning .badge,
.btn-danger .badge {
text-shadow: none;
}
.btn:active,
.btn.active {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #dbdbdb;
border-color: #ccc;
}
.btn-default:hover,
.btn-default:focus {
background-color: #e0e0e0;
background-position: 0 -15px;
}
.btn-default:active,
.btn-default.active {
background-color: #e0e0e0;
border-color: #dbdbdb;
}
.btn-default.disabled,
.btn-default[disabled],
fieldset[disabled] .btn-default,
.btn-default.disabled:hover,
.btn-default[disabled]:hover,
fieldset[disabled] .btn-default:hover,
.btn-default.disabled:focus,
.btn-default[disabled]:focus,
fieldset[disabled] .btn-default:focus,
.btn-default.disabled.focus,
.btn-default[disabled].focus,
fieldset[disabled] .btn-default.focus,
.btn-default.disabled:active,
.btn-default[disabled]:active,
fieldset[disabled] .btn-default:active,
.btn-default.disabled.active,
.btn-default[disabled].active,
fieldset[disabled] .btn-default.active {
background-color: #e0e0e0;
background-image: none;
}
.btn-primary {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #245580;
}
.btn-primary:hover,
.btn-primary:focus {
background-color: #265a88;
background-position: 0 -15px;
}
.btn-primary:active,
.btn-primary.active {
background-color: #265a88;
border-color: #245580;
}
.btn-primary.disabled,
.btn-primary[disabled],
fieldset[disabled] .btn-primary,
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus,
.btn-primary.disabled:active,
.btn-primary[disabled]:active,
fieldset[disabled] .btn-primary:active,
.btn-primary.disabled.active,
.btn-primary[disabled].active,
fieldset[disabled] .btn-primary.active {
background-color: #265a88;
background-image: none;
}
.btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #3e8f3e;
}
.btn-success:hover,
.btn-success:focus {
background-color: #419641;
background-position: 0 -15px;
}
.btn-success:active,
.btn-success.active {
background-color: #419641;
border-color: #3e8f3e;
}
.btn-success.disabled,
.btn-success[disabled],
fieldset[disabled] .btn-success,
.btn-success.disabled:hover,
.btn-success[disabled]:hover,
fieldset[disabled] .btn-success:hover,
.btn-success.disabled:focus,
.btn-success[disabled]:focus,
fieldset[disabled] .btn-success:focus,
.btn-success.disabled.focus,
.btn-success[disabled].focus,
fieldset[disabled] .btn-success.focus,
.btn-success.disabled:active,
.btn-success[disabled]:active,
fieldset[disabled] .btn-success:active,
.btn-success.disabled.active,
.btn-success[disabled].active,
fieldset[disabled] .btn-success.active {
background-color: #419641;
background-image: none;
}
.btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #28a4c9;
}
.btn-info:hover,
.btn-info:focus {
background-color: #2aabd2;
background-position: 0 -15px;
}
.btn-info:active,
.btn-info.active {
background-color: #2aabd2;
border-color: #28a4c9;
}
.btn-info.disabled,
.btn-info[disabled],
fieldset[disabled] .btn-info,
.btn-info.disabled:hover,
.btn-info[disabled]:hover,
fieldset[disabled] .btn-info:hover,
.btn-info.disabled:focus,
.btn-info[disabled]:focus,
fieldset[disabled] .btn-info:focus,
.btn-info.disabled.focus,
.btn-info[disabled].focus,
fieldset[disabled] .btn-info.focus,
.btn-info.disabled:active,
.btn-info[disabled]:active,
fieldset[disabled] .btn-info:active,
.btn-info.disabled.active,
.btn-info[disabled].active,
fieldset[disabled] .btn-info.active {
background-color: #2aabd2;
background-image: none;
}
.btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #e38d13;
}
.btn-warning:hover,
.btn-warning:focus {
background-color: #eb9316;
background-position: 0 -15px;
}
.btn-warning:active,
.btn-warning.active {
background-color: #eb9316;
border-color: #e38d13;
}
.btn-warning.disabled,
.btn-warning[disabled],
fieldset[disabled] .btn-warning,
.btn-warning.disabled:hover,
.btn-warning[disabled]:hover,
fieldset[disabled] .btn-warning:hover,
.btn-warning.disabled:focus,
.btn-warning[disabled]:focus,
fieldset[disabled] .btn-warning:focus,
.btn-warning.disabled.focus,
.btn-warning[disabled].focus,
fieldset[disabled] .btn-warning.focus,
.btn-warning.disabled:active,
.btn-warning[disabled]:active,
fieldset[disabled] .btn-warning:active,
.btn-warning.disabled.active,
.btn-warning[disabled].active,
fieldset[disabled] .btn-warning.active {
background-color: #eb9316;
background-image: none;
}
.btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #b92c28;
}
.btn-danger:hover,
.btn-danger:focus {
background-color: #c12e2a;
background-position: 0 -15px;
}
.btn-danger:active,
.btn-danger.active {
background-color: #c12e2a;
border-color: #b92c28;
}
.btn-danger.disabled,
.btn-danger[disabled],
fieldset[disabled] .btn-danger,
.btn-danger.disabled:hover,
.btn-danger[disabled]:hover,
fieldset[disabled] .btn-danger:hover,
.btn-danger.disabled:focus,
.btn-danger[disabled]:focus,
fieldset[disabled] .btn-danger:focus,
.btn-danger.disabled.focus,
.btn-danger[disabled].focus,
fieldset[disabled] .btn-danger.focus,
.btn-danger.disabled:active,
.btn-danger[disabled]:active,
fieldset[disabled] .btn-danger:active,
.btn-danger.disabled.active,
.btn-danger[disabled].active,
fieldset[disabled] .btn-danger.active {
background-color: #c12e2a;
background-image: none;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #2e6da4;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
.navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
}
.navbar-default .navbar-nav > .open > a,
.navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}
.navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-radius: 4px;
}
.navbar-inverse .navbar-nav > .open > a,
.navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
}
@media (max-width: 767px) {
.navbar .navbar-nav .open .dropdown-menu > .active > a,
.navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
.navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
color: #fff;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
}
.alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-repeat: repeat-x;
border-color: #b2dba1;
}
.alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-repeat: repeat-x;
border-color: #9acfea;
}
.alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-repeat: repeat-x;
border-color: #f5e79e;
}
.alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-repeat: repeat-x;
border-color: #dca7a7;
}
.progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #286090;
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
background-repeat: repeat-x;
border-color: #2b669a;
}
.list-group-item.active .badge,
.list-group-item.active:hover .badge,
.list-group-item.active:focus .badge {
text-shadow: none;
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
background-repeat: repeat-x;
}
.panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-repeat: repeat-x;
}
.panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-repeat: repeat-x;
}
.panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-repeat: repeat-x;
}
.panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-repeat: repeat-x;
}
.well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
}
/*# sourceMappingURL=bootstrap-theme.css.map */
================================================
FILE: static/assets/css/bootstrap.css
================================================
/*!
* Bootstrap v3.3.5 (http://getbootstrap.com)
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
html {
font-family: sans-serif;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
body {
margin: 0;
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}
audio,
canvas,
progress,
video {
display: inline-block;
vertical-align: baseline;
}
audio:not([controls]) {
display: none;
height: 0;
}
[hidden],
template {
display: none;
}
a {
background-color: transparent;
}
a:active,
a:hover {
outline: 0;
}
abbr[title] {
border-bottom: 1px dotted;
}
b,
strong {
font-weight: bold;
}
dfn {
font-style: italic;
}
h1 {
margin: .67em 0;
font-size: 2em;
}
mark {
color: #000;
background: #ff0;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sup {
top: -.5em;
}
sub {
bottom: -.25em;
}
img {
border: 0;
}
svg:not(:root) {
overflow: hidden;
}
figure {
margin: 1em 40px;
}
hr {
height: 0;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
pre {
overflow: auto;
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
button,
input,
optgroup,
select,
textarea {
margin: 0;
font: inherit;
color: inherit;
}
button {
overflow: visible;
}
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;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
padding: 0;
border: 0;
}
input {
line-height: normal;
}
input[type="checkbox"],
input[type="radio"] {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
input[type="search"] {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
-webkit-appearance: textfield;
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
fieldset {
padding: .35em .625em .75em;
margin: 0 2px;
border: 1px solid #c0c0c0;
}
legend {
padding: 0;
border: 0;
}
textarea {
overflow: auto;
}
optgroup {
font-weight: bold;
}
table {
border-spacing: 0;
border-collapse: collapse;
}
td,
th {
padding: 0;
}
/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
@media print {
*,
*:before,
*:after {
color: #000 !important;
text-shadow: none !important;
background: transparent !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
a,
a:visited {
text-decoration: underline;
}
a[href]:after {
content: " (" attr(href) ")";
}
abbr[title]:after {
content: " (" attr(title) ")";
}
a[href^="#"]:after,
a[href^="javascript:"]:after {
content: "";
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
thead {
display: table-header-group;
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
.navbar {
display: none;
}
.btn > .caret,
.dropup > .btn > .caret {
border-top-color: #000 !important;
}
.label {
border: 1px solid #000;
}
.table {
border-collapse: collapse !important;
}
.table td,
.table th {
background-color: #fff !important;
}
.table-bordered th,
.table-bordered td {
border: 1px solid #ddd !important;
}
}
@font-face {
font-family: 'Glyphicons Halflings';
src: url('../fonts/glyphicons-halflings-regular.eot');
src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
}
.glyphicon {
position: relative;
top: 1px;
display: inline-block;
font-family: 'Glyphicons Halflings';
font-style: normal;
font-weight: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.glyphicon-asterisk:before {
content: "\2a";
}
.glyphicon-plus:before {
content: "\2b";
}
.glyphicon-euro:before,
.glyphicon-eur:before {
content: "\20ac";
}
.glyphicon-minus:before {
content: "\2212";
}
.glyphicon-cloud:before {
content: "\2601";
}
.glyphicon-envelope:before {
content: "\2709";
}
.glyphicon-pencil:before {
content: "\270f";
}
.glyphicon-glass:before {
content: "\e001";
}
.glyphicon-music:before {
content: "\e002";
}
.glyphicon-search:before {
content: "\e003";
}
.glyphicon-heart:before {
content: "\e005";
}
.glyphicon-star:before {
content: "\e006";
}
.glyphicon-star-empty:before {
content: "\e007";
}
.glyphicon-user:before {
content: "\e008";
}
.glyphicon-film:before {
content: "\e009";
}
.glyphicon-th-large:before {
content: "\e010";
}
.glyphicon-th:before {
content: "\e011";
}
.glyphicon-th-list:before {
content: "\e012";
}
.glyphicon-ok:before {
content: "\e013";
}
.glyphicon-remove:before {
content: "\e014";
}
.glyphicon-zoom-in:before {
content: "\e015";
}
.glyphicon-zoom-out:before {
content: "\e016";
}
.glyphicon-off:before {
content: "\e017";
}
.glyphicon-signal:before {
content: "\e018";
}
.glyphicon-cog:before {
content: "\e019";
}
.glyphicon-trash:before {
content: "\e020";
}
.glyphicon-home:before {
content: "\e021";
}
.glyphicon-file:before {
content: "\e022";
}
.glyphicon-time:before {
content: "\e023";
}
.glyphicon-road:before {
content: "\e024";
}
.glyphicon-download-alt:before {
content: "\e025";
}
.glyphicon-download:before {
content: "\e026";
}
.glyphicon-upload:before {
content: "\e027";
}
.glyphicon-inbox:before {
content: "\e028";
}
.glyphicon-play-circle:before {
content: "\e029";
}
.glyphicon-repeat:before {
content: "\e030";
}
.glyphicon-refresh:before {
content: "\e031";
}
.glyphicon-list-alt:before {
content: "\e032";
}
.glyphicon-lock:before {
content: "\e033";
}
.glyphicon-flag:before {
content: "\e034";
}
.glyphicon-headphones:before {
content: "\e035";
}
.glyphicon-volume-off:before {
content: "\e036";
}
.glyphicon-volume-down:before {
content: "\e037";
}
.glyphicon-volume-up:before {
content: "\e038";
}
.glyphicon-qrcode:before {
content: "\e039";
}
.glyphicon-barcode:before {
content: "\e040";
}
.glyphicon-tag:before {
content: "\e041";
}
.glyphicon-tags:before {
content: "\e042";
}
.glyphicon-book:before {
content: "\e043";
}
.glyphicon-bookmark:before {
content: "\e044";
}
.glyphicon-print:before {
content: "\e045";
}
.glyphicon-camera:before {
content: "\e046";
}
.glyphicon-font:before {
content: "\e047";
}
.glyphicon-bold:before {
content: "\e048";
}
.glyphicon-italic:before {
content: "\e049";
}
.glyphicon-text-height:before {
content: "\e050";
}
.glyphicon-text-width:before {
content: "\e051";
}
.glyphicon-align-left:before {
content: "\e052";
}
.glyphicon-align-center:before {
content: "\e053";
}
.glyphicon-align-right:before {
content: "\e054";
}
.glyphicon-align-justify:before {
content: "\e055";
}
.glyphicon-list:before {
content: "\e056";
}
.glyphicon-indent-left:before {
content: "\e057";
}
.glyphicon-indent-right:before {
content: "\e058";
}
.glyphicon-facetime-video:before {
content: "\e059";
}
.glyphicon-picture:before {
content: "\e060";
}
.glyphicon-map-marker:before {
content: "\e062";
}
.glyphicon-adjust:before {
content: "\e063";
}
.glyphicon-tint:before {
content: "\e064";
}
.glyphicon-edit:before {
content: "\e065";
}
.glyphicon-share:before {
content: "\e066";
}
.glyphicon-check:before {
content: "\e067";
}
.glyphicon-move:before {
content: "\e068";
}
.glyphicon-step-backward:before {
content: "\e069";
}
.glyphicon-fast-backward:before {
content: "\e070";
}
.glyphicon-backward:before {
content: "\e071";
}
.glyphicon-play:before {
content: "\e072";
}
.glyphicon-pause:before {
content: "\e073";
}
.glyphicon-stop:before {
content: "\e074";
}
.glyphicon-forward:before {
content: "\e075";
}
.glyphicon-fast-forward:before {
content: "\e076";
}
.glyphicon-step-forward:before {
content: "\e077";
}
.glyphicon-eject:before {
content: "\e078";
}
.glyphicon-chevron-left:before {
content: "\e079";
}
.glyphicon-chevron-right:before {
content: "\e080";
}
.glyphicon-plus-sign:before {
content: "\e081";
}
.glyphicon-minus-sign:before {
content: "\e082";
}
.glyphicon-remove-sign:before {
content: "\e083";
}
.glyphicon-ok-sign:before {
content: "\e084";
}
.glyphicon-question-sign:before {
content: "\e085";
}
.glyphicon-info-sign:before {
content: "\e086";
}
.glyphicon-screenshot:before {
content: "\e087";
}
.glyphicon-remove-circle:before {
content: "\e088";
}
.glyphicon-ok-circle:before {
content: "\e089";
}
.glyphicon-ban-circle:before {
content: "\e090";
}
.glyphicon-arrow-left:before {
content: "\e091";
}
.glyphicon-arrow-right:before {
content: "\e092";
}
.glyphicon-arrow-up:before {
content: "\e093";
}
.glyphicon-arrow-down:before {
content: "\e094";
}
.glyphicon-share-alt:before {
content: "\e095";
}
.glyphicon-resize-full:before {
content: "\e096";
}
.glyphicon-resize-small:before {
content: "\e097";
}
.glyphicon-exclamation-sign:before {
content: "\e101";
}
.glyphicon-gift:before {
content: "\e102";
}
.glyphicon-leaf:before {
content: "\e103";
}
.glyphicon-fire:before {
content: "\e104";
}
.glyphicon-eye-open:before {
content: "\e105";
}
.glyphicon-eye-close:before {
content: "\e106";
}
.glyphicon-warning-sign:before {
content: "\e107";
}
.glyphicon-plane:before {
content: "\e108";
}
.glyphicon-calendar:before {
content: "\e109";
}
.glyphicon-random:before {
content: "\e110";
}
.glyphicon-comment:before {
content: "\e111";
}
.glyphicon-magnet:before {
content: "\e112";
}
.glyphicon-chevron-up:before {
content: "\e113";
}
.glyphicon-chevron-down:before {
content: "\e114";
}
.glyphicon-retweet:before {
content: "\e115";
}
.glyphicon-shopping-cart:before {
content: "\e116";
}
.glyphicon-folder-close:before {
content: "\e117";
}
.glyphicon-folder-open:before {
content: "\e118";
}
.glyphicon-resize-vertical:before {
content: "\e119";
}
.glyphicon-resize-horizontal:before {
content: "\e120";
}
.glyphicon-hdd:before {
content: "\e121";
}
.glyphicon-bullhorn:before {
content: "\e122";
}
.glyphicon-bell:before {
content: "\e123";
}
.glyphicon-certificate:before {
content: "\e124";
}
.glyphicon-thumbs-up:before {
content: "\e125";
}
.glyphicon-thumbs-down:before {
content: "\e126";
}
.glyphicon-hand-right:before {
content: "\e127";
}
.glyphicon-hand-left:before {
content: "\e128";
}
.glyphicon-hand-up:before {
content: "\e129";
}
.glyphicon-hand-down:before {
content: "\e130";
}
.glyphicon-circle-arrow-right:before {
content: "\e131";
}
.glyphicon-circle-arrow-left:before {
content: "\e132";
}
.glyphicon-circle-arrow-up:before {
content: "\e133";
}
.glyphicon-circle-arrow-down:before {
content: "\e134";
}
.glyphicon-globe:before {
content: "\e135";
}
.glyphicon-wrench:before {
content: "\e136";
}
.glyphicon-tasks:before {
content: "\e137";
}
.glyphicon-filter:before {
content: "\e138";
}
.glyphicon-briefcase:before {
content: "\e139";
}
.glyphicon-fullscreen:before {
content: "\e140";
}
.glyphicon-dashboard:before {
content: "\e141";
}
.glyphicon-paperclip:before {
content: "\e142";
}
.glyphicon-heart-empty:before {
content: "\e143";
}
.glyphicon-link:before {
content: "\e144";
}
.glyphicon-phone:before {
content: "\e145";
}
.glyphicon-pushpin:before {
content: "\e146";
}
.glyphicon-usd:before {
content: "\e148";
}
.glyphicon-gbp:before {
content: "\e149";
}
.glyphicon-sort:before {
content: "\e150";
}
.glyphicon-sort-by-alphabet:before {
content: "\e151";
}
.glyphicon-sort-by-alphabet-alt:before {
content: "\e152";
}
.glyphicon-sort-by-order:before {
content: "\e153";
}
.glyphicon-sort-by-order-alt:before {
content: "\e154";
}
.glyphicon-sort-by-attributes:before {
content: "\e155";
}
.glyphicon-sort-by-attributes-alt:before {
content: "\e156";
}
.glyphicon-unchecked:before {
content: "\e157";
}
.glyphicon-expand:before {
content: "\e158";
}
.glyphicon-collapse-down:before {
content: "\e159";
}
.glyphicon-collapse-up:before {
content: "\e160";
}
.glyphicon-log-in:before {
content: "\e161";
}
.glyphicon-flash:before {
content: "\e162";
}
.glyphicon-log-out:before {
content: "\e163";
}
.glyphicon-new-window:before {
content: "\e164";
}
.glyphicon-record:before {
content: "\e165";
}
.glyphicon-save:before {
content: "\e166";
}
.glyphicon-open:before {
content: "\e167";
}
.glyphicon-saved:before {
content: "\e168";
}
.glyphicon-import:before {
content: "\e169";
}
.glyphicon-export:before {
content: "\e170";
}
.glyphicon-send:before {
content: "\e171";
}
.glyphicon-floppy-disk:before {
content: "\e172";
}
.glyphicon-floppy-saved:before {
content: "\e173";
}
.glyphicon-floppy-remove:before {
content: "\e174";
}
.glyphicon-floppy-save:before {
content: "\e175";
}
.glyphicon-floppy-open:before {
content: "\e176";
}
.glyphicon-credit-card:before {
content: "\e177";
}
.glyphicon-transfer:before {
content: "\e178";
}
.glyphicon-cutlery:before {
content: "\e179";
}
.glyphicon-header:before {
content: "\e180";
}
.glyphicon-compressed:before {
content: "\e181";
}
.glyphicon-earphone:before {
content: "\e182";
}
.glyphicon-phone-alt:before {
content: "\e183";
}
.glyphicon-tower:before {
content: "\e184";
}
.glyphicon-stats:before {
content: "\e185";
}
.glyphicon-sd-video:before {
content: "\e186";
}
.glyphicon-hd-video:before {
content: "\e187";
}
.glyphicon-subtitles:before {
content: "\e188";
}
.glyphicon-sound-stereo:before {
content: "\e189";
}
.glyphicon-sound-dolby:before {
content: "\e190";
}
.glyphicon-sound-5-1:before {
content: "\e191";
}
.glyphicon-sound-6-1:before {
content: "\e192";
}
.glyphicon-sound-7-1:before {
content: "\e193";
}
.glyphicon-copyright-mark:before {
content: "\e194";
}
.glyphicon-registration-mark:before {
content: "\e195";
}
.glyphicon-cloud-download:before {
content: "\e197";
}
.glyphicon-cloud-upload:before {
content: "\e198";
}
.glyphicon-tree-conifer:before {
content: "\e199";
}
.glyphicon-tree-deciduous:before {
content: "\e200";
}
.glyphicon-cd:before {
content: "\e201";
}
.glyphicon-save-file:before {
content: "\e202";
}
.glyphicon-open-file:before {
content: "\e203";
}
.glyphicon-level-up:before {
content: "\e204";
}
.glyphicon-copy:before {
con
gitextract_gajczjdw/
├── .idea/
│ ├── SimpletourDevops.iml
│ ├── inspectionProfiles/
│ │ ├── Project_Default.xml
│ │ └── profiles_settings.xml
│ ├── misc.xml
│ ├── modules.xml
│ └── vcs.xml
├── Publicapi/
│ ├── __init__.py
│ ├── dnspod/
│ │ ├── __init__.py
│ │ └── apicn.py
│ ├── dockerapi/
│ │ ├── Manager.py
│ │ └── __init__.py
│ └── saltstackapi/
│ ├── Assets_Module.py
│ ├── SaltConApi.py
│ └── __init__.py
├── README.md
├── SimpletourDevops/
│ ├── __init__.py
│ ├── apps.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── dockermanager/
│ ├── Docker_Controller.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── domainmanager/
│ └── urls.py
├── manage.py
├── requirements.txt
├── run_eventlet.py
├── saltadmin/
│ ├── Minions_Controller.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ ├── utils.py
│ └── views.py
├── servermanager/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations/
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20161121_1740.py
│ │ ├── 0003_auto_20161128_1031.py
│ │ ├── 0004_auto_20161128_1032.py
│ │ ├── 0005_auto_20161128_1032.py
│ │ ├── 0006_auto_20161128_1034.py
│ │ ├── 0007_auto_20161128_1038.py
│ │ ├── 0008_auto_20161128_1109.py
│ │ ├── 0009_auto_20161128_1112.py
│ │ ├── 0010_auto_20161128_1113.py
│ │ ├── 0011_auto_20161202_1049.py
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── static/
│ └── assets/
│ ├── css/
│ │ ├── _variables.css
│ │ ├── bootstrap-theme.css
│ │ ├── bootstrap.css
│ │ ├── components.css
│ │ ├── core.css
│ │ ├── elements.css
│ │ ├── icons.css
│ │ ├── pages.css
│ │ ├── responsive.css
│ │ ├── statusecho.css
│ │ ├── style.css
│ │ ├── variables.css
│ │ └── xterm.css
│ ├── js/
│ │ ├── bootstrap.js
│ │ ├── detect.js
│ │ ├── fastclick.js
│ │ ├── jquery.app.js
│ │ ├── jquery.blockUI.js
│ │ ├── jquery.core.js
│ │ ├── jquery.nicescroll.js
│ │ ├── jquery.slimscroll.js
│ │ ├── json.js
│ │ ├── json2yaml.js
│ │ ├── npm.js
│ │ ├── spin.js
│ │ ├── waves.js
│ │ └── xterm.js
│ ├── pages/
│ │ ├── chartjs.init.js
│ │ ├── datatables.editable.init.js
│ │ ├── easy-pie-chart.init.js
│ │ ├── jquery.bs-table.js
│ │ ├── jquery.dashboard.js
│ │ ├── jquery.flot.init.js
│ │ ├── jquery.footable.js
│ │ └── jquery.sweet-alert.init.js
│ └── plugins/
│ ├── Chart.js/
│ │ ├── Chart.js
│ │ └── src/
│ │ ├── Chart.Bar.js
│ │ ├── Chart.Core.js
│ │ ├── Chart.Doughnut.js
│ │ ├── Chart.Line.js
│ │ ├── Chart.PolarArea.js
│ │ └── Chart.Radar.js
│ ├── bootstrap-datepicker/
│ │ └── dist/
│ │ ├── css/
│ │ │ ├── bootstrap-datepicker.css
│ │ │ ├── bootstrap-datepicker.standalone.css
│ │ │ ├── bootstrap-datepicker3.css
│ │ │ └── bootstrap-datepicker3.standalone.css
│ │ └── js/
│ │ └── bootstrap-datepicker.js
│ ├── bootstrap-select/
│ │ ├── css/
│ │ │ ├── bootstrap-select.css
│ │ │ └── variables.css
│ │ ├── dist/
│ │ │ ├── css/
│ │ │ │ └── bootstrap-select.css
│ │ │ └── js/
│ │ │ ├── bootstrap-select.js
│ │ │ └── i18n/
│ │ │ ├── defaults-bg_BG.js
│ │ │ ├── defaults-cs_CZ.js
│ │ │ ├── defaults-da_DK.js
│ │ │ ├── defaults-de_DE.js
│ │ │ ├── defaults-en_US.js
│ │ │ ├── defaults-es_CL.js
│ │ │ ├── defaults-eu.js
│ │ │ ├── defaults-fa_IR.js
│ │ │ ├── defaults-fr_FR.js
│ │ │ ├── defaults-hu_HU.js
│ │ │ ├── defaults-it_IT.js
│ │ │ ├── defaults-ko_KR.js
│ │ │ ├── defaults-nl_NL.js
│ │ │ ├── defaults-pl_PL.js
│ │ │ ├── defaults-pt_BR.js
│ │ │ ├── defaults-pt_PT.js
│ │ │ ├── defaults-ro_RO.js
│ │ │ ├── defaults-ru_RU.js
│ │ │ ├── defaults-sk_SK.js
│ │ │ ├── defaults-sl_SI.js
│ │ │ ├── defaults-sv_SE.js
│ │ │ ├── defaults-tr_TR.js
│ │ │ ├── defaults-ua_UA.js
│ │ │ ├── defaults-zh_CN.js
│ │ │ └── defaults-zh_TW.js
│ │ └── js/
│ │ ├── .jshintrc
│ │ ├── bootstrap-select.js
│ │ └── i18n/
│ │ ├── defaults-bg_BG.js
│ │ ├── defaults-cs_CZ.js
│ │ ├── defaults-da_DK.js
│ │ ├── defaults-de_DE.js
│ │ ├── defaults-en_US.js
│ │ ├── defaults-es_CL.js
│ │ ├── defaults-eu.js
│ │ ├── defaults-fa_IR.js
│ │ ├── defaults-fr_FR.js
│ │ ├── defaults-hu_HU.js
│ │ ├── defaults-it_IT.js
│ │ ├── defaults-ko_KR.js
│ │ ├── defaults-nl_NL.js
│ │ ├── defaults-pl_PL.js
│ │ ├── defaults-pt_BR.js
│ │ ├── defaults-pt_PT.js
│ │ ├── defaults-ro_RO.js
│ │ ├── defaults-ru_RU.js
│ │ ├── defaults-sk_SK.js
│ │ ├── defaults-sl_SI.js
│ │ ├── defaults-sv_SE.js
│ │ ├── defaults-tr_TR.js
│ │ ├── defaults-ua_UA.js
│ │ ├── defaults-zh_CN.js
│ │ └── defaults-zh_TW.js
│ ├── bootstrap-table/
│ │ ├── dist/
│ │ │ ├── bootstrap-table-all.js
│ │ │ ├── bootstrap-table-locale-all.js
│ │ │ ├── bootstrap-table.css
│ │ │ ├── bootstrap-table.js
│ │ │ ├── extensions/
│ │ │ │ ├── cookie/
│ │ │ │ │ └── bootstrap-table-cookie.js
│ │ │ │ ├── editable/
│ │ │ │ │ └── bootstrap-table-editable.js
│ │ │ │ ├── export/
│ │ │ │ │ └── bootstrap-table-export.js
│ │ │ │ ├── filter/
│ │ │ │ │ └── bootstrap-table-filter.js
│ │ │ │ ├── filter-control/
│ │ │ │ │ └── bootstrap-table-filter-control.js
│ │ │ │ ├── flat-json/
│ │ │ │ │ └── bootstrap-table-flat-json.js
│ │ │ │ ├── key-events/
│ │ │ │ │ └── bootstrap-table-key-events.js
│ │ │ │ ├── mobile/
│ │ │ │ │ └── bootstrap-table-mobile.js
│ │ │ │ ├── multiple-sort/
│ │ │ │ │ └── bootstrap-table-multiple-sort.js
│ │ │ │ ├── natural-sorting/
│ │ │ │ │ └── bootstrap-table-natural-sorting.js
│ │ │ │ ├── reorder-columns/
│ │ │ │ │ └── bootstrap-table-reorder-columns.js
│ │ │ │ ├── reorder-rows/
│ │ │ │ │ ├── bootstrap-table-reorder-rows.css
│ │ │ │ │ └── bootstrap-table-reorder-rows.js
│ │ │ │ ├── resizable/
│ │ │ │ │ └── bootstrap-table-resizable.js
│ │ │ │ └── toolbar/
│ │ │ │ └── bootstrap-table-toolbar.js
│ │ │ └── locale/
│ │ │ ├── bootstrap-table-ar-SA.js
│ │ │ ├── bootstrap-table-cs-CZ.js
│ │ │ ├── bootstrap-table-da-DK.js
│ │ │ ├── bootstrap-table-de-DE.js
│ │ │ ├── bootstrap-table-el-GR.js
│ │ │ ├── bootstrap-table-en-US.js
│ │ │ ├── bootstrap-table-es-AR.js
│ │ │ ├── bootstrap-table-es-CR.js
│ │ │ ├── bootstrap-table-es-MX.js
│ │ │ ├── bootstrap-table-es-NI.js
│ │ │ ├── bootstrap-table-es-SP.js
│ │ │ ├── bootstrap-table-fr-BE.js
│ │ │ ├── bootstrap-table-fr-FR.js
│ │ │ ├── bootstrap-table-hu-HU.js
│ │ │ ├── bootstrap-table-it-IT.js
│ │ │ ├── bootstrap-table-ja-JP.js
│ │ │ ├── bootstrap-table-ka-GE.js
│ │ │ ├── bootstrap-table-ko-KR.js
│ │ │ ├── bootstrap-table-ms-MY.js
│ │ │ ├── bootstrap-table-nb-NO.js
│ │ │ ├── bootstrap-table-nl-NL.js
│ │ │ ├── bootstrap-table-pl-PL.js
│ │ │ ├── bootstrap-table-pt-BR.js
│ │ │ ├── bootstrap-table-pt-PT.js
│ │ │ ├── bootstrap-table-ro-RO.js
│ │ │ ├── bootstrap-table-ru-RU.js
│ │ │ ├── bootstrap-table-sk-SK.js
│ │ │ ├── bootstrap-table-sv-SE.js
│ │ │ ├── bootstrap-table-th-TH.js
│ │ │ ├── bootstrap-table-tr-TR.js
│ │ │ ├── bootstrap-table-uk-UA.js
│ │ │ ├── bootstrap-table-ur-PK.js
│ │ │ ├── bootstrap-table-vi-VN.js
│ │ │ ├── bootstrap-table-zh-CN.js
│ │ │ └── bootstrap-table-zh-TW.js
│ │ └── src/
│ │ ├── bootstrap-table.css
│ │ ├── bootstrap-table.js
│ │ ├── extensions/
│ │ │ ├── cookie/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-cookie.js
│ │ │ ├── editable/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-editable.js
│ │ │ ├── export/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-export.js
│ │ │ ├── filter/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-filter.js
│ │ │ ├── filter-control/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-filter-control.js
│ │ │ ├── flat-json/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-flat-json.js
│ │ │ ├── key-events/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-key-events.js
│ │ │ ├── mobile/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-mobile.js
│ │ │ ├── multiple-sort/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-multiple-sort.js
│ │ │ ├── natural-sorting/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-natural-sorting.js
│ │ │ ├── reorder-columns/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-reorder-columns.js
│ │ │ ├── reorder-rows/
│ │ │ │ ├── README.md
│ │ │ │ ├── bootstrap-table-reorder-rows.css
│ │ │ │ └── bootstrap-table-reorder-rows.js
│ │ │ ├── resizable/
│ │ │ │ ├── README.md
│ │ │ │ └── bootstrap-table-resizable.js
│ │ │ └── toolbar/
│ │ │ ├── README.md
│ │ │ └── bootstrap-table-toolbar.js
│ │ └── locale/
│ │ ├── README.md
│ │ ├── bootstrap-table-ar-SA.js
│ │ ├── bootstrap-table-cs-CZ.js
│ │ ├── bootstrap-table-da-DK.js
│ │ ├── bootstrap-table-de-DE.js
│ │ ├── bootstrap-table-el-GR.js
│ │ ├── bootstrap-table-en-US.js
│ │ ├── bootstrap-table-en-US.js.template
│ │ ├── bootstrap-table-es-AR.js
│ │ ├── bootstrap-table-es-CR.js
│ │ ├── bootstrap-table-es-MX.js
│ │ ├── bootstrap-table-es-NI.js
│ │ ├── bootstrap-table-es-SP.js
│ │ ├── bootstrap-table-fr-BE.js
│ │ ├── bootstrap-table-fr-FR.js
│ │ ├── bootstrap-table-hu-HU.js
│ │ ├── bootstrap-table-it-IT.js
│ │ ├── bootstrap-table-ja-JP.js
│ │ ├── bootstrap-table-ka-GE.js
│ │ ├── bootstrap-table-ko-KR.js
│ │ ├── bootstrap-table-ms-MY.js
│ │ ├── bootstrap-table-nb-NO.js
│ │ ├── bootstrap-table-nl-NL.js
│ │ ├── bootstrap-table-pl-PL.js
│ │ ├── bootstrap-table-pt-BR.js
│ │ ├── bootstrap-table-pt-PT.js
│ │ ├── bootstrap-table-ro-RO.js
│ │ ├── bootstrap-table-ru-RU.js
│ │ ├── bootstrap-table-sk-SK.js
│ │ ├── bootstrap-table-sv-SE.js
│ │ ├── bootstrap-table-th-TH.js
│ │ ├── bootstrap-table-tr-TR.js
│ │ ├── bootstrap-table-uk-UA.js
│ │ ├── bootstrap-table-ur-PK.js
│ │ ├── bootstrap-table-vi-VN.js
│ │ ├── bootstrap-table-zh-CN.js
│ │ └── bootstrap-table-zh-TW.js
│ ├── bootstrap-touchspin/
│ │ ├── dist/
│ │ │ ├── jquery.bootstrap-touchspin.css
│ │ │ └── jquery.bootstrap-touchspin.js
│ │ └── src/
│ │ ├── jquery.bootstrap-touchspin.css
│ │ └── jquery.bootstrap-touchspin.js
│ ├── custombox/
│ │ └── src/
│ │ ├── css/
│ │ │ └── custombox.css
│ │ └── js/
│ │ ├── custombox.js
│ │ └── legacy.js
│ ├── datatables/
│ │ └── dataTables.bootstrap.js
│ ├── flot-chart/
│ │ ├── jquery.flot.crosshair.js
│ │ ├── jquery.flot.js
│ │ ├── jquery.flot.pie.js
│ │ ├── jquery.flot.resize.js
│ │ ├── jquery.flot.selection.js
│ │ ├── jquery.flot.stack.js
│ │ └── jquery.flot.time.js
│ ├── footable/
│ │ └── css/
│ │ └── footable.core.css
│ ├── jquery-datatables-editable/
│ │ ├── dataTables.bootstrap.js
│ │ ├── datatables.css
│ │ └── jquery.dataTables.js
│ ├── jquery-knob/
│ │ ├── excanvas.js
│ │ └── jquery.knob.js
│ ├── jquery.easy-pie-chart/
│ │ ├── dist/
│ │ │ ├── angular.easypiechart.js
│ │ │ ├── easypiechart.js
│ │ │ └── jquery.easypiechart.js
│ │ └── src/
│ │ ├── angular.directive.js
│ │ ├── easypiechart.js
│ │ ├── jquery.plugin.js
│ │ └── renderer/
│ │ └── canvas.js
│ ├── magnific-popup/
│ │ ├── dist/
│ │ │ ├── jquery.magnific-popup.js
│ │ │ └── magnific-popup.css
│ │ └── src/
│ │ ├── css/
│ │ │ ├── _settings.scss
│ │ │ └── main.scss
│ │ └── js/
│ │ ├── ajax.js
│ │ ├── core.js
│ │ ├── fastclick.js
│ │ ├── gallery.js
│ │ ├── iframe.js
│ │ ├── image.js
│ │ ├── inline.js
│ │ ├── retina.js
│ │ └── zoom.js
│ ├── morris/
│ │ ├── morris.css
│ │ └── morris.js
│ ├── multiselect/
│ │ ├── css/
│ │ │ └── multi-select.css
│ │ └── js/
│ │ └── jquery.multi-select.js
│ ├── notifications/
│ │ ├── notification.css
│ │ └── notify-metro.js
│ ├── notifyjs/
│ │ ├── dist/
│ │ │ ├── notify-combined.js
│ │ │ ├── notify.js
│ │ │ └── styles/
│ │ │ ├── bootstrap/
│ │ │ │ └── notify-bootstrap.js
│ │ │ └── metro/
│ │ │ ├── notify-metro.css
│ │ │ └── notify-metro.js
│ │ └── src/
│ │ ├── notify.coffee
│ │ └── styles/
│ │ ├── STYLES-README.md
│ │ └── bootstrap/
│ │ └── notify-bootstrap.coffee
│ ├── peity/
│ │ └── jquery.peity.js
│ ├── raphael/
│ │ └── raphael-min.js
│ ├── select2/
│ │ ├── .bower.json
│ │ ├── .gitignore
│ │ ├── CONTRIBUTING.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bower.json
│ │ ├── component.json
│ │ ├── composer.json
│ │ ├── package.json
│ │ ├── release.sh
│ │ ├── select2-bootstrap.css
│ │ ├── select2.css
│ │ ├── select2.jquery.json
│ │ ├── select2.js
│ │ ├── select2_locale_ar.js
│ │ ├── select2_locale_az.js
│ │ ├── select2_locale_bg.js
│ │ ├── select2_locale_ca.js
│ │ ├── select2_locale_cs.js
│ │ ├── select2_locale_da.js
│ │ ├── select2_locale_de.js
│ │ ├── select2_locale_el.js
│ │ ├── select2_locale_en.js.template
│ │ ├── select2_locale_es.js
│ │ ├── select2_locale_et.js
│ │ ├── select2_locale_eu.js
│ │ ├── select2_locale_fa.js
│ │ ├── select2_locale_fi.js
│ │ ├── select2_locale_fr.js
│ │ ├── select2_locale_gl.js
│ │ ├── select2_locale_he.js
│ │ ├── select2_locale_hr.js
│ │ ├── select2_locale_hu.js
│ │ ├── select2_locale_id.js
│ │ ├── select2_locale_is.js
│ │ ├── select2_locale_it.js
│ │ ├── select2_locale_ja.js
│ │ ├── select2_locale_ka.js
│ │ ├── select2_locale_ko.js
│ │ ├── select2_locale_lt.js
│ │ ├── select2_locale_lv.js
│ │ ├── select2_locale_mk.js
│ │ ├── select2_locale_ms.js
│ │ ├── select2_locale_nb.js
│ │ ├── select2_locale_nl.js
│ │ ├── select2_locale_pl.js
│ │ ├── select2_locale_pt-BR.js
│ │ ├── select2_locale_pt-PT.js
│ │ ├── select2_locale_ro.js
│ │ ├── select2_locale_rs.js
│ │ ├── select2_locale_ru.js
│ │ ├── select2_locale_sk.js
│ │ ├── select2_locale_sv.js
│ │ ├── select2_locale_th.js
│ │ ├── select2_locale_tr.js
│ │ ├── select2_locale_ug-CN.js
│ │ ├── select2_locale_uk.js
│ │ ├── select2_locale_vi.js
│ │ ├── select2_locale_zh-CN.js
│ │ └── select2_locale_zh-TW.js
│ ├── summernote/
│ │ ├── dist/
│ │ │ ├── summernote-bs3.css
│ │ │ ├── summernote.css
│ │ │ └── summernote.js
│ │ ├── lang/
│ │ │ ├── summernote-ar-AR.js
│ │ │ ├── summernote-bg-BG.js
│ │ │ ├── summernote-ca-ES.js
│ │ │ ├── summernote-cs-CZ.js
│ │ │ ├── summernote-da-DK.js
│ │ │ ├── summernote-de-DE.js
│ │ │ ├── summernote-es-ES.js
│ │ │ ├── summernote-es-EU.js
│ │ │ ├── summernote-fa-IR.js
│ │ │ ├── summernote-fi-FI.js
│ │ │ ├── summernote-fr-FR.js
│ │ │ ├── summernote-he-IL.js
│ │ │ ├── summernote-hu-HU.js
│ │ │ ├── summernote-id-ID.js
│ │ │ ├── summernote-it-IT.js
│ │ │ ├── summernote-ja-JP.js
│ │ │ ├── summernote-ko-KR.js
│ │ │ ├── summernote-lt-LT.js
│ │ │ ├── summernote-nb-NO.js
│ │ │ ├── summernote-nl-NL.js
│ │ │ ├── summernote-pl-PL.js
│ │ │ ├── summernote-pt-BR.js
│ │ │ ├── summernote-pt-PT.js
│ │ │ ├── summernote-ro-RO.js
│ │ │ ├── summernote-ru-RU.js
│ │ │ ├── summernote-sk-SK.js
│ │ │ ├── summernote-sl-SI.js
│ │ │ ├── summernote-sr-RS-Latin.js
│ │ │ ├── summernote-sr-RS.js
│ │ │ ├── summernote-sv-SE.js
│ │ │ ├── summernote-th-TH.js
│ │ │ ├── summernote-tr-TR.js
│ │ │ ├── summernote-uk-UA.js
│ │ │ ├── summernote-vi-VN.js
│ │ │ ├── summernote-zh-CN.js
│ │ │ └── summernote-zh-TW.js
│ │ ├── meteor/
│ │ │ ├── README.md
│ │ │ ├── package-standalone.js
│ │ │ ├── package.js
│ │ │ ├── publish.sh
│ │ │ ├── runtests.sh
│ │ │ └── test.js
│ │ ├── plugin/
│ │ │ ├── summernote-ext-hello.js
│ │ │ ├── summernote-ext-hint.js
│ │ │ └── summernote-ext-video.js
│ │ └── src/
│ │ ├── css/
│ │ │ ├── elements.css
│ │ │ └── summernote.css
│ │ ├── js/
│ │ │ ├── EventHandler.js
│ │ │ ├── Renderer.js
│ │ │ ├── app.js
│ │ │ ├── core/
│ │ │ │ ├── agent.js
│ │ │ │ ├── async.js
│ │ │ │ ├── dom.js
│ │ │ │ ├── func.js
│ │ │ │ ├── key.js
│ │ │ │ ├── list.js
│ │ │ │ └── range.js
│ │ │ ├── defaults.js
│ │ │ ├── editing/
│ │ │ │ ├── Bullet.js
│ │ │ │ ├── History.js
│ │ │ │ ├── Style.js
│ │ │ │ ├── Table.js
│ │ │ │ └── Typing.js
│ │ │ ├── intro.js
│ │ │ ├── module/
│ │ │ │ ├── Button.js
│ │ │ │ ├── Clipboard.js
│ │ │ │ ├── Codeview.js
│ │ │ │ ├── DragAndDrop.js
│ │ │ │ ├── Editor.js
│ │ │ │ ├── Fullscreen.js
│ │ │ │ ├── Handle.js
│ │ │ │ ├── HelpDialog.js
│ │ │ │ ├── ImageDialog.js
│ │ │ │ ├── LinkDialog.js
│ │ │ │ ├── Popover.js
│ │ │ │ ├── Statusbar.js
│ │ │ │ └── Toolbar.js
│ │ │ ├── outro.js
│ │ │ └── summernote.js
│ │ ├── less/
│ │ │ ├── elements.less
│ │ │ └── summernote.less
│ │ └── sass/
│ │ └── summernote.scss
│ ├── sweetalert/
│ │ └── dist/
│ │ ├── sweetalert-dev.js
│ │ └── sweetalert.css
│ ├── switchery/
│ │ ├── dist/
│ │ │ ├── switchery.css
│ │ │ └── switchery.js
│ │ ├── meteor/
│ │ │ ├── export.js
│ │ │ └── tests.js
│ │ ├── switchery.css
│ │ └── switchery.js
│ ├── tiny-editable/
│ │ ├── mindmup-editabletable.js
│ │ └── numeric-input-example.js
│ └── waypoints/
│ └── lib/
│ ├── jquery.waypoints.js
│ ├── noframework.waypoints.js
│ ├── shortcuts/
│ │ ├── infinite.js
│ │ ├── inview.js
│ │ └── sticky.js
│ ├── waypoints.debug.js
│ └── zepto.waypoints.js
├── supervisord.conf
├── templates/
│ ├── 403.html
│ ├── 404.html
│ ├── 500.html
│ ├── base.html
│ ├── dockermanager/
│ │ ├── containers_list.html
│ │ ├── dockerhosts_add.html
│ │ ├── dockerhosts_edit.html
│ │ ├── dockerhosts_list.html
│ │ ├── dockerhosts_logs.html
│ │ ├── images_list.html
│ │ └── websocket.html
│ ├── domainmanager/
│ │ ├── domain_list.html
│ │ └── domain_records.html
│ ├── saltadmin/
│ │ ├── key_list.html
│ │ ├── minion_status.html
│ │ ├── salt_cmd.html
│ │ ├── saltjob_detail.html
│ │ ├── saltjob_list.html
│ │ ├── saltmaster_list.html
│ │ └── saltmodule_deploy.html
│ ├── servermanager/
│ │ ├── assets_list.html
│ │ ├── assetschange.html
│ │ ├── assetsdetail.html
│ │ ├── hosts.html
│ │ ├── servers_change.html
│ │ ├── servers_detail.html
│ │ └── servers_list.html
│ ├── tempdir/
│ │ ├── foot_script.html
│ │ ├── head_css.html
│ │ └── head_script.html
│ └── webapp/
│ ├── index.html
│ ├── login.html
│ ├── register.html
│ ├── resetpass.html
│ ├── sendresetpw.html
│ ├── sysrestuserpassword.html
│ └── userinfo.html
├── uwsgi.ini
└── webapp/
├── Extends/
│ ├── PageList.py
│ └── __init__.py
├── __init__.py
├── admin.py
├── apps.py
├── forms.py
├── migrations/
│ └── __init__.py
├── models.py
├── tasks.py
├── tests.py
├── urls.py
└── views.py
SYMBOL INDEX (797 symbols across 95 files)
FILE: Publicapi/dnspod/apicn.py
class ApiCn (line 11) | class ApiCn:
method __init__ (line 12) | def __init__(self, email, password, **kw):
method request (line 23) | def request(self, **kw):
class InfoVersion (line 44) | class InfoVersion(ApiCn):
class UserDetail (line 47) | class UserDetail(ApiCn):
class UserInfo (line 50) | class UserInfo(ApiCn):
class UserLog (line 53) | class UserLog(ApiCn):
class DomainCreate (line 56) | class DomainCreate(ApiCn):
method __init__ (line 57) | def __init__(self, domain, **kw):
class DomainId (line 61) | class DomainId(ApiCn):
method __init__ (line 62) | def __init__(self, domain, **kw):
class DomainList (line 66) | class DomainList(ApiCn):
class _DomainApiBase (line 69) | class _DomainApiBase(ApiCn):
method __init__ (line 70) | def __init__(self, domain_id, **kw):
class DomainRemove (line 74) | class DomainRemove(_DomainApiBase):
class DomainStatus (line 77) | class DomainStatus(_DomainApiBase):
method __init__ (line 78) | def __init__(self, status, **kw):
class DomainInfo (line 82) | class DomainInfo(_DomainApiBase):
class DomainLog (line 85) | class DomainLog(_DomainApiBase):
class RecordType (line 88) | class RecordType(ApiCn):
method __init__ (line 89) | def __init__(self, domain_grade, **kw):
class RecordLine (line 93) | class RecordLine(ApiCn):
method __init__ (line 94) | def __init__(self, domain_grade, **kw):
class RecordCreate (line 98) | class RecordCreate(_DomainApiBase):
method __init__ (line 99) | def __init__(self, sub_domain, record_type, record_line, value, ttl, m...
class RecordModify (line 111) | class RecordModify(RecordCreate):
method __init__ (line 112) | def __init__(self, record_id, **kw):
class RecordList (line 116) | class RecordList(_DomainApiBase):
class _RecordBase (line 119) | class _RecordBase(_DomainApiBase):
method __init__ (line 120) | def __init__(self, record_id, **kw):
class RecordRemove (line 124) | class RecordRemove(_RecordBase):
class RecordDdns (line 127) | class RecordDdns(_DomainApiBase):
method __init__ (line 128) | def __init__(self, record_id, sub_domain, record_line, **kw):
class RecordStatus (line 137) | class RecordStatus(_RecordBase):
method __init__ (line 138) | def __init__(self, status, **kw):
class RecordInfo (line 142) | class RecordInfo(_RecordBase):
FILE: Publicapi/dockerapi/Manager.py
class Dockerapi (line 13) | class Dockerapi(object):
method __init__ (line 14) | def __init__(self, host, port):
method GetallContainers (line 17) | def GetallContainers(self):
method SearchContainers (line 21) | def SearchContainers(self, Searchparameter):
method ContainerStatus (line 25) | def ContainerStatus(self, Status):
method InspectContainer (line 29) | def InspectContainer(self,name):
method Dockerversion (line 34) | def Dockerversion(self):
method StartContainer (line 38) | def StartContainer(self, name):
method StopContainer (line 42) | def StopContainer(self, name):
method DelayedstopContainer (line 46) | def DelayedstopContainer(self, name, timeout):
method Dockerinfo (line 50) | def Dockerinfo(self):
method RestartContainer (line 54) | def RestartContainer(self, name):
method DelayedRestart (line 58) | def DelayedRestart(self, name, timeout):
method RenameDocker (line 62) | def RenameDocker(self, name, newname):
method TopContainer (line 66) | def TopContainer(self, name):
method killContainer (line 70) | def killContainer(self, name):
method PauseContainer (line 74) | def PauseContainer(self, name):
method UnpauseContainer (line 78) | def UnpauseContainer(self, name):
method removeContainer (line 82) | def removeContainer(self, name, v=False, link=False, force=False):
method LogContainer (line 86) | def LogContainer(self,name,timestamps=False,tail=all):
method AllImages (line 93) | def AllImages(self):
method DeleteImages (line 97) | def DeleteImages(self,imagename):
FILE: Publicapi/saltstackapi/Assets_Module.py
class ServerBaseInfo (line 6) | class ServerBaseInfo(object):
method __init__ (line 7) | def __init__(self,data,minion):
class ServerCPUInfo (line 23) | class ServerCPUInfo(ServerBaseInfo):
method __init__ (line 24) | def __init__(self,data,minion):
method ServerCPU (line 27) | def ServerCPU(self):
class ServerNICInfo (line 41) | class ServerNICInfo(ServerBaseInfo):
method __init__ (line 42) | def __init__(self,data,minion):
method ServerNIC (line 45) | def ServerNIC(self):
class ServerDiskInfo (line 50) | class ServerDiskInfo(ServerBaseInfo):
method __init__ (line 51) | def __init__(self,data,minion):
method ServerDISK (line 54) | def ServerDISK(self):
FILE: Publicapi/saltstackapi/SaltConApi.py
class SaltApi (line 12) | class SaltApi(object):
method __init__ (line 14) | def __init__(self,url,user,password):
method PostRequest (line 26) | def PostRequest(self,obj,parurl='/'):
method grains (line 34) | def grains(self,tgt,args):
method grainsall (line 40) | def grainsall(self,tgt):
method pillarall (line 46) | def pillarall(self,tgt):
method List_all_keys (line 53) | def List_all_keys(self):
method shell_remote_execution (line 63) | def shell_remote_execution(self,tgt,arg):
method Softwarete_deploy (line 71) | def Softwarete_deploy(self,tgt,arg):
method actionKeys (line 82) | def actionKeys(self,keystrings,action):
method dictActionKeys (line 92) | def dictActionKeys(self,keydict,action):
method cpFiletoMinions (line 98) | def cpFiletoMinions(self,tgt):
method runner (line 105) | def runner(self,arg):
method salt_runner (line 112) | def salt_runner(self, jid):
method SaltEvents (line 125) | def SaltEvents(self):
method AcceptKey (line 131) | def AcceptKey(self, key_id):
method DeleteKey (line 138) | def DeleteKey(self, key_id):
method RejectKey (line 145) | def RejectKey(self, key_id):
method Saltalive (line 151) | def Saltalive(self,tgt):
function format (line 162) | def format(data):
FILE: SimpletourDevops/apps.py
class SuitConfig (line 9) | class SuitConfig(DjangoSuitConfig):
FILE: dockermanager/Docker_Controller.py
function GetDockerServerinfo (line 16) | def GetDockerServerinfo():
function GetDockerImages (line 60) | def GetDockerImages():
FILE: dockermanager/admin.py
class DockerHostModels (line 4) | class DockerHostModels(admin.ModelAdmin):
class DockerContainerModels (line 6) | class DockerContainerModels(admin.ModelAdmin):
FILE: dockermanager/apps.py
class DockermanagerConfig (line 6) | class DockermanagerConfig(AppConfig):
FILE: dockermanager/forms.py
class DockerServerAdd (line 19) | class DockerServerAdd(forms.Form):
class DockerServerEdit (line 35) | class DockerServerEdit(ModelForm):
class Meta (line 36) | class Meta:
FILE: dockermanager/models.py
class Dockerimage (line 9) | class Dockerimage(models.Model):
method __unicode__ (line 18) | def __unicode__(self):
class Meta (line 21) | class Meta:
class DockerHost (line 26) | class DockerHost(models.Model):
method __unicode__ (line 40) | def __unicode__(self):
class Meta (line 43) | class Meta:
class DockerContainer (line 48) | class DockerContainer(models.Model):
method __unicode__ (line 58) | def __unicode__(self):
class Meta (line 61) | class Meta:
class DockerContainerInfo (line 69) | class DockerContainerInfo(models.Model):
class ContainerPorts (line 83) | class ContainerPorts(models.Model):
method __unicode__ (line 90) | def __unicode__(self):
class Meta (line 93) | class Meta:
FILE: dockermanager/views.py
function Dockercontainerlist (line 26) | def Dockercontainerlist(request,page):
function DockercontainerSearch (line 70) | def DockercontainerSearch(request,page):
function DockerHosts (line 109) | def DockerHosts(request):
function DockerHostAdd (line 131) | def DockerHostAdd(request):
function DockerImages (line 162) | def DockerImages(request,page):
function DockerImageDelete (line 186) | def DockerImageDelete(request, imageid):
function DockerHostDel (line 205) | def DockerHostDel(request,hostid):
function DockerHostEdit (line 215) | def DockerHostEdit(request,hostid):
function DockerContainerStop (line 233) | def DockerContainerStop(request,containerid):
function DockerContainerRestart (line 244) | def DockerContainerRestart(request,containerId):
function DockerContainerDel (line 256) | def DockerContainerDel(request,containerId):
function DockerContainerStart (line 270) | def DockerContainerStart(request, containerId):
function DockerLogOutput (line 282) | def DockerLogOutput(request,containerid):
function StartCeleryStatus (line 308) | def StartCeleryStatus(request,celeryid):
function StopCeleryStatus (line 334) | def StopCeleryStatus(request,celeryid):
function RestartCeleryStatus (line 360) | def RestartCeleryStatus(request,celeryid):
function DeleteCeleryStatus (line 384) | def DeleteCeleryStatus(request,celeryid):
function webSocket (line 409) | def webSocket(request,containerId):
function getsocket (line 419) | def getsocket(request,containerId):
FILE: saltadmin/Minions_Controller.py
function GetALLkeys (line 17) | def GetALLkeys():
function UpdateMinionInfo (line 57) | def UpdateMinionInfo(mininboj,minions,url,username,password):
function GetMinionConf (line 81) | def GetMinionConf():
function GetJobs (line 96) | def GetJobs(url,username,password):
function GetSaltJobs (line 109) | def GetSaltJobs():
function JobResultFromat (line 117) | def JobResultFromat(data):
FILE: saltadmin/admin.py
class SaltJobsModels (line 4) | class SaltJobsModels(admin.ModelAdmin):
class CmdRunLogModels (line 9) | class CmdRunLogModels(admin.ModelAdmin):
class MinionGroupModels (line 13) | class MinionGroupModels(admin.ModelAdmin):
FILE: saltadmin/apps.py
class SaltadminConfig (line 6) | class SaltadminConfig(AppConfig):
FILE: saltadmin/forms.py
class KeyManager (line 10) | class KeyManager(forms.Form):
class CheckSaltServer (line 15) | class CheckSaltServer(forms.ModelForm):
class Meta (line 37) | class Meta:
FILE: saltadmin/models.py
class SaltServer (line 6) | class SaltServer(models.Model):
method __unicode__ (line 16) | def __unicode__(self):
class Meta (line 19) | class Meta:
class Modules (line 27) | class Modules(models.Model):
method __unicode__ (line 31) | def __unicode__(self):
class Meta (line 34) | class Meta:
class Minions (line 54) | class Minions(models.Model):
method __unicode__ (line 65) | def __unicode__(self):
class Meta (line 68) | class Meta:
class MinionStatus (line 73) | class MinionStatus(models.Model):
class MinionGroup (line 81) | class MinionGroup(models.Model):
method __unicode__ (line 85) | def __unicode__(self):
class Meta (line 88) | class Meta:
class CmdRunLog (line 93) | class CmdRunLog(models.Model):
class Meta (line 103) | class Meta:
class SaltJobs (line 108) | class SaltJobs(models.Model):
class Meta (line 117) | class Meta:
class ModuleDeployLog (line 123) | class ModuleDeployLog(models.Model):
class Meta (line 138) | class Meta:
FILE: saltadmin/utils.py
function get_system_info (line 8) | def get_system_info():
FILE: saltadmin/views.py
function SaltMasterList (line 21) | def SaltMasterList(request):
function SaltMasterDelete (line 37) | def SaltMasterDelete(request,masterid):
function SalMasterChange (line 47) | def SalMasterChange(request,masterid):
function KeyList (line 78) | def KeyList(request):
function Minion_Status (line 117) | def Minion_Status(request):
function SoftInstall (line 131) | def SoftInstall(request):
function JobList (line 199) | def JobList(request,page):
function jobdetail (line 222) | def jobdetail(request):
function RemoteCmd (line 241) | def RemoteCmd(request):
function CmdResult (line 302) | def CmdResult(request,jid):
function DeployResult (line 329) | def DeployResult(request,jid):
function SaltMinionGrains (line 358) | def SaltMinionGrains(request):
FILE: servermanager/admin.py
class ServerResource (line 18) | class ServerResource(resources.ModelResource):
class Meta (line 19) | class Meta:
class AssetsResource (line 22) | class AssetsResource(resources.ModelResource):
class Meta (line 23) | class Meta:
class AssetsAdmin (line 35) | class AssetsAdmin(ImportExportModelAdmin):
class CpuModels (line 48) | class CpuModels(admin.ModelAdmin):
class DiskModels (line 53) | class DiskModels(admin.ModelAdmin):
class NicModels (line 57) | class NicModels(admin.ModelAdmin):
class SoftwareModels (line 62) | class SoftwareModels(admin.ModelAdmin):
class DeviceTypeModels (line 65) | class DeviceTypeModels(admin.ModelAdmin):
class BusinessModels (line 69) | class BusinessModels(admin.ModelAdmin):
class ProviderModels (line 74) | class ProviderModels(admin.ModelAdmin):
class ServerModels (line 77) | class ServerModels(admin.ModelAdmin):
method get_idc (line 81) | def get_idc(self, obj):
class IdcModels (line 87) | class IdcModels(admin.ModelAdmin):
FILE: servermanager/apps.py
class ServermanagerConfig (line 6) | class ServermanagerConfig(AppConfig):
FILE: servermanager/migrations/0001_initial.py
class Migration (line 9) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0002_auto_20161121_1740.py
class Migration (line 10) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0003_auto_20161128_1031.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0004_auto_20161128_1032.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0005_auto_20161128_1032.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0006_auto_20161128_1034.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0007_auto_20161128_1038.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0008_auto_20161128_1109.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0009_auto_20161128_1112.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0010_auto_20161128_1113.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/migrations/0011_auto_20161202_1049.py
class Migration (line 8) | class Migration(migrations.Migration):
FILE: servermanager/models.py
class DeviceType (line 8) | class DeviceType(models.Model):
method __unicode__ (line 11) | def __unicode__(self):
class Meta (line 14) | class Meta:
class IDC (line 24) | class IDC(models.Model):
method __unicode__ (line 31) | def __unicode__(self):
class Meta (line 34) | class Meta:
class Business (line 41) | class Business(models.Model):
method __unicode__ (line 45) | def __unicode__(self):
class Meta (line 48) | class Meta:
class Provider (line 58) | class Provider(models.Model):
method __unicode__ (line 65) | def __unicode__(self):
class Meta (line 68) | class Meta:
class Assets (line 75) | class Assets(models.Model):
method __unicode__ (line 130) | def __unicode__(self):
class Meta (line 133) | class Meta:
class Software (line 144) | class Software(models.Model):
method __unicode__ (line 149) | def __unicode__(self):
class Meta (line 152) | class Meta:
class Server (line 161) | class Server(models.Model):
method __unicode__ (line 214) | def __unicode__(self):
class Meta (line 217) | class Meta:
class Cpu (line 225) | class Cpu(models.Model):
method __unicode__ (line 253) | def __unicode__(self):
class Meta (line 256) | class Meta:
class Disk (line 259) | class Disk(models.Model):
method __unicode__ (line 288) | def __unicode__(self):
class Meta (line 292) | class Meta:
class NIC (line 295) | class NIC(models.Model):
method __unicode__ (line 309) | def __unicode__(self):
class Meta (line 312) | class Meta:
FILE: servermanager/views.py
function HostLists (line 15) | def HostLists(request):
function AssetsLists (line 20) | def AssetsLists(request,page):
function AssetsDetail (line 67) | def AssetsDetail(request,id):
function ServerList (line 76) | def ServerList(request,page):
function ServerDetail (line 114) | def ServerDetail(request,id):
function DeleteServer (line 137) | def DeleteServer(request,id):
function DeleteAsset (line 149) | def DeleteAsset(request,id):
function ChangeAsset (line 166) | def ChangeAsset(request,id):
function ChangeServer (line 227) | def ChangeServer(request,id):
function UpdateServer (line 313) | def UpdateServer(request,id):
function CeleryStatus (line 322) | def CeleryStatus(request,celeryid):
FILE: static/assets/js/bootstrap.js
function transitionEnd (line 34) | function transitionEnd() {
function removeElement (line 126) | function removeElement() {
function Plugin (line 142) | function Plugin(option) {
function Plugin (line 251) | function Plugin(option) {
function Plugin (line 470) | function Plugin(option) {
function getTargetFromTrigger (line 689) | function getTargetFromTrigger($trigger) {
function Plugin (line 701) | function Plugin(option) {
function getParent (line 768) | function getParent($this) {
function clearMenus (line 781) | function clearMenus(e) {
function Plugin (line 874) | function Plugin(option) {
function Plugin (line 1200) | function Plugin(option, _relatedTarget) {
function complete (line 1566) | function complete() {
function Plugin (line 1736) | function Plugin(option) {
function Plugin (line 1845) | function Plugin(option) {
function ScrollSpy (line 1888) | function ScrollSpy(element, options) {
function Plugin (line 2008) | function Plugin(option) {
function next (line 2117) | function next() {
function Plugin (line 2163) | function Plugin(option) {
function Plugin (line 2320) | function Plugin(option) {
FILE: static/assets/js/fastclick.js
function FastClick (line 20) | function FastClick(layer) {
FILE: static/assets/js/jquery.app.js
function executeFunctionByName (line 202) | function executeFunctionByName(functionName, context /*, args */) {
function resizeitems (line 258) | function resizeitems(){
function initscrolls (line 266) | function initscrolls(){
function toggle_slimscroll (line 283) | function toggle_slimscroll(item){
FILE: static/assets/js/jquery.blockUI.js
function setup (line 19) | function setup($) {
FILE: static/assets/js/jquery.nicescroll.js
function k (line 9) | function k(){var d=b.win;if("zIndex"in d)return d.zIndex();for(;0<d.leng...
function l (line 9) | function l(d,c,f){c=d.css(c);d=parseFloat(c);return isNaN(d)?(d=u[c]||0,...
function q (line 9) | function q(d,c,f,g){b._bind(d,c,function(b){b=b?b:window.event;var g={or...
function t (line 10) | function t(d,c,f){var g,e;0==d.deltaMode?(g=-Math.floor(d.deltaX*(b.opt....
function e (line 93) | function e(){if(b.cancelAnimationFrame)return!0;b.scrollrunning=!0;if(p=...
FILE: static/assets/js/jquery.slimscroll.js
function _onWheel (line 314) | function _onWheel(e)
function scrollContent (line 336) | function scrollContent(y, isWheel, isJump)
function attachWheel (line 385) | function attachWheel(target)
function getBarHeight (line 398) | function getBarHeight()
function showBar (line 409) | function showBar()
function hideBar (line 444) | function hideBar()
FILE: static/assets/js/json2yaml.js
function getType (line 7) | function getType(obj) {
function convert (line 24) | function convert(obj, ret) {
function convertArray (line 49) | function convertArray(obj, ret) {
function convertHash (line 61) | function convertHash(obj, ret) {
function normalizeString (line 80) | function normalizeString(str) {
function convertString (line 88) | function convertString(obj, ret) {
FILE: static/assets/js/spin.js
function createEl (line 49) | function createEl(tag, prop) {
function ins (line 60) | function ins(parent /* child1, child2, ...*/) {
function addAnimation (line 73) | function addAnimation(alpha, trail, i, lines) {
function vendor (line 99) | function vendor(el, prop) {
function css (line 115) | function css(el, prop) {
function merge (line 126) | function merge(obj) {
function getColor (line 139) | function getColor(color, idx) {
function Spinner (line 169) | function Spinner(o) {
function fill (line 249) | function fill(color, shadow) {
function initVML (line 288) | function initVML() {
FILE: static/assets/js/waves.js
function isWindow (line 10) | function isWindow(obj) {
function getWindow (line 14) | function getWindow(elem) {
function offset (line 18) | function offset(elem) {
function convertStyle (line 35) | function convertStyle(obj) {
function getWavesEffectElement (line 246) | function getWavesEffectElement(e) {
function showEffect (line 271) | function showEffect(e) {
function t (line 338) | function t(e){var t=e.length,r=$.type(e);return"function"===r||$.isWindo...
function n (line 338) | function n(e,r){var a=r||[];return null!=e&&(t(Object(e))?!function(e,t)...
function e (line 338) | function e(){for(var e=this.offsetParent||document;e&&"html"===!e.nodeTy...
function n (line 338) | function n(e){for(var t=-1,r=e?e.length:0,a=[];++t<r;){var n=e[t];n&&a.p...
function o (line 338) | function o(e){return g.isWrapped(e)?e=[].slice.call(e):g.isNode(e)&&(e=[...
function i (line 338) | function i(e){var t=$.data(e,"velocity");return null===t?a:t}
function s (line 338) | function s(e){return function(t){return Math.round(t*e)*(1/e)}}
function l (line 338) | function l(e,r,a,n){function o(e,t){return 1-3*t+3*e}function i(e,t){ret...
function u (line 338) | function u(e,t){var r=e;return g.isString(e)?v.Easings[e]||(r=!1):r=g.is...
function c (line 338) | function c(e){if(e){var t=(new Date).getTime(),r=v.State.calls.length;r>...
function p (line 338) | function p(e,t){if(!v.State.calls[e])return!1;for(var r=v.State.calls[e]...
function e (line 338) | function e(e){return-e.tension*e.x-e.friction*e.v}
function t (line 338) | function t(t,r,a){var n={x:t.x+a.dx*r,v:t.v+a.dv*r,tension:t.tension,fri...
function r (line 338) | function r(r,a){var n={dx:r.v,dv:e(r)},o=t(r,.5*a,n),i=t(r,.5*a,o),s=t(r...
function s (line 338) | function s(e,r){function n(){u&&x.setPropertyValue(e,"display","none")}v...
function t (line 338) | function t(t){return parseFloat(x.getPropertyValue(e,t))}
function e (line 338) | function e(){return l?T.promise||null:f}
function n (line 338) | function n(){function e(e){function p(e,t){var r=a,i=a,s=a;return g.isAr...
function k (line 339) | function k(a,b,c){return setTimeout(q(a,c),b)}
function l (line 339) | function l(a,b,c){return Array.isArray(a)?(m(a,c[b],c),!0):!1}
function m (line 339) | function m(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.lengt...
function n (line 339) | function n(a,b,c){for(var e=Object.keys(b),f=0;f<e.length;)(!c||c&&a[e[f...
function o (line 339) | function o(a,b){return n(a,b,!0)}
function p (line 339) | function p(a,b,c){var e,d=b.prototype;e=a.prototype=Object.create(d),e.c...
function q (line 339) | function q(a,b){return function(){return a.apply(b,arguments)}}
function r (line 339) | function r(a,b){return typeof a==g?a.apply(b?b[0]||d:d,b):a}
function s (line 339) | function s(a,b){return a===d?b:a}
function t (line 339) | function t(a,b,c){m(x(b),function(b){a.addEventListener(b,c,!1)})}
function u (line 339) | function u(a,b,c){m(x(b),function(b){a.removeEventListener(b,c,!1)})}
function v (line 339) | function v(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}
function w (line 339) | function w(a,b){return a.indexOf(b)>-1}
function x (line 339) | function x(a){return a.trim().split(/\s+/g)}
function y (line 339) | function y(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;d<a.l...
function z (line 339) | function z(a){return Array.prototype.slice.call(a,0)}
function A (line 339) | function A(a,b,c){for(var d=[],e=[],f=0;f<a.length;){var g=b?a[f][b]:a[f...
function B (line 339) | function B(a,b){for(var c,f,g=b[0].toUpperCase()+b.slice(1),h=0;h<e.leng...
function D (line 339) | function D(){return C++}
function E (line 339) | function E(a){var b=a.ownerDocument;return b.defaultView||b.parentWindow}
function ab (line 339) | function ab(a,b){var c=this;this.manager=a,this.callback=b,this.element=...
function bb (line 339) | function bb(a){var b,c=a.options.inputClass;return b=c?c:H?wb:I?Eb:G?Gb:...
function cb (line 339) | function cb(a,b,c){var d=c.pointers.length,e=c.changedPointers.length,f=...
function db (line 339) | function db(a,b){var c=a.session,d=b.pointers,e=d.length;c.firstInput||(...
function eb (line 339) | function eb(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=...
function fb (line 339) | function fb(a,b){var f,g,h,j,c=a.lastInterval||b,e=b.timeStamp-c.timeSta...
function gb (line 339) | function gb(a){for(var b=[],c=0;c<a.pointers.length;)b[c]={clientX:h(a.p...
function hb (line 339) | function hb(a){var b=a.length;if(1===b)return{x:h(a[0].clientX),y:h(a[0]...
function ib (line 339) | function ib(a,b,c){return{x:b/a||0,y:c/a||0}}
function jb (line 339) | function jb(a,b){return a===b?S:i(a)>=i(b)?a>0?T:U:b>0?V:W}
function kb (line 339) | function kb(a,b,c){c||(c=$);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];retu...
function lb (line 339) | function lb(a,b,c){c||(c=$);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];retu...
function mb (line 339) | function mb(a,b){return lb(b[1],b[0],_)-lb(a[1],a[0],_)}
function nb (line 339) | function nb(a,b){return kb(b[0],b[1],_)/kb(a[0],a[1],_)}
function rb (line 339) | function rb(){this.evEl=pb,this.evWin=qb,this.allow=!0,this.pressed=!1,a...
function wb (line 339) | function wb(){this.evEl=ub,this.evWin=vb,ab.apply(this,arguments),this.s...
function Ab (line 339) | function Ab(){this.evTarget=yb,this.evWin=zb,this.started=!1,ab.apply(th...
function Bb (line 339) | function Bb(a,b){var c=z(a.touches),d=z(a.changedTouches);return b&(Q|R)...
function Eb (line 339) | function Eb(){this.evTarget=Db,this.targetIds={},ab.apply(this,arguments)}
function Fb (line 339) | function Fb(a,b){var c=z(a.touches),d=this.targetIds;if(b&(O|P)&&1===c.l...
function Gb (line 339) | function Gb(){ab.apply(this,arguments);var a=q(this.handler,this);this.t...
function Pb (line 339) | function Pb(a,b){this.manager=a,this.set(b)}
function Qb (line 339) | function Qb(a){if(w(a,Mb))return Mb;var b=w(a,Nb),c=w(a,Ob);return b&&c?...
function Yb (line 339) | function Yb(a){this.id=D(),this.manager=null,this.options=o(a||{},this.d...
function Zb (line 339) | function Zb(a){return a&Wb?"cancel":a&Ub?"end":a&Tb?"move":a&Sb?"start":""}
function $b (line 339) | function $b(a){return a==W?"down":a==V?"up":a==T?"left":a==U?"right":""}
function _b (line 339) | function _b(a,b){var c=b.manager;return c?c.get(a):a}
function ac (line 339) | function ac(){Yb.apply(this,arguments)}
function bc (line 339) | function bc(){ac.apply(this,arguments),this.pX=null,this.pY=null}
function cc (line 339) | function cc(){ac.apply(this,arguments)}
function dc (line 339) | function dc(){Yb.apply(this,arguments),this._timer=null,this._input=null}
function ec (line 339) | function ec(){ac.apply(this,arguments)}
function fc (line 339) | function fc(){ac.apply(this,arguments)}
function gc (line 339) | function gc(){Yb.apply(this,arguments),this.pTime=!1,this.pCenter=!1,thi...
function hc (line 339) | function hc(a,b){return b=b||{},b.recognizers=s(b.recognizers,hc.default...
function kc (line 339) | function kc(a,b){b=b||{},this.options=o(b,hc.defaults),this.options.inpu...
function lc (line 339) | function lc(a,b){var c=a.element;m(a.options.cssProps,function(a,d){c.st...
function mc (line 339) | function mc(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.ges...
function d (line 339) | function d(d){b.manager.emit(b.options.event+(d?Zb(c):""),a)}
function hammerify (line 348) | function hammerify(el, options) {
FILE: static/assets/js/xterm.js
function s (line 1) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
function CompositionHelper (line 20) | function CompositionHelper(textarea, compositionView, terminal) {
function EventEmitter (line 232) | function EventEmitter() {
function on (line 265) | function on() {
function Viewport (line 312) | function Viewport(terminal, viewportElement, scrollArea, charMeasureElem...
function prepareTextForClipboard (line 438) | function prepareTextForClipboard(text) {
function copyHandler (line 457) | function copyHandler(ev, term) {
function pasteHandler (line 475) | function pasteHandler(ev, term) {
function rightClickHandler (line 510) | function rightClickHandler(ev, term) {
function _interopRequireWildcard (line 660) | function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj...
function Terminal (line 685) | function Terminal(options){var self=this;if(!(this instanceof Terminal))...
function out (line 723) | function out(r,g,b){colors.push('#'+hex(r)+hex(g)+hex(b));}
function hex (line 723) | function hex(c){c=c.toString(16);return c.length<2?'0'+c:c;}
function rightClickHandlerWrapper (line 749) | function rightClickHandlerWrapper(ev){_Clipboard.rightClickHandler.call(...
function sendButton (line 793) | function sendButton(ev){var button,pos;// get the xterm-style button
function sendMove (line 802) | function sendMove(ev){var button=pressed,pos;pos=getCoords(ev);if(!pos)r...
function encode (line 806) | function encode(data,ch){if(!self.utfMouse){if(ch===255)return data.push...
function sendEvent (line 812) | function sendEvent(button,pos){// self.emit('mouse', {
function getButton (line 820) | function getButton(ev){var button,shift,meta,ctrl,mod;// two low bits:
function getCoords (line 833) | function getCoords(ev){var x,y,w,h,el;// ignore browsers without pageX f...
function on (line 2206) | function on(el,type,handler,capture){if(!Array.isArray(el)){el=[el];}el....
function off (line 2206) | function off(el,type,handler,capture){el.removeEventListener(type,handle...
function cancel (line 2206) | function cancel(ev,force){if(!this.cancelEvents&&!force){return;}ev.prev...
function inherits (line 2206) | function inherits(child,parent){function f(){this.constructor=child;}f.p...
function isBoldBroken (line 2208) | function isBoldBroken(document){var body=document.getElementsByTagName('...
function indexOf (line 2208) | function indexOf(obj,el){var i=obj.length;while(i--){if(obj[i]===el)retu...
function isThirdLevelShift (line 2208) | function isThirdLevelShift(term,ev){var thirdLevelKey=term.browser.isMac...
function matchColor (line 2209) | function matchColor(r1,g1,b1){var hash=r1<<16|g1<<8|b1;if(matchColor._ca...
function each (line 2210) | function each(obj,iter,con){if(obj.forEach)return obj.forEach(iter,con);...
function keys (line 2210) | function keys(obj){if(Object.keys)return Object.keys(obj);var key,keys=[...
function bisearch (line 2213) | function bisearch(ucs){var min=0;var max=COMBINING.length-1;var mid;if(u...
function wcwidth (line 2213) | function wcwidth(ucs){// test for 8-bit control characters
FILE: static/assets/pages/chartjs.init.js
function generateChart (line 24) | function generateChart(){
FILE: static/assets/pages/jquery.bs-table.js
function invoiceFormatter (line 45) | function invoiceFormatter(value, row) {
function nameFormatter (line 51) | function nameFormatter(value, row) {
function dateFormatter (line 57) | function dateFormatter(value, row) {
function statusFormatter (line 65) | function statusFormatter(value, row) {
function priceSorter (line 83) | function priceSorter(a, b) {
FILE: static/assets/pages/jquery.flot.init.js
function showTooltip (line 18) | function showTooltip(x, y, contents) {
function updatePlot (line 354) | function updatePlot() {
FILE: static/assets/plugins/Chart.js/Chart.js
function tmpl (line 474) | function tmpl(str, data){
FILE: static/assets/plugins/Chart.js/src/Chart.Core.js
function tmpl (line 474) | function tmpl(str, data){
FILE: static/assets/plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.js
function UTCDate (line 9) | function UTCDate(){
function UTCToday (line 12) | function UTCToday(){
function isUTCEquals (line 16) | function isUTCEquals(date1, date2) {
function alias (line 23) | function alias(method){
function opts_from_el (line 1419) | function opts_from_el(el, prefix){
function opts_from_locale (line 1436) | function opts_from_locale(lang){
function match_part (line 1644) | function match_part(){
FILE: static/assets/plugins/bootstrap-select/dist/js/bootstrap-select.js
function normalizeToBase (line 215) | function normalizeToBase(text) {
function htmlEscape (line 238) | function htmlEscape(html) {
function Plugin (line 1576) | function Plugin(option, event) {
FILE: static/assets/plugins/bootstrap-select/js/bootstrap-select.js
function normalizeToBase (line 192) | function normalizeToBase(text) {
function htmlEscape (line 215) | function htmlEscape(html) {
function Plugin (line 1553) | function Plugin(option, event) {
FILE: static/assets/plugins/bootstrap-table/dist/bootstrap-table-all.js
function recurse (line 3088) | function recurse(cur, prop) {
function alphanum (line 3680) | function alphanum(a, b) {
FILE: static/assets/plugins/bootstrap-table/dist/extensions/flat-json/bootstrap-table-flat-json.js
function recurse (line 31) | function recurse(cur, prop) {
FILE: static/assets/plugins/bootstrap-table/dist/extensions/natural-sorting/bootstrap-table-natural-sorting.js
function alphanum (line 11) | function alphanum(a, b) {
FILE: static/assets/plugins/bootstrap-table/src/extensions/flat-json/bootstrap-table-flat-json.js
function recurse (line 31) | function recurse(cur, prop) {
FILE: static/assets/plugins/bootstrap-table/src/extensions/natural-sorting/bootstrap-table-natural-sorting.js
function alphanum (line 11) | function alphanum(a, b) {
FILE: static/assets/plugins/bootstrap-touchspin/dist/jquery.bootstrap-touchspin.js
function _scopedEventName (line 14) | function _scopedEventName(name, id) {
function _scopeEventNames (line 18) | function _scopeEventNames(names, id) {
function init (line 108) | function init() {
function _setInitval (line 134) | function _setInitval() {
function changeSettings (line 140) | function changeSettings(newsettings) {
function _initSettings (line 152) | function _initSettings() {
function _parseAttributes (line 156) | function _parseAttributes() {
function _updateSettings (line 167) | function _updateSettings(newsettings) {
function _buildHtml (line 171) | function _buildHtml() {
function _advanceInputGroup (line 190) | function _advanceInputGroup(parentelement) {
function _buildInputGroup (line 225) | function _buildInputGroup() {
function _initElements (line 247) | function _initElements() {
function _hideEmptyPrefixPostfix (line 257) | function _hideEmptyPrefixPostfix() {
function _bindEvents (line 267) | function _bindEvents() {
function _bindEventsInterface (line 471) | function _bindEventsInterface() {
function _forcestepdivisibility (line 499) | function _forcestepdivisibility(value) {
function _checkValue (line 512) | function _checkValue() {
function _getBoostedStep (line 553) | function _getBoostedStep() {
function upOnce (line 571) | function upOnce() {
function downOnce (line 597) | function downOnce() {
function startDownSpin (line 623) | function startDownSpin() {
function startUpSpin (line 640) | function startUpSpin() {
function stopSpin (line 657) | function stopSpin() {
FILE: static/assets/plugins/bootstrap-touchspin/src/jquery.bootstrap-touchspin.js
function _scopedEventName (line 6) | function _scopedEventName(name, id) {
function _scopeEventNames (line 10) | function _scopeEventNames(names, id) {
function init (line 100) | function init() {
function _setInitval (line 126) | function _setInitval() {
function changeSettings (line 132) | function changeSettings(newsettings) {
function _initSettings (line 144) | function _initSettings() {
function _parseAttributes (line 148) | function _parseAttributes() {
function _updateSettings (line 159) | function _updateSettings(newsettings) {
function _buildHtml (line 163) | function _buildHtml() {
function _advanceInputGroup (line 182) | function _advanceInputGroup(parentelement) {
function _buildInputGroup (line 217) | function _buildInputGroup() {
function _initElements (line 239) | function _initElements() {
function _hideEmptyPrefixPostfix (line 249) | function _hideEmptyPrefixPostfix() {
function _bindEvents (line 259) | function _bindEvents() {
function _bindEventsInterface (line 463) | function _bindEventsInterface() {
function _forcestepdivisibility (line 491) | function _forcestepdivisibility(value) {
function _checkValue (line 504) | function _checkValue() {
function _getBoostedStep (line 545) | function _getBoostedStep() {
function upOnce (line 563) | function upOnce() {
function downOnce (line 589) | function downOnce() {
function startDownSpin (line 615) | function startDownSpin() {
function startUpSpin (line 632) | function startUpSpin() {
function stopSpin (line 649) | function stopSpin() {
FILE: static/assets/plugins/custombox/src/js/legacy.js
function cbExtendObjects (line 845) | function cbExtendObjects () {
FILE: static/assets/plugins/flot-chart/jquery.flot.crosshair.js
function init (line 70) | function init(plot) {
FILE: static/assets/plugins/flot-chart/jquery.flot.js
function H (line 32) | function H(J,K,I){return K<J?J:(K>I?I:K)}
function Canvas (line 51) | function Canvas(cls, container) {
function Plot (line 492) | function Plot(placeholder, data_, options_, plugins) {
function floorInBase (line 3057) | function floorInBase(n, base) {
FILE: static/assets/plugins/flot-chart/jquery.flot.pie.js
function init (line 68) | function init(plot) {
FILE: static/assets/plugins/flot-chart/jquery.flot.resize.js
function m (line 23) | function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r...
function g (line 23) | function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width...
function init (line 28) | function init(plot) {
FILE: static/assets/plugins/flot-chart/jquery.flot.selection.js
function init (line 70) | function init(plot) {
FILE: static/assets/plugins/flot-chart/jquery.flot.stack.js
function init (line 39) | function init(plot) {
FILE: static/assets/plugins/flot-chart/jquery.flot.time.js
function floorInBase (line 24) | function floorInBase(n, base) {
function formatDate (line 31) | function formatDate(d, fmt, monthNames, dayNames) {
function makeUtcWrapper (line 111) | function makeUtcWrapper(d) {
function dateGenerator (line 145) | function dateGenerator(ts, opts) {
function init (line 197) | function init(plot) {
FILE: static/assets/plugins/jquery-datatables-editable/jquery.dataTables.js
function _fnHungarianMap (line 328) | function _fnHungarianMap ( o )
function _fnCamelToHungarian (line 366) | function _fnCamelToHungarian ( src, user, force )
function _fnLanguageCompat (line 405) | function _fnLanguageCompat( lang )
function _fnCompatOpts (line 457) | function _fnCompatOpts ( init )
function _fnCompatCols (line 490) | function _fnCompatCols ( init )
function _fnBrowserDetect (line 510) | function _fnBrowserDetect( settings )
function _fnReduce (line 564) | function _fnReduce ( that, fn, init, start, end, inc )
function _fnAddColumn (line 598) | function _fnAddColumn( oSettings, nTh )
function _fnColumnOptions (line 630) | function _fnColumnOptions( oSettings, iCol, oOptions )
function _fnAdjustColumnSizing (line 757) | function _fnAdjustColumnSizing ( settings )
function _fnVisibleToColumnIndex (line 789) | function _fnVisibleToColumnIndex( oSettings, iMatch )
function _fnColumnIndexToVisible (line 807) | function _fnColumnIndexToVisible( oSettings, iMatch )
function _fnVisbleColumns (line 822) | function _fnVisbleColumns( oSettings )
function _fnGetColumns (line 836) | function _fnGetColumns( oSettings, sParam )
function _fnColumnTypes (line 855) | function _fnColumnTypes ( settings )
function _fnApplyColumnDefs (line 926) | function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
function _fnAddData (line 1006) | function _fnAddData ( oSettings, aDataIn, nTr, anTds )
function _fnAddTr (line 1054) | function _fnAddTr( settings, trs )
function _fnNodeToDataIndex (line 1077) | function _fnNodeToDataIndex( oSettings, n )
function _fnNodeToColumnIndex (line 1091) | function _fnNodeToColumnIndex( oSettings, iRow, n )
function _fnGetCellData (line 1106) | function _fnGetCellData( settings, rowIdx, colIdx, type )
function _fnSetCellData (line 1153) | function _fnSetCellData( settings, rowIdx, colIdx, val )
function _fnSplitObjNotation (line 1175) | function _fnSplitObjNotation( str )
function _fnGetObjectDataFn (line 1190) | function _fnGetObjectDataFn( mSource )
function _fnSetObjectDataFn (line 1313) | function _fnSetObjectDataFn( mSource )
function _fnGetDataMaster (line 1422) | function _fnGetDataMaster ( settings )
function _fnClearTable (line 1433) | function _fnClearTable( settings )
function _fnDeleteIndex (line 1448) | function _fnDeleteIndex( a, iTarget, splice )
function _fnInvalidate (line 1487) | function _fnInvalidate( settings, rowIdx, src, colIdx )
function _fnGetRowElements (line 1565) | function _fnGetRowElements( settings, row, colIdx, d )
function _fnCreateTr (line 1659) | function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
function _fnRowAttributes (line 1736) | function _fnRowAttributes( row )
function _fnBuildHead (line 1774) | function _fnBuildHead( oSettings )
function _fnDrawHead (line 1860) | function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
function _fnDraw (line 1958) | function _fnDraw( oSettings )
function _fnReDraw (line 2099) | function _fnReDraw( settings, holdPosition )
function _fnAddOptionsHtml (line 2137) | function _fnAddOptionsHtml ( oSettings )
function _fnDetectHeader (line 2292) | function _fnDetectHeader ( aLayout, nThead )
function _fnGetUniqueThs (line 2367) | function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
function _fnBuildAjax (line 2404) | function _fnBuildAjax( oSettings, data, fn )
function _fnAjaxUpdate (line 2537) | function _fnAjaxUpdate( settings )
function _fnAjaxParameters (line 2568) | function _fnAjaxParameters( settings )
function _fnAjaxUpdateDraw (line 2676) | function _fnAjaxUpdateDraw ( settings, json )
function _fnAjaxDataSrc (line 2726) | function _fnAjaxDataSrc ( oSettings, json )
function _fnFeatureHtmlFilter (line 2749) | function _fnFeatureHtmlFilter ( settings )
function _fnFilterComplete (line 2837) | function _fnFilterComplete ( oSettings, oInput, iForce )
function _fnFilterCustom (line 2890) | function _fnFilterCustom( settings )
function _fnFilterColumn (line 2927) | function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, ca...
function _fnFilter (line 2957) | function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
function _fnFilterCreateSearch (line 3009) | function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
function _fnEscapeRegex (line 3045) | function _fnEscapeRegex ( sVal )
function _fnFilterData (line 3056) | function _fnFilterData ( settings )
function _fnSearchToCamel (line 3129) | function _fnSearchToCamel ( obj )
function _fnSearchToHung (line 3148) | function _fnSearchToHung ( obj )
function _fnFeatureHtmlInfo (line 3164) | function _fnFeatureHtmlInfo ( settings )
function _fnUpdateInfo (line 3198) | function _fnUpdateInfo ( settings )
function _fnInfoMacros (line 3236) | function _fnInfoMacros ( settings, str )
function _fnInitialise (line 3263) | function _fnInitialise ( settings )
function _fnInitComplete (line 3344) | function _fnInitComplete ( settings, json )
function _fnLengthChange (line 3358) | function _fnLengthChange ( settings, val )
function _fnFeatureHtmlLength (line 3376) | function _fnFeatureHtmlLength ( settings )
function _fnFeatureHtmlPaginate (line 3437) | function _fnFeatureHtmlPaginate ( settings )
function _fnPageChange (line 3498) | function _fnPageChange ( settings, action, redraw )
function _fnFeatureHtmlProcessing (line 3571) | function _fnFeatureHtmlProcessing ( settings )
function _fnProcessingDisplay (line 3588) | function _fnProcessingDisplay ( settings, show )
function _fnFeatureHtmlTable (line 3603) | function _fnFeatureHtmlTable ( settings )
function _fnScrollDraw (line 3767) | function _fnScrollDraw ( settings )
function _fnApplyToChildren (line 4057) | function _fnApplyToChildren( fn, an1, an2 )
function _fnCalculateColumnWidths (line 4096) | function _fnCalculateColumnWidths ( oSettings )
function _fnThrottle (line 4284) | function _fnThrottle( fn, freq ) {
function _fnConvertToWidth (line 4319) | function _fnConvertToWidth ( width, parent )
function _fnScrollingWidthAdjust (line 4343) | function _fnScrollingWidthAdjust ( settings, n )
function _fnGetWidestNode (line 4364) | function _fnGetWidestNode( settings, colIdx )
function _fnGetMaxLenString (line 4385) | function _fnGetMaxLenString( settings, colIdx )
function _fnStringToCss (line 4409) | function _fnStringToCss( s )
function _fnScrollBarWidth (line 4433) | function _fnScrollBarWidth ()
function _fnSortFlatten (line 4463) | function _fnSortFlatten ( settings )
function _fnSort (line 4535) | function _fnSort ( oSettings )
function _fnSortAria (line 4661) | function _fnSortAria ( settings )
function _fnSortListener (line 4716) | function _fnSortListener ( settings, colIdx, append, callback )
function _fnSortAttachListener (line 4800) | function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
function _fnSortingClasses (line 4838) | function _fnSortingClasses( settings )
function _fnSortData (line 4871) | function _fnSortData( settings, idx )
function _fnSaveState (line 4914) | function _fnSaveState ( settings )
function _fnLoadState (line 4949) | function _fnLoadState ( settings, oInit )
function _fnSettingsFromNode (line 5036) | function _fnSettingsFromNode ( table )
function _fnLog (line 5055) | function _fnLog( settings, level, msg, tn )
function _fnMap (line 5096) | function _fnMap( ret, src, name, mappedName )
function _fnExtend (line 5138) | function _fnExtend( out, extender, breakRefs )
function _fnBindAction (line 5174) | function _fnBindAction( n, oData, fn )
function _fnCallbackReg (line 5203) | function _fnCallbackReg( oSettings, sStore, fn, sName )
function _fnCallbackFire (line 5229) | function _fnCallbackFire( settings, callbackArr, eventName, args )
function _fnLengthOverflow (line 5251) | function _fnLengthOverflow ( settings )
function _fnRenderer (line 5276) | function _fnRenderer( settings, type )
function _fnDataSource (line 5305) | function _fnDataSource ( settings )
function _numbers (line 14146) | function _numbers ( page, pages ) {
function _addNumericSort (line 14427) | function _addNumericSort ( decimalPlace ) {
function _fnExternApiFunc (line 14650) | function _fnExternApiFunc (fn)
FILE: static/assets/plugins/jquery-knob/excanvas.js
function getContext (line 56) | function getContext() {
function bind (line 79) | function bind(f, obj, var_args) {
function onPropertyChange (line 171) | function onPropertyChange(e) {
function onResize (line 186) | function onResize(e) {
function createMatrixIdentity (line 204) | function createMatrixIdentity() {
function matrixMultiply (line 212) | function matrixMultiply(m1, m2) {
function copyState (line 229) | function copyState(o1, o2) {
function processStyle (line 246) | function processStyle(styleString) {
function processLineCap (line 270) | function processLineCap(lineCap) {
function CanvasRenderingContext2D_ (line 288) | function CanvasRenderingContext2D_(surfaceElement) {
function bezierCurveTo (line 355) | function bezierCurveTo(self, cp1, cp2, p) {
function matrixIsFinite (line 800) | function matrixIsFinite(m) {
function setM (line 811) | function setM(ctx, m, updateLineScale) {
function CanvasGradient_ (line 896) | function CanvasGradient_(aType) {
function CanvasPattern_ (line 914) | function CanvasPattern_() {}
FILE: static/assets/plugins/morris/morris.js
function ctor (line 13) | function ctor() { this.constructor = child; }
function EventEmitter (line 21) | function EventEmitter() {}
function Grid (line 76) | function Grid(options) {
function Hover (line 655) | function Hover(options) {
function Line (line 718) | function Line(options) {
function Area (line 1289) | function Area(options) {
function Bar (line 1382) | function Bar(options) {
function Donut (line 1641) | function Donut(options) {
function DonutSegment (line 1800) | function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundCol...
FILE: static/assets/plugins/notifyjs/dist/notify-combined.js
function Notification (line 243) | function Notification(elem, data, options) {
FILE: static/assets/plugins/notifyjs/dist/notify.js
function Notification (line 243) | function Notification(elem, data, options) {
FILE: static/assets/plugins/raphael/raphael-min.js
function c (line 9) | function c(a){if(c.is(a,"function"))return u?a():b.on("raphael.DOMload",...
function d (line 9) | function d(a){if("function"==typeof a||Object(a)!==a)return a;var b=new ...
function e (line 9) | function e(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return a.push...
function f (line 9) | function f(a,b,c){function d(){var f=Array.prototype.slice.call(argument...
function g (line 9) | function g(){return this.hex}
function h (line 9) | function h(a,b){for(var c=[],d=0,e=a.length;e-2*!b>d;d+=2){var f=[{x:+a[...
function i (line 9) | function i(a,b,c,d,e){var f=-3*b+9*c-9*d+3*e,g=a*f+6*b-12*c+6*d;return a...
function j (line 9) | function j(a,b,c,d,e,f,g,h,j){null==j&&(j=1),j=j>1?1:0>j?0:j;for(var k=j...
function k (line 9) | function k(a,b,c,d,e,f,g,h,i){if(!(0>i||j(a,b,c,d,e,f,g,h)<i)){var k,l=1...
function l (line 9) | function l(a,b,c,d,e,f,g,h){if(!(O(a,c)<P(e,g)||P(a,c)>O(e,g)||O(b,d)<P(...
function m (line 9) | function m(a,b,d){var e=c.bezierBBox(a),f=c.bezierBBox(b);if(!c.isBBoxIn...
function n (line 9) | function n(a,b,d){a=c._path2curve(a),b=c._path2curve(b);for(var e,f,g,h,...
function o (line 9) | function o(a,b,c,d,e,f){null!=a?(this.a=+a,this.b=+b,this.c=+c,this.d=+d...
function p (line 9) | function p(){return this.x+H+this.y+H+this.width+" × "+this.height}
function q (line 9) | function q(a,b,c,d,e,f){function g(a){return((l*a+k)*a+j)*a}function h(a...
function r (line 9) | function r(a,b){var c=[],d={};if(this.ms=b,this.times=1,a){for(var e in ...
function s (line 9) | function s(a,d,e,f,g,h){e=_(e);var i,j,k,l,m,n,p=a.ms,r={},s={},t={};if(...
function t (line 9) | function t(a){for(var b=0;b<ic.length;b++)ic[b].el.paper==a&&ic.splice(b...
function b (line 10) | function b(a){return a[0]*a[0]+a[1]*a[1]}
function d (line 10) | function d(a){var c=N.sqrt(b(a));a[0]&&(a[0]/=c),a[1]&&(a[1]/=c)}
function i (line 10) | function i(i){(i.originalEvent||i).preventDefault();var j=i.clientX,k=i....
function e (line 10) | function e(){/in/.test(a.readyState)?setTimeout(e,9):c.eve("raphael.DOMl...
FILE: static/assets/plugins/select2/select2.js
function reinsertElement (line 108) | function reinsertElement(element) {
function stripDiacritics (line 116) | function stripDiacritics(str) {
function indexOf (line 125) | function indexOf(value, array) {
function measureScrollbar (line 133) | function measureScrollbar () {
function equal (line 151) | function equal(a, b) {
function splitVal (line 168) | function splitVal(string, separator, transform) {
function getSideBorderPadding (line 176) | function getSideBorderPadding(element) {
function installKeyUpChangeEvent (line 180) | function installKeyUpChangeEvent(element) {
function installFilteredMouseMove (line 203) | function installFilteredMouseMove(element) {
function debounce (line 221) | function debounce(quietMillis, fn, ctx) {
function installDebouncedScroll (line 233) | function installDebouncedScroll(threshold, element) {
function focus (line 240) | function focus($el) {
function getCursorInfo (line 271) | function getCursorInfo(el) {
function killEvent (line 288) | function killEvent(event) {
function killEventImmediately (line 292) | function killEventImmediately(event) {
function measureTextWidth (line 297) | function measureTextWidth(e) {
function syncCssClasses (line 320) | function syncCssClasses(dest, src, adapter) {
function markMatch (line 355) | function markMatch(text, term, markup, escapeMarkup) {
function defaultEscapeMarkup (line 371) | function defaultEscapeMarkup(markup) {
function ajax (line 403) | function ajax(options) {
function local (line 478) | function local(options) {
function tags (line 537) | function tags(data) {
function checkFormatter (line 563) | function checkFormatter(formatter, formatterName) {
function evaluate (line 578) | function evaluate(val, context) {
function countResults (line 586) | function countResults(results) {
function defaultTokenizer (line 609) | function defaultTokenizer(input, selection, selectCallback, opts) {
function cleanupJQueryElements (line 651) | function cleanupJQueryElements() {
function clazz (line 666) | function clazz(SuperClass, methods) {
function postRender (line 1710) | function postRender() {
function render (line 1721) | function render(html) {
function resolveContainerWidth (line 1909) | function resolveContainerWidth() {
FILE: static/assets/plugins/select2/select2_locale_hr.js
function character (line 21) | function character (n) {
FILE: static/assets/plugins/select2/select2_locale_lt.js
function character (line 23) | function character (n) {
FILE: static/assets/plugins/select2/select2_locale_pl.js
function character (line 35) | function character(n, word, pluralSuffix) {
FILE: static/assets/plugins/select2/select2_locale_ru.js
function character (line 20) | function character (n) {
FILE: static/assets/plugins/select2/select2_locale_uk.js
function character (line 22) | function character (n, word) {
FILE: static/assets/plugins/sweetalert/dist/sweetalert-dev.js
function s (line 4) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
function argumentOrDefault (line 73) | function argumentOrDefault(key) {
function shouldSetConfirmButtonColor (line 373) | function shouldSetConfirmButtonColor(color) {
function tick (line 572) | function tick() {
function tick (line 599) | function tick() {
function getModal (line 792) | function getModal() {
FILE: static/assets/plugins/switchery/dist/switchery.js
function require (line 12) | function require(name) {
function showError (line 67) | function showError(name) {
function Transitionize (line 170) | function Transitionize(element, props) {
function FastClick (line 228) | function FastClick(layer) {
function ClassList (line 1048) | function ClassList(el) {
function one (line 1237) | function one(selector, el) {
function match (line 1299) | function match(el, selector) {
function Events (line 1405) | function Events(el, obj) {
function cb (line 1458) | function cb(){
function parse (line 1550) | function parse(event) {
function Switchery (line 1615) | function Switchery(element, options) {
FILE: static/assets/plugins/switchery/switchery.js
function Switchery (line 55) | function Switchery(element, options) {
FILE: static/assets/plugins/waypoints/lib/jquery.waypoints.js
function Waypoint (line 14) | function Waypoint(options) {
function requestAnimationFrameShim (line 170) | function requestAnimationFrameShim(callback) {
function Context (line 180) | function Context(element) {
function resizeHandler (line 225) | function resizeHandler() {
function scrollHandler (line 241) | function scrollHandler() {
function byTriggerPoint (line 468) | function byTriggerPoint(a, b) {
function byReverseTriggerPoint (line 472) | function byReverseTriggerPoint(a, b) {
function Group (line 483) | function Group(options) {
function JQueryAdapter (line 576) | function JQueryAdapter(element) {
function createExtension (line 616) | function createExtension(framework) {
FILE: static/assets/plugins/waypoints/lib/noframework.waypoints.js
function Waypoint (line 14) | function Waypoint(options) {
function requestAnimationFrameShim (line 170) | function requestAnimationFrameShim(callback) {
function Context (line 180) | function Context(element) {
function resizeHandler (line 225) | function resizeHandler() {
function scrollHandler (line 241) | function scrollHandler() {
function byTriggerPoint (line 468) | function byTriggerPoint(a, b) {
function byReverseTriggerPoint (line 472) | function byReverseTriggerPoint(a, b) {
function Group (line 483) | function Group(options) {
function isWindow (line 575) | function isWindow(element) {
function getWindow (line 579) | function getWindow(element) {
function NoFrameworkAdapter (line 586) | function NoFrameworkAdapter(element) {
function removeListeners (line 602) | function removeListeners(element, listeners, handler) {
function merge (line 707) | function merge(target, obj) {
FILE: static/assets/plugins/waypoints/lib/shortcuts/infinite.js
function Infinite (line 14) | function Infinite(options) {
FILE: static/assets/plugins/waypoints/lib/shortcuts/inview.js
function noop (line 10) | function noop() {}
function Inview (line 15) | function Inview(options) {
FILE: static/assets/plugins/waypoints/lib/shortcuts/sticky.js
function Sticky (line 14) | function Sticky(options) {
FILE: static/assets/plugins/waypoints/lib/waypoints.debug.js
function checkWaypointStyles (line 21) | function checkWaypointStyles() {
FILE: static/assets/plugins/waypoints/lib/zepto.waypoints.js
function Waypoint (line 14) | function Waypoint(options) {
function requestAnimationFrameShim (line 170) | function requestAnimationFrameShim(callback) {
function Context (line 180) | function Context(element) {
function resizeHandler (line 225) | function resizeHandler() {
function scrollHandler (line 241) | function scrollHandler() {
function byTriggerPoint (line 468) | function byTriggerPoint(a, b) {
function byReverseTriggerPoint (line 472) | function byReverseTriggerPoint(a, b) {
function Group (line 483) | function Group(options) {
function ZeptoAdapter (line 576) | function ZeptoAdapter(element) {
function createDimensionMethod (line 604) | function createDimensionMethod($element, includeBorder) {
function createExtension (line 659) | function createExtension(framework) {
FILE: webapp/Extends/PageList.py
function Page (line 8) | def Page(page,url,all_pages_count,search=str('')):
function PageCount (line 57) | def PageCount(page):
FILE: webapp/admin.py
class MyUserCreationForm (line 17) | class MyUserCreationForm(UserCreationForm): # 增加用户表单重新定义,继承自UserCreatio...
method __init__ (line 18) | def __init__(self, *args, **kwargs):
class MyUserChangeForm (line 23) | class MyUserChangeForm(UserChangeForm): # 编辑用户表单重新定义,继承自UserChangeForm
method __init__ (line 24) | def __init__(self, *args, **kwargs):
class CustomUserAdmin (line 31) | class CustomUserAdmin(UserAdmin):
method __init__ (line 32) | def __init__(self, *args, **kwargs):
method changelist_view (line 40) | def changelist_view(self, request, extra_context=None):
class UserAdmin (line 69) | class UserAdmin(admin.ModelAdmin):
class LoginHistory (line 75) | class LoginHistory(admin.ModelAdmin):
FILE: webapp/apps.py
class WebappConfig (line 6) | class WebappConfig(AppConfig):
FILE: webapp/forms.py
class SimpleLogin (line 9) | class SimpleLogin(forms.Form):
class Register (line 21) | class Register(forms.Form):
method pwd_validate (line 47) | def pwd_validate(self,pwd1,pwd2):
class ResetPassword (line 51) | class ResetPassword(forms.Form):
method pwd_validate (line 64) | def pwd_validate(self,pwd1,pwd2):
FILE: webapp/models.py
class Department (line 7) | class Department(models.Model):
method __unicode__ (line 9) | def __unicode__(self):
class Meta (line 12) | class Meta:
class MyUserManager (line 19) | class MyUserManager(BaseUserManager):
method create_user (line 20) | def create_user(self, email, username, password=None):
method create_superuser (line 38) | def create_superuser(self, email, username, password):
class Suser (line 55) | class Suser(AbstractBaseUser,PermissionsMixin):
method get_full_name (line 98) | def get_full_name(self):
method get_short_name (line 102) | def get_short_name(self):
method __str__ (line 106) | def __str__(self): # __unicode__ on Python 2
method is_admin (line 111) | def is_admin(self):
method __unicode__ (line 117) | def __unicode__(self):
class Meta (line 120) | class Meta:
class History_Login (line 131) | class History_Login(models.Model):
class Meta (line 139) | class Meta:
class Operation (line 146) | class Operation(models.Model):
class Meta (line 150) | class Meta:
FILE: webapp/tasks.py
function sendmail (line 63) | def sendmail(mail):
function resetpass (line 74) | def resetpass(mail):
function SaltGrains (line 85) | def SaltGrains(minion):
function StopContainer (line 94) | def StopContainer(docker):
function StartContainer (line 102) | def StartContainer(IP,port,container):
function RestartContainer (line 110) | def RestartContainer(IP,port,container):
function SaltGrainsAll (line 119) | def SaltGrainsAll():
function DockerServers (line 129) | def DockerServers():
function GetMinionStatus (line 139) | def GetMinionStatus():
function GetSaltjobs (line 145) | def GetSaltjobs():
function UpdateServerInfo (line 152) | def UpdateServerInfo(serverid):
function DeleteContainer (line 323) | def DeleteContainer(IP,port,container):
FILE: webapp/views.py
function index (line 22) | def index(request):
function Login (line 39) | def Login(request):
function Register (line 79) | def Register(request):
function Activate (line 111) | def Activate(request, token):
function Logout (line 133) | def Logout(request):
function SendResetEmail (line 146) | def SendResetEmail(request):
function ResetPassword (line 165) | def ResetPassword(request,token):
function Userinfo (line 200) | def Userinfo(reqest):
function SysrestUserpassword (line 209) | def SysrestUserpassword(request,id):
Condensed preview — 559 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,401K chars).
[
{
"path": ".idea/SimpletourDevops.iml",
"chars": 461,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"PYTHON_MODULE\" version=\"4\">\n <component name=\"NewModuleRootManager"
},
{
"path": ".idea/inspectionProfiles/Project_Default.xml",
"chars": 1151,
"preview": "<component name=\"InspectionProjectProfileManager\">\n <profile version=\"1.0\">\n <option name=\"myName\" value=\"Project De"
},
{
"path": ".idea/inspectionProfiles/profiles_settings.xml",
"chars": 235,
"preview": "<component name=\"InspectionProjectProfileManager\">\n <settings>\n <option name=\"PROJECT_PROFILE\" value=\"Project Defaul"
},
{
"path": ".idea/misc.xml",
"chars": 1076,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectLevelVcsManager\" settingsEditedMa"
},
{
"path": ".idea/modules.xml",
"chars": 532,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": ".idea/vcs.xml",
"chars": 219,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": "Publicapi/__init__.py",
"chars": 58,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n"
},
{
"path": "Publicapi/dnspod/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "Publicapi/dnspod/apicn.py",
"chars": 3869,
"preview": "#!/usr/bin/env python\n#-*- coding:utf-8 -*-\n\nimport httplib, urllib\ntry: import json\nexcept: import simplejson as json\ni"
},
{
"path": "Publicapi/dockerapi/Manager.py",
"chars": 3603,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n\nimport docker\n\n\n'''\nDocker 容器API公共模块,可进行容器及镜像管理\n'''\n\nclass Do"
},
{
"path": "Publicapi/dockerapi/__init__.py",
"chars": 58,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n"
},
{
"path": "Publicapi/saltstackapi/Assets_Module.py",
"chars": 2759,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n\nclass ServerBaseInfo(object):\n def __init__(self,data,mini"
},
{
"path": "Publicapi/saltstackapi/SaltConApi.py",
"chars": 6873,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\nimport urllib,urllib2\nimport json\nimport requests\nimport yaml\n"
},
{
"path": "Publicapi/saltstackapi/__init__.py",
"chars": 58,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n"
},
{
"path": "README.md",
"chars": 3906,
"preview": "# SimpletourDevops\ndjango+python+celery+saltstack+docker实现的运维管理后台\n\n作者QQ:923401910\n\nv1.0:完成资产信息录入及使用saltstack自动采集更新\n "
},
{
"path": "SimpletourDevops/__init__.py",
"chars": 167,
"preview": "#coding:utf-8\nfrom django.core import signals\nfrom django.db import close_old_connections\n\n# 取消信号关联,实现数据库长连接\nsignals.req"
},
{
"path": "SimpletourDevops/apps.py",
"chars": 1521,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n\nfrom suit.apps import DjangoSuitConfig\nfrom suit.menu import "
},
{
"path": "SimpletourDevops/settings.py",
"chars": 4051,
"preview": "#coding:utf8\n\"\"\"\nDjango settings for SimpletourDevops project.\n\nGenerated by 'django-admin startproject' using Django 1."
},
{
"path": "SimpletourDevops/urls.py",
"chars": 1129,
"preview": "\"\"\"SimpletourDevops URL Configuration\n\nThe `urlpatterns` list routes URLs to views. For more information please see:\n "
},
{
"path": "SimpletourDevops/wsgi.py",
"chars": 409,
"preview": "\"\"\"\nWSGI config for SimpletourDevops project.\n\nIt exposes the WSGI callable as a module-level variable named ``applicati"
},
{
"path": "dockermanager/Docker_Controller.py",
"chars": 3881,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\nimport os\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"Sim"
},
{
"path": "dockermanager/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "dockermanager/admin.py",
"chars": 416,
"preview": "#coding:utf8\nfrom django.contrib import admin\nfrom dockermanager.models import *\nclass DockerHostModels(admin.ModelAdmin"
},
{
"path": "dockermanager/apps.py",
"chars": 142,
"preview": "from __future__ import unicode_literals\n\nfrom django.apps import AppConfig\n\n\nclass DockermanagerConfig(AppConfig):\n n"
},
{
"path": "dockermanager/forms.py",
"chars": 1435,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n\nfrom django import forms\nfrom servermanager.models import Ser"
},
{
"path": "dockermanager/migrations/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "dockermanager/models.py",
"chars": 3852,
"preview": "#coding:utf8\nfrom __future__ import unicode_literals\n\nfrom django.db import models\n\nfrom servermanager.models import Ser"
},
{
"path": "dockermanager/tests.py",
"chars": 60,
"preview": "from django.test import TestCase\n\n# Create your tests here.\n"
},
{
"path": "dockermanager/urls.py",
"chars": 2077,
"preview": "from django.conf.urls import url\n\nfrom dockermanager.views import (Dockercontainerlist,DockerHosts,DockerImages,Dockerco"
},
{
"path": "dockermanager/views.py",
"chars": 17081,
"preview": "#coding:utf8\nfrom django.shortcuts import render,render_to_response\nfrom django.http import HttpResponse,HttpResponseRed"
},
{
"path": "domainmanager/urls.py",
"chars": 475,
"preview": "from django.conf.urls import url\n\n\nfrom domainmanager.views import (SimpletourDomainLists,SimpletourGetdomainApi,Simplet"
},
{
"path": "manage.py",
"chars": 259,
"preview": "#!/usr/bin/env python\nimport os\nimport sys\n\nif __name__ == \"__main__\":\n os.environ.setdefault(\"DJANGO_SETTINGS_MODULE"
},
{
"path": "requirements.txt",
"chars": 200,
"preview": "django==1.9.9\ndjango-import-export==0.5.1\nitsdangerous==0.24\ncelery\nhttps://github.com/darklow/django-suit/tarball/v2\nMy"
},
{
"path": "run_eventlet.py",
"chars": 367,
"preview": "from eventlet import wsgi, patcher\npatcher.monkey_patch()\n\nimport sys\nimport getopt\nimport eventlet\nfrom SimpletourDevop"
},
{
"path": "saltadmin/Minions_Controller.py",
"chars": 17193,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n\nimport os\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"Si"
},
{
"path": "saltadmin/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "saltadmin/admin.py",
"chars": 680,
"preview": "from django.contrib import admin\nfrom saltadmin.models import *\n\nclass SaltJobsModels(admin.ModelAdmin):\n list_displa"
},
{
"path": "saltadmin/apps.py",
"chars": 134,
"preview": "from __future__ import unicode_literals\n\nfrom django.apps import AppConfig\n\n\nclass SaltadminConfig(AppConfig):\n name "
},
{
"path": "saltadmin/forms.py",
"chars": 1454,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\n\nfrom django import forms\nfrom saltadmin.models import SaltSer"
},
{
"path": "saltadmin/migrations/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "saltadmin/models.py",
"chars": 4368,
"preview": "#coding:utf8\nfrom __future__ import unicode_literals\n\nfrom django.db import models\n\nclass SaltServer(models.Model):\n "
},
{
"path": "saltadmin/tests.py",
"chars": 60,
"preview": "from django.test import TestCase\n\n# Create your tests here.\n"
},
{
"path": "saltadmin/urls.py",
"chars": 1088,
"preview": "from django.conf.urls import url\n\nfrom saltadmin.views import (KeyList,Minion_Status,SoftInstall,JobList,RemoteCmd,SaltM"
},
{
"path": "saltadmin/utils.py",
"chars": 1325,
"preview": "#!/usr/bin/env python\n#coding:utf-8\n\n__author__ = 'Luodi'\nimport commands\nimport os\n\ndef get_system_info():\n cmd_get_"
},
{
"path": "saltadmin/views.py",
"chars": 11549,
"preview": "#coding:utf8\nfrom django.shortcuts import render\nfrom django.http import HttpResponse,HttpResponseRedirect\nfrom django.c"
},
{
"path": "servermanager/__init__.py",
"chars": 2,
"preview": "\n\n"
},
{
"path": "servermanager/admin.py",
"chars": 3165,
"preview": "#coding:utf8\n\nfrom django.contrib import admin\nfrom django.forms import ModelForm,TextInput,Textarea\nfrom django.contrib"
},
{
"path": "servermanager/apps.py",
"chars": 142,
"preview": "from __future__ import unicode_literals\n\nfrom django.apps import AppConfig\n\n\nclass ServermanagerConfig(AppConfig):\n n"
},
{
"path": "servermanager/migrations/0001_initial.py",
"chars": 13886,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-21 17:40\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0002_auto_20161121_1740.py",
"chars": 1543,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-21 17:40\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0003_auto_20161128_1031.py",
"chars": 478,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 10:31\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0004_auto_20161128_1032.py",
"chars": 494,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 10:32\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0005_auto_20161128_1032.py",
"chars": 469,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 10:32\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0006_auto_20161128_1034.py",
"chars": 2021,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 10:34\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0007_auto_20161128_1038.py",
"chars": 1117,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 10:38\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0008_auto_20161128_1109.py",
"chars": 716,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 11:09\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0009_auto_20161128_1112.py",
"chars": 486,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 11:12\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0010_auto_20161128_1113.py",
"chars": 532,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-11-28 11:13\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/0011_auto_20161202_1049.py",
"chars": 521,
"preview": "# -*- coding: utf-8 -*-\n# Generated by Django 1.9.9 on 2016-12-02 10:49\nfrom __future__ import unicode_literals\n\nfrom dj"
},
{
"path": "servermanager/migrations/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "servermanager/models.py",
"chars": 9644,
"preview": "#coding:utf8\nfrom __future__ import unicode_literals\nfrom django.db import models\nfrom webapp.models import Suser\n\n\n'''设"
},
{
"path": "servermanager/tests.py",
"chars": 60,
"preview": "from django.test import TestCase\n\n# Create your tests here.\n"
},
{
"path": "servermanager/urls.py",
"chars": 1145,
"preview": "from django.conf.urls import url\n\n\nfrom servermanager.views import (HostLists,ServerDetail,ChangeServer,\n "
},
{
"path": "servermanager/views.py",
"chars": 12687,
"preview": "#coding:utf8\nfrom django.shortcuts import render\nfrom django.http import HttpResponse\nfrom django.contrib.auth.decorator"
},
{
"path": "static/assets/css/_variables.css",
"chars": 109,
"preview": "/*\nTemplate Name: Moltran Dashboard\nAuthor: CoderThemes\nEmail: coderthemes@gmail.com\nFile: Variables.less\n*/\n"
},
{
"path": "static/assets/css/bootstrap-theme.css",
"chars": 26132,
"preview": "/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://gi"
},
{
"path": "static/assets/css/bootstrap.css",
"chars": 147430,
"preview": "/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://gi"
},
{
"path": "static/assets/css/components.css",
"chars": 44772,
"preview": "/*\nTemplate Name: UBold Dashboard\nAuthor: CoderThemes\nEmail: coderthemes@gmail.com\nFile: Components\n*/\n/* =============\n"
},
{
"path": "static/assets/css/core.css",
"chars": 38825,
"preview": "/*@import url(https://fonts.gmirror.org/css?family=Noto+Sans:400,700);\n@import url(https://fonts.gmirror.org/css?family="
},
{
"path": "static/assets/css/elements.css",
"chars": 0,
"preview": ""
},
{
"path": "static/assets/css/icons.css",
"chars": 175137,
"preview": "/*\nTemplate Name: UBold Dashboard\nAuthor: CoderThemes\nEmail: coderthemes@gmail.com\nFile: Icons\n*/\n/*!\n * Font Awesome 4"
},
{
"path": "static/assets/css/pages.css",
"chars": 36605,
"preview": "/*\nTemplate Name: UBold Dashboard\nAuthor: CoderThemes\nEmail: coderthemes@gmail.com\nFile: Pages\n*/\n/* =============\n Ca"
},
{
"path": "static/assets/css/responsive.css",
"chars": 2205,
"preview": "/*\nTemplate Name: Ubold Dashboard\nAuthor: CoderThemes\nEmail: coderthemes@gmail.com\nFile: Responsive\n*/\n@media only scree"
},
{
"path": "static/assets/css/statusecho.css",
"chars": 939,
"preview": "\n.state_color_510 {\n background-color: #90EE90;\n border-radius: 4px;\n color: #ffffff;\n display: inline-block"
},
{
"path": "static/assets/css/style.css",
"chars": 416,
"preview": "body {\n font-family: helvetica, sans-serif, arial;\n font-size: 1em;\n color: #111;\n}\n\nh1 {\n text-align: cente"
},
{
"path": "static/assets/css/variables.css",
"chars": 0,
"preview": ""
},
{
"path": "static/assets/css/xterm.css",
"chars": 33981,
"preview": "/**\n * xterm.js: xterm, in the browser\n * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT L"
},
{
"path": "static/assets/js/bootstrap.js",
"chars": 68890,
"preview": "/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under the MIT license"
},
{
"path": "static/assets/js/detect.js",
"chars": 2219,
"preview": "/**\n * jQuery.browser.mobile (http://detectmobilebrowser.com/)\n *\n * jQuery.browser.mobile will be true if the browser i"
},
{
"path": "static/assets/js/fastclick.js",
"chars": 23032,
"preview": "/**\n * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.\n *\n * @version 0.6.11\n * @coding"
},
{
"path": "static/assets/js/jquery.app.js",
"chars": 9170,
"preview": "/**\n* Theme: Ubold Admin Template\n* Author: Coderthemes\n* Module/App: Main Js\n*/\n\n\n!function($) {\n \"use strict\";\n\n "
},
{
"path": "static/assets/js/jquery.blockUI.js",
"chars": 19966,
"preview": "/*!\n * jQuery blockUI plugin\n * Version 2.70.0-2014.11.23\n * Requires jQuery v1.7 or later\n *\n * Examples at: http://mal"
},
{
"path": "static/assets/js/jquery.core.js",
"chars": 9784,
"preview": "//portlets\n!function($) {\n \"use strict\";\n\n /**\n Portlet Widget\n */\n var Portlet = function() {\n th"
},
{
"path": "static/assets/js/jquery.nicescroll.js",
"chars": 59364,
"preview": "/* jquery.nicescroll 3.5.0 InuYaksa*2013 MIT http://areaaperta.com/nicescroll */(function(e){var z=!1,E=!1,L=5E3,M=2E3,y"
},
{
"path": "static/assets/js/jquery.slimscroll.js",
"chars": 13659,
"preview": "/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)\n * Dual licensed under the MIT (http://www.opensource.org/license"
},
{
"path": "static/assets/js/json.js",
"chars": 2293,
"preview": "var formatJson = function(json, options) {\n var reg = null,\n formatted = '',\n pad = 0,\n PADDING "
},
{
"path": "static/assets/js/json2yaml.js",
"chars": 2314,
"preview": "(function (self) { \n /*\n * TODO, lots of concatenation (slow in js)\n */\n var spacing = \" \";\n\n function getType(o"
},
{
"path": "static/assets/js/npm.js",
"chars": 484,
"preview": "// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.\nrequ"
},
{
"path": "static/assets/js/spin.js",
"chars": 11686,
"preview": "/**\n * Copyright (c) 2011-2014 Felix Gnass\n * Licensed under the MIT license\n * http://spin.js.org/\n *\n * Example:\n v"
},
{
"path": "static/assets/js/waves.js",
"chars": 69263,
"preview": "\n\n;(function(window) {\n 'use strict';\n\n var Waves = Waves || {};\n var $$ = document.querySelectorAll.bind(docum"
},
{
"path": "static/assets/js/xterm.js",
"chars": 132185,
"preview": "(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"func"
},
{
"path": "static/assets/pages/chartjs.init.js",
"chars": 6934,
"preview": "/**\nTemplate Name: Ubold Dashboard\nAuthor: CoderThemes\nEmail: coderthemes@gmail.com\nFile: Chartjs\n*/\n\n\n!function($) {\n "
},
{
"path": "static/assets/pages/datatables.editable.init.js",
"chars": 5374,
"preview": "/**\n* Theme: Ubold Admin Template\n* Author: Coderthemes\n* Component: Editable\n* \n*/\n\n(function( $ ) {\n\n\t'use strict';\n\n\t"
},
{
"path": "static/assets/pages/easy-pie-chart.init.js",
"chars": 1561,
"preview": "/**\n* Theme: Ubold Admin Template\n* Author: Coderthemes\n* Easy pie chart\n*/\n\n!function($) {\n \"use strict\";\n\n var E"
},
{
"path": "static/assets/pages/jquery.bs-table.js",
"chars": 2487,
"preview": "\n/**\n* Theme: Ubold Admin Template\n* Author: Coderthemes\n* bootstrap tables\n*/\n\n\n\n$(document).ready(function() {\n\n\n\t// B"
},
{
"path": "static/assets/pages/jquery.dashboard.js",
"chars": 2967,
"preview": "\n/**\n* Theme: Ubold Admin Template\n* Author: Coderthemes\n* Morris Chart\n*/\n\n!function($) {\n \"use strict\";\n\n var Da"
},
{
"path": "static/assets/pages/jquery.flot.init.js",
"chars": 11052,
"preview": "/**\n * Theme: Ubold Admin Template\n * Author: Coderthemes\n * Module/App: Flot-Chart\n */\n\n! function($) {\n\t\"use strict\";\n"
},
{
"path": "static/assets/pages/jquery.footable.js",
"chars": 2672,
"preview": "/**\n* Theme: Ubold Dashboard\n* Author: Coderthemes\n* Foo table\n*/\n\n$(window).on('load', function() {\n\n\t// Row Toggler\n\t/"
},
{
"path": "static/assets/pages/jquery.sweet-alert.init.js",
"chars": 2910,
"preview": "\n/**\n* Theme: Ubold Admin Template\n* Author: Coderthemes\n* SweetAlert\n*/\n\n!function($) {\n \"use strict\";\n\n var Swee"
},
{
"path": "static/assets/plugins/Chart.js/Chart.js",
"chars": 109612,
"preview": "/*!\n * Chart.js\n * http://chartjs.org/\n * Version: 1.0.2\n *\n * Copyright 2015 Nick Downie\n * Released under the MIT lice"
},
{
"path": "static/assets/plugins/Chart.js/src/Chart.Bar.js",
"chars": 9689,
"preview": "(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\n\tvar defaultConfig = {"
},
{
"path": "static/assets/plugins/Chart.js/src/Chart.Core.js",
"chars": 64571,
"preview": "/*!\n * Chart.js\n * http://chartjs.org/\n * Version: {{ version }}\n *\n * Copyright 2015 Nick Downie\n * Released under the "
},
{
"path": "static/assets/plugins/Chart.js/src/Chart.Doughnut.js",
"chars": 5837,
"preview": "(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\t//Cache a local reference to Chart.helpers\n\t\thelp"
},
{
"path": "static/assets/plugins/Chart.js/src/Chart.Line.js",
"chars": 11788,
"preview": "(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\tvar defaultConfig = {\n"
},
{
"path": "static/assets/plugins/Chart.js/src/Chart.PolarArea.js",
"chars": 7641,
"preview": "(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\t//Cache a local reference to Chart.helpers\n\t\thelp"
},
{
"path": "static/assets/plugins/Chart.js/src/Chart.Radar.js",
"chars": 10089,
"preview": "(function(){\n\t\"use strict\";\n\n\tvar root = this,\n\t\tChart = root.Chart,\n\t\thelpers = Chart.helpers;\n\n\n\n\tChart.Type.extend({\n"
},
{
"path": "static/assets/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.css",
"chars": 17085,
"preview": "/*!\n * Datepicker for Bootstrap v1.4.1 (https://github.com/eternicode/bootstrap-datepicker)\n *\n * Copyright 2012 Stefan "
},
{
"path": "static/assets/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.standalone.css",
"chars": 17943,
"preview": "/*!\n * Datepicker for Bootstrap v1.4.1 (https://github.com/eternicode/bootstrap-datepicker)\n *\n * Copyright 2012 Stefan "
},
{
"path": "static/assets/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css",
"chars": 32847,
"preview": "/*!\n * Datepicker for Bootstrap v1.4.1 (https://github.com/eternicode/bootstrap-datepicker)\n *\n * Copyright 2012 Stefan "
},
{
"path": "static/assets/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker3.standalone.css",
"chars": 33654,
"preview": "/*!\n * Datepicker for Bootstrap v1.4.1 (https://github.com/eternicode/bootstrap-datepicker)\n *\n * Copyright 2012 Stefan "
},
{
"path": "static/assets/plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.js",
"chars": 50050,
"preview": "/*!\n * Datepicker for Bootstrap v1.4.1 (https://github.com/eternicode/bootstrap-datepicker)\n *\n * Copyright 2012 Stefan "
},
{
"path": "static/assets/plugins/bootstrap-select/css/bootstrap-select.css",
"chars": 5967,
"preview": ".bootstrap-select {\n width: 220px \\0;\n /*IE9 and below*/\n}\n.bootstrap-select > .dropdown-toggle {\n width: 100%;\n pad"
},
{
"path": "static/assets/plugins/bootstrap-select/css/variables.css",
"chars": 0,
"preview": ""
},
{
"path": "static/assets/plugins/bootstrap-select/dist/css/bootstrap-select.css",
"chars": 6643,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/bootstrap-select.js",
"chars": 60299,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-bg_BG.js",
"chars": 1476,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-cs_CZ.js",
"chars": 1092,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-da_DK.js",
"chars": 1417,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-de_DE.js",
"chars": 1102,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-en_US.js",
"chars": 1412,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-es_CL.js",
"chars": 1106,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-eu.js",
"chars": 1107,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-fa_IR.js",
"chars": 1189,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-fr_FR.js",
"chars": 1509,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-hu_HU.js",
"chars": 1258,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-it_IT.js",
"chars": 1110,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-ko_KR.js",
"chars": 1206,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-nl_NL.js",
"chars": 1106,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-pl_PL.js",
"chars": 1182,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-pt_BR.js",
"chars": 1104,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-pt_PT.js",
"chars": 1093,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-ro_RO.js",
"chars": 1121,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-ru_RU.js",
"chars": 1139,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-sk_SK.js",
"chars": 1195,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-sl_SI.js",
"chars": 1275,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-sv_SE.js",
"chars": 1325,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-tr_TR.js",
"chars": 1449,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-ua_UA.js",
"chars": 1100,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-zh_CN.js",
"chars": 1003,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/dist/js/i18n/defaults-zh_TW.js",
"chars": 1058,
"preview": "/*!\n * Bootstrap-select v1.7.3 (http://silviomoreto.github.io/bootstrap-select)\n *\n * Copyright 2013-2015 bootstrap-sele"
},
{
"path": "static/assets/plugins/bootstrap-select/js/.jshintrc",
"chars": 230,
"preview": "{\n \"curly\": true,\n \"eqeqeq\": true,\n \"immed\": true,\n \"latedef\": true,\n \"newcap\": true,\n \"noarg\": true,\n \"sub\": tru"
},
{
"path": "static/assets/plugins/bootstrap-select/js/bootstrap-select.js",
"chars": 59555,
"preview": "(function ($) {\n 'use strict';\n\n //<editor-fold desc=\"Shims\">\n if (!String.prototype.includes) {\n (function () {\n "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-bg_BG.js",
"chars": 842,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: BG (Bulgaria)\n * Region: BG (Bulgaria)\n */\n(function "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-cs_CZ.js",
"chars": 453,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: CS\n * Region: CZ (Czech Republic)\n */\n(function ($) {"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-da_DK.js",
"chars": 780,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: DA (Danish)\n * Region: DK (Denmark)\n */\n(function ($)"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-de_DE.js",
"chars": 487,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: DE (German, deutsch)\n * Region: DE (Germany, Deutschl"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-en_US.js",
"chars": 782,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: EN (English)\n * Region: US (United States)\n */\n(funct"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-es_CL.js",
"chars": 468,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: ES (Spanish)\n * Region: CL (Chile)\n */\n(function ($) "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-eu.js",
"chars": 458,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: EU (Basque)\n * Region: \n */\n(function ($) {\n $.fn.se"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-fa_IR.js",
"chars": 548,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: FA (Farsi)\n * Region: IR (Iran)\n */\n(function ($) {\n "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-fr_FR.js",
"chars": 881,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: FR (French; Français)\n * Region: FR (France)\n */\n(fun"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-hu_HU.js",
"chars": 624,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: HU (Hungarian)\n * Region: HU (Hungary)\n */\n(function "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-it_IT.js",
"chars": 539,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: IT (Italian; italiano)\n * Region: IT (Italy; Italia)\n"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-ko_KR.js",
"chars": 573,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: KO (Korean)\n * Region: KR (South Korea)\n */\n(function"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-nl_NL.js",
"chars": 515,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: NL (Dutch; Nederlands)\n * Region: NL (Europe)\n * Auth"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-pl_PL.js",
"chars": 544,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: PL (Polish)\n * Region: EU (Europe)\n */\n(function ($) "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-pt_BR.js",
"chars": 540,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: PT (Portuguese; português)\n * Region: BR (Brazil; Bra"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-pt_PT.js",
"chars": 522,
"preview": "/*\n* Translated default messages for bootstrap-select.\n* Locale: PT (Portuguese; português)\n* Region: PT (Portugal; Port"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-ro_RO.js",
"chars": 523,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: RO (Romanian)\n * Region: RO (Romania)\n * Alex Florea "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-ru_RU.js",
"chars": 523,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: RU (Russian; Русский)\n * Region: RU (Russian Federati"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-sk_SK.js",
"chars": 557,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: SK\n * Region: SK (Slovak Republic)\n */\n(function ($) "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-sl_SI.js",
"chars": 642,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: SL (Slovenian)\n * Region: SI (Slovenia)\n */\n(function"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-sv_SE.js",
"chars": 688,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: SV (Swedish)\n * Region: SE (Sweden)\n */\n(function ($)"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-tr_TR.js",
"chars": 835,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: TR (Turkey)\n * Region: TR (Europe)\n * Author: Serhan "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-ua_UA.js",
"chars": 478,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: UA (Ukrainian; Українська)\n * Region: UA (Ukraine)\n *"
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-zh_CN.js",
"chars": 365,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: ZH (Chinese)\n * Region: CN (China)\n */\n(function ($) "
},
{
"path": "static/assets/plugins/bootstrap-select/js/i18n/defaults-zh_TW.js",
"chars": 421,
"preview": "/*\n * Translated default messages for bootstrap-select.\n * Locale: ZH (Chinese)\n * Region: TW (Taiwan)\n */\n(function ($)"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/bootstrap-table-all.js",
"chars": 149098,
"preview": "/**\n * @author zhixin wen <wenzhixin2010@gmail.com>\n * version: 1.8.1\n * https://github.com/wenzhixin/bootstrap-table/\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/bootstrap-table-locale-all.js",
"chars": 38218,
"preview": "/**\n * Bootstrap Table English translation\n * Author: Zhixin Wen<wenzhixin2010@gmail.com>\n */\n(function ($) {\n 'use s"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/bootstrap-table.css",
"chars": 5972,
"preview": "/**\n * @author zhixin wen <wenzhixin2010@gmail.com>\n * version: 1.8.1\n * https://github.com/wenzhixin/bootstrap-table/\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/bootstrap-table.js",
"chars": 81958,
"preview": "/**\n * @author zhixin wen <wenzhixin2010@gmail.com>\n * version: 1.8.1\n * https://github.com/wenzhixin/bootstrap-table/\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/cookie/bootstrap-table-cookie.js",
"chars": 8395,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.1.0\n *\n * @update zhixin wen"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/editable/bootstrap-table-editable.js",
"chars": 2590,
"preview": "/**\n * @author zhixin wen <wenzhixin2010@gmail.com>\n * extensions: https://github.com/vitalets/x-editable\n */\n\n!function"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/export/bootstrap-table-export.js",
"chars": 3025,
"preview": "/**\n * @author zhixin wen <wenzhixin2010@gmail.com>\n * extensions: https://github.com/kayalshri/tableExport.jquery.plugi"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/filter/bootstrap-table-filter.js",
"chars": 1988,
"preview": "/**\n * @author zhixin wen <wenzhixin2010@gmail.com>\n * extensions: https://github.com/lukaskral/bootstrap-table-filter\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/filter-control/bootstrap-table-filter-control.js",
"chars": 10283,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.0.0\n */\n\n!function ($) {\n\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/flat-json/bootstrap-table-flat-json.js",
"chars": 1981,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.2.0\n */\n\n\n(function ($) {\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/key-events/bootstrap-table-key-events.js",
"chars": 2656,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.0.0\n *\n * @update zhixin wen"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile.js",
"chars": 2448,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.1.0\n */\n\n!function ($) {\n\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/multiple-sort/bootstrap-table-multiple-sort.js",
"chars": 15372,
"preview": "/**\n * @author Nadim Basalamah <dimbslmh@gmail.com>\n * @version: v1.0.0\n * https://github.com/dimbslmh/bootstrap-table/t"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/natural-sorting/bootstrap-table-natural-sorting.js",
"chars": 959,
"preview": "/**\n * @author: Brian Huisman\n * @webSite: http://www.greywyvern.com\n * @version: v1.0.0\n * JS function to allow natural"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/reorder-columns/bootstrap-table-reorder-columns.js",
"chars": 3315,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.1.0\n */\n\n!function ($) {\n\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/reorder-rows/bootstrap-table-reorder-rows.css",
"chars": 819,
"preview": ".reorder_rows_onDragClass td {\n background-color: #eee;\n -webkit-box-shadow: 11px 5px 12px 2px #333, 0 1px 0 #ccc "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/reorder-rows/bootstrap-table-reorder-rows.js",
"chars": 3231,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.0.0\n */\n\n!function ($) {\n\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/resizable/bootstrap-table-resizable.js",
"chars": 2194,
"preview": "/**\n * @author: Dennis Hernández\n * @webSite: http://djhvscf.github.io/Blog\n * @version: v1.0.0\n */\n\n(function ($) {\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/extensions/toolbar/bootstrap-table-toolbar.js",
"chars": 8689,
"preview": "/**\n * @author: aperez <aperez@datadec.es>\n * @version: v2.0.0\n *\n * @update Dennis Hernández <http://djhvscf.github.io/"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-ar-SA.js",
"chars": 1171,
"preview": "/**\n * Bootstrap Table English translation\n * Author: Zhixin Wen<wenzhixin2010@gmail.com>\n */\n(function ($) {\n 'use s"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-cs-CZ.js",
"chars": 1321,
"preview": "/**\n * Bootstrap Table Czech translation\n * Author: Lukas Kral (monarcha@seznam.cz)\n * Author: Jakub Svestka <svestka199"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-da-DK.js",
"chars": 1069,
"preview": "/**\n * Bootstrap Table danish translation\n * Author: Your Name Jan Borup Coyle, github@coyle.dk\n */\n(function ($) {\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-de-DE.js",
"chars": 998,
"preview": "/**\n* Bootstrap Table German translation\n* Author: Paul Mohr - Sopamo<p.mohr@sopamo.de>\n*/\n(function ($) {\n 'use strict"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-el-GR.js",
"chars": 862,
"preview": "/**\n * Bootstrap Table Greek translation\n * Author: giannisdallas\n */\n(function ($) {\n 'use strict';\n\n $.fn.bootst"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-en-US.js",
"chars": 1244,
"preview": "/**\n * Bootstrap Table English translation\n * Author: Zhixin Wen<wenzhixin2010@gmail.com>\n */\n(function ($) {\n 'use s"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-es-AR.js",
"chars": 937,
"preview": "/**\n * Bootstrap Table Spanish (Argentina) translation\n * Author: Felix Vera (felix.vera@gmail.com)\n */\n(function ($) {\n"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-es-CR.js",
"chars": 1218,
"preview": "/**\n * Bootstrap Table Spanish (Costa Rica) translation\n * Author: Dennis Hernández (http://djhvscf.github.io/Blog/)\n */"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-es-MX.js",
"chars": 1027,
"preview": "/**\n * Bootstrap Table Spanish (México) translation (Obtenido de traducción de Argentina)\n * Author: Felix Vera (felix.v"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-es-NI.js",
"chars": 1217,
"preview": "/**\n * Bootstrap Table Spanish (Nicaragua) translation\n * Author: Dennis Hernández (http://djhvscf.github.io/Blog/)\n */\n"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-es-SP.js",
"chars": 1177,
"preview": "/**\n * Bootstrap Table Spanish (España) translation\n * Author: Antonio Pérez <anpegar@gmail.com>\n */\n (function ($) {\n "
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-fr-BE.js",
"chars": 860,
"preview": "/**\n * Bootstrap Table French (Belgium) translation\n * Author: Julien Bisconti (julien.bisconti@gmail.com)\n */\n(function"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-fr-FR.js",
"chars": 1279,
"preview": "/**\n * Bootstrap Table French (France) translation\n * Author: Dennis Hernández (http://djhvscf.github.io/Blog/)\n * Modif"
},
{
"path": "static/assets/plugins/bootstrap-table/dist/locale/bootstrap-table-hu-HU.js",
"chars": 1073,
"preview": "/**\n * Bootstrap Table Hungarian translation\n * Author: Nagy Gergely <info@nagygergely.eu>\n */\n(function ($) {\n 'use "
}
]
// ... and 359 more files (download for full content)
About this extraction
This page contains the full source code of the roddyofchina/SimpletourDevops GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 559 files (4.8 MB), approximately 1.3M tokens, and a symbol index with 797 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.