mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 21:14:41 +00:00
Compare commits
155 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
493dc5c032 | ||
|
|
9a73bc2a18 | ||
|
|
55a9acd9f6 | ||
|
|
d060968b7a | ||
|
|
88a7f53130 | ||
|
|
26e5b18a5d | ||
|
|
011ace96f6 | ||
|
|
5c00655d14 | ||
|
|
eb36c262db | ||
|
|
29d1861545 | ||
|
|
3c9b410693 | ||
|
|
4c3b41433b | ||
|
|
1fd13668c0 | ||
|
|
d1ab7261a6 | ||
|
|
0fc65bcb3a | ||
|
|
f1ce8bfd99 | ||
|
|
3f472f1864 | ||
|
|
229d94cae7 | ||
|
|
c28e1bbf93 | ||
|
|
a840029000 | ||
|
|
aad2646cf2 | ||
|
|
ca1f8ad73e | ||
|
|
dea02763a2 | ||
|
|
ea67385a64 | ||
|
|
fa2daa2767 | ||
|
|
fcb906aa85 | ||
|
|
489a617126 | ||
|
|
601e7ce10b | ||
|
|
4a6fc9a945 | ||
|
|
b377af1d24 | ||
|
|
3fc00f8da7 | ||
|
|
6e39fe5f8c | ||
|
|
20c240a123 | ||
|
|
3ea9fc0de0 | ||
|
|
b80b08ef07 | ||
|
|
505af8d101 | ||
|
|
ae35a6d291 | ||
|
|
2b95c07a47 | ||
|
|
27a011e715 | ||
|
|
476831a12f | ||
|
|
9675eff69e | ||
|
|
85a044246e | ||
|
|
5c41fbcf3d | ||
|
|
6baab7a525 | ||
|
|
ab3b5a9077 | ||
|
|
5811c271b2 | ||
|
|
cf5387346d | ||
|
|
8df63c6c5c | ||
|
|
1d17d27c96 | ||
|
|
bdcbae69a5 | ||
|
|
cdbc3437be | ||
|
|
8940b520e0 | ||
|
|
1d62fbd670 | ||
|
|
a0b56d809e | ||
|
|
f1f6d33e26 | ||
|
|
f292edd2ba | ||
|
|
caa9b50b65 | ||
|
|
61b824065b | ||
|
|
9a900b2ca0 | ||
|
|
4c1cbc98a4 | ||
|
|
8660b95756 | ||
|
|
e7ebdc040f | ||
|
|
6c235d3f2a | ||
|
|
997d912f4d | ||
|
|
2508a4e07d | ||
|
|
90b997337c | ||
|
|
0bb3c92335 | ||
|
|
7fd539c57e | ||
|
|
52bd22ab2b | ||
|
|
46e9458e82 | ||
|
|
3f5595e794 | ||
|
|
d22cc7d3f6 | ||
|
|
eb03a3e6c7 | ||
|
|
65cc1f4752 | ||
|
|
99db197a39 | ||
|
|
7e2a5d553c | ||
|
|
f02337b83b | ||
|
|
f66b67b0c9 | ||
|
|
91087b5341 | ||
|
|
c67191d8c2 | ||
|
|
0fac461783 | ||
|
|
ec5bc922e7 | ||
|
|
7194792c3f | ||
|
|
76c8bade7f | ||
|
|
126857fab0 | ||
|
|
9ca57e105e | ||
|
|
2651140095 | ||
|
|
14175bc438 | ||
|
|
956328da86 | ||
|
|
cc46a96a75 | ||
|
|
049090444e | ||
|
|
796c25b7a5 | ||
|
|
9057290188 | ||
|
|
fcc57bb734 | ||
|
|
a98f5e087c | ||
|
|
403d563869 | ||
|
|
88c15104b4 | ||
|
|
6176289b88 | ||
|
|
5cfd44da79 | ||
|
|
2437da33a6 | ||
|
|
49ca0af746 | ||
|
|
9440b89fab | ||
|
|
f020c1162d | ||
|
|
120fb2cea2 | ||
|
|
37130966cf | ||
|
|
795b82c42c | ||
|
|
57ad33d53a | ||
|
|
a6ceee7bc0 | ||
|
|
44bb05fad0 | ||
|
|
a5fee0ee97 | ||
|
|
da99b2d01a | ||
|
|
1433e3297b | ||
|
|
cad7af13af | ||
|
|
39cb8904a3 | ||
|
|
2ed372b3cd | ||
|
|
8bca76b78b | ||
|
|
595e0f28af | ||
|
|
4939fe10aa | ||
|
|
d2962a8e70 | ||
|
|
d7d53d639b | ||
|
|
d2ff1b0506 | ||
|
|
7191735737 | ||
|
|
21f3fd85d9 | ||
|
|
ba77e07e36 | ||
|
|
0d6e7ca339 | ||
|
|
b1d5d9858b | ||
|
|
4f06be0e45 | ||
|
|
812ffd56a8 | ||
|
|
6ba845eec5 | ||
|
|
4fa72289ed | ||
|
|
5cdd842a3e | ||
|
|
cc5504c0a9 | ||
|
|
b3aa22605d | ||
|
|
32e00b17b1 | ||
|
|
16108f03ac | ||
|
|
e7f990b224 | ||
|
|
c5d824c4ba | ||
|
|
39ccbe251f | ||
|
|
e69d2e587b | ||
|
|
8a28d3c589 | ||
|
|
8fe0e4aa73 | ||
|
|
30a23a93a2 | ||
|
|
53157fbb1f | ||
|
|
fb15695dab | ||
|
|
5f5091f1e2 | ||
|
|
df92766c74 | ||
|
|
cc8b3e8f06 | ||
|
|
a116db8dbd | ||
|
|
d697547cb7 | ||
|
|
01960c0391 | ||
|
|
953c393e71 | ||
|
|
0873f7dd46 | ||
|
|
8d93a7f320 | ||
|
|
801eca0a14 | ||
|
|
a3ec7b70c9 |
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
15
.github/ISSUE_TEMPLATE/submit-application.md
vendored
Normal file
15
.github/ISSUE_TEMPLATE/submit-application.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
name: Submit application
|
||||||
|
about: Add an app to this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: LinkLeong
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Tested platform
|
||||||
|
e.g. linux/amd64,linux/arm-v7,linux-arm64
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Please export and upload the configuration file of this application
|
||||||
62
.github/workflows/casa.yml
vendored
62
.github/workflows/casa.yml
vendored
@@ -77,39 +77,36 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '14'
|
||||||
|
|
||||||
# - name: Build frontend with nodejs and yarn
|
- name: Build frontend with nodejs and yarn
|
||||||
# run: |
|
run: |
|
||||||
# cd casa/UI
|
cd UI
|
||||||
# ls
|
ls
|
||||||
# yarn install
|
yarn install
|
||||||
# yarn build
|
yarn build
|
||||||
|
|
||||||
- name: list work
|
- name: list work
|
||||||
run: pwd
|
run: pwd
|
||||||
|
|
||||||
# - name: Build with xgo
|
- name: Build with xgo
|
||||||
# uses: crazy-max/ghaction-xgo@v1
|
uses: crazy-max/ghaction-xgo@v1
|
||||||
# with:
|
with:
|
||||||
# xgo_version: latest
|
xgo_version: v0.7.5
|
||||||
# go_version: ${{ matrix.go_version }}
|
go_version: ${{ matrix.go_version }}
|
||||||
# dest: build
|
dest: build
|
||||||
# prefix: casa
|
prefix: casa
|
||||||
# targets: linux/amd64,linux/arm64
|
targets: linux/amd64,linux/arm64,linux/arm-7
|
||||||
# v: true
|
v: true
|
||||||
# x: false
|
x: false
|
||||||
# race: false
|
race: false
|
||||||
# ldflags: -s -w
|
ldflags: -s -w
|
||||||
# buildmode: default
|
buildmode: default
|
||||||
|
#
|
||||||
- name: List Files
|
# - name: List Files
|
||||||
run: |
|
# run: |
|
||||||
ls
|
# ls
|
||||||
mkdir build
|
# mkdir build
|
||||||
cd build
|
# ls
|
||||||
touch casa-linux-amd64
|
# echo "::set-output name=status::success"
|
||||||
touch casa-linux-arm64
|
|
||||||
ls
|
|
||||||
echo "::set-output name=status::success"
|
|
||||||
|
|
||||||
- name: Pack builds
|
- name: Pack builds
|
||||||
run: |
|
run: |
|
||||||
@@ -120,11 +117,7 @@ jobs:
|
|||||||
- name: list work
|
- name: list work
|
||||||
run: ls
|
run: ls
|
||||||
|
|
||||||
# - name: move
|
|
||||||
# run: |
|
|
||||||
# ls
|
|
||||||
# mv /workdir/casa/upload/linux-amd64-casaos.tar.gz ./linux-amd64-casaos.tar.gz
|
|
||||||
# mv /workdir/casa/upload/linux-arm64-casaos.tar.gz ./linux-arm64-casaos.tar.gz
|
|
||||||
- name: Update release
|
- name: Update release
|
||||||
uses: meeDamian/github-release@2.0
|
uses: meeDamian/github-release@2.0
|
||||||
with:
|
with:
|
||||||
@@ -132,6 +125,7 @@ jobs:
|
|||||||
files: >
|
files: >
|
||||||
linux-amd64-casaos.tar.gz
|
linux-amd64-casaos.tar.gz
|
||||||
linux-arm64-casaos.tar.gz
|
linux-arm64-casaos.tar.gz
|
||||||
|
linux-arm-7-casaos.tar.gz
|
||||||
tag: v${{ env.VERSION }}
|
tag: v${{ env.VERSION }}
|
||||||
body: >
|
body: >
|
||||||
${{ env.BODY }}
|
${{ env.BODY }}
|
||||||
|
|||||||
79
.github/workflows/demo.yml
vendored
Normal file
79
.github/workflows/demo.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
name: Demo Reset
|
||||||
|
|
||||||
|
# Controls when the workflow will run
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 * * * *"
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')
|
||||||
|
# OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')
|
||||||
|
# NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)
|
||||||
|
|
||||||
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
|
jobs:
|
||||||
|
# This workflow contains a single job called "build"
|
||||||
|
reset:
|
||||||
|
# The type of runner that the job will run on
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
|
steps:
|
||||||
|
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Configure AWS credentials from Test account
|
||||||
|
uses: aws-actions/configure-aws-credentials@v1
|
||||||
|
with:
|
||||||
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
aws-region: us-west-2
|
||||||
|
|
||||||
|
- name: Get old instance and snapshot name, create new instance name
|
||||||
|
run: |
|
||||||
|
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||||
|
echo "OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||||
|
echo "NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create instances from snapshot
|
||||||
|
run: |
|
||||||
|
aws lightsail create-instances-from-snapshot \
|
||||||
|
--instance-snapshot-name ${{ env.OLD_INSTANCE_SNAPSHOT_NAME }} \
|
||||||
|
--instance-names ${{ env.NEW_INSTANCE_NAME }} \
|
||||||
|
--availability-zone us-west-2a \
|
||||||
|
--bundle-id large_2_0
|
||||||
|
|
||||||
|
- name: Wait for new instance running
|
||||||
|
run: |
|
||||||
|
TIMEOUT=$(($(date +%s)+600))
|
||||||
|
while [ $TIMEOUT -gt $(date +%s) ]
|
||||||
|
do
|
||||||
|
NEW_INSTANCE_STATE=$(aws lightsail get-instance-state --instance-name ${{ env.NEW_INSTANCE_NAME }} | grep '"name":' | sed 's/ //g' | sed 's/"//g' | sed 's/name://g')
|
||||||
|
if [ $NEW_INSTANCE_STATE == running ]
|
||||||
|
then
|
||||||
|
echo "New instance is running now"
|
||||||
|
sleep 10s
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Put instance public ports
|
||||||
|
run: |
|
||||||
|
aws lightsail put-instance-public-ports \
|
||||||
|
--port-infos fromPort=0,toPort=65535,protocol=all \
|
||||||
|
--instance-name ${{ env.NEW_INSTANCE_NAME }}
|
||||||
|
|
||||||
|
- name: Attach static ip
|
||||||
|
run: |
|
||||||
|
aws lightsail attach-static-ip \
|
||||||
|
--static-ip-name CasaOS-Demo-IP \
|
||||||
|
--instance-name ${{ env.NEW_INSTANCE_NAME }}
|
||||||
|
|
||||||
|
- name: Delete old instance
|
||||||
|
run: |
|
||||||
|
aws lightsail delete-instance \
|
||||||
|
--instance-name ${{ env.OLD_INSTANCE_NAME }}
|
||||||
|
|
||||||
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
# IntelliJ project files
|
# IntelliJ project files
|
||||||
.idea
|
.idea
|
||||||
|
.vscode
|
||||||
*.iml
|
*.iml
|
||||||
out
|
out
|
||||||
gen
|
gen
|
||||||
@@ -28,4 +29,7 @@ gen
|
|||||||
/out/
|
/out/
|
||||||
/db/
|
/db/
|
||||||
/docs/
|
/docs/
|
||||||
/conf/
|
/conf/conf.ini
|
||||||
|
__debug_bin
|
||||||
|
main
|
||||||
|
CasaOS
|
||||||
|
|||||||
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
86
README.md
86
README.md
@@ -1,4 +1,4 @@
|
|||||||
# CasaOS - A simple, easy-to-use, elegant open-source home server system.
|
# CasaOS - A simple, easy-to-use, elegant open-source Home Cloud system.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -6,18 +6,55 @@
|
|||||||
[](https://github.com/IceWhaleTech/CasaOS/pulls)
|
[](https://github.com/IceWhaleTech/CasaOS/pulls)
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/issues)
|
[](https://github.com/IceWhaleTech/CasaOS/issues)
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/stargazers)
|
[](https://github.com/IceWhaleTech/CasaOS/stargazers)
|
||||||
[](https://discord.gg/Gx4BCEtHjx)
|
[](https://discord.gg/knqAbbBbeX)
|
||||||
|
|
||||||
CasaOS is an open-source home server system based on the Docker ecosystem and designed for home scenarios. It is committed to building the world's most simple, easy-to-use, and elegant home server system.
|
CasaOS is an open-source Home Cloud system based on the Docker ecosystem and designed for home scenarios. It is committed to building the world's most simple, easy-to-use, and elegant Home Cloud system.
|
||||||
|
|
||||||
IceWhale team believes that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
IceWhale team believes that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
> ⚠️ Note:
|
||||||
|
>
|
||||||
|
> CasaOS is still in the early development stage and may vary significantly with the final release. Feel free to test run and share your feedback in the [Discord server](https://discord.gg/knqAbbBbeX)!
|
||||||
|
|
||||||
|
### Quick Setup CasaOS
|
||||||
|
|
||||||
|
Fresh install a system from the list below and run the this command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
wget -qO- https://get.icewhale.io/casaos.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://get.icewhale.io/casaos.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstall CasaOS
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### System Compatibility
|
||||||
|
|
||||||
|
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)
|
||||||
|
- Raspberry Pi Lite OS aarch64/arm64 (⚠️ Not Fully Tested Yet)
|
||||||
|
- Debian 11 amd64 (⚠️ Not Fully Tested Yet)
|
||||||
|
- OpenWrt 21.02 amd64 (⚠️ Not Fully Tested Yet)
|
||||||
|
- OpenWrt 21.02 aarch64/arm64 (⚠️ Not Fully Tested Yet)
|
||||||
|
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
- UI designed for home scenarios - simple, elegant, and easy-to-use
|
- UI designed for home scenarios - simple, elegant, and easy-to-use
|
||||||
- Quick Docker app installation with only three steps, plus automatic management
|
- Quick Docker app installation with only three steps, plus automatic management
|
||||||
- App Store for private cloud 🚧
|
- App Store for Home Cloud 🚧
|
||||||
- Home data/digital asset management 🚧
|
- Home data/digital asset management 🚧
|
||||||
- Smart home manager 🚧
|
- Smart home manager 🚧
|
||||||
|
|
||||||
@@ -34,48 +71,11 @@ After looking at many systems and software on the market, the team found no serv
|
|||||||
|
|
||||||
So, we set out to build this open source project to develop CasaOS with our own hands, everyone in the community, and you.
|
So, we set out to build this open source project to develop CasaOS with our own hands, everyone in the community, and you.
|
||||||
|
|
||||||
> A warm welcome for you to share and discuss your great ideas in the [Discord server](https://discord.gg/Gx4BCEtHjx)!
|
> A warm welcome for you to share and discuss your great ideas in the [Discord server](https://discord.gg/knqAbbBbeX)!
|
||||||
|
|
||||||
[](https://discord.gg/Gx4BCEtHjx)
|
[](https://discord.gg/knqAbbBbeX)
|
||||||
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
> ⚠️ Note:
|
|
||||||
>
|
|
||||||
> CasaOS is still in the early development stage and may vary significantly with the final release. Feel free to test run and share your feedback in the [Discord server](https://discord.gg/Gx4BCEtHjx)!
|
|
||||||
|
|
||||||
### System Compatibility
|
|
||||||
|
|
||||||
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)
|
|
||||||
- Debian 11 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- OpenWrt 21.02 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- Raspberry Pi OS aarch64/arm64 (🚧 Under Planning)
|
|
||||||
- OpenWrt 21.02 aarch64/arm64 (🚧 Under Planning)
|
|
||||||
|
|
||||||
### Quick Setup CasaOS
|
|
||||||
|
|
||||||
Fresh install a system from the above list and run the below command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
curl -fsSL https://get.icewhale.io/casaos.sh | bash
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## To Do
|
|
||||||
|
|
||||||
**v 0.1.x**
|
|
||||||
|
|
||||||
- [x] An elegant UI for home scenarios
|
|
||||||
- [x] Custom installation of Docker Apps
|
|
||||||
- [x] Update, stop, uninstall, restart, etc. of Docker apps
|
|
||||||
- [x] Docker CLI parser
|
|
||||||
- [x] System Update
|
|
||||||
- [ ] Getting Started tutorial
|
|
||||||
- [ ] Docker Compose parser
|
|
||||||
- [ ] App config file import and export
|
|
||||||
- [ ] macvlan network mode
|
|
||||||
|
|
||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
- Jerry Liu
|
- Jerry Liu
|
||||||
|
|||||||
2
UI
2
UI
Submodule UI updated: c75085250a...25c7eec90d
@@ -1,52 +1,42 @@
|
|||||||
[app]
|
[app]
|
||||||
PAGE_SIZE = 10
|
PAGE_SIZE = 10
|
||||||
RuntimeRootPath = runtime/
|
RuntimeRootPath = runtime/
|
||||||
;LogSavePath = /casaOS/logs/server/
|
LogSavePath = /casaOS/logs/server/
|
||||||
LogSavePath = /oasis/logs/server/
|
|
||||||
LogSaveName = log
|
LogSaveName = log
|
||||||
LogFileExt = log
|
LogFileExt = log
|
||||||
; 必须的格式
|
|
||||||
DateStrFormat = 20060102
|
DateStrFormat = 20060102
|
||||||
DateTimeFormat = 2006-01-02 15:04:05
|
DateTimeFormat = 2006-01-02 15:04:05
|
||||||
TimeFormat = 15:04:05
|
TimeFormat = 15:04:05
|
||||||
DateFormat = 2006-01-02
|
DateFormat = 2006-01-02
|
||||||
;ProjectPath = /casaOS/server
|
ProjectPath = /casaOS/server
|
||||||
ProjectPath = /oasis/server
|
|
||||||
|
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
HttpPort = 8089
|
HttpPort = 8089
|
||||||
RunMode = debug
|
RunMode = release
|
||||||
;ServerApi = http://113.52.135.30:8090
|
ServerApi = https://api.casaos.zimaboard.com
|
||||||
;ServerApi = https://casaos.zimaboard.com
|
|
||||||
;ServerApi = http://192.168.2.167:8090
|
|
||||||
ServerApi = http://192.168.2.142:8090
|
|
||||||
|
|
||||||
[user]
|
[user]
|
||||||
UserName = admin
|
UserName = admin
|
||||||
PWD = zimaboard
|
PWD = zimaboard
|
||||||
Email = aaa@222.ddd
|
Email = user@gmail.com
|
||||||
Description = ddddddd
|
Description = description
|
||||||
|
Initialized = false
|
||||||
Token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImVyZXJlIiwicGFzc3dvcmQiOiJhZHNmZGYiLCJleHAiOjE2MjQwMDU0ODEsImlzcyI6Imdpbi1ibG9nIn0.JNsCccZuFCwlSMLJg62iOIB2xymk_k7xGa11xhZ07bc
|
Token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImVyZXJlIiwicGFzc3dvcmQiOiJhZHNmZGYiLCJleHAiOjE2MjQwMDU0ODEsImlzcyI6Imdpbi1ibG9nIn0.JNsCccZuFCwlSMLJg62iOIB2xymk_k7xGa11xhZ07bc
|
||||||
|
|
||||||
[zerotier]
|
[zerotier]
|
||||||
UserName = ddddd
|
UserName = user
|
||||||
PWD =
|
PWD = pwd
|
||||||
Token = yBKYyavr2RdFAIVN7iTpzlsB1o6CqTgm
|
Token = yBKYyavr2RdFAIVN7iTpzlsB1o6CqTgm
|
||||||
|
|
||||||
[redis]
|
[redis]
|
||||||
Host = 192.168.2.167:6379
|
Host = 127.0.0.1:6379
|
||||||
Password =
|
Password =
|
||||||
MaxIdle = 30
|
MaxIdle = 30
|
||||||
MaxActive = 30
|
MaxActive = 30
|
||||||
IdleTimeout = 200
|
IdleTimeout = 200
|
||||||
|
|
||||||
[system]
|
[system]
|
||||||
AutoUpdate = true
|
ConfigStr =
|
||||||
SearchSwitch = true
|
WidgetList =
|
||||||
WidgetsSwitch = false
|
|
||||||
ShortcutsSwitch = true
|
|
||||||
SearchEngine = baidu
|
|
||||||
Background = http://baidu.com1
|
|
||||||
BackgroundType = d
|
|
||||||
|
|
||||||
2901
docs/docs.go
2901
docs/docs.go
File diff suppressed because it is too large
Load Diff
2839
docs/swagger.json
2839
docs/swagger.json
File diff suppressed because it is too large
Load Diff
1753
docs/swagger.yaml
1753
docs/swagger.yaml
File diff suppressed because it is too large
Load Diff
24
go.mod
24
go.mod
@@ -7,9 +7,8 @@ require (
|
|||||||
github.com/Microsoft/hcsshim v0.8.22 // indirect
|
github.com/Microsoft/hcsshim v0.8.22 // indirect
|
||||||
github.com/PuerkitoBio/goquery v1.7.0
|
github.com/PuerkitoBio/goquery v1.7.0
|
||||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
|
|
||||||
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
||||||
github.com/containerd/containerd v1.5.5
|
github.com/containerd/containerd v1.5.7
|
||||||
github.com/containerd/continuity v0.2.0 // indirect
|
github.com/containerd/continuity v0.2.0 // indirect
|
||||||
github.com/docker/docker v20.10.7+incompatible
|
github.com/docker/docker v20.10.7+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
@@ -18,9 +17,7 @@ require (
|
|||||||
github.com/gin-gonic/gin v1.7.2
|
github.com/gin-gonic/gin v1.7.2
|
||||||
github.com/go-ini/ini v1.62.0
|
github.com/go-ini/ini v1.62.0
|
||||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
github.com/go-openapi/spec v0.20.4 // indirect
|
||||||
github.com/go-openapi/spec v0.20.3 // indirect
|
|
||||||
github.com/go-openapi/swag v0.19.15 // indirect
|
|
||||||
github.com/go-playground/validator/v10 v10.6.1 // indirect
|
github.com/go-playground/validator/v10 v10.6.1 // indirect
|
||||||
github.com/gogo/googleapis v1.4.1 // indirect
|
github.com/gogo/googleapis v1.4.1 // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
@@ -35,11 +32,11 @@ require (
|
|||||||
github.com/klauspost/compress v1.13.6 // indirect
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/opencontainers/runc v1.0.2 // indirect
|
|
||||||
github.com/opencontainers/selinux v1.8.5 // indirect
|
github.com/opencontainers/selinux v1.8.5 // indirect
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109
|
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
github.com/prometheus/procfs v0.7.3 // indirect
|
||||||
@@ -50,21 +47,20 @@ require (
|
|||||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
github.com/swaggo/gin-swagger v1.3.0
|
github.com/swaggo/gin-swagger v1.3.0
|
||||||
github.com/swaggo/swag v1.7.0
|
github.com/swaggo/swag v1.7.3
|
||||||
github.com/tidwall/gjson v1.8.0
|
github.com/tidwall/gjson v1.10.2
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/sjson v1.2.3
|
||||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
||||||
github.com/ugorji/go v1.2.6 // indirect
|
github.com/ugorji/go v1.2.6 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||||
golang.org/x/mod v0.5.0 // indirect
|
golang.org/x/mod v0.5.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20210924151903-3ad01bbaa167 // indirect
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
||||||
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284 // indirect
|
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||||
golang.org/x/tools v0.1.5 // indirect
|
golang.org/x/tools v0.1.7 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 // indirect
|
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 // indirect
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
google.golang.org/grpc v1.41.0 // indirect
|
||||||
|
|||||||
57
go.sum
57
go.sum
@@ -68,7 +68,7 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
|
|||||||
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
|
||||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||||
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
|
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
|
||||||
github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||||
github.com/Microsoft/hcsshim v0.8.22 h1:CulZ3GW8sNJExknToo+RWD+U+6ZM5kkNfuxywSDPd08=
|
github.com/Microsoft/hcsshim v0.8.22 h1:CulZ3GW8sNJExknToo+RWD+U+6ZM5kkNfuxywSDPd08=
|
||||||
github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
|
github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0=
|
||||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||||
@@ -168,8 +168,8 @@ github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo
|
|||||||
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
|
github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI=
|
||||||
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
|
github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s=
|
||||||
github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
|
github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
|
||||||
github.com/containerd/containerd v1.5.5 h1:q1gxsZsGZ8ddVe98yO6pR21b5xQSMiR61lD0W96pgQo=
|
github.com/containerd/containerd v1.5.7 h1:rQyoYtj4KddB3bxG6SAqd4+08gePNyJjRqvOIfV3rkM=
|
||||||
github.com/containerd/containerd v1.5.5/go.mod h1:oSTh0QpT1w6jYcGmbiSbxv9OSQYaa88mPyWIuU79zyo=
|
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
||||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
@@ -335,19 +335,17 @@ github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo
|
|||||||
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||||
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
|
||||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||||
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||||
github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA=
|
|
||||||
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
|
|
||||||
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
|
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
|
||||||
|
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||||
|
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
|
|
||||||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||||
@@ -367,6 +365,7 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
|
|||||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||||
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||||
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
|
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
|
||||||
@@ -484,6 +483,7 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
|||||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
|
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||||
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
|
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
|
||||||
@@ -547,8 +547,8 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
|||||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||||
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
|
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
|
||||||
@@ -613,7 +613,6 @@ github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59P
|
|||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||||
github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
|
||||||
github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
|
github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
@@ -629,6 +628,8 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3
|
|||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA=
|
github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA=
|
||||||
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
@@ -685,6 +686,7 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
|
|||||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||||
github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4=
|
github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4=
|
||||||
github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
|
github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
|
||||||
|
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
@@ -733,19 +735,20 @@ github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuI
|
|||||||
github.com/swaggo/gin-swagger v1.3.0 h1:eOmp7r57oUgZPw2dJOjcGNMse9cvXcI4tTqBcnZtPsI=
|
github.com/swaggo/gin-swagger v1.3.0 h1:eOmp7r57oUgZPw2dJOjcGNMse9cvXcI4tTqBcnZtPsI=
|
||||||
github.com/swaggo/gin-swagger v1.3.0/go.mod h1:oy1BRA6WvgtCp848lhxce7BnWH4C8Bxa0m5SkWx+cS0=
|
github.com/swaggo/gin-swagger v1.3.0/go.mod h1:oy1BRA6WvgtCp848lhxce7BnWH4C8Bxa0m5SkWx+cS0=
|
||||||
github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
|
github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
|
||||||
github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
|
github.com/swaggo/swag v1.7.3 h1:ucB7irEdRrhjmW+Z1Ss4GjO68oPKQFjSgOR8BCAvcbU=
|
||||||
github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
|
github.com/swaggo/swag v1.7.3/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI=
|
||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||||
github.com/tidwall/gjson v1.8.0 h1:Qt+orfosKn0rbNTZqHYDqBrmm3UDA4KRkv70fDzG+PQ=
|
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
|
||||||
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
|
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
|
||||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8=
|
||||||
|
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
||||||
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
|
github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek=
|
||||||
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
|
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
|
||||||
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
|
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
|
||||||
@@ -787,7 +790,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||||
@@ -903,8 +906,9 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
golang.org/x/net v0.0.0-20210924151903-3ad01bbaa167 h1:eDd+TJqbgfXruGQ5sJRU7tEtp/58OAx4+Ayjxg4SM+4=
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210924151903-3ad01bbaa167/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
|
||||||
|
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -991,6 +995,7 @@ golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -1002,8 +1007,10 @@ golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284 h1:lBPNCmq8u4zFP3huKCmUQ2Fx8kcY4X+O12UgGnyKsrg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo=
|
||||||
|
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@@ -1072,10 +1079,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||||||
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
|
||||||
|
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
28
main.go
28
main.go
@@ -3,47 +3,59 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"github.com/IceWhaleTech/CasaOS/route"
|
"github.com/IceWhaleTech/CasaOS/route"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var sqliteDB *gorm.DB
|
var sqliteDB *gorm.DB
|
||||||
|
|
||||||
var swagHandler gin.HandlerFunc
|
|
||||||
var configFlag = flag.String("c", "", "config address")
|
var configFlag = flag.String("c", "", "config address")
|
||||||
|
|
||||||
|
var showUserInfo = flag.Bool("show-user-info", false, "show user info")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
config.InitSetup(*configFlag)
|
config.InitSetup(*configFlag)
|
||||||
|
config.UpdateSetup()
|
||||||
loger2.LogSetup()
|
loger2.LogSetup()
|
||||||
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
|
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
|
||||||
//gredis.GetRedisConn(config.RedisInfo),
|
//gredis.GetRedisConn(config.RedisInfo),
|
||||||
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
|
||||||
|
service.Cache = cache.Init()
|
||||||
|
route.InitFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
// @title Oasis API
|
// @title casaOS API
|
||||||
// @version 1.0.0
|
// @version 1.0.0
|
||||||
// @contact.name lauren.pan
|
// @contact.name lauren.pan
|
||||||
// @contact.url https://www.zimaboard.com
|
// @contact.url https://www.zimaboard.com
|
||||||
// @contact.email lauren.pan@icewhale.org
|
// @contact.email lauren.pan@icewhale.org
|
||||||
// @description Oasis v1版本api
|
// @description casaOS v1版本api
|
||||||
// @host 192.168.2.114:8089
|
// @host 192.168.2.217:8089
|
||||||
// @securityDefinitions.apikey ApiKeyAuth
|
// @securityDefinitions.apikey ApiKeyAuth
|
||||||
// @in header
|
// @in header
|
||||||
// @name Authorization
|
// @name Authorization
|
||||||
// @BasePath /v1
|
// @BasePath /v1
|
||||||
func main() {
|
func main() {
|
||||||
|
if *showUserInfo {
|
||||||
|
fmt.Println("CasaOS User Info")
|
||||||
|
fmt.Println("UserName:" + config.UserInfo.UserName)
|
||||||
|
fmt.Println("Password:" + config.UserInfo.PWD)
|
||||||
|
return
|
||||||
|
}
|
||||||
//model.Setup()
|
//model.Setup()
|
||||||
//gredis.Setup()
|
//gredis.Setup()
|
||||||
r := route.InitRouter(swagHandler)
|
r := route.InitRouter()
|
||||||
//service.SyncTask(sqliteDB)
|
//service.SyncTask(sqliteDB)
|
||||||
cron2 := cron.New() //创建一个cron实例
|
cron2 := cron.New() //创建一个cron实例
|
||||||
//执行定时任务(每5秒执行一次)
|
//执行定时任务(每5秒执行一次)
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Cors() gin.HandlerFunc {
|
func Cors() gin.HandlerFunc {
|
||||||
@@ -17,7 +18,7 @@ func Cors() gin.HandlerFunc {
|
|||||||
//服务器支持的所有跨域请求的方法
|
//服务器支持的所有跨域请求的方法
|
||||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
||||||
//允许跨域设置可以返回其他子段,可以自定义字段
|
//允许跨域设置可以返回其他子段,可以自定义字段
|
||||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session")
|
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
|
||||||
// 允许浏览器(客户端)可以解析的头部 (重要)
|
// 允许浏览器(客户端)可以解析的头部 (重要)
|
||||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
||||||
//设置缓存时间
|
//设置缓存时间
|
||||||
|
|||||||
58
model/app.go
58
model/app.go
@@ -7,32 +7,38 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ServerAppList struct {
|
type ServerAppList struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Tagline string `json:"tagline"`
|
Tagline string `json:"tagline"`
|
||||||
Tags Strings `gorm:"type:json" json:"tags"`
|
Tags Strings `gorm:"type:json" json:"tags"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
||||||
Category string `json:"category"`
|
Category string `json:"category"`
|
||||||
TcpPort uint `json:"tcp_port"`
|
CategoryFont string `json:"category_font"`
|
||||||
PortMap uint `json:"port_map"`
|
PortMap string `json:"port_map"`
|
||||||
ImageVersion string `json:"image_version"`
|
ImageVersion string `json:"image_version"`
|
||||||
Tip string `json:"tip"`
|
Tip string `json:"tip"`
|
||||||
Configures configures `gorm:"type:json" json:"configures"`
|
Envs EnvArray `json:"envs"`
|
||||||
NetworkModel string `json:"network_mode"`
|
Ports PortArray `json:"ports"`
|
||||||
Image string `json:"image"`
|
Volumes PathArray `json:"volumes"`
|
||||||
Index string `json:"index"`
|
Devices PathArray `json:"devices"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
NetworkModel string `json:"network_model"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
Image string `json:"image"`
|
||||||
State string `json:"state"`
|
Index string `json:"index"`
|
||||||
Author string `json:"author"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
MinMemory int `json:"min_memory"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
MinDisk int `json:"min_disk"`
|
State string `json:"state"`
|
||||||
MaxMemory uint64 `json:"max_memory"`
|
Author string `json:"author"`
|
||||||
Thumbnail string `json:"thumbnail"`
|
MinMemory int `json:"min_memory"`
|
||||||
Healthy string `json:"healthy"`
|
MinDisk int `json:"min_disk"`
|
||||||
Plugins Strings `json:"plugins"`
|
MaxMemory uint64 `json:"max_memory"`
|
||||||
|
Thumbnail string `json:"thumbnail"`
|
||||||
|
Healthy string `json:"healthy"`
|
||||||
|
Plugins Strings `json:"plugins"`
|
||||||
|
Origin string `json:"origin"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Developer string `json:"developer"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ports struct {
|
type Ports struct {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ type ServerCategoryList struct {
|
|||||||
//CreatedAt time.Time `json:"created_at"`
|
//CreatedAt time.Time `json:"created_at"`
|
||||||
//
|
//
|
||||||
//UpdatedAt time.Time `json:"updated_at"`
|
//UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
Font string `json:"font"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Count uint `json:"count"`
|
Count uint `json:"count"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,57 @@ type LSBLKModel struct {
|
|||||||
Format string `json:"format"`
|
Format string `json:"format"`
|
||||||
Health string `json:"health"`
|
Health string `json:"health"`
|
||||||
HotPlug bool `json:"hotplug"`
|
HotPlug bool `json:"hotplug"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
FSUsed string `json:"fsused"`
|
FSUsed string `json:"fsused"`
|
||||||
|
Temperature int `json:"temperature"`
|
||||||
Tran string `json:"tran"`
|
Tran string `json:"tran"`
|
||||||
MinIO uint64 `json:"min-io"`
|
MinIO uint64 `json:"min-io"`
|
||||||
UsedPercent float64 `json:"used_percent"`
|
UsedPercent float64 `json:"used_percent"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
Children []LSBLKModel `json:"children"`
|
Children []LSBLKModel `json:"children"`
|
||||||
|
SubSystems string `json:"subsystems"`
|
||||||
//详情特有
|
//详情特有
|
||||||
StartSector uint64 `json:"start_sector,omitempty"`
|
StartSector uint64 `json:"start_sector,omitempty"`
|
||||||
|
Rota bool `json:"rota"` //true(hhd) false(ssd)
|
||||||
|
DiskType string `json:"disk_type"`
|
||||||
EndSector uint64 `json:"end_sector,omitempty"`
|
EndSector uint64 `json:"end_sector,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Drive struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Health string `json:"health"`
|
||||||
|
Temperature int `json:"temperature"`
|
||||||
|
DiskType string `json:"disk_type"`
|
||||||
|
NeedFormat bool `json:"need_format"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriveUSB struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Used uint64 `json:"use"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Mount bool `json:"mount"` //是否完全挂载
|
||||||
|
Avail uint64 `json:"avail"` //可用空间
|
||||||
|
}
|
||||||
|
|
||||||
|
type Storage struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
MountPoint string `json:"mountpoint"`
|
||||||
|
Size string `json:"size"`
|
||||||
|
Avail string `json:"avail"` //可用空间
|
||||||
|
Type string `json:"type"`
|
||||||
|
CreatedAt int64 `json:"create_at"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
DriveName string `json:"drive_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Summary struct {
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
Avail uint64 `json:"avail"` //可用空间
|
||||||
|
Health bool `json:"health"`
|
||||||
|
Used uint64 `json:"used"`
|
||||||
|
}
|
||||||
|
|||||||
8
model/docker.go
Normal file
8
model/docker.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type DockerStatsModel struct {
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
Pre interface{} `json:"pre"`
|
||||||
|
}
|
||||||
@@ -17,20 +17,22 @@ type UdpPorts struct {
|
|||||||
/*******************使用gorm支持json************************************/
|
/*******************使用gorm支持json************************************/
|
||||||
|
|
||||||
type PortMap struct {
|
type PortMap struct {
|
||||||
ContainerPort string `json:"container,omitempty"`
|
ContainerPort string `json:"container"`
|
||||||
CommendPort string `json:"host,omitempty"`
|
CommendPort string `json:"host"`
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
Type int `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PortArrey []PortMap
|
type PortArray []PortMap
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p PortArrey) Value() (driver.Value, error) {
|
func (p PortArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *PortArrey) Scan(input interface{}) error {
|
func (p *PortArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,20 +43,22 @@ func (p *PortArrey) Scan(input interface{}) error {
|
|||||||
type Env struct {
|
type Env struct {
|
||||||
Name string `json:"container"`
|
Name string `json:"container"`
|
||||||
Value string `json:"host"`
|
Value string `json:"host"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
Type int `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type JSON json.RawMessage
|
type JSON json.RawMessage
|
||||||
|
|
||||||
type EnvArrey []Env
|
type EnvArray []Env
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p EnvArrey) Value() (driver.Value, error) {
|
func (p EnvArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
//return .MarshalJSON()
|
//return .MarshalJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *EnvArrey) Scan(input interface{}) error {
|
func (p *EnvArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,17 +69,19 @@ func (p *EnvArrey) Scan(input interface{}) error {
|
|||||||
type PathMap struct {
|
type PathMap struct {
|
||||||
ContainerPath string `json:"container"`
|
ContainerPath string `json:"container"`
|
||||||
Path string `json:"host"`
|
Path string `json:"host"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PathArrey []PathMap
|
type PathArray []PathMap
|
||||||
|
|
||||||
// Value 实现方法
|
// Value 实现方法
|
||||||
func (p PathArrey) Value() (driver.Value, error) {
|
func (p PathArray) Value() (driver.Value, error) {
|
||||||
return json.Marshal(p)
|
return json.Marshal(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan 实现方法
|
// Scan 实现方法
|
||||||
func (p *PathArrey) Scan(input interface{}) error {
|
func (p *PathArray) Scan(input interface{}) error {
|
||||||
return json.Unmarshal(input.([]byte), p)
|
return json.Unmarshal(input.([]byte), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,10 +109,10 @@ type CustomizationPostData struct {
|
|||||||
Index string `json:"index"`
|
Index string `json:"index"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
Envs EnvArrey `json:"envs"`
|
Envs EnvArray `json:"envs"`
|
||||||
Ports PortArrey `json:"ports"`
|
Ports PortArray `json:"ports"`
|
||||||
Volumes PathArrey `json:"volumes"`
|
Volumes PathArray `json:"volumes"`
|
||||||
Devices PathArrey `json:"devices"`
|
Devices PathArray `json:"devices"`
|
||||||
//Port string `json:"port,omitempty"`
|
//Port string `json:"port,omitempty"`
|
||||||
PortMap string `json:"port_map"`
|
PortMap string `json:"port_map"`
|
||||||
CpuShares int64 `json:"cpu_shares"`
|
CpuShares int64 `json:"cpu_shares"`
|
||||||
|
|||||||
7
model/search.go
Normal file
7
model/search.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type SearchFileInfo struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
}
|
||||||
69
model/smartctl_model.go
Normal file
69
model/smartctl_model.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
//
|
||||||
|
type SmartctlA struct {
|
||||||
|
Smartctl struct {
|
||||||
|
Version []int `json:"version"`
|
||||||
|
SvnRevision string `json:"svn_revision"`
|
||||||
|
PlatformInfo string `json:"platform_info"`
|
||||||
|
BuildInfo string `json:"build_info"`
|
||||||
|
Argv []string `json:"argv"`
|
||||||
|
ExitStatus int `json:"exit_status"`
|
||||||
|
} `json:"smartctl"`
|
||||||
|
Device struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
InfoName string `json:"info_name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Protocol string `json:"protocol"`
|
||||||
|
} `json:"device"`
|
||||||
|
ModelName string `json:"model_name"`
|
||||||
|
SerialNumber string `json:"serial_number"`
|
||||||
|
FirmwareVersion string `json:"firmware_version"`
|
||||||
|
UserCapacity struct {
|
||||||
|
Blocks int `json:"blocks"`
|
||||||
|
Bytes int64 `json:"bytes"`
|
||||||
|
} `json:"user_capacity"`
|
||||||
|
SmartStatus struct {
|
||||||
|
Passed bool `json:"passed"`
|
||||||
|
} `json:"smart_status"`
|
||||||
|
AtaSmartData struct {
|
||||||
|
OfflineDataCollection struct {
|
||||||
|
Status struct {
|
||||||
|
Value int `json:"value"`
|
||||||
|
String string `json:"string"`
|
||||||
|
} `json:"status"`
|
||||||
|
CompletionSeconds int `json:"completion_seconds"`
|
||||||
|
} `json:"offline_data_collection"`
|
||||||
|
SelfTest struct {
|
||||||
|
Status struct {
|
||||||
|
Value int `json:"value"`
|
||||||
|
String string `json:"string"`
|
||||||
|
Passed bool `json:"passed"`
|
||||||
|
} `json:"status"`
|
||||||
|
PollingMinutes struct {
|
||||||
|
Short int `json:"short"`
|
||||||
|
Extended int `json:"extended"`
|
||||||
|
Conveyance int `json:"conveyance"`
|
||||||
|
} `json:"polling_minutes"`
|
||||||
|
} `json:"self_test"`
|
||||||
|
Capabilities struct {
|
||||||
|
Values []int `json:"values"`
|
||||||
|
ExecOfflineImmediateSupported bool `json:"exec_offline_immediate_supported"`
|
||||||
|
OfflineIsAbortedUponNewCmd bool `json:"offline_is_aborted_upon_new_cmd"`
|
||||||
|
OfflineSurfaceScanSupported bool `json:"offline_surface_scan_supported"`
|
||||||
|
SelfTestsSupported bool `json:"self_tests_supported"`
|
||||||
|
ConveyanceSelfTestSupported bool `json:"conveyance_self_test_supported"`
|
||||||
|
SelectiveSelfTestSupported bool `json:"selective_self_test_supported"`
|
||||||
|
AttributeAutosaveEnabled bool `json:"attribute_autosave_enabled"`
|
||||||
|
ErrorLoggingSupported bool `json:"error_logging_supported"`
|
||||||
|
GpLoggingSupported bool `json:"gp_logging_supported"`
|
||||||
|
} `json:"capabilities"`
|
||||||
|
} `json:"ata_smart_data"`
|
||||||
|
PowerOnTime struct {
|
||||||
|
Hours int `json:"hours"`
|
||||||
|
} `json:"power_on_time"`
|
||||||
|
PowerCycleCount int `json:"power_cycle_count"`
|
||||||
|
Temperature struct {
|
||||||
|
Current int `json:"current"`
|
||||||
|
} `json:"temperature"`
|
||||||
|
}
|
||||||
@@ -15,13 +15,15 @@ type UserModel struct {
|
|||||||
Head string
|
Head string
|
||||||
Email string
|
Email string
|
||||||
Description string
|
Description string
|
||||||
|
Initialized bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//服务配置
|
//服务配置
|
||||||
type ServerModel struct {
|
type ServerModel struct {
|
||||||
HttpPort string
|
HttpPort string
|
||||||
RunMode string
|
RunMode string
|
||||||
ServerApi string
|
ServerApi string
|
||||||
|
LockAccount bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//服务配置
|
//服务配置
|
||||||
@@ -60,11 +62,13 @@ type RedisModel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SystemConfig struct {
|
type SystemConfig struct {
|
||||||
SearchSwitch bool `json:"search_switch"` //搜索开关
|
ConfigStr string `json:"config_str"`
|
||||||
SearchEngine string `json:"search_engine"` //搜索引擎
|
WidgetList string `json:"widget_list"`
|
||||||
ShortcutsSwitch bool `json:"shortcuts_switch"`
|
ConfigPath string `json:"config_path"`
|
||||||
WidgetsSwitch bool `json:"widgets_switch"`
|
SyncPort string `json:"sync_port"`
|
||||||
BackgroundType string `json:"background_type"`
|
SyncKey string `json:"sync_key"`
|
||||||
Background string `json:"background"`
|
}
|
||||||
AutoUpdate bool `json:"auto_update"`
|
|
||||||
|
type CasaOSGlobalVariables struct {
|
||||||
|
AppChange bool
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
8
model/system_app/sync.go
Normal file
8
model/system_app/sync.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package system_app
|
||||||
|
|
||||||
|
import "encoding/xml"
|
||||||
|
|
||||||
|
type SyncConfig struct {
|
||||||
|
XMLName xml.Name `xml:"configuration"`
|
||||||
|
Key string `xml:"gui>apikey"`
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type Path struct {
|
type Path struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
IsDir bool `json:"is_dir"`
|
||||||
|
Date time.Time `json:"date"`
|
||||||
}
|
}
|
||||||
|
|||||||
11
pkg/cache/cache.go
vendored
Normal file
11
pkg/cache/cache.go
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init() *cache.Cache {
|
||||||
|
return cache.New(5*time.Minute, 60*time.Second)
|
||||||
|
}
|
||||||
@@ -2,14 +2,15 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/go-ini/ini"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/go-ini/ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
//系统配置
|
//系统配置
|
||||||
@@ -32,6 +33,8 @@ var ServerInfo = &model.ServerModel{}
|
|||||||
|
|
||||||
var SystemConfigInfo = &model.SystemConfig{}
|
var SystemConfigInfo = &model.SystemConfig{}
|
||||||
|
|
||||||
|
var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
|
||||||
|
|
||||||
var Cfg *ini.File
|
var Cfg *ini.File
|
||||||
|
|
||||||
//初始化设置,获取系统的部分信息。
|
//初始化设置,获取系统的部分信息。
|
||||||
@@ -55,6 +58,7 @@ func InitSetup(config string) {
|
|||||||
mapTo("redis", RedisInfo)
|
mapTo("redis", RedisInfo)
|
||||||
mapTo("server", ServerInfo)
|
mapTo("server", ServerInfo)
|
||||||
mapTo("system", SystemConfigInfo)
|
mapTo("system", SystemConfigInfo)
|
||||||
|
SystemConfigInfo.ConfigPath = configDir
|
||||||
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
15
pkg/config/update.go
Normal file
15
pkg/config/update.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
|
||||||
|
//检查目录是否存在
|
||||||
|
func mkdirDATAAll() {
|
||||||
|
dirArray := [7]string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
|
||||||
|
for _, v := range dirArray {
|
||||||
|
file.IsNotExistMkDir(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateSetup() {
|
||||||
|
mkdirDATAAll()
|
||||||
|
}
|
||||||
@@ -4,30 +4,35 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewSshClient() (*ssh.Client, error) {
|
func NewSshClient(user, password string) (*ssh.Client, error) {
|
||||||
|
|
||||||
|
// connet to ssh
|
||||||
|
// addr = fmt.Sprintf("%s:%d", host, port)
|
||||||
|
|
||||||
config := &ssh.ClientConfig{
|
config := &ssh.ClientConfig{
|
||||||
Timeout: time.Second * 5,
|
Timeout: time.Second * 5,
|
||||||
User: "root",
|
User: user,
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
//HostKeyCallback: ,
|
//HostKeyCallback: ,
|
||||||
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
||||||
}
|
}
|
||||||
//if h.Type == "password" {
|
//if h.Type == "password" {
|
||||||
config.Auth = []ssh.AuthMethod{ssh.Password("123456")}
|
config.Auth = []ssh.AuthMethod{ssh.Password(password)}
|
||||||
//} else {
|
//} else {
|
||||||
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
|
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
|
||||||
//}
|
//}
|
||||||
addr := fmt.Sprintf("%s:%d", "192.168.2.142", 22)
|
addr := fmt.Sprintf("%s:%d", "127.0.0.1", 22)
|
||||||
c, err := ssh.Dial("tcp", addr, config)
|
c, err := ssh.Dial("tcp", addr, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -98,6 +103,98 @@ const (
|
|||||||
wsMsgResize = "resize"
|
wsMsgResize = "resize"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||||
|
func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
||||||
|
//tells other go routine quit
|
||||||
|
username := ""
|
||||||
|
for {
|
||||||
|
|
||||||
|
//read websocket msg
|
||||||
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
msgObj := wsMsg{}
|
||||||
|
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
||||||
|
msgObj.Type = "cmd"
|
||||||
|
msgObj.Cmd = string(wsData)
|
||||||
|
}
|
||||||
|
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
||||||
|
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
||||||
|
//}
|
||||||
|
switch msgObj.Type {
|
||||||
|
case wsMsgCmd:
|
||||||
|
//handle xterm.js stdin
|
||||||
|
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||||
|
decodeBytes := []byte(msgObj.Cmd)
|
||||||
|
if msgObj.Cmd == "\u007f" {
|
||||||
|
if len(username) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wsConn.WriteMessage(websocket.TextMessage, []byte("\b\x1b[K"))
|
||||||
|
username = username[:len(username)-1]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if msgObj.Cmd == "\r" {
|
||||||
|
return username
|
||||||
|
}
|
||||||
|
username += msgObj.Cmd
|
||||||
|
|
||||||
|
if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
|
||||||
|
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||||
|
}
|
||||||
|
//write input cmd to log buffer
|
||||||
|
if _, err := logBuff.Write(decodeBytes); err != nil {
|
||||||
|
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
||||||
|
//tells other go routine quit
|
||||||
|
password := ""
|
||||||
|
for {
|
||||||
|
|
||||||
|
//read websocket msg
|
||||||
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Error("reading webSocket message failed")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
msgObj := wsMsg{}
|
||||||
|
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
||||||
|
msgObj.Type = "cmd"
|
||||||
|
msgObj.Cmd = string(wsData)
|
||||||
|
}
|
||||||
|
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
||||||
|
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
||||||
|
//}
|
||||||
|
switch msgObj.Type {
|
||||||
|
case wsMsgCmd:
|
||||||
|
//handle xterm.js stdin
|
||||||
|
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||||
|
if msgObj.Cmd == "\r" {
|
||||||
|
return password
|
||||||
|
}
|
||||||
|
|
||||||
|
if msgObj.Cmd == "\u007f" {
|
||||||
|
if len(password) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
password = password[:len(password)-1]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
password += msgObj.Cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||||
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
||||||
//tells other go routine quit
|
//tells other go routine quit
|
||||||
@@ -187,6 +284,64 @@ func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||||
|
func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
||||||
|
//tells other go routine quit
|
||||||
|
defer setQuit(exitCh)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-exitCh:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
//read websocket msg
|
||||||
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Error("reading webSocket message failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//unmashal bytes into struct
|
||||||
|
//msgObj := wsMsg{
|
||||||
|
// Type: "cmd",
|
||||||
|
// Cmd: "",
|
||||||
|
// Rows: 50,
|
||||||
|
// Cols: 180,
|
||||||
|
//}
|
||||||
|
msgObj := wsMsg{}
|
||||||
|
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
||||||
|
msgObj.Type = "cmd"
|
||||||
|
msgObj.Cmd = string(wsData)
|
||||||
|
}
|
||||||
|
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
||||||
|
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
||||||
|
//}
|
||||||
|
switch msgObj.Type {
|
||||||
|
|
||||||
|
case wsMsgResize:
|
||||||
|
//handle xterm.js size change
|
||||||
|
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
||||||
|
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
||||||
|
logrus.WithError(err).Error("ssh pty change windows size failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case wsMsgCmd:
|
||||||
|
//handle xterm.js stdin
|
||||||
|
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||||
|
decodeBytes := []byte(msgObj.Cmd)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
||||||
|
}
|
||||||
|
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
||||||
|
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||||
|
}
|
||||||
|
//write input cmd to log buffer
|
||||||
|
if _, err := logBuff.Write(decodeBytes); err != nil {
|
||||||
|
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
|
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
|
||||||
if err := ssConn.Session.Wait(); err != nil {
|
if err := ssConn.Session.Wait(); err != nil {
|
||||||
logrus.WithError(err).Error("ssh session wait failed")
|
logrus.WithError(err).Error("ssh session wait failed")
|
||||||
@@ -241,7 +396,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
|
|||||||
if err = json2.Unmarshal(p, &msgObj); err != nil {
|
if err = json2.Unmarshal(p, &msgObj); err != nil {
|
||||||
writer.Write(p)
|
writer.Write(p)
|
||||||
} else if msgObj.Type == wsMsgResize {
|
} else if msgObj.Type == wsMsgResize {
|
||||||
writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r" ))
|
writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
func GetDir(id, envName string) string {
|
func GetDir(id, envName string) string {
|
||||||
var path string
|
|
||||||
switch envName {
|
if strings.Contains(envName, "$AppID") && len(id) > 0 {
|
||||||
case "/config":
|
return strings.ReplaceAll(envName, "$AppID", id)
|
||||||
path = "/oasis/app_data/" + id + "/"
|
|
||||||
default:
|
|
||||||
//path = "/media"
|
|
||||||
}
|
}
|
||||||
return path
|
return envName
|
||||||
}
|
}
|
||||||
|
|||||||
10
pkg/docker/volumes_test.go
Normal file
10
pkg/docker/volumes_test.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetDir(t *testing.T) {
|
||||||
|
fmt.Println(GetDir("", "config"))
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func GetGithubClient() *github.Client {
|
func GetGithubClient() *github.Client {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ts := oauth2.StaticTokenSource(
|
ts := oauth2.StaticTokenSource(
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package github
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestGetRepos(t *testing.T) {
|
|
||||||
GetRepos()
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
package gredis
|
package gredis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gomodule/redigo/redis"
|
|
||||||
"oasis/model"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/gomodule/redigo/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetRedisConn(m *model.RedisModel) *redis.Pool {
|
func GetRedisConn(m *model.RedisModel) *redis.Pool {
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ package sqlite
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var gdb *gorm.DB
|
var gdb *gorm.DB
|
||||||
@@ -30,7 +31,7 @@ func GetDb(projectPath string) *gorm.DB {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
gdb = db
|
gdb = db
|
||||||
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{})
|
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("检查和创建数据库出错", err)
|
fmt.Println("检查和创建数据库出错", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetCtrlUrl(host,device string) string {
|
func GetCtrlUrl(host, device string) string {
|
||||||
request := ctrlUrlRequest(host, device)
|
request := ctrlUrlRequest(host, device)
|
||||||
response, _ := http.DefaultClient.Do(request)
|
response, _ := http.DefaultClient.Do(request)
|
||||||
resultBody, _ := ioutil.ReadAll(response.Body)
|
resultBody, _ := ioutil.ReadAll(response.Body)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package upnp
|
package upnp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
ip_helper2 "oasis/pkg/utils/ip_helper"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetCtrlUrl(t *testing.T) {
|
func TestGetCtrlUrl(t *testing.T) {
|
||||||
|
|||||||
@@ -22,21 +22,21 @@ func send() (string, error) {
|
|||||||
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
|
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
|
||||||
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
|
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
|
||||||
var conn *net.UDPConn
|
var conn *net.UDPConn
|
||||||
remotAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
remoteAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("组播地址格式不正确")
|
return "", errors.New("组播地址格式不正确")
|
||||||
}
|
}
|
||||||
locaAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
|
localAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("本地ip地址格式不正确")
|
return "", errors.New("本地ip地址格式不正确")
|
||||||
}
|
}
|
||||||
conn, err = net.ListenUDP("udp", locaAddr)
|
conn, err = net.ListenUDP("udp", localAddr)
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("监听udp出错")
|
return "", errors.New("监听udp出错")
|
||||||
}
|
}
|
||||||
_, err = conn.WriteToUDP([]byte(str), remotAddr)
|
_, err = conn.WriteToUDP([]byte(str), remoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("发送msg到组播地址出错")
|
return "", errors.New("发送msg到组播地址出错")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,40 +2,37 @@ package upnp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
//
|
//
|
||||||
////添加一个端口映射
|
////添加一个端口映射
|
||||||
func (n *Upnp)AddPortMapping(localPort, remotePort int, protocol string) (err error) {
|
func (n *Upnp) AddPortMapping(localPort, remotePort int, protocol string) (err error) {
|
||||||
defer func(err error) {
|
defer func() {
|
||||||
if errTemp := recover(); errTemp != nil {
|
if errTemp := recover(); errTemp != nil {
|
||||||
//log.Println("upnp模块报错了", errTemp)
|
loger2.NewOLoger().Error("upnp模块报错了", errTemp)
|
||||||
err = errTemp.(error)
|
|
||||||
}
|
}
|
||||||
}(err)
|
}()
|
||||||
if issuccess := addSend(localPort, remotePort, protocol,n.GatewayHost, n.CtrlUrl,n.LocalHost); issuccess {
|
|
||||||
|
if isSuccess := addSend(localPort, remotePort, protocol, n.GatewayHost, n.CtrlUrl, n.LocalHost); isSuccess {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return errors.New("添加一个端口映射失败")
|
return errors.New("添加一个端口映射失败")
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addSend(localPort, remotePort int, protocol, host, ctrUrl,localHost string) bool {
|
func addSend(localPort, remotePort int, protocol, host, ctrUrl, localHost string) bool {
|
||||||
request := addRequest(localPort, remotePort, protocol, host, ctrUrl,localHost)
|
request := addRequest(localPort, remotePort, protocol, host, ctrUrl, localHost)
|
||||||
response, _ := http.DefaultClient.Do(request)
|
response, _ := http.DefaultClient.Do(request)
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
//resultBody, _ := ioutil.ReadAll(response.Body)
|
||||||
//fmt.Println(string(resultBody))
|
//fmt.Println(string(resultBody))
|
||||||
if response.StatusCode == 200 {
|
return response.StatusCode == 200
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
@@ -45,7 +42,7 @@ type Node struct {
|
|||||||
Child []Node
|
Child []Node
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl,localHost string) *http.Request {
|
func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl, localHost string) *http.Request {
|
||||||
//请求头
|
//请求头
|
||||||
header := http.Header{}
|
header := http.Header{}
|
||||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
||||||
@@ -109,27 +106,25 @@ func (n *Node) BuildXML() string {
|
|||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Upnp)DelPortMapping(remotePort int, protocol string) bool {
|
func (n *Upnp) DelPortMapping(remotePort int, protocol string) bool {
|
||||||
issuccess := delSendSend(remotePort, protocol,n.GatewayHost,n.CtrlUrl)
|
isSuccess := delSendSend(remotePort, protocol, n.GatewayHost, n.CtrlUrl)
|
||||||
if issuccess {
|
if isSuccess {
|
||||||
//this.MappingPort.delMapping(remotePort, protocol)
|
//this.MappingPort.delMapping(remotePort, protocol)
|
||||||
//fmt.Println("删除了一个端口映射: remote:", remotePort)
|
//fmt.Println("删除了一个端口映射: remote:", remotePort)
|
||||||
}
|
}
|
||||||
return issuccess
|
return isSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
func delSendSend(remotePort int, protocol,host,ctlUrl string) bool {
|
func delSendSend(remotePort int, protocol, host, ctlUrl string) bool {
|
||||||
delrequest := delbuildRequest(remotePort, protocol,host,ctlUrl)
|
delrequest := delbuildRequest(remotePort, protocol, host, ctlUrl)
|
||||||
response, _ := http.DefaultClient.Do(delrequest)
|
response, _ := http.DefaultClient.Do(delrequest)
|
||||||
//resultBody, _ := ioutil.ReadAll(response.Body)
|
//resultBody, _ := ioutil.ReadAll(response.Body)
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
if response.StatusCode == 200 {
|
|
||||||
// log.Println(string(resultBody))
|
return response.StatusCode == 200
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
func delbuildRequest(remotePort int, protocol,host,ctlUrl string) *http.Request {
|
|
||||||
|
func delbuildRequest(remotePort int, protocol, host, ctlUrl string) *http.Request {
|
||||||
//请求头
|
//请求头
|
||||||
header := http.Header{}
|
header := http.Header{}
|
||||||
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
type Upnp struct {
|
type Upnp struct {
|
||||||
LocalHost string `json:"local_host"`
|
LocalHost string `json:"local_host"`
|
||||||
GatewayName string `json:"gateway_name"` //网关名称
|
GatewayName string `json:"gateway_name"` //网关名称
|
||||||
GatewayHost string `json:"gateway_host"` //网关ip和端口
|
GatewayHost string `json:"gateway_host"` //网关ip和端口
|
||||||
DeviceDescUrl string `json:"device_desc_url"` //设备描述url
|
DeviceDescUrl string `json:"device_desc_url"` //设备描述url
|
||||||
CtrlUrl string `json:"ctrl_url"` //控制请求url
|
CtrlUrl string `json:"ctrl_url"` //控制请求url
|
||||||
}
|
}
|
||||||
|
|
||||||
func Testaaa() {
|
func Testaaa() {
|
||||||
@@ -23,4 +23,3 @@ func Testaaa() {
|
|||||||
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
|
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package command
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func OnlyExec(cmdStr string) {
|
func OnlyExec(cmdStr string) {
|
||||||
@@ -75,6 +77,7 @@ func ExecResultStr(cmdStr string) string {
|
|||||||
func ExecLSBLK() []byte {
|
func ExecLSBLK() []byte {
|
||||||
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("lsblk", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
@@ -84,7 +87,26 @@ func ExecLSBLK() []byte {
|
|||||||
func ExecLSBLKByPath(path string) []byte {
|
func ExecLSBLKByPath(path string) []byte {
|
||||||
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println("lsblk", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//exec smart
|
||||||
|
func ExecSmartCTLByPath(path string) []byte {
|
||||||
|
timeout := 3
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
output, err := exec.CommandContext(ctx, "smartctl", "-a", path, "-j").Output()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("smartctl", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExecEnabledSMART(path string) {
|
||||||
|
|
||||||
|
exec.Command("smartctl", "-s on", path).Output()
|
||||||
|
}
|
||||||
|
|||||||
26
pkg/utils/env_helper/env.go
Normal file
26
pkg/utils/env_helper/env.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package env_helper
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func ReplaceDefaultENV(key, tz string) string {
|
||||||
|
temp := ""
|
||||||
|
switch key {
|
||||||
|
case "$DefaultPassword":
|
||||||
|
temp = "casaos"
|
||||||
|
case "$DefaultUserName":
|
||||||
|
temp = "admin"
|
||||||
|
|
||||||
|
case "$PUID":
|
||||||
|
temp = "1000"
|
||||||
|
case "$PGID":
|
||||||
|
temp = "1000"
|
||||||
|
case "$TZ":
|
||||||
|
temp = tz
|
||||||
|
}
|
||||||
|
return temp
|
||||||
|
}
|
||||||
|
|
||||||
|
//replace env default setting
|
||||||
|
func ReplaceStringDefaultENV(str string) string {
|
||||||
|
return strings.ReplaceAll(strings.ReplaceAll(str, "$DefaultPassword", ReplaceDefaultENV("$DefaultPassword", "")), "$DefaultUserName", ReplaceDefaultENV("$DefaultUserName", ""))
|
||||||
|
}
|
||||||
@@ -50,6 +50,7 @@ func MkDir(src string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
os.Chmod(src, 0777)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -100,10 +101,9 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 判断所给路径文件/文件夹是否存在
|
// 判断所给路径文件/文件夹是否存在
|
||||||
func Exists(path string) bool {
|
func Exists(path string) bool {
|
||||||
_, err := os.Stat(path) //os.Stat获取文件信息
|
_, err := os.Stat(path) //os.Stat获取文件信息
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
return true
|
return true
|
||||||
@@ -126,3 +126,36 @@ func IsDir(path string) bool {
|
|||||||
func IsFile(path string) bool {
|
func IsFile(path string) bool {
|
||||||
return !IsDir(path)
|
return !IsDir(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateFile(path string) error {
|
||||||
|
file, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotExistMkDir create a directory if it does not exist
|
||||||
|
func IsNotExistCreateFile(src string) error {
|
||||||
|
if notExist := CheckNotExist(src); notExist == true {
|
||||||
|
if err := CreateFile(src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadFullFile(path string) []byte {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
content, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return []byte("")
|
||||||
|
}
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|||||||
176
pkg/utils/file/reader.go
Normal file
176
pkg/utils/file/reader.go
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
buffSize = 1 << 20
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadLineFromEnd --
|
||||||
|
type ReadLineFromEnd struct {
|
||||||
|
f *os.File
|
||||||
|
|
||||||
|
fileSize int
|
||||||
|
bwr *bytes.Buffer
|
||||||
|
lineBuff []byte
|
||||||
|
swapBuff []byte
|
||||||
|
|
||||||
|
isFirst bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReadLineFromEnd --
|
||||||
|
func NewReadLineFromEnd(name string) (rd *ReadLineFromEnd, err error) {
|
||||||
|
f, err := os.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
info, err := f.Stat()
|
||||||
|
if info.IsDir() {
|
||||||
|
return nil, fmt.Errorf("not file")
|
||||||
|
}
|
||||||
|
fileSize := int(info.Size())
|
||||||
|
rd = &ReadLineFromEnd{
|
||||||
|
f: f,
|
||||||
|
fileSize: fileSize,
|
||||||
|
bwr: bytes.NewBuffer([]byte{}),
|
||||||
|
lineBuff: make([]byte, 0),
|
||||||
|
swapBuff: make([]byte, buffSize),
|
||||||
|
isFirst: true,
|
||||||
|
}
|
||||||
|
return rd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadLine 结尾包含'\n'
|
||||||
|
func (c *ReadLineFromEnd) ReadLine() (line []byte, err error) {
|
||||||
|
var ok bool
|
||||||
|
for {
|
||||||
|
ok, err = c.buff()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
line, err = c.bwr.ReadBytes('\n')
|
||||||
|
if err == io.EOF && c.fileSize > 0 {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return line, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close --
|
||||||
|
func (c *ReadLineFromEnd) Close() (err error) {
|
||||||
|
return c.f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ReadLineFromEnd) buff() (ok bool, err error) {
|
||||||
|
if c.fileSize == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.bwr.Len() >= buffSize {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := 0
|
||||||
|
if c.fileSize > buffSize {
|
||||||
|
offset = c.fileSize - buffSize
|
||||||
|
}
|
||||||
|
_, err = c.f.Seek(int64(offset), 0)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := c.f.Read(c.swapBuff)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if c.fileSize < n {
|
||||||
|
n = c.fileSize
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
m := bytes.LastIndex(c.swapBuff[:n], []byte{'\n'})
|
||||||
|
if m == -1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if m < n-1 {
|
||||||
|
err = c.writeLine(c.swapBuff[m+1 : n])
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
ok = true
|
||||||
|
} else if m == n-1 && !c.isFirst {
|
||||||
|
err = c.writeLine(nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
n = m
|
||||||
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if n > 0 {
|
||||||
|
reverseBytes(c.swapBuff[:n])
|
||||||
|
c.lineBuff = append(c.lineBuff, c.swapBuff[:n]...)
|
||||||
|
}
|
||||||
|
if offset == 0 {
|
||||||
|
err = c.writeLine(nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
c.fileSize = offset
|
||||||
|
if c.isFirst {
|
||||||
|
c.isFirst = false
|
||||||
|
}
|
||||||
|
return ok, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ReadLineFromEnd) writeLine(b []byte) (err error) {
|
||||||
|
if len(b) > 0 {
|
||||||
|
_, err = c.bwr.Write(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(c.lineBuff) > 0 {
|
||||||
|
reverseBytes(c.lineBuff)
|
||||||
|
_, err = c.bwr.Write(c.lineBuff)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.lineBuff = c.lineBuff[:0]
|
||||||
|
}
|
||||||
|
_, err = c.bwr.Write([]byte{'\n'})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func reverseBytes(b []byte) {
|
||||||
|
n := len(b)
|
||||||
|
if n <= 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
k := n - 1
|
||||||
|
if k != i {
|
||||||
|
b[i], b[k] = b[k], b[i]
|
||||||
|
}
|
||||||
|
n--
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,13 @@ package httper
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
//发送GET请求
|
//发送GET请求
|
||||||
@@ -52,10 +53,13 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
//发送POST请求
|
//发送POST请求
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||||
//content:请求放回的内容
|
//content:请求放回的内容
|
||||||
func Post(url string, data interface{}, contentType string) (content string) {
|
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
||||||
jsonStr, _ := json.Marshal(data)
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||||
req.Header.Add("content-type", contentType)
|
req.Header.Add("content-type", contentType)
|
||||||
|
for k, v := range head {
|
||||||
|
req.Header.Add(k, v)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package jwt
|
package jwt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
jwt "github.com/golang-jwt/jwt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
jwt "github.com/golang-jwt/jwt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Claims struct {
|
type Claims struct {
|
||||||
@@ -15,8 +16,7 @@ var jwtSecret []byte
|
|||||||
|
|
||||||
//创建token
|
//创建token
|
||||||
func GenerateToken(username, password string) (string, error) {
|
func GenerateToken(username, password string) (string, error) {
|
||||||
nowTime := time.Now()
|
expireTime := time.Now().AddDate(999, 0, 0)
|
||||||
expireTime := nowTime.Add(3 * time.Hour)
|
|
||||||
clims := Claims{
|
clims := Claims{
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ package jwt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func JWT(swagHandler gin.HandlerFunc) gin.HandlerFunc {
|
func JWT(swagHandler gin.HandlerFunc) gin.HandlerFunc {
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ package loger
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
//定义一个int的别名
|
//定义一个int的别名
|
||||||
@@ -20,6 +20,7 @@ type OLog interface {
|
|||||||
Warn(v ...interface{})
|
Warn(v ...interface{})
|
||||||
Error(v ...interface{})
|
Error(v ...interface{})
|
||||||
Fatal(v ...interface{})
|
Fatal(v ...interface{})
|
||||||
|
Path() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type oLog struct {
|
type oLog struct {
|
||||||
@@ -47,9 +48,8 @@ const (
|
|||||||
func LogSetup() {
|
func LogSetup() {
|
||||||
var err error
|
var err error
|
||||||
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||||
fileName := fmt.Sprintf("%s%s.%s",
|
fileName := fmt.Sprintf("%s.%s",
|
||||||
config.AppInfo.LogSaveName,
|
config.AppInfo.LogSaveName,
|
||||||
time.Now().Format(config.AppInfo.DateStrFormat),
|
|
||||||
config.AppInfo.LogFileExt,
|
config.AppInfo.LogFileExt,
|
||||||
)
|
)
|
||||||
F, err = file2.MustOpen(fileName, filePath)
|
F, err = file2.MustOpen(fileName, filePath)
|
||||||
@@ -60,7 +60,14 @@ func LogSetup() {
|
|||||||
logger = log.New(F, DefaultPrefix, log.LstdFlags)
|
logger = log.New(F, DefaultPrefix, log.LstdFlags)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
func (o *oLog) Path() string {
|
||||||
|
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
|
||||||
|
fileName := fmt.Sprintf("%s.%s",
|
||||||
|
config.AppInfo.LogSaveName,
|
||||||
|
config.AppInfo.LogFileExt,
|
||||||
|
)
|
||||||
|
return filePath + fileName
|
||||||
|
}
|
||||||
func (o *oLog) Debug(v ...interface{}) {
|
func (o *oLog) Debug(v ...interface{}) {
|
||||||
setPrefix(DEBUG)
|
setPrefix(DEBUG)
|
||||||
logger.Println(v)
|
logger.Println(v)
|
||||||
|
|||||||
@@ -7,14 +7,27 @@ const (
|
|||||||
ERROR_AUTH_TOKEN = 401
|
ERROR_AUTH_TOKEN = 401
|
||||||
|
|
||||||
//user
|
//user
|
||||||
PWD_INVALID = 10001
|
PWD_INVALID = 10001
|
||||||
|
PWD_IS_EMPTY = 10002
|
||||||
|
|
||||||
|
PWD_INVALID_OLD = 10003
|
||||||
|
ACCOUNT_LOCK = 10004
|
||||||
//system
|
//system
|
||||||
DIR_ALREADY_EXISTS = 20001
|
DIR_ALREADY_EXISTS = 20001
|
||||||
|
FILE_ALREADY_EXISTS = 20002
|
||||||
|
FILE_OR_DIR_EXISTS = 20003
|
||||||
|
PORT_IS_OCCUPIED = 20004
|
||||||
|
|
||||||
//zerotier
|
//zerotier
|
||||||
GET_TOKEN_ERROR = 30001
|
GET_TOKEN_ERROR = 30001
|
||||||
|
|
||||||
|
//disk
|
||||||
|
NAME_NOT_AVAILABLE = 40001
|
||||||
|
DISK_NEEDS_FORMAT = 40002
|
||||||
|
DISK_BUSYING = 40003
|
||||||
|
REMOVE_MOUNT_POINT_ERROR = 40004
|
||||||
|
FORMAT_ERROR = 40005
|
||||||
|
|
||||||
//app
|
//app
|
||||||
UNINSTALL_APP_ERROR = 50001
|
UNINSTALL_APP_ERROR = 50001
|
||||||
PULL_IMAGE_ERROR = 50002
|
PULL_IMAGE_ERROR = 50002
|
||||||
@@ -31,29 +44,41 @@ const (
|
|||||||
var MsgFlags = map[int]string{
|
var MsgFlags = map[int]string{
|
||||||
SUCCESS: "ok",
|
SUCCESS: "ok",
|
||||||
ERROR: "fail",
|
ERROR: "fail",
|
||||||
INVALID_PARAMS: "Invalid params",
|
INVALID_PARAMS: "Parameters Error",
|
||||||
ERROR_AUTH_TOKEN: "error auth token",
|
ERROR_AUTH_TOKEN: "Error auth token",
|
||||||
|
|
||||||
//user
|
//user
|
||||||
PWD_INVALID: "Password invalid",
|
PWD_INVALID: "Invalid password",
|
||||||
|
PWD_IS_EMPTY: "Password is empty",
|
||||||
|
PWD_INVALID_OLD: "Invalid old password",
|
||||||
|
ACCOUNT_LOCK: "Account is locked",
|
||||||
|
|
||||||
//system
|
//system
|
||||||
DIR_ALREADY_EXISTS: "Directory already exists",
|
DIR_ALREADY_EXISTS: "Folder already exists",
|
||||||
|
FILE_ALREADY_EXISTS: "File already exists",
|
||||||
|
FILE_OR_DIR_EXISTS: "File or folder already exists",
|
||||||
|
PORT_IS_OCCUPIED: "Port is occupied",
|
||||||
|
|
||||||
//zerotier
|
//zerotier
|
||||||
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
|
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
|
||||||
|
|
||||||
//app
|
//app
|
||||||
UNINSTALL_APP_ERROR: "uninstall app error",
|
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
||||||
PULL_IMAGE_ERROR: "pull image error",
|
PULL_IMAGE_ERROR: "Error pulling image",
|
||||||
DEVICE_NOT_EXIST: "device not exist",
|
DEVICE_NOT_EXIST: "Device does not exist",
|
||||||
|
|
||||||
|
//disk
|
||||||
|
NAME_NOT_AVAILABLE: "Name not available",
|
||||||
|
DISK_NEEDS_FORMAT: "Drive needs to be formatted",
|
||||||
|
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
|
||||||
|
DISK_BUSYING: "Drive is busy",
|
||||||
|
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
|
||||||
|
|
||||||
//
|
//
|
||||||
FILE_DOES_NOT_EXIST: "file does not exist",
|
FILE_DOES_NOT_EXIST: "File does not exist",
|
||||||
|
|
||||||
FILE_READ_ERROR: "file read error",
|
FILE_READ_ERROR: "File read error",
|
||||||
SHORTCUTS_URL_ERROR: "url error",
|
SHORTCUTS_URL_ERROR: "URL error",
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取错误信息
|
//获取错误信息
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ func IsPortAvailable(port int, t string) bool {
|
|||||||
uc, err := net.ListenUDP("udp", sadd)
|
uc, err := net.ListenUDP("udp", sadd)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
defer uc.Close()
|
defer uc.Close()
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRandomString(t *testing.T) {
|
func TestRandomString(t *testing.T) {
|
||||||
fmt.Println(RandomString(6,true))
|
fmt.Println(RandomString(6, true))
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
package sort
|
package sort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package version
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsNeedUpdate() (bool, model.Version) {
|
func IsNeedUpdate() (bool, model.Version) {
|
||||||
@@ -35,3 +36,23 @@ func IsNeedUpdate() (bool, model.Version) {
|
|||||||
}
|
}
|
||||||
return false, version
|
return false, version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//a版本大于b版本
|
||||||
|
func VersionCompared(a string, b string) bool {
|
||||||
|
v1 := strings.Split(a, ".")
|
||||||
|
v2 := strings.Split(b, ".")
|
||||||
|
for len(v1) < len(v2) {
|
||||||
|
v1 = append(v1, "0")
|
||||||
|
}
|
||||||
|
for len(v2) < len(v1) {
|
||||||
|
v2 = append(v2, "0")
|
||||||
|
}
|
||||||
|
for i := 0; i < len(v1); i++ {
|
||||||
|
a, _ := strconv.Atoi(v1[i])
|
||||||
|
b, _ := strconv.Atoi(v2[i])
|
||||||
|
if a > b {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build doc
|
||||||
// +build doc
|
// +build doc
|
||||||
|
|
||||||
package route
|
package route
|
||||||
@@ -5,9 +6,10 @@ package route
|
|||||||
import (
|
import (
|
||||||
_ "github.com/IceWhaleTech/CasaOS/docs"
|
_ "github.com/IceWhaleTech/CasaOS/docs"
|
||||||
ginSwagger "github.com/swaggo/gin-swagger"
|
ginSwagger "github.com/swaggo/gin-swagger"
|
||||||
"github.com/swaggo/gin-swagger/swaggerFiles"
|
swaggerFiles "github.com/swaggo/gin-swagger/swaggerFiles"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
// swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
|
||||||
swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
|
swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
|
||||||
}
|
}
|
||||||
|
|||||||
236
route/init.go
Normal file
236
route/init.go
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model/system_app"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitFunction() {
|
||||||
|
go checkSystemApp()
|
||||||
|
Update2_3()
|
||||||
|
CheckSerialDiskMount()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var syncIsExistence = false
|
||||||
|
|
||||||
|
func installSyncthing(appId string) {
|
||||||
|
|
||||||
|
var appInfo model.ServerAppList
|
||||||
|
m := model.CustomizationPostData{}
|
||||||
|
var dockerImage string
|
||||||
|
var dockerImageVersion string
|
||||||
|
appInfo = service.MyService.OAPI().GetServerAppInfo(appId, "system", "us_en")
|
||||||
|
dockerImage = appInfo.Image
|
||||||
|
dockerImageVersion = appInfo.ImageVersion
|
||||||
|
|
||||||
|
if len(appInfo.ImageVersion) == 0 {
|
||||||
|
dockerImageVersion = "latest"
|
||||||
|
}
|
||||||
|
|
||||||
|
if appInfo.NetworkModel != "host" {
|
||||||
|
for i := 0; i < len(appInfo.Ports); i++ {
|
||||||
|
if p, _ := strconv.Atoi(appInfo.Ports[i].ContainerPort); port.IsPortAvailable(p, appInfo.Ports[i].Protocol) {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
} else {
|
||||||
|
if appInfo.Ports[i].Protocol == "tcp" {
|
||||||
|
if p, err := port.GetAvailablePort("tcp"); err == nil {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
} else if appInfo.Ports[i].Protocol == "upd" {
|
||||||
|
if p, err := port.GetAvailablePort("udp"); err == nil {
|
||||||
|
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if appInfo.Ports[i].Type == 0 {
|
||||||
|
appInfo.PortMap = appInfo.Ports[i].CommendPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(appInfo.Devices); i++ {
|
||||||
|
if !file.CheckNotExist(appInfo.Devices[i].ContainerPath) {
|
||||||
|
appInfo.Devices[i].Path = appInfo.Devices[i].ContainerPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(appInfo.Tip) > 0 {
|
||||||
|
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
|
||||||
|
}
|
||||||
|
|
||||||
|
appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||||
|
|
||||||
|
id := uuid.NewV4().String()
|
||||||
|
|
||||||
|
installLog := model2.AppNotify{}
|
||||||
|
|
||||||
|
// step:下载镜像
|
||||||
|
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||||
|
if err != nil {
|
||||||
|
//pull image error
|
||||||
|
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.CpuShares = 50
|
||||||
|
m.Envs = appInfo.Envs
|
||||||
|
m.Memory = int64(appInfo.MaxMemory)
|
||||||
|
m.Origin = "system"
|
||||||
|
m.PortMap = appInfo.PortMap
|
||||||
|
m.Ports = appInfo.Ports
|
||||||
|
m.Restart = "always"
|
||||||
|
m.Volumes = appInfo.Volumes
|
||||||
|
|
||||||
|
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("container create error", err)
|
||||||
|
// create container error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//step:start container
|
||||||
|
err = service.MyService.Docker().DockerContainerStart(id)
|
||||||
|
if err != nil {
|
||||||
|
//start container error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
portsStr, _ := json.Marshal(appInfo.Ports)
|
||||||
|
envsStr, _ := json.Marshal(appInfo.Envs)
|
||||||
|
volumesStr, _ := json.Marshal(appInfo.Volumes)
|
||||||
|
devicesStr, _ := json.Marshal(appInfo.Devices)
|
||||||
|
//step: 保存数据到数据库
|
||||||
|
md := model2.AppListDBModel{
|
||||||
|
CustomId: id,
|
||||||
|
Title: appInfo.Title,
|
||||||
|
//ScreenshotLink: appInfo.ScreenshotLink,
|
||||||
|
Slogan: appInfo.Tagline,
|
||||||
|
Description: appInfo.Description,
|
||||||
|
//Tags: appInfo.Tags,
|
||||||
|
Icon: appInfo.Icon,
|
||||||
|
Version: dockerImageVersion,
|
||||||
|
ContainerId: containerId,
|
||||||
|
Image: dockerImage,
|
||||||
|
Index: appInfo.Index,
|
||||||
|
PortMap: appInfo.PortMap,
|
||||||
|
Label: appInfo.Title,
|
||||||
|
EnableUPNP: false,
|
||||||
|
Ports: string(portsStr),
|
||||||
|
Envs: string(envsStr),
|
||||||
|
Volumes: string(volumesStr),
|
||||||
|
Position: true,
|
||||||
|
NetModel: appInfo.NetworkModel,
|
||||||
|
Restart: m.Restart,
|
||||||
|
CpuShares: 50,
|
||||||
|
Memory: int64(appInfo.MaxMemory),
|
||||||
|
Devices: string(devicesStr),
|
||||||
|
Origin: m.Origin,
|
||||||
|
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
|
||||||
|
}
|
||||||
|
service.MyService.App().SaveContainer(md)
|
||||||
|
|
||||||
|
checkSystemApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the system application is installed
|
||||||
|
func checkSystemApp() {
|
||||||
|
list := service.MyService.App().GetSystemAppList()
|
||||||
|
for _, v := range *list {
|
||||||
|
if v.Image == "linuxserver/syncthing" {
|
||||||
|
if v.State != "running" {
|
||||||
|
//step:start container
|
||||||
|
service.MyService.Docker().DockerContainerStart(v.CustomId)
|
||||||
|
}
|
||||||
|
syncIsExistence = true
|
||||||
|
if config.SystemConfigInfo.SyncPort != v.Port {
|
||||||
|
config.SystemConfigInfo.SyncPort = v.Port
|
||||||
|
}
|
||||||
|
var paths []model.PathMap
|
||||||
|
json.Unmarshal([]byte(v.Volumes), &paths)
|
||||||
|
path := ""
|
||||||
|
for _, i := range paths {
|
||||||
|
if i.ContainerPath == "/config" {
|
||||||
|
path = docker.GetDir(v.CustomId, i.Path) + "/config.xml"
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
if file.CheckNotExist(path) {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content := file.ReadFullFile(path)
|
||||||
|
syncConfig := &system_app.SyncConfig{}
|
||||||
|
xml.Unmarshal(content, &syncConfig)
|
||||||
|
config.SystemConfigInfo.SyncKey = syncConfig.Key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !syncIsExistence {
|
||||||
|
installSyncthing("74")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func CheckSerialDiskMount() {
|
||||||
|
// check mount point
|
||||||
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
|
||||||
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
|
mountPoint := make(map[string]string, len(dbList))
|
||||||
|
//remount
|
||||||
|
for _, v := range dbList {
|
||||||
|
mountPoint[v.UUID] = v.MountPoint
|
||||||
|
}
|
||||||
|
for _, v := range list {
|
||||||
|
command.ExecEnabledSMART(v.Path)
|
||||||
|
if v.Children != nil {
|
||||||
|
for _, h := range v.Children {
|
||||||
|
if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
|
||||||
|
if m, ok := mountPoint[h.UUID]; ok {
|
||||||
|
//mount point check
|
||||||
|
volume := m
|
||||||
|
if !file.CheckNotExist(m) {
|
||||||
|
for i := 0; file.CheckNotExist(volume); i++ {
|
||||||
|
volume = m + strconv.Itoa(i+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.Disk().MountDisk(h.Path, volume)
|
||||||
|
if volume != m {
|
||||||
|
ms := model2.SerialDisk{}
|
||||||
|
ms.UUID = v.UUID
|
||||||
|
ms.MountPoint = volume
|
||||||
|
service.MyService.Disk().UpdateMountPoint(ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir")
|
||||||
|
|
||||||
|
}
|
||||||
|
func Update2_3() {
|
||||||
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")
|
||||||
|
}
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/middleware"
|
"github.com/IceWhaleTech/CasaOS/middleware"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
||||||
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||||
"github.com/IceWhaleTech/CasaOS/web"
|
"github.com/IceWhaleTech/CasaOS/web"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var swagHandler gin.HandlerFunc
|
var swagHandler gin.HandlerFunc
|
||||||
|
var OnlineDemo bool = false
|
||||||
|
|
||||||
func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
func InitRouter() *gin.Engine {
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.Use(middleware.Cors())
|
r.Use(middleware.Cors())
|
||||||
@@ -26,10 +28,16 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
if swagHandler != nil {
|
if swagHandler != nil {
|
||||||
r.GET("/swagger/*any", swagHandler)
|
r.GET("/swagger/*any", swagHandler)
|
||||||
}
|
}
|
||||||
//登录
|
|
||||||
r.POST("/v1/user/login", v1.Login)
|
r.POST("/v1/user/login", v1.Login)
|
||||||
|
|
||||||
r.GET("/debug", v1.GetSystemConfigDebug)
|
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
||||||
|
|
||||||
|
r.GET("/v1/debug", v1.GetSystemConfigDebug)
|
||||||
|
//set user
|
||||||
|
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
||||||
|
//get user info
|
||||||
|
r.GET("/v1/user/info", v1.UserInfo)
|
||||||
|
|
||||||
v1Group := r.Group("/v1")
|
v1Group := r.Group("/v1")
|
||||||
|
|
||||||
@@ -38,8 +46,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
v1UserGroup := v1Group.Group("/user")
|
v1UserGroup := v1Group.Group("/user")
|
||||||
v1UserGroup.Use()
|
v1UserGroup.Use()
|
||||||
{
|
{
|
||||||
//设置用户
|
|
||||||
v1UserGroup.POST("/setusernamepwd", v1.Set_Name_Pwd)
|
|
||||||
//chang head
|
//chang head
|
||||||
v1UserGroup.POST("/changhead", v1.Up_Load_Head)
|
v1UserGroup.POST("/changhead", v1.Up_Load_Head)
|
||||||
//chang user name
|
//chang user name
|
||||||
@@ -48,8 +55,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
v1UserGroup.PUT("/changuserpwd", v1.Chang_User_Pwd)
|
v1UserGroup.PUT("/changuserpwd", v1.Chang_User_Pwd)
|
||||||
//edit user info
|
//edit user info
|
||||||
v1UserGroup.POST("/changuserinfo", v1.Chang_User_Info)
|
v1UserGroup.POST("/changuserinfo", v1.Chang_User_Info)
|
||||||
//get user info
|
|
||||||
v1UserGroup.GET("/info", v1.UserInfo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v1ZiMaGroup := v1Group.Group("/zima")
|
v1ZiMaGroup := v1Group.Group("/zima")
|
||||||
@@ -64,8 +70,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
|
|
||||||
//获取网络信息
|
//获取网络信息
|
||||||
v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo)
|
v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo)
|
||||||
//获取网络信息
|
|
||||||
v1ZiMaGroup.GET("/getinfo", v1.Info)
|
|
||||||
//获取系统信息
|
//获取系统信息
|
||||||
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
|
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
|
||||||
}
|
}
|
||||||
@@ -135,6 +140,8 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
{
|
{
|
||||||
//获取我的已安装的列表
|
//获取我的已安装的列表
|
||||||
v1AppGroup.GET("/mylist", v1.MyAppList)
|
v1AppGroup.GET("/mylist", v1.MyAppList)
|
||||||
|
//
|
||||||
|
v1AppGroup.GET("/usage", v1.AppUsageList)
|
||||||
//app详情
|
//app详情
|
||||||
v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
|
v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
|
||||||
//获取未安装的列表
|
//获取未安装的列表
|
||||||
@@ -170,7 +177,7 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
||||||
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
||||||
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
//v1AppGroup.POST("/custom/install", v1.CustomInstallApp)
|
||||||
|
v1AppGroup.POST("/share", v1.ShareAppFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1SysGroup := v1Group.Group("/sys")
|
v1SysGroup := v1Group.Group("/sys")
|
||||||
@@ -182,7 +189,14 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
v1SysGroup.GET("/sys", v1.Sys)
|
v1SysGroup.GET("/sys", v1.Sys)
|
||||||
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
||||||
v1SysGroup.GET("/config", v1.GetSystemConfig)
|
v1SysGroup.GET("/config", v1.GetSystemConfig)
|
||||||
|
v1SysGroup.GET("/error/logs", v1.GetCasaOSErrorLogs)
|
||||||
v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
||||||
|
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
|
||||||
|
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
|
||||||
|
v1SysGroup.GET("/port", v1.GetCasaOSPort)
|
||||||
|
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
||||||
|
v1SysGroup.POST("/kill", v1.PostKillCasaOS)
|
||||||
|
v1SysGroup.GET("/info", v1.Info)
|
||||||
}
|
}
|
||||||
v1FileGroup := v1Group.Group("/file")
|
v1FileGroup := v1Group.Group("/file")
|
||||||
v1FileGroup.Use()
|
v1FileGroup.Use()
|
||||||
@@ -191,33 +205,43 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
v1FileGroup.PUT("/rename", v1.RenamePath)
|
v1FileGroup.PUT("/rename", v1.RenamePath)
|
||||||
v1FileGroup.GET("/read", v1.GetFilerContent)
|
v1FileGroup.GET("/read", v1.GetFilerContent)
|
||||||
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||||
v1FileGroup.GET("/dirpath", v1.DirPath)
|
v1FileGroup.GET("/catalog", v1.DirPath)
|
||||||
//创建目录
|
//创建目录
|
||||||
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
||||||
|
v1FileGroup.POST("/create", v1.PostCreateFile)
|
||||||
|
|
||||||
v1FileGroup.GET("/download", v1.GetDownloadFile)
|
v1FileGroup.GET("/download", v1.GetDownloadFile)
|
||||||
|
v1FileGroup.PUT("/move", v1.PutFileMove)
|
||||||
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
||||||
}
|
}
|
||||||
v1DiskGroup := v1Group.Group("/disk")
|
v1DiskGroup := v1Group.Group("/disk")
|
||||||
v1DiskGroup.Use()
|
v1DiskGroup.Use()
|
||||||
{
|
{
|
||||||
//获取磁盘列表
|
v1DiskGroup.GET("/check", v1.GetDiskCheck)
|
||||||
v1DiskGroup.GET("/list", v1.GetPlugInDisk)
|
|
||||||
|
v1DiskGroup.GET("/list", v1.GetDiskList)
|
||||||
|
|
||||||
//获取磁盘详情
|
//获取磁盘详情
|
||||||
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
||||||
|
|
||||||
//格式化磁盘
|
//format storage
|
||||||
v1DiskGroup.POST("/format", v1.FormatDisk)
|
v1DiskGroup.POST("/format", v1.FormatDisk)
|
||||||
|
|
||||||
//添加分区
|
// add storage
|
||||||
v1DiskGroup.POST("/addpart", v1.AddPartition)
|
v1DiskGroup.POST("/storage", v1.AddPartition)
|
||||||
|
|
||||||
|
//mount SATA disk
|
||||||
|
v1DiskGroup.POST("/mount", v1.PostMountDisk)
|
||||||
|
|
||||||
|
//umount sata disk
|
||||||
|
v1DiskGroup.POST("/umount", v1.PostDiskUmount)
|
||||||
|
|
||||||
//获取可以格式化的内容
|
//获取可以格式化的内容
|
||||||
v1DiskGroup.GET("/type", v1.FormatDiskType)
|
v1DiskGroup.GET("/type", v1.FormatDiskType)
|
||||||
|
|
||||||
//删除分区
|
//删除分区
|
||||||
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
||||||
|
v1DiskGroup.GET("/usb", v1.GetUSBList)
|
||||||
|
|
||||||
}
|
}
|
||||||
v1ShareGroup := v1Group.Group("/share")
|
v1ShareGroup := v1Group.Group("/share")
|
||||||
@@ -252,6 +276,14 @@ func InitRouter(swagHandler gin.HandlerFunc) *gin.Engine {
|
|||||||
v1NotifyGroup.GET("/ws", v1.NotifyWS)
|
v1NotifyGroup.GET("/ws", v1.NotifyWS)
|
||||||
v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
|
v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead)
|
||||||
}
|
}
|
||||||
|
v1SearchGroup := v1Group.Group("/search")
|
||||||
|
v1SearchGroup.Use()
|
||||||
|
{
|
||||||
|
v1SearchGroup.GET("/search", v1.GetSearchList)
|
||||||
|
}
|
||||||
|
v1Group.GET("/sync/config", v1.GetSyncConfig)
|
||||||
|
v1Group.Any("/syncthing/*url", v1.SyncToSyncthing)
|
||||||
|
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
166
route/v1/app.go
166
route/v1/app.go
@@ -1,15 +1,17 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/sort"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取远程列表
|
// @Summary 获取远程列表
|
||||||
@@ -29,20 +31,34 @@ func AppList(c *gin.Context) {
|
|||||||
//service.MyService.Docker().DockerContainerCommit("test2")
|
//service.MyService.Docker().DockerContainerCommit("test2")
|
||||||
|
|
||||||
index := c.DefaultQuery("index", "1")
|
index := c.DefaultQuery("index", "1")
|
||||||
size := c.DefaultQuery("size", "10")
|
size := c.DefaultQuery("size", "10000")
|
||||||
t := c.DefaultQuery("type", "rank")
|
t := c.DefaultQuery("type", "rank")
|
||||||
categoryId := c.DefaultQuery("category_id", "0")
|
categoryId := c.DefaultQuery("category_id", "0")
|
||||||
key := c.DefaultQuery("key", "")
|
key := c.DefaultQuery("key", "")
|
||||||
list, count := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key)
|
language := c.GetHeader("Language")
|
||||||
for i := 0; i < len(list); i++ {
|
recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key, language)
|
||||||
ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
// for i := 0; i < len(recommend); i++ {
|
||||||
if ct != nil {
|
// ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
||||||
list[i].State = ct.State
|
// if ct != nil {
|
||||||
}
|
// recommend[i].State = ct.State
|
||||||
}
|
// }
|
||||||
data := make(map[string]interface{}, 2)
|
// }
|
||||||
data["count"] = count
|
// for i := 0; i < len(list); i++ {
|
||||||
data["items"] = list
|
// ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
||||||
|
// if ct != nil {
|
||||||
|
// list[i].State = ct.State
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for i := 0; i < len(community); i++ {
|
||||||
|
// ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
|
||||||
|
// if ct != nil {
|
||||||
|
// community[i].State = ct.State
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
data := make(map[string]interface{}, 3)
|
||||||
|
data["recommend"] = recommend
|
||||||
|
data["list"] = list
|
||||||
|
data["community"] = community
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
}
|
}
|
||||||
@@ -99,6 +115,18 @@ func MyAppList(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary my app hardware usage list
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags app
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /app/usage [get]
|
||||||
|
func AppUsageList(c *gin.Context) {
|
||||||
|
list := service.MyService.App().GetHardwareUsage()
|
||||||
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
|
}
|
||||||
|
|
||||||
// @Summary 应用详情
|
// @Summary 应用详情
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
@@ -110,51 +138,71 @@ func MyAppList(c *gin.Context) {
|
|||||||
func AppInfo(c *gin.Context) {
|
func AppInfo(c *gin.Context) {
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
info := service.MyService.App().GetServerAppInfo(id)
|
language := c.GetHeader("Language")
|
||||||
|
info := service.MyService.OAPI().GetServerAppInfo(id, "", language)
|
||||||
if info.NetworkModel != "host" {
|
if info.NetworkModel != "host" {
|
||||||
port, _ := port2.GetAvailablePort("tcp")
|
for i := 0; i < len(info.Ports); i++ {
|
||||||
info.PortMap = uint(port)
|
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
|
||||||
for i := 0; i < len(info.Configures.TcpPorts); i++ {
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
info.Configures.TcpPorts[i].CommendPort, _ = port2.GetAvailablePort("tcp")
|
} else {
|
||||||
}
|
if info.Ports[i].Protocol == "tcp" {
|
||||||
for i := 0; i < len(info.Configures.UdpPorts); i++ {
|
if p, err := port2.GetAvailablePort("tcp"); err == nil {
|
||||||
info.Configures.UdpPorts[i].CommendPort, _ = port2.GetAvailablePort("udp")
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
} else if info.Ports[i].Protocol == "upd" {
|
||||||
|
if p, err := port2.GetAvailablePort("udp"); err == nil {
|
||||||
|
info.Ports[i].CommendPort = strconv.Itoa(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.Ports[i].Type == 0 {
|
||||||
|
info.PortMap = info.Ports[i].CommendPort
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info.PortMap = info.TcpPort
|
for i := 0; i < len(info.Ports); i++ {
|
||||||
}
|
if info.Ports[i].Type == 0 {
|
||||||
|
info.PortMap = info.Ports[i].ContainerPort
|
||||||
for i := 0; i < len(info.Configures.Devices); i++ {
|
break
|
||||||
if !file.CheckNotExist(info.Configures.Devices[i].ContainerPath) {
|
}
|
||||||
info.Configures.Devices[i].Path = info.Configures.Devices[i].ContainerPath
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
portOrder := func(c1, c2 *model.Ports) bool {
|
for i := 0; i < len(info.Devices); i++ {
|
||||||
return c1.Type < c2.Type
|
if !file.CheckNotExist(info.Devices[i].ContainerPath) {
|
||||||
|
info.Devices[i].Path = info.Devices[i].ContainerPath
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// if len(info.Tip) > 0 {
|
||||||
|
// info.Tip = env_helper.ReplaceStringDefaultENV(info.Tip)
|
||||||
|
// }
|
||||||
|
|
||||||
envOrder := func(c1, c2 *model.Envs) bool {
|
// portOrder := func(c1, c2 *model.Ports) bool {
|
||||||
return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
}
|
// }
|
||||||
|
|
||||||
volOrder := func(c1, c2 *model.Volume) bool {
|
// envOrder := func(c1, c2 *model.Envs) bool {
|
||||||
return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
}
|
// }
|
||||||
|
|
||||||
devOrder := func(c1, c2 *model.Devices) bool {
|
// volOrder := func(c1, c2 *model.Volume) bool {
|
||||||
return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// devOrder := func(c1, c2 *model.Devices) bool {
|
||||||
|
// return c1.Type < c2.Type
|
||||||
|
// }
|
||||||
|
|
||||||
//sort
|
//sort
|
||||||
if info.NetworkModel != "host" {
|
// if info.NetworkModel != "host" {
|
||||||
sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
||||||
sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
||||||
}
|
// }
|
||||||
|
|
||||||
sort.EnvSort(envOrder).Sort(info.Configures.Envs)
|
// sort.EnvSort(envOrder).Sort(info.Envs)
|
||||||
sort.VolSort(volOrder).Sort(info.Configures.Volumes)
|
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
||||||
sort.DevSort(devOrder).Sort(info.Configures.Devices)
|
// sort.DevSort(devOrder).Sort(info.Devices)
|
||||||
|
|
||||||
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
|
||||||
|
|
||||||
@@ -176,7 +224,31 @@ func CategoryList(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rear := append([]model.ServerCategoryList{}, list[0:]...)
|
rear := append([]model.ServerCategoryList{}, list[0:]...)
|
||||||
list = append(list[:0], model.ServerCategoryList{Count: count, Name: "All"})
|
list = append(list[:0], model.ServerCategoryList{Count: count, Name: "All", Font: "apps"})
|
||||||
list = append(list, rear...)
|
list = append(list, rear...)
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary 分享该应用配置
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags app
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /app/share [post]
|
||||||
|
func ShareAppFile(c *gin.Context) {
|
||||||
|
str, _ := ioutil.ReadAll(c.Request.Body)
|
||||||
|
content := service.MyService.OAPI().ShareAppFile(str)
|
||||||
|
c.JSON(http.StatusOK, json.RawMessage(content))
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Resource Usage
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags app
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /app/share [post]
|
||||||
|
func AppListResourceUsage() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func DDNSAddConfig(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var m model2.DDNSUpdataDBModel
|
var m model2.DDNSUpdateDBModel
|
||||||
c.Bind(&m)
|
c.Bind(&m)
|
||||||
if err := service.MyService.DDNS().SaveConfig(m); err != nil {
|
if err := service.MyService.DDNS().SaveConfig(m); err != nil {
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
|
|||||||
450
route/v1/disk.go
450
route/v1/disk.go
@@ -1,65 +1,162 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取磁盘列表
|
var diskMap = make(map[string]string)
|
||||||
|
|
||||||
|
// @Summary disk list
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/list [get]
|
// @Router /disk/list [get]
|
||||||
func GetPlugInDisk(c *gin.Context) {
|
func GetDiskList(c *gin.Context) {
|
||||||
|
list := service.MyService.Disk().LSBLK(false)
|
||||||
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
part := make(map[string]int64, len(dbList))
|
||||||
|
for _, v := range dbList {
|
||||||
|
part[v.MountPoint] = v.CreatedAt
|
||||||
|
}
|
||||||
|
findSystem := 0
|
||||||
|
|
||||||
//ls := service.MyService.Disk().GetPlugInDisk()
|
disks := []model.Drive{}
|
||||||
//fmt.Println(ls)
|
storage := []model.Storage{}
|
||||||
//dd, _ := disk.Partitions(true)
|
avail := []model.Drive{}
|
||||||
//fmt.Println(dd)
|
for i := 0; i < len(list); i++ {
|
||||||
//
|
disk := model.Drive{}
|
||||||
//dir, err := ioutil.ReadDir("/sys/block")
|
if list[i].Rota {
|
||||||
//if err != nil {
|
disk.DiskType = "HDD"
|
||||||
// panic(err)
|
} else {
|
||||||
//}
|
disk.DiskType = "SSD"
|
||||||
//
|
}
|
||||||
//files := make([]string, 0)
|
disk.Serial = list[i].Serial
|
||||||
//
|
disk.Name = list[i].Name
|
||||||
////fmt.Println(regexp.MatchString("sd[a-z]*[0-9]", "sda"))
|
disk.Size = list[i].Size
|
||||||
//
|
disk.Path = list[i].Path
|
||||||
//for _, f := range dir {
|
disk.Model = list[i].Model
|
||||||
// if match, _ := regexp.MatchString("sd[a-z]", f.Name()); match {
|
|
||||||
// files = append(files, f.Name())
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//fmt.Println(files)
|
|
||||||
//filess := make([]string, 0)
|
|
||||||
//for _, file := range files {
|
|
||||||
// dirs, _ := ioutil.ReadDir("/sys/block/" + file)
|
|
||||||
//
|
|
||||||
// for _, f := range dirs {
|
|
||||||
// if match, _ := regexp.MatchString("sd[a-z]*[0-9]", f.Name()); match {
|
|
||||||
// filess = append(filess, f.Name())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//fmt.Println(filess)
|
|
||||||
//
|
|
||||||
//for _, s := range filess {
|
|
||||||
// fmt.Println(disk.Usage("/dev/" + s))
|
|
||||||
//}
|
|
||||||
|
|
||||||
lst := service.MyService.Disk().LSBLK()
|
if len(list[i].Children) > 0 && findSystem == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: lst})
|
for j := 0; j < len(list[i].Children); j++ {
|
||||||
|
if len(list[i].Children[j].Children) > 0 {
|
||||||
|
for _, v := range list[i].Children[j].Children {
|
||||||
|
if v.MountPoint == "/" {
|
||||||
|
stor := model.Storage{}
|
||||||
|
stor.Name = "System"
|
||||||
|
stor.MountPoint = v.MountPoint
|
||||||
|
stor.Size = v.FSSize
|
||||||
|
stor.Avail = v.FSAvail
|
||||||
|
stor.Path = v.Path
|
||||||
|
stor.Type = v.FsType
|
||||||
|
stor.DriveName = "System"
|
||||||
|
disk.Model = "System"
|
||||||
|
if strings.Contains(v.SubSystems, "mmc") {
|
||||||
|
disk.DiskType = "MMC"
|
||||||
|
} else if strings.Contains(v.SubSystems, "usb") {
|
||||||
|
disk.DiskType = "USB"
|
||||||
|
}
|
||||||
|
disk.Health = "true"
|
||||||
|
|
||||||
|
disks = append(disks, disk)
|
||||||
|
storage = append(storage, stor)
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if list[i].Children[j].MountPoint == "/" {
|
||||||
|
stor := model.Storage{}
|
||||||
|
stor.Name = "System"
|
||||||
|
stor.MountPoint = list[i].Children[j].MountPoint
|
||||||
|
stor.Size = list[i].Children[j].FSSize
|
||||||
|
stor.Avail = list[i].Children[j].FSAvail
|
||||||
|
stor.Path = list[i].Children[j].Path
|
||||||
|
stor.Type = list[i].Children[j].FsType
|
||||||
|
stor.DriveName = "System"
|
||||||
|
disk.Model = "System"
|
||||||
|
if strings.Contains(list[i].Children[j].SubSystems, "mmc") {
|
||||||
|
disk.DiskType = "MMC"
|
||||||
|
} else if strings.Contains(list[i].Children[j].SubSystems, "usb") {
|
||||||
|
disk.DiskType = "USB"
|
||||||
|
}
|
||||||
|
disk.Health = "true"
|
||||||
|
|
||||||
|
disks = append(disks, disk)
|
||||||
|
storage = append(storage, stor)
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if findSystem == 1 {
|
||||||
|
findSystem += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
temp.SmartStatus.Passed = true
|
||||||
|
}
|
||||||
|
if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
|
||||||
|
stor := model.Storage{}
|
||||||
|
stor.MountPoint = list[i].Children[0].MountPoint
|
||||||
|
stor.Size = list[i].Children[0].FSSize
|
||||||
|
stor.Avail = list[i].Children[0].FSAvail
|
||||||
|
stor.Path = list[i].Children[0].Path
|
||||||
|
stor.Type = list[i].Children[0].FsType
|
||||||
|
stor.DriveName = list[i].Name
|
||||||
|
pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
|
||||||
|
if len(pathArr) == 3 {
|
||||||
|
stor.Name = pathArr[2]
|
||||||
|
}
|
||||||
|
if t, ok := part[list[i].Children[0].MountPoint]; ok {
|
||||||
|
stor.CreatedAt = t
|
||||||
|
}
|
||||||
|
storage = append(storage, stor)
|
||||||
|
} else {
|
||||||
|
//todo 长度有问题
|
||||||
|
if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
|
||||||
|
disk.NeedFormat = false
|
||||||
|
avail = append(avail, disk)
|
||||||
|
} else {
|
||||||
|
disk.NeedFormat = true
|
||||||
|
avail = append(avail, disk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disk.Temperature = temp.Temperature.Current
|
||||||
|
disk.Health = strconv.FormatBool(temp.SmartStatus.Passed)
|
||||||
|
|
||||||
|
disks = append(disks, disk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data := make(map[string]interface{}, 3)
|
||||||
|
data["drive"] = disks
|
||||||
|
data["storage"] = storage
|
||||||
|
data["avail"] = avail
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取磁盘列表
|
// @Summary get disk list
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
@@ -68,7 +165,7 @@ func GetPlugInDisk(c *gin.Context) {
|
|||||||
// @Router /disk/lists [get]
|
// @Router /disk/lists [get]
|
||||||
func GetPlugInDisks(c *gin.Context) {
|
func GetPlugInDisks(c *gin.Context) {
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK()
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
var result []*disk.UsageStat
|
var result []*disk.UsageStat
|
||||||
for _, item := range list {
|
for _, item := range list {
|
||||||
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
||||||
@@ -76,12 +173,12 @@ func GetPlugInDisks(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: result})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: result})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 磁盘详情
|
// @Summary disk detail
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path query string true "要获取的磁盘详情 例如/dev/sda"
|
// @Param path query string true "for example /dev/sda"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/info [get]
|
// @Router /disk/info [get]
|
||||||
func GetDiskInfo(c *gin.Context) {
|
func GetDiskInfo(c *gin.Context) {
|
||||||
@@ -93,31 +190,46 @@ func GetDiskInfo(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: m})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 磁盘详情
|
// @Summary format storage
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda1"
|
// @Param path formData string true "e.g. /dev/sda1"
|
||||||
|
// @Param pwd formData string true "user password"
|
||||||
|
// @Param volume formData string true "mount point"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/format [post]
|
// @Router /disk/format [post]
|
||||||
func FormatDisk(c *gin.Context) {
|
func FormatDisk(c *gin.Context) {
|
||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
|
t := "ext4"
|
||||||
|
pwd := c.PostForm("pwd")
|
||||||
|
volume := c.PostForm("volume")
|
||||||
|
|
||||||
t := c.PostForm("type")
|
if pwd != config.UserInfo.PWD {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(path) == 0 || len(t) == 0 {
|
if len(path) == 0 || len(t) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
if _, ok := diskMap[path]; ok {
|
||||||
//删除挂载点
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diskMap[path] = "busying"
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
||||||
|
format := service.MyService.Disk().FormatDisk(path, t)
|
||||||
//格式化磁盘
|
if len(format) == 0 {
|
||||||
service.MyService.Disk().FormatDisk(path, t)
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.FORMAT_ERROR, Message: oasis_err.GetMsg(oasis_err.FORMAT_ERROR)})
|
||||||
|
delete(diskMap, path)
|
||||||
//重新挂载
|
return
|
||||||
|
}
|
||||||
|
service.MyService.Disk().MountDisk(path, volume)
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
delete(diskMap, path)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,25 +266,231 @@ func RemovePartition(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 添加分区
|
// @Summary add storage
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags disk
|
// @Tags disk
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda"
|
// @Param path formData string true "disk path e.g. /dev/sda"
|
||||||
// @Param size formData string true "需要分区容量大小(MB)"
|
// @Param serial formData string true "serial"
|
||||||
// @Param num formData string true "磁盘符号"
|
// @Param name formData string true "name"
|
||||||
|
// @Param format formData bool true "need format(true)"
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /disk/addpart [post]
|
// @Router /disk/storage [post]
|
||||||
func AddPartition(c *gin.Context) {
|
func AddPartition(c *gin.Context) {
|
||||||
|
name := c.PostForm("name")
|
||||||
path := c.PostForm("path")
|
path := c.PostForm("path")
|
||||||
size, _ := strconv.Atoi(c.DefaultPostForm("size", "0"))
|
format, _ := strconv.ParseBool(c.PostForm("format"))
|
||||||
num := c.DefaultPostForm("num", "9")
|
if len(name) == 0 || len(path) == 0 {
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, ok := diskMap[path]; ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !file.CheckNotExist("/DATA/" + name) {
|
||||||
|
// /mnt/name exist
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.NAME_NOT_AVAILABLE, Message: oasis_err.GetMsg(oasis_err.NAME_NOT_AVAILABLE)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
diskMap[path] = "busying"
|
||||||
|
currentDisk := service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if !format {
|
||||||
|
if len(currentDisk.Children) != 1 || !(len(currentDisk.Children) > 0 && currentDisk.Children[0].FsType == "ext4") {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_err.DISK_NEEDS_FORMAT)})
|
||||||
|
delete(diskMap, path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
service.MyService.Disk().AddPartition(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
//size*1024*1024/512
|
formatBool := true
|
||||||
service.MyService.Disk().AddPartition(path, num, uint64(size*1024*2))
|
for formatBool {
|
||||||
|
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if len(currentDisk.Children) != 1 {
|
||||||
|
formatBool = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
}
|
||||||
|
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
||||||
|
if len(currentDisk.Children) != 1 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_err.DISK_NEEDS_FORMAT)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mountPath := "/DATA/" + name
|
||||||
|
m := model2.SerialDisk{}
|
||||||
|
m.MountPoint = mountPath
|
||||||
|
m.Path = currentDisk.Children[0].Path
|
||||||
|
m.UUID = currentDisk.Children[0].UUID
|
||||||
|
m.State = 0
|
||||||
|
m.CreatedAt = time.Now().Unix()
|
||||||
|
service.MyService.Disk().SaveMountPoint(m)
|
||||||
|
|
||||||
|
//mount dir
|
||||||
|
service.MyService.Disk().MountDisk(currentDisk.Children[0].Path, mountPath)
|
||||||
|
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
|
||||||
|
delete(diskMap, path)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary add mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string true "for example: /dev/sda1"
|
||||||
|
// @Param serial formData string true "disk id"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/mount [post]
|
||||||
|
func PostMountDisk(c *gin.Context) {
|
||||||
|
// for example: path=/dev/sda1
|
||||||
|
path := c.PostForm("path")
|
||||||
|
serial := c.PostForm("serial")
|
||||||
|
|
||||||
|
mountPath := "/DATA/volume"
|
||||||
|
var list = service.MyService.Disk().GetSerialAll()
|
||||||
|
var pathMapList = make(map[string]string, len(list))
|
||||||
|
for _, v := range list {
|
||||||
|
pathMapList[v.MountPoint] = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(list)+1; i++ {
|
||||||
|
if _, ok := pathMapList[mountPath+strconv.Itoa(i)]; !ok {
|
||||||
|
mountPath = mountPath + strconv.Itoa(i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mount dir
|
||||||
|
service.MyService.Disk().MountDisk(path, mountPath)
|
||||||
|
|
||||||
|
m := model2.SerialDisk{}
|
||||||
|
m.MountPoint = mountPath
|
||||||
|
m.Path = path
|
||||||
|
m.UUID = serial
|
||||||
|
m.State = 0
|
||||||
|
//service.MyService.Disk().SaveMountPoint(m)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary remove mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string true "e.g. /dev/sda1"
|
||||||
|
// @Param mount_point formData string true "e.g. /mnt/volume1"
|
||||||
|
// @Param pwd formData string true "user password"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/umount [post]
|
||||||
|
func PostDiskUmount(c *gin.Context) {
|
||||||
|
|
||||||
|
path := c.PostForm("path")
|
||||||
|
mountPoint := c.PostForm("volume")
|
||||||
|
pwd := c.PostForm("pwd")
|
||||||
|
|
||||||
|
if len(path) == 0 || len(mountPoint) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if pwd != config.UserInfo.PWD {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := diskMap[path]; ok {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
||||||
|
//delete data
|
||||||
|
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
|
||||||
|
service.MyService.Disk().RemoveLSBLKCache()
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary confirm delete disk
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param id path string true "id"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/remove/{id} [delete]
|
||||||
|
func DeleteDisk(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
service.MyService.Disk().DeleteMount(id)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary check mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/init [get]
|
||||||
|
func GetDiskCheck(c *gin.Context) {
|
||||||
|
|
||||||
|
dbList := service.MyService.Disk().GetSerialAll()
|
||||||
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
|
|
||||||
|
mapList := make(map[string]string)
|
||||||
|
|
||||||
|
for _, v := range list {
|
||||||
|
mapList[v.Serial] = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range dbList {
|
||||||
|
if _, ok := mapList[v.UUID]; !ok {
|
||||||
|
//disk undefind
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary check mount point
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags disk
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /disk/usb [get]
|
||||||
|
func GetUSBList(c *gin.Context) {
|
||||||
|
list := service.MyService.Disk().LSBLK(false)
|
||||||
|
data := []model.DriveUSB{}
|
||||||
|
for _, v := range list {
|
||||||
|
if v.Tran == "usb" {
|
||||||
|
temp := model.DriveUSB{}
|
||||||
|
temp.Model = v.Model
|
||||||
|
temp.Name = v.Name
|
||||||
|
temp.Size = v.Size
|
||||||
|
mountTemp := true
|
||||||
|
if len(v.Children) == 0 {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
for _, child := range v.Children {
|
||||||
|
if len(child.MountPoint) > 0 {
|
||||||
|
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||||
|
temp.Avail += avail
|
||||||
|
} else {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
temp.Mount = mountTemp
|
||||||
|
data = append(data, temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,14 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
|
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
@@ -19,11 +26,8 @@ import (
|
|||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"net/http"
|
"github.com/tidwall/gjson"
|
||||||
"reflect"
|
"golang.org/x/crypto/ssh"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
@@ -64,19 +68,46 @@ func DockerTerminal(c *gin.Context) {
|
|||||||
//打开本机的ssh接口
|
//打开本机的ssh接口
|
||||||
func WsSsh(c *gin.Context) {
|
func WsSsh(c *gin.Context) {
|
||||||
wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
|
wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
defer wsConn.Close()
|
|
||||||
cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
|
|
||||||
rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
|
|
||||||
client, _ := docker.NewSshClient()
|
|
||||||
defer client.Close()
|
|
||||||
ssConn, _ := docker.NewSshConn(cols, rows, client)
|
|
||||||
defer ssConn.Close()
|
|
||||||
quitChan := make(chan bool, 3)
|
|
||||||
|
|
||||||
var logBuff = new(bytes.Buffer)
|
var logBuff = new(bytes.Buffer)
|
||||||
|
quitChan := make(chan bool, 3)
|
||||||
|
user := ""
|
||||||
|
password := ""
|
||||||
|
var login int = 1
|
||||||
|
cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
|
||||||
|
rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
|
||||||
|
var client *ssh.Client
|
||||||
|
for login != 0 {
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
wsConn.WriteMessage(websocket.TextMessage, []byte("login:"))
|
||||||
|
user = docker.ReceiveWsMsgUser(wsConn, logBuff)
|
||||||
|
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
|
||||||
|
wsConn.WriteMessage(websocket.TextMessage, []byte("password:"))
|
||||||
|
password = docker.ReceiveWsMsgPassword(wsConn, logBuff)
|
||||||
|
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
|
||||||
|
client, err = docker.NewSshClient(user, password)
|
||||||
|
|
||||||
|
if err != nil && client == nil {
|
||||||
|
wsConn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
|
||||||
|
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
|
||||||
|
} else {
|
||||||
|
login = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if client != nil {
|
||||||
|
defer client.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
ssConn, _ := docker.NewSshConn(cols, rows, client)
|
||||||
|
defer ssConn.Close()
|
||||||
|
|
||||||
go ssConn.ReceiveWsMsg(wsConn, logBuff, quitChan)
|
go ssConn.ReceiveWsMsg(wsConn, logBuff, quitChan)
|
||||||
go ssConn.SendComboOutput(wsConn, quitChan)
|
go ssConn.SendComboOutput(wsConn, quitChan)
|
||||||
go ssConn.SessionWait(quitChan)
|
go ssConn.SessionWait(quitChan)
|
||||||
|
|
||||||
<-quitChan
|
<-quitChan
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -114,6 +145,7 @@ func SpeedPush(c *gin.Context) {
|
|||||||
// @Router /app/install/{id} [post]
|
// @Router /app/install/{id} [post]
|
||||||
func InstallApp(c *gin.Context) {
|
func InstallApp(c *gin.Context) {
|
||||||
appId := c.Param("id")
|
appId := c.Param("id")
|
||||||
|
language := c.GetHeader("Language")
|
||||||
var appInfo model.ServerAppList
|
var appInfo model.ServerAppList
|
||||||
m := model.CustomizationPostData{}
|
m := model.CustomizationPostData{}
|
||||||
c.BindJSON(&m)
|
c.BindJSON(&m)
|
||||||
@@ -143,7 +175,7 @@ func InstallApp(c *gin.Context) {
|
|||||||
dockerImageVersion = "latest"
|
dockerImageVersion = "latest"
|
||||||
}
|
}
|
||||||
if m.Origin != "custom" {
|
if m.Origin != "custom" {
|
||||||
appInfo = service.MyService.App().GetServerAppInfo(appId)
|
appInfo = service.MyService.OAPI().GetServerAppInfo(appId, "", language)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -187,14 +219,24 @@ func InstallApp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if m.Origin == "custom" {
|
||||||
|
for _, device := range m.Devices {
|
||||||
|
if file.CheckNotExist(device.Path) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for _, device := range m.Devices {
|
|
||||||
if file.CheckNotExist(device.Path) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
dev := []model.PathMap{}
|
||||||
|
for _, device := range dev {
|
||||||
|
if !file.CheckNotExist(device.Path) {
|
||||||
|
dev = append(dev, device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.Devices = dev
|
||||||
}
|
}
|
||||||
|
|
||||||
//restart := c.PostForm("restart") //always 总是重启, unless-stopped 除非用户手动停止容器,否则总是重新启动, on-failure:仅当容器退出代码非零时重新启动
|
//restart := c.PostForm("restart") //always 总是重启, unless-stopped 除非用户手动停止容器,否则总是重新启动, on-failure:仅当容器退出代码非零时重新启动
|
||||||
//if len(restart) > 0 {
|
//if len(restart) > 0 {
|
||||||
//
|
//
|
||||||
@@ -209,10 +251,9 @@ func InstallApp(c *gin.Context) {
|
|||||||
var relyMap = make(map[string]string)
|
var relyMap = make(map[string]string)
|
||||||
go func() {
|
go func() {
|
||||||
installLog := model2.AppNotify{}
|
installLog := model2.AppNotify{}
|
||||||
installLog.CustomId = id
|
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
|
installLog.CustomId = id
|
||||||
installLog.Message = "installing rely"
|
installLog.Message = "installing rely"
|
||||||
installLog.Speed = 10
|
|
||||||
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
|
||||||
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
@@ -238,11 +279,11 @@ func InstallApp(c *gin.Context) {
|
|||||||
rely.ContainerId = mysqlContainerId
|
rely.ContainerId = mysqlContainerId
|
||||||
rely.CustomId = mid
|
rely.CustomId = mid
|
||||||
rely.ContainerCustomId = id
|
rely.ContainerCustomId = id
|
||||||
var msqlConfig model2.MysqlConfigs
|
var mysqlConfig model2.MysqlConfigs
|
||||||
|
|
||||||
//结构体转换
|
//结构体转换
|
||||||
copier.Copy(&msqlConfig, &mc)
|
copier.Copy(&mysqlConfig, &mc)
|
||||||
rely.Config = msqlConfig
|
rely.Config = mysqlConfig
|
||||||
service.MyService.Rely().Create(rely)
|
service.MyService.Rely().Create(rely)
|
||||||
|
|
||||||
relyMap["mysql"] = mid
|
relyMap["mysql"] = mid
|
||||||
@@ -250,16 +291,13 @@ func InstallApp(c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
docker_base.MysqlDelete(mysqlContainerId)
|
docker_base.MysqlDelete(mysqlContainerId)
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
installLog.Speed = 30
|
|
||||||
installLog.Message = err.Error()
|
installLog.Message = err.Error()
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
installLog.Speed = 50
|
|
||||||
installLog.Message = "pulling"
|
installLog.Message = "pulling"
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
|
|
||||||
@@ -267,7 +305,6 @@ func InstallApp(c *gin.Context) {
|
|||||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
installLog.Speed = 70
|
|
||||||
installLog.Message = err.Error()
|
installLog.Message = err.Error()
|
||||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
@@ -283,36 +320,45 @@ func InstallApp(c *gin.Context) {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
//step:创建容器
|
//step:创建容器
|
||||||
|
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetworkModel)
|
||||||
|
// if err != nil {
|
||||||
|
// //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
|
||||||
|
// installLog.State = 0
|
||||||
|
// installLog.Speed = 75
|
||||||
|
// installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||||
|
// installLog.Message = err.Error()
|
||||||
|
// service.MyService.Notify().UpdateLog(installLog)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
|
||||||
installLog.ContainerId = containerId
|
installLog.Name = appInfo.Title
|
||||||
|
installLog.Icon = appInfo.Icon
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
installLog.Speed = 80
|
|
||||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||||
installLog.Message = err.Error()
|
installLog.Message = err.Error()
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
|
||||||
installLog.Speed = 80
|
|
||||||
installLog.Message = "starting"
|
installLog.Message = "starting"
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// echo -e "hellow\nworld" >>
|
||||||
|
|
||||||
//step:启动容器
|
//step:启动容器
|
||||||
err = service.MyService.Docker().DockerContainerStart(id)
|
err = service.MyService.Docker().DockerContainerStart(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||||
installLog.Speed = 90
|
|
||||||
installLog.Message = err.Error()
|
installLog.Message = err.Error()
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
|
||||||
installLog.Speed = 90
|
|
||||||
if m.Origin != CUSTOM {
|
if m.Origin != CUSTOM {
|
||||||
installLog.Message = "setting upnp"
|
installLog.Message = "setting upnp"
|
||||||
} else {
|
} else {
|
||||||
@@ -357,13 +403,11 @@ func InstallApp(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
installLog.Speed = 95
|
|
||||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||||
installLog.Message = err.Error()
|
installLog.Message = err.Error()
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
} else {
|
} else {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
|
||||||
installLog.Speed = 95
|
|
||||||
installLog.Message = "checking"
|
installLog.Message = "checking"
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
}
|
}
|
||||||
@@ -375,14 +419,12 @@ func InstallApp(c *gin.Context) {
|
|||||||
if err != nil && container.ContainerJSONBase.State.Running {
|
if err != nil && container.ContainerJSONBase.State.Running {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
installLog.Speed = 100
|
|
||||||
installLog.Type = types.NOTIFY_TYPE_ERROR
|
installLog.Type = types.NOTIFY_TYPE_ERROR
|
||||||
installLog.Message = err.Error()
|
installLog.Message = err.Error()
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
|
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
|
||||||
installLog.Speed = 100
|
|
||||||
installLog.Message = "installed"
|
installLog.Message = "installed"
|
||||||
service.MyService.Notify().UpdateLog(installLog)
|
service.MyService.Notify().UpdateLog(installLog)
|
||||||
}
|
}
|
||||||
@@ -390,6 +432,12 @@ func InstallApp(c *gin.Context) {
|
|||||||
rely := model.MapStrings{}
|
rely := model.MapStrings{}
|
||||||
|
|
||||||
copier.Copy(&rely, &relyMap)
|
copier.Copy(&rely, &relyMap)
|
||||||
|
// if m.Origin != "custom" {
|
||||||
|
// for i := 0; i < len(m.Volumes); i++ {
|
||||||
|
// m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].Path)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
portsStr, _ := json2.Marshal(m.Ports)
|
portsStr, _ := json2.Marshal(m.Ports)
|
||||||
envsStr, _ := json2.Marshal(m.Envs)
|
envsStr, _ := json2.Marshal(m.Envs)
|
||||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||||
@@ -429,6 +477,7 @@ func InstallApp(c *gin.Context) {
|
|||||||
// m.PortMap = m.Port
|
// m.PortMap = m.Port
|
||||||
//}
|
//}
|
||||||
service.MyService.App().SaveContainer(md)
|
service.MyService.App().SaveContainer(md)
|
||||||
|
config.CasaOSGlobalVariables.AppChange = true
|
||||||
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -643,7 +692,7 @@ func UnInstallApp(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//step:删除容器
|
//step:删除容器
|
||||||
err = service.MyService.Docker().DockerContainerRemove(appId)
|
err = service.MyService.Docker().DockerContainerRemove(appId, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
@@ -658,7 +707,12 @@ func UnInstallApp(c *gin.Context) {
|
|||||||
if info.Origin != "custom" {
|
if info.Origin != "custom" {
|
||||||
|
|
||||||
//step: 删除文件夹
|
//step: 删除文件夹
|
||||||
service.MyService.App().DelAppConfigDir(appId)
|
vol := gjson.Get(info.Volumes, "#.host")
|
||||||
|
for _, v := range vol.Array() {
|
||||||
|
if strings.Contains(v.String(), appId) {
|
||||||
|
service.MyService.App().DelAppConfigDir(v.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//step: 删除install log
|
//step: 删除install log
|
||||||
service.MyService.Notify().DelLog(appId)
|
service.MyService.Notify().DelLog(appId)
|
||||||
@@ -700,7 +754,7 @@ func UnInstallApp(c *gin.Context) {
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
config.CasaOSGlobalVariables.AppChange = true
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -763,7 +817,6 @@ func ContainerLog(c *gin.Context) {
|
|||||||
func GetInstallSpeed(c *gin.Context) {
|
func GetInstallSpeed(c *gin.Context) {
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
b := service.MyService.Notify().GetLog(id)
|
b := service.MyService.Notify().GetLog(id)
|
||||||
b.Id = b.CustomId
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: b})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: b})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -873,19 +926,24 @@ func UpdateSetting(c *gin.Context) {
|
|||||||
envsStr, _ := json2.Marshal(m.Envs)
|
envsStr, _ := json2.Marshal(m.Envs)
|
||||||
volumesStr, _ := json2.Marshal(m.Volumes)
|
volumesStr, _ := json2.Marshal(m.Volumes)
|
||||||
devicesStr, _ := json2.Marshal(m.Devices)
|
devicesStr, _ := json2.Marshal(m.Devices)
|
||||||
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(string(volumesStr), appInfo.Volumes) || m.PortMap != appInfo.PortMap {
|
if !reflect.DeepEqual(string(portsStr), appInfo.Ports) || !reflect.DeepEqual(string(envsStr), appInfo.Envs) || !reflect.DeepEqual(string(volumesStr), appInfo.Volumes) || m.PortMap != appInfo.PortMap || m.NetworkModel != appInfo.NetModel {
|
||||||
|
|
||||||
var newUUid = uuid.NewV4().String()
|
var newUUid = uuid.NewV4().String()
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
containerId, err = service.MyService.Docker().DockerContainerCreate(appInfo.Image+":"+appInfo.Version, newUUid, cpd, appInfo.NetModel)
|
// networkName, err := service.MyService.Docker().GetNetWorkNameByNetWorkID(appInfo.NetModel)
|
||||||
|
// if err != nil {
|
||||||
|
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
containerId, err = service.MyService.Docker().DockerContainerCreate(appInfo.Image+":"+appInfo.Version, newUUid, cpd, m.NetworkModel)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = service.MyService.Docker().DockerContainerRemove(id)
|
err = service.MyService.Docker().DockerContainerRemove(id, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
||||||
return
|
return
|
||||||
@@ -980,6 +1038,7 @@ func UpdateSetting(c *gin.Context) {
|
|||||||
appInfo.Icon = m.Icon
|
appInfo.Icon = m.Icon
|
||||||
appInfo.Volumes = string(volumesStr)
|
appInfo.Volumes = string(volumesStr)
|
||||||
appInfo.Devices = string(devicesStr)
|
appInfo.Devices = string(devicesStr)
|
||||||
|
appInfo.NetModel = m.NetworkModel
|
||||||
appInfo.Position = m.Position
|
appInfo.Position = m.Position
|
||||||
appInfo.EnableUPNP = m.EnableUPNP
|
appInfo.EnableUPNP = m.EnableUPNP
|
||||||
appInfo.Restart = m.Restart
|
appInfo.Restart = m.Restart
|
||||||
@@ -1087,16 +1146,20 @@ func ContainerUpdateInfo(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var port model.PortArrey
|
var port model.PortArray
|
||||||
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
json2.Unmarshal([]byte(appInfo.Ports), &port)
|
||||||
|
|
||||||
var envs model.EnvArrey
|
var envs model.EnvArray
|
||||||
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
json2.Unmarshal([]byte(appInfo.Envs), &envs)
|
||||||
|
|
||||||
var vol model.PathArrey
|
var vol model.PathArray
|
||||||
json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
json2.Unmarshal([]byte(appInfo.Volumes), &vol)
|
||||||
|
|
||||||
var dir model.PathArrey
|
for i := 0; i < len(vol); i++ {
|
||||||
|
vol[i].Path = strings.ReplaceAll(vol[i].Path, "$AppID", appId)
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir model.PathArray
|
||||||
json2.Unmarshal([]byte(appInfo.Devices), &dir)
|
json2.Unmarshal([]byte(appInfo.Devices), &dir)
|
||||||
|
|
||||||
//volumesStr, _ := json2.Marshal(m.Volumes)
|
//volumesStr, _ := json2.Marshal(m.Volumes)
|
||||||
|
|||||||
@@ -4,16 +4,19 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func downloadReadFile(c *gin.Context) {
|
func downloadReadFile(c *gin.Context) {
|
||||||
@@ -218,6 +221,25 @@ func MkdirAll(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary 创建文件
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept multipart/form-data
|
||||||
|
// @Tags file
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param path formData string false "路径"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /file/create [post]
|
||||||
|
func PostCreateFile(c *gin.Context) {
|
||||||
|
path := c.PostForm("path")
|
||||||
|
var code int
|
||||||
|
if len(path) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
code, _ = service.MyService.ZiMa().CreateFile(path)
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
|
||||||
|
}
|
||||||
|
|
||||||
// @Summary 上传文件
|
// @Summary 上传文件
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
@@ -236,3 +258,64 @@ func PostFileUpload(c *gin.Context) {
|
|||||||
io.Copy(out, file)
|
io.Copy(out, file)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PutFileMove(c *gin.Context) {
|
||||||
|
from := "/Users/liangjianli/go/CasaOS"
|
||||||
|
to := "/Users/liangjianli/go/CasaOS/test"
|
||||||
|
//t := 1 //是否覆盖
|
||||||
|
|
||||||
|
//方法体
|
||||||
|
stopCh := make(chan int)
|
||||||
|
f, err := os.Stat(from)
|
||||||
|
if err != nil {
|
||||||
|
//未拿到文件信息
|
||||||
|
fmt.Println("stat", err)
|
||||||
|
}
|
||||||
|
//未创建新的文件夹
|
||||||
|
if f.IsDir() {
|
||||||
|
//from 是文件夹,定义to也是文件夹
|
||||||
|
if list, err := ioutil.ReadDir(from); err == nil {
|
||||||
|
for _, v := range list {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
if err = Copy(stopCh, filepath.Join(from, v.Name()), filepath.Join(to, v.Name())); err != nil {
|
||||||
|
fmt.Printf("copy %s ,err %d", v.Name(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p := filepath.Dir(to)
|
||||||
|
if _, err = os.Stat(p); err != nil {
|
||||||
|
if err = os.MkdirAll(p, 0777); err != nil {
|
||||||
|
fmt.Println("mkdir", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Open(from)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("open file error ", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
out, err := os.Create(to)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("create to file err", err)
|
||||||
|
}
|
||||||
|
defer out.Close()
|
||||||
|
io.Copy(out, file)
|
||||||
|
time.Sleep(time.Second * 4)
|
||||||
|
close(stopCh)
|
||||||
|
}
|
||||||
|
func Copy(stop chan int, from, to string) error {
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-stop:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
fmt.Println(from)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
22
route/v1/search.go
Normal file
22
route/v1/search.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetSearchList(c *gin.Context) {
|
||||||
|
key := c.DefaultQuery("key", "")
|
||||||
|
if len(key) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list, err := service.MyService.Search().SearchList(key)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list})
|
||||||
|
}
|
||||||
35
route/v1/sync.go
Normal file
35
route/v1/sync.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SyncToSyncthing(c *gin.Context) {
|
||||||
|
u := c.Param("url")
|
||||||
|
target := "http://" + strings.Split(c.Request.Host, ":")[0] + ":" + config.SystemConfigInfo.SyncPort
|
||||||
|
remote, err := url.Parse(target)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
proxy := httputil.NewSingleHostReverseProxy(remote)
|
||||||
|
c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
|
||||||
|
//c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
|
||||||
|
c.Request.URL.Path = u
|
||||||
|
|
||||||
|
proxy.ServeHTTP(c.Writer, c.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSyncConfig(c *gin.Context) {
|
||||||
|
data := make(map[string]string)
|
||||||
|
data["key"] = config.SystemConfigInfo.SyncKey
|
||||||
|
data["port"] = config.SystemConfigInfo.SyncPort
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
@@ -1,18 +1,26 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 系统信息
|
// @Summary 系统信息
|
||||||
@@ -26,13 +34,12 @@ func CheckVersion(c *gin.Context) {
|
|||||||
need, version := version.IsNeedUpdate()
|
need, version := version.IsNeedUpdate()
|
||||||
if need {
|
if need {
|
||||||
installLog := model2.AppNotify{}
|
installLog := model2.AppNotify{}
|
||||||
installLog.CustomId = ""
|
|
||||||
installLog.State = 0
|
installLog.State = 0
|
||||||
installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
|
installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
|
||||||
installLog.Speed = 100
|
|
||||||
installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
|
installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
|
||||||
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
installLog.Name = "CasaOS System"
|
||||||
service.MyService.Notify().AddLog(installLog)
|
service.MyService.Notify().AddLog(installLog)
|
||||||
}
|
}
|
||||||
data := make(map[string]interface{}, 1)
|
data := make(map[string]interface{}, 1)
|
||||||
@@ -51,10 +58,8 @@ func CheckVersion(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /sys/update [post]
|
// @Router /sys/update [post]
|
||||||
func SystemUpdate(c *gin.Context) {
|
func SystemUpdate(c *gin.Context) {
|
||||||
fmt.Println("开始更新")
|
|
||||||
need, version := version.IsNeedUpdate()
|
need, version := version.IsNeedUpdate()
|
||||||
if need {
|
if need {
|
||||||
fmt.Println("进入更新")
|
|
||||||
service.MyService.System().UpdateSystemVersion(version.Version)
|
service.MyService.System().UpdateSystemVersion(version.Version)
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
|
||||||
@@ -62,28 +67,40 @@ func SystemUpdate(c *gin.Context) {
|
|||||||
|
|
||||||
//系统配置
|
//系统配置
|
||||||
func GetSystemConfig(c *gin.Context) {
|
func GetSystemConfig(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: config.SystemConfigInfo})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.ConfigStr)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary get logs
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/error/logs [get]
|
||||||
|
func GetCasaOSErrorLogs(c *gin.Context) {
|
||||||
|
line, _ := strconv.Atoi(c.DefaultQuery("line", "100"))
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 修改配置文件
|
// @Summary 修改配置文件
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Tags user
|
// @Tags sys
|
||||||
// @Param file formData file true "用户头像"
|
// @Param config formData string true "config json string"
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/changhead [post]
|
// @Router /sys/changhead [post]
|
||||||
func PostSetSystemConfig(c *gin.Context) {
|
func PostSetSystemConfig(c *gin.Context) {
|
||||||
var systemConfig model.SystemConfig
|
buf := make([]byte, 1024)
|
||||||
c.BindJSON(&systemConfig)
|
n, _ := c.Request.Body.Read(buf)
|
||||||
service.MyService.System().UpSystemConfig(systemConfig)
|
|
||||||
|
service.MyService.System().UpSystemConfig(string(buf[0:n]), "")
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
model.Result{
|
model.Result{
|
||||||
Success: oasis_err.SUCCESS,
|
Success: oasis_err.SUCCESS,
|
||||||
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
Data: config.SystemConfigInfo,
|
Data: json.RawMessage(config.SystemConfigInfo.ConfigStr),
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//系统配置
|
//系统配置
|
||||||
@@ -91,10 +108,280 @@ func GetSystemConfigDebug(c *gin.Context) {
|
|||||||
|
|
||||||
array := service.MyService.System().GetSystemConfigDebug()
|
array := service.MyService.System().GetSystemConfigDebug()
|
||||||
disk := service.MyService.ZiMa().GetDiskInfo()
|
disk := service.MyService.ZiMa().GetDiskInfo()
|
||||||
array = append(array, fmt.Sprintf("disk,totle:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
|
sys := service.MyService.ZiMa().GetSysInfo()
|
||||||
|
//todo 准备sync需要显示的数据(镜像,容器)
|
||||||
|
var systemAppStatus string
|
||||||
|
images := service.MyService.Docker().IsExistImage("linuxserver/syncthing")
|
||||||
|
systemAppStatus += "Sync img: " + strconv.FormatBool(images) + "\n\t"
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: array})
|
list := service.MyService.App().GetSystemAppList()
|
||||||
|
for _, v := range *list {
|
||||||
|
systemAppStatus += v.Image + ",\n\t"
|
||||||
|
}
|
||||||
|
|
||||||
|
systemAppStatus += "Sync Key length: " + strconv.Itoa(len(config.SystemConfigInfo.SyncKey))
|
||||||
|
|
||||||
|
var bugContent string = fmt.Sprintf(`
|
||||||
|
- OS: %s
|
||||||
|
- CasaOS Version: %s
|
||||||
|
- Disk Total: %v
|
||||||
|
- Disk Used: %v
|
||||||
|
- Sync State: %s
|
||||||
|
- System Info: %s
|
||||||
|
- Browser: $Browser$
|
||||||
|
- Version: $Version$
|
||||||
|
`, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, systemAppStatus, array)
|
||||||
|
|
||||||
|
// array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: bugContent})
|
||||||
}
|
}
|
||||||
func Sys(c *gin.Context) {
|
func Sys(c *gin.Context) {
|
||||||
service.DockerPull()
|
service.DockerPull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//widget配置
|
||||||
|
func GetWidgetConfig(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.WidgetList)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary 修改组件配置文件
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/widget/config [post]
|
||||||
|
func PostSetWidgetConfig(c *gin.Context) {
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
n, _ := c.Request.Body.Read(buf)
|
||||||
|
fmt.Println("错误", strconv.Itoa(n))
|
||||||
|
service.MyService.System().UpSystemConfig("", string(buf[0:n]))
|
||||||
|
fmt.Println("错误1", string(buf[0:n]))
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
Data: json.RawMessage(config.SystemConfigInfo.WidgetList),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary get casaos server port
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/port [get]
|
||||||
|
func GetCasaOSPort(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
Data: config.ServerInfo.HttpPort,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary edit casaos server port
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param port formData string true "port"
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/port [put]
|
||||||
|
func PutCasaOSPort(c *gin.Context) {
|
||||||
|
port, err := strconv.Atoi(c.PostForm("port"))
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.ERROR,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isAvailable := port2.IsPortAvailable(port, "tcp")
|
||||||
|
if !isAvailable {
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.PORT_IS_OCCUPIED,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.PORT_IS_OCCUPIED),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
service.MyService.System().UpSystemPort(strconv.Itoa(port))
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary 检查是否进入引导状态
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /guide/check [get]
|
||||||
|
func GetGuideCheck(c *gin.Context) {
|
||||||
|
initUser := false
|
||||||
|
if !config.UserInfo.Initialized {
|
||||||
|
initUser = true
|
||||||
|
}
|
||||||
|
data := make(map[string]interface{}, 1)
|
||||||
|
data["need_init_user"] = initUser
|
||||||
|
c.JSON(http.StatusOK,
|
||||||
|
model.Result{
|
||||||
|
Success: oasis_err.SUCCESS,
|
||||||
|
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary active killing casaos
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/kill [post]
|
||||||
|
func PostKillCasaOS(c *gin.Context) {
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary system info
|
||||||
|
// @Produce application/json
|
||||||
|
// @Accept application/json
|
||||||
|
// @Tags sys
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Success 200 {string} string "ok"
|
||||||
|
// @Router /sys/info [get]
|
||||||
|
func Info(c *gin.Context) {
|
||||||
|
var data = make(map[string]interface{}, 6)
|
||||||
|
|
||||||
|
list := service.MyService.Disk().LSBLK(true)
|
||||||
|
|
||||||
|
summary := model.Summary{}
|
||||||
|
healthy := true
|
||||||
|
findSystem := 0
|
||||||
|
|
||||||
|
for i := 0; i < len(list); i++ {
|
||||||
|
if len(list[i].Children) > 0 && findSystem == 0 {
|
||||||
|
|
||||||
|
for j := 0; j < len(list[i].Children); j++ {
|
||||||
|
|
||||||
|
if len(list[i].Children[j].Children) > 0 {
|
||||||
|
for _, v := range list[i].Children[j].Children {
|
||||||
|
if v.MountPoint == "/" {
|
||||||
|
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if list[i].Children[j].MountPoint == "/" {
|
||||||
|
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
findSystem = 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if findSystem == 1 {
|
||||||
|
findSystem += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" {
|
||||||
|
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
||||||
|
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//list[i].Temperature = temp.Temperature.Current
|
||||||
|
if !temp.SmartStatus.Passed {
|
||||||
|
healthy = false
|
||||||
|
}
|
||||||
|
if len(list[i].Children) > 0 {
|
||||||
|
for _, v := range list[i].Children {
|
||||||
|
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
||||||
|
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
||||||
|
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
||||||
|
summary.Size += s
|
||||||
|
summary.Avail += a
|
||||||
|
summary.Used += u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.Health = healthy
|
||||||
|
data["disk"] = summary
|
||||||
|
usbList := service.MyService.Disk().LSBLK(false)
|
||||||
|
usb := []model.DriveUSB{}
|
||||||
|
for _, v := range usbList {
|
||||||
|
if v.Tran == "usb" {
|
||||||
|
temp := model.DriveUSB{}
|
||||||
|
temp.Model = v.Model
|
||||||
|
temp.Name = v.Name
|
||||||
|
temp.Size = v.Size
|
||||||
|
mountTemp := true
|
||||||
|
if len(v.Children) == 0 {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
for _, child := range v.Children {
|
||||||
|
if len(child.MountPoint) > 0 {
|
||||||
|
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
||||||
|
temp.Avail += avail
|
||||||
|
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
||||||
|
temp.Used += used
|
||||||
|
} else {
|
||||||
|
mountTemp = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
temp.Mount = mountTemp
|
||||||
|
usb = append(usb, temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data["usb"] = usb
|
||||||
|
cpu := service.MyService.ZiMa().GetCpuPercent()
|
||||||
|
num := service.MyService.ZiMa().GetCpuCoreNum()
|
||||||
|
cpuData := make(map[string]interface{})
|
||||||
|
cpuData["percent"] = cpu
|
||||||
|
cpuData["num"] = num
|
||||||
|
data["cpu"] = cpuData
|
||||||
|
data["mem"] = service.MyService.ZiMa().GetMemInfo()
|
||||||
|
|
||||||
|
//拼装网络信息
|
||||||
|
netList := service.MyService.ZiMa().GetNetInfo()
|
||||||
|
newNet := []model.IOCountersStat{}
|
||||||
|
nets := service.MyService.ZiMa().GetNet(true)
|
||||||
|
for _, n := range netList {
|
||||||
|
for _, netCardName := range nets {
|
||||||
|
if n.Name == netCardName {
|
||||||
|
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
||||||
|
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
||||||
|
item.DateTime = time.Now()
|
||||||
|
newNet = append(newNet, item)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data["net"] = newNet
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,13 +2,15 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var user_service service.UserService
|
var user_service service.UserService
|
||||||
@@ -32,7 +34,7 @@ func Set_Name_Pwd(c *gin.Context) {
|
|||||||
username := c.PostForm("username")
|
username := c.PostForm("username")
|
||||||
pwd := c.PostForm("pwd")
|
pwd := c.PostForm("pwd")
|
||||||
//老用户名是否存在即新用户名和密码的验证
|
//老用户名是否存在即新用户名和密码的验证
|
||||||
if len(config.UserInfo.UserName) > 0 || len(username) == 0 || len(pwd) == 0 {
|
if config.UserInfo.Initialized || len(username) == 0 || len(pwd) == 0 {
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
@@ -69,15 +71,18 @@ func Login(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//if config.UserInfo.UserName == username && config.UserInfo.PWD == pwd {
|
if config.UserInfo.UserName == username && config.UserInfo.PWD == pwd {
|
||||||
if username == "admin" && pwd == "admin" {
|
//if username == "admin" && pwd == "admin" {
|
||||||
token := jwt2.GetToken(username, pwd)
|
|
||||||
|
data := make(map[string]string, 2)
|
||||||
|
data["token"] = jwt2.GetToken(username, pwd)
|
||||||
|
data["version"] = types.CURRENTVERSION
|
||||||
//user_service.SetUser("", "", token, "", "")
|
//user_service.SetUser("", "", token, "", "")
|
||||||
c.JSON(http.StatusOK,
|
c.JSON(http.StatusOK,
|
||||||
model.Result{
|
model.Result{
|
||||||
Success: oasis_err2.SUCCESS,
|
Success: oasis_err2.SUCCESS,
|
||||||
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
||||||
Data: token,
|
Data: data,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -106,7 +111,6 @@ func Up_Load_Head(c *gin.Context) {
|
|||||||
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
||||||
Data: config.UserInfo.Head,
|
Data: config.UserInfo.Head,
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 修改用户名
|
// @Summary 修改用户名
|
||||||
@@ -119,6 +123,10 @@ func Up_Load_Head(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/changusername [put]
|
// @Router /user/changusername [put]
|
||||||
func Chang_User_Name(c *gin.Context) {
|
func Chang_User_Name(c *gin.Context) {
|
||||||
|
if config.ServerInfo.LockAccount {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)})
|
||||||
|
return
|
||||||
|
}
|
||||||
oldname := c.PostForm("oldname")
|
oldname := c.PostForm("oldname")
|
||||||
username := c.PostForm("username")
|
username := c.PostForm("username")
|
||||||
if len(username) == 0 || config.UserInfo.UserName != oldname {
|
if len(username) == 0 || config.UserInfo.UserName != oldname {
|
||||||
@@ -127,7 +135,6 @@ func Chang_User_Name(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
user_service.SetUser(username, "", "", "", "")
|
user_service.SetUser(username, "", "", "", "")
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 修改密码
|
// @Summary 修改密码
|
||||||
@@ -142,13 +149,20 @@ func Chang_User_Name(c *gin.Context) {
|
|||||||
func Chang_User_Pwd(c *gin.Context) {
|
func Chang_User_Pwd(c *gin.Context) {
|
||||||
oldpwd := c.PostForm("oldpwd")
|
oldpwd := c.PostForm("oldpwd")
|
||||||
pwd := c.PostForm("pwd")
|
pwd := c.PostForm("pwd")
|
||||||
if len(pwd) == 0 || config.UserInfo.PWD != oldpwd {
|
if config.UserInfo.PWD != oldpwd {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if config.ServerInfo.LockAccount {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(pwd) == 0 {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_IS_EMPTY, Message: oasis_err2.GetMsg(oasis_err2.PWD_IS_EMPTY)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user_service.SetUser("", pwd, "", "", "")
|
user_service.SetUser("", pwd, "", "", "")
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 修改用户信息
|
// @Summary 修改用户信息
|
||||||
@@ -174,21 +188,23 @@ func Chang_User_Info(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
user_service.SetUser(username, pwd, "", email, description)
|
user_service.SetUser(username, pwd, "", email, description)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
data := make(map[string]string, 2)
|
||||||
return
|
|
||||||
|
data["token"] = jwt2.GetToken(username, pwd)
|
||||||
|
data["user_name"] = username
|
||||||
|
data["head"] = config.UserInfo.Head
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取用户详情
|
// @Summary 获取用户详情
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept mapplication/json
|
// @Accept mapplication/json
|
||||||
// @Tags user
|
// @Tags user
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /user/info [get]
|
// @Router /user/info [get]
|
||||||
func UserInfo(c *gin.Context) {
|
func UserInfo(c *gin.Context) {
|
||||||
var u = make(map[string]string, 2)
|
var u = make(map[string]string, 2)
|
||||||
u["user_name"] = config.UserInfo.UserName
|
u["user_name"] = config.UserInfo.UserName
|
||||||
u["token"] = config.UserInfo.Token
|
|
||||||
u["head"] = config.UserInfo.Head
|
u["head"] = config.UserInfo.Head
|
||||||
u["email"] = config.UserInfo.Email
|
u["email"] = config.UserInfo.Email
|
||||||
u["description"] = config.UserInfo.Description
|
u["description"] = config.UserInfo.Description
|
||||||
@@ -198,5 +214,4 @@ func UserInfo(c *gin.Context) {
|
|||||||
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
|
||||||
Data: u,
|
Data: u,
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 登录zerotier获取token
|
// @Summary 登录zerotier获取token
|
||||||
@@ -432,11 +433,17 @@ func ZeroTierDeleteNetwork(c *gin.Context) {
|
|||||||
// @Router /zerotier/join/{id} [post]
|
// @Router /zerotier/join/{id} [post]
|
||||||
func ZeroTierJoinNetwork(c *gin.Context) {
|
func ZeroTierJoinNetwork(c *gin.Context) {
|
||||||
networkId := c.Param("id")
|
networkId := c.Param("id")
|
||||||
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
|
if len(networkId) != 16 {
|
||||||
if len(networkId) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
for _, v := range networkId {
|
||||||
|
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.ZeroTier().ZeroTierJoinNetwork(networkId)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,10 +457,19 @@ func ZeroTierJoinNetwork(c *gin.Context) {
|
|||||||
// @Router /zerotier/leave/{id} [post]
|
// @Router /zerotier/leave/{id} [post]
|
||||||
func ZeroTierLeaveNetwork(c *gin.Context) {
|
func ZeroTierLeaveNetwork(c *gin.Context) {
|
||||||
networkId := c.Param("id")
|
networkId := c.Param("id")
|
||||||
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
|
|
||||||
if len(networkId) == 0 {
|
if len(networkId) != 16 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, v := range networkId {
|
||||||
|
if !service.MyService.ZeroTier().NetworkIdFilter(v) {
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service.MyService.ZeroTier().ZeroTierLeaveNetwork(networkId)
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 获取cpu信息
|
// @Summary 获取cpu信息
|
||||||
@@ -83,48 +83,6 @@ func NetInfo(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet})
|
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取信息
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags zima
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /zima/getinfo [get]
|
|
||||||
func Info(c *gin.Context) {
|
|
||||||
var data = make(map[string]interface{}, 4)
|
|
||||||
|
|
||||||
var diskArr []*disk.UsageStat
|
|
||||||
diskArr = append(diskArr, service.MyService.ZiMa().GetDiskInfo())
|
|
||||||
data["disk"] = diskArr
|
|
||||||
cpu := service.MyService.ZiMa().GetCpuPercent()
|
|
||||||
num := service.MyService.ZiMa().GetCpuCoreNum()
|
|
||||||
cpuData := make(map[string]interface{})
|
|
||||||
cpuData["percent"] = cpu
|
|
||||||
cpuData["num"] = num
|
|
||||||
data["cpu"] = cpuData
|
|
||||||
data["mem"] = service.MyService.ZiMa().GetMemInfo()
|
|
||||||
|
|
||||||
//拼装网络信息
|
|
||||||
netList := service.MyService.ZiMa().GetNetInfo()
|
|
||||||
newNet := []model.IOCountersStat{}
|
|
||||||
nets := service.MyService.ZiMa().GetNet(true)
|
|
||||||
for _, n := range netList {
|
|
||||||
for _, netCardName := range nets {
|
|
||||||
if n.Name == netCardName {
|
|
||||||
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
|
|
||||||
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
|
|
||||||
item.DateTime = time.Now()
|
|
||||||
newNet = append(newNet, item)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data["net"] = newNet
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取信息系统信息
|
// @Summary 获取信息系统信息
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
|
|||||||
234
service/app.go
234
service/app.go
@@ -2,35 +2,40 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
json2 "encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
client2 "github.com/docker/docker/client"
|
client2 "github.com/docker/docker/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppService interface {
|
type AppService interface {
|
||||||
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
GetMyList(index, size int, position bool) *[]model2.MyAppList
|
||||||
SaveContainer(m model2.AppListDBModel)
|
SaveContainer(m model2.AppListDBModel)
|
||||||
GetServerAppInfo(id string) model.ServerAppList
|
|
||||||
GetUninstallInfo(id string) model2.AppListDBModel
|
GetUninstallInfo(id string) model2.AppListDBModel
|
||||||
RemoveContainerById(id string)
|
RemoveContainerById(id string)
|
||||||
GetContainerInfo(name string) (types.Container, error)
|
GetContainerInfo(name string) (types.Container, error)
|
||||||
GetAppDBInfo(id string) model2.AppListDBModel
|
GetAppDBInfo(id string) model2.AppListDBModel
|
||||||
UpdateApp(m model2.AppListDBModel)
|
UpdateApp(m model2.AppListDBModel)
|
||||||
GetSimpleContainerInfo(name string) (types.Container, error)
|
GetSimpleContainerInfo(name string) (types.Container, error)
|
||||||
DelAppConfigDir(id string)
|
DelAppConfigDir(path string)
|
||||||
|
GetSystemAppList() *[]model2.MyAppList
|
||||||
|
GetHardwareUsageSteam()
|
||||||
|
GetHardwareUsage() []model.DockerStatsModel
|
||||||
|
GetAppStats(id string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type appStruct struct {
|
type appStruct struct {
|
||||||
@@ -41,7 +46,7 @@ type appStruct struct {
|
|||||||
//获取我的应用列表
|
//获取我的应用列表
|
||||||
func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList {
|
func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppList {
|
||||||
//获取docker应用
|
//获取docker应用
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||||
}
|
}
|
||||||
@@ -52,11 +57,10 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取本地数据库应用
|
//获取本地数据库应用
|
||||||
|
|
||||||
var lm []model2.AppListDBModel
|
var lm []model2.AppListDBModel
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan").Find(&lm)
|
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image").Find(&lm)
|
||||||
|
|
||||||
list := []model2.MyAppList{}
|
list := []model2.MyAppList{}
|
||||||
lMap := make(map[string]interface{})
|
lMap := make(map[string]interface{})
|
||||||
@@ -69,11 +73,70 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
lMap[dbModel.ContainerId] = dbModel
|
lMap[dbModel.ContainerId] = dbModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, container := range containers {
|
||||||
|
|
||||||
|
if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
|
||||||
|
m := lMap[container.ID].(model2.AppListDBModel)
|
||||||
|
if len(m.Label) == 0 {
|
||||||
|
m.Label = m.Title
|
||||||
|
}
|
||||||
|
|
||||||
|
// info, err := cli.ContainerInspect(context.Background(), container.ID)
|
||||||
|
// var tm string
|
||||||
|
// if err != nil {
|
||||||
|
// tm = time.Now().String()
|
||||||
|
// } else {
|
||||||
|
// tm = info.State.StartedAt
|
||||||
|
//}
|
||||||
|
list = append(list, model2.MyAppList{
|
||||||
|
Name: m.Label,
|
||||||
|
Icon: m.Icon,
|
||||||
|
State: container.State,
|
||||||
|
CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
|
||||||
|
Port: m.PortMap,
|
||||||
|
Index: m.Index,
|
||||||
|
//UpTime: tm,
|
||||||
|
Image: m.Image,
|
||||||
|
Slogan: m.Slogan,
|
||||||
|
//Rely: m.Rely,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &list
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//system application list
|
||||||
|
func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
|
||||||
|
//获取docker应用
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
fts := filters.NewArgs()
|
||||||
|
fts.Add("label", "origin=system")
|
||||||
|
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("获取docker容器失败", "app.sys", "line:123", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取本地数据库应用
|
||||||
|
|
||||||
|
var lm []model2.AppListDBModel
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image,volumes").Find(&lm)
|
||||||
|
|
||||||
|
list := []model2.MyAppList{}
|
||||||
|
lMap := make(map[string]interface{})
|
||||||
|
for _, dbModel := range lm {
|
||||||
|
lMap[dbModel.ContainerId] = dbModel
|
||||||
|
}
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
|
|
||||||
if lMap[container.ID] != nil {
|
if lMap[container.ID] != nil {
|
||||||
var m model2.AppListDBModel
|
m := lMap[container.ID].(model2.AppListDBModel)
|
||||||
m = lMap[container.ID].(model2.AppListDBModel)
|
|
||||||
if len(m.Label) == 0 {
|
if len(m.Label) == 0 {
|
||||||
m.Label = m.Title
|
m.Label = m.Title
|
||||||
}
|
}
|
||||||
@@ -93,11 +156,12 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
|
|||||||
Port: m.PortMap,
|
Port: m.PortMap,
|
||||||
Index: m.Index,
|
Index: m.Index,
|
||||||
UpTime: tm,
|
UpTime: tm,
|
||||||
|
Image: m.Image,
|
||||||
Slogan: m.Slogan,
|
Slogan: m.Slogan,
|
||||||
|
Volumes: m.Volumes,
|
||||||
//Rely: m.Rely,
|
//Rely: m.Rely,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &list
|
return &list
|
||||||
@@ -115,7 +179,7 @@ func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
|
|||||||
filters.Add("name", name)
|
filters.Add("name", name)
|
||||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
|
a.log.Error("获取docker容器失败", "app.getcontainerinfo", "line:182", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(containers) > 0 {
|
if len(containers) > 0 {
|
||||||
@@ -135,6 +199,10 @@ func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error)
|
|||||||
filters := filters.NewArgs()
|
filters := filters.NewArgs()
|
||||||
filters.Add("name", name)
|
filters.Add("name", name)
|
||||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
|
||||||
|
if err != nil {
|
||||||
|
return types.Container{}, err
|
||||||
|
}
|
||||||
|
|
||||||
if len(containers) > 0 {
|
if len(containers) > 0 {
|
||||||
return containers[0], nil
|
return containers[0], nil
|
||||||
}
|
}
|
||||||
@@ -155,27 +223,6 @@ func (a *appStruct) GetUninstallInfo(id string) model2.AppListDBModel {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) GetServerAppInfo(id string) model.ServerAppList {
|
|
||||||
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
t := make(chan string)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
|
||||||
|
|
||||||
t <- gjson.Get(str, "data").String()
|
|
||||||
}()
|
|
||||||
head["Authorization"] = <-t
|
|
||||||
|
|
||||||
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/info/"+id, head)
|
|
||||||
|
|
||||||
info := model.ServerAppList{}
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
|
||||||
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
//创建容器成功后保存容器
|
//创建容器成功后保存容器
|
||||||
func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
|
func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
|
a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
|
||||||
@@ -185,14 +232,125 @@ func (a *appStruct) UpdateApp(m model2.AppListDBModel) {
|
|||||||
a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
|
a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) DelAppConfigDir(id string) {
|
func (a *appStruct) DelAppConfigDir(path string) {
|
||||||
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + docker.GetDir(id, "/config"))
|
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *appStruct) RemoveContainerById(id string) {
|
func (a *appStruct) RemoveContainerById(id string) {
|
||||||
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
|
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dataStats sync.Map
|
||||||
|
|
||||||
|
var isFinish bool = false
|
||||||
|
|
||||||
|
func (a *appStruct) GetAppStats(id string) string {
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
con, err := cli.ContainerStats(context.Background(), id, false)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
defer con.Body.Close()
|
||||||
|
c, _ := ioutil.ReadAll(con.Body)
|
||||||
|
return string(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
|
||||||
|
|
||||||
|
steam := true
|
||||||
|
for !isFinish {
|
||||||
|
if steam {
|
||||||
|
steam = false
|
||||||
|
go func() {
|
||||||
|
a.GetHardwareUsageSteam()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
runtime.Gosched()
|
||||||
|
}
|
||||||
|
list := []model.DockerStatsModel{}
|
||||||
|
|
||||||
|
dataStats.Range(func(key, value interface{}) bool {
|
||||||
|
list = append(list, value.(model.DockerStatsModel))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return list
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *appStruct) GetHardwareUsageSteam() {
|
||||||
|
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
var lm []model2.AppListDBModel
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
if config.CasaOSGlobalVariables.AppChange {
|
||||||
|
lm = []model2.AppListDBModel{}
|
||||||
|
config.CasaOSGlobalVariables.AppChange = false
|
||||||
|
a.db.Table(model2.CONTAINERTABLENAME).Select("label,title,icon,container_id").Where("origin != ?", "system").Find(&lm)
|
||||||
|
dataApps := dataStats
|
||||||
|
dataStats.Range(func(key, value interface{}) bool {
|
||||||
|
dataStats.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
for _, v := range lm {
|
||||||
|
m, _ := dataApps.Load(v.ContainerId)
|
||||||
|
if m != nil {
|
||||||
|
dataStats.Store(v.ContainerId, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for _, v := range lm {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(v model2.AppListDBModel, i int) {
|
||||||
|
defer wg.Done()
|
||||||
|
stats, err := cli.ContainerStats(ctx, v.ContainerId, true)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
decode := json.NewDecoder(stats.Body)
|
||||||
|
var data interface{}
|
||||||
|
if err := decode.Decode(&data); err == io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m, _ := dataStats.Load(v.ContainerId)
|
||||||
|
dockerStats := model.DockerStatsModel{}
|
||||||
|
if m != nil {
|
||||||
|
dockerStats.Pre = m.(model.DockerStatsModel).Data
|
||||||
|
}
|
||||||
|
dockerStats.Data = data
|
||||||
|
dockerStats.Icon = v.Icon
|
||||||
|
if len(v.Label) > 0 {
|
||||||
|
dockerStats.Title = v.Label
|
||||||
|
} else {
|
||||||
|
dockerStats.Title = v.Title
|
||||||
|
}
|
||||||
|
dataStats.Store(v.ContainerId, dockerStats)
|
||||||
|
if i == 99 {
|
||||||
|
stats.Body.Close()
|
||||||
|
}
|
||||||
|
}(v, i)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
isFinish = true
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
}
|
||||||
|
isFinish = false
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
|
||||||
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
|
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
|
||||||
return &appStruct{db: db, log: logger}
|
return &appStruct{db: db, log: logger}
|
||||||
}
|
}
|
||||||
|
|||||||
128
service/casa.go
Normal file
128
service/casa.go
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
json2 "encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CasaService interface {
|
||||||
|
GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList)
|
||||||
|
GetServerCategoryList() []model.ServerCategoryList
|
||||||
|
GetTaskList(size int) []model2.TaskDBModel
|
||||||
|
GetServerAppInfo(id, t string, language string) model.ServerAppList
|
||||||
|
ShareAppFile(body []byte) string
|
||||||
|
}
|
||||||
|
|
||||||
|
type casaService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) ShareAppFile(body []byte) string {
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
content := httper2.Post(config.ServerInfo.ServerApi+"/v1/community/add", body, "application/json", head)
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetTaskList(size int) []model2.TaskDBModel {
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/task/list/"+strconv.Itoa(size), head)
|
||||||
|
|
||||||
|
list := []model2.TaskDBModel{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList) {
|
||||||
|
|
||||||
|
keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, language)
|
||||||
|
|
||||||
|
if result, ok := Cache.Get(keyName); ok {
|
||||||
|
res, ok := result.(string)
|
||||||
|
if ok {
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(res, "data.list").String()), &list)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(res, "data.recommend").String()), &recommend)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(res, "data.community").String()), &community)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index="+index+"&size="+size+"&rank="+tp+"&category_id="+categoryId+"&key="+key+"&language="+language, head)
|
||||||
|
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &list)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend)
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &community)
|
||||||
|
|
||||||
|
if len(list) > 0 {
|
||||||
|
Cache.SetDefault(keyName, listS)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
|
||||||
|
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
|
||||||
|
|
||||||
|
list := []model.ServerCategoryList{}
|
||||||
|
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
||||||
|
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {
|
||||||
|
|
||||||
|
head := make(map[string]string)
|
||||||
|
|
||||||
|
head["Authorization"] = GetToken()
|
||||||
|
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t+"&language="+language, head)
|
||||||
|
|
||||||
|
info := model.ServerAppList{}
|
||||||
|
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
func GetToken() string {
|
||||||
|
t := make(chan string)
|
||||||
|
keyName := "casa_token"
|
||||||
|
|
||||||
|
var auth string
|
||||||
|
if result, ok := Cache.Get(keyName); ok {
|
||||||
|
auth, ok = result.(string)
|
||||||
|
if ok {
|
||||||
|
|
||||||
|
return auth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
||||||
|
|
||||||
|
t <- gjson.Get(str, "data").String()
|
||||||
|
}()
|
||||||
|
auth = <-t
|
||||||
|
|
||||||
|
Cache.SetDefault(keyName, auth)
|
||||||
|
return auth
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOasisService() CasaService {
|
||||||
|
return &casaService{}
|
||||||
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"github.com/IceWhaleTech/CasaOS/service/ddns"
|
"github.com/IceWhaleTech/CasaOS/service/ddns"
|
||||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"os/exec"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ddnsStruct struct {
|
type ddnsStruct struct {
|
||||||
@@ -20,17 +21,15 @@ type DDNSService interface {
|
|||||||
GetConfigList() *[]model.DDNSList
|
GetConfigList() *[]model.DDNSList
|
||||||
DeleteConfig(id uint) bool
|
DeleteConfig(id uint) bool
|
||||||
GetType(name string) (uint, string)
|
GetType(name string) (uint, string)
|
||||||
SaveConfig(model model.DDNSUpdataDBModel) error
|
SaveConfig(model model.DDNSUpdateDBModel) error
|
||||||
}
|
}
|
||||||
|
|
||||||
//判断当前添加的是否存在
|
//判断当前添加的是否存在
|
||||||
func (d *ddnsStruct) IsExis(t int, domain string, host string) bool {
|
func (d *ddnsStruct) IsExis(t int, domain string, host string) bool {
|
||||||
var count int64
|
var count int64
|
||||||
d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count)
|
d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count)
|
||||||
if count > 0 {
|
|
||||||
return true
|
return count > 0
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//前台获取已配置的ddns列表
|
//前台获取已配置的ddns列表
|
||||||
@@ -41,7 +40,7 @@ func (d *ddnsStruct) GetConfigList() *[]model.DDNSList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *ddnsStruct) DeleteConfig(id uint) bool {
|
func (d *ddnsStruct) DeleteConfig(id uint) bool {
|
||||||
d.db.Delete(&model.DDNSUpdataDBModel{Id: id})
|
d.db.Delete(&model.DDNSUpdateDBModel{Id: id})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,12 +65,12 @@ func (d *ddnsStruct) GetType(name string) (uint, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//保存配置到数据库
|
//保存配置到数据库
|
||||||
func (d *ddnsStruct) GetDockerRootDir(model model.DDNSUpdataDBModel) error {
|
func (d *ddnsStruct) GetDockerRootDir(model model.DDNSUpdateDBModel) error {
|
||||||
return d.db.Create(&model).Error
|
return d.db.Create(&model).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
//保存配置到数据库
|
//保存配置到数据库
|
||||||
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdataDBModel) error {
|
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdateDBModel) error {
|
||||||
return d.db.Create(&model).Error
|
return d.db.Create(&model).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +86,7 @@ func chackPing(b chan bool, url string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//更新列表
|
//更新列表
|
||||||
func UpdataDDNSList(db *gorm.DB) {
|
func UpdateDDNSList(db *gorm.DB) {
|
||||||
var s []model.DDNSCoreList
|
var s []model.DDNSCoreList
|
||||||
db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns_type.api_host as api_host,o_ddns.id,`host`,domain,user_name,`password`,`key`,secret,type").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s)
|
db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns_type.api_host as api_host,o_ddns.id,`host`,domain,user_name,`password`,`key`,secret,type").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s)
|
||||||
for _, item := range s {
|
for _, item := range s {
|
||||||
|
|||||||
@@ -31,4 +31,3 @@ func SetOauth(request *http.Request, value string) {
|
|||||||
func SetXFilter(request *http.Request, value string) {
|
func SetXFilter(request *http.Request, value string) {
|
||||||
request.Header.Set("X-Filter", value)
|
request.Header.Set("X-Filter", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
186
service/disk.go
186
service/disk.go
@@ -3,28 +3,73 @@ package service
|
|||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"strconv"
|
"gorm.io/gorm"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DiskService interface {
|
type DiskService interface {
|
||||||
GetPlugInDisk() []string
|
GetPlugInDisk() []string
|
||||||
LSBLK() []model.LSBLKModel
|
LSBLK(isUseCache bool) []model.LSBLKModel
|
||||||
FormatDisk(path, format string) string
|
SmartCTL(path string) model.SmartctlA
|
||||||
UmountPointAndRemoveDir(path string) string
|
FormatDisk(path, format string) []string
|
||||||
|
UmountPointAndRemoveDir(path string) []string
|
||||||
GetDiskInfo(path string) model.LSBLKModel
|
GetDiskInfo(path string) model.LSBLKModel
|
||||||
DelPartition(path, num string) string
|
DelPartition(path, num string) string
|
||||||
AddPartition(path, num string, size uint64) string
|
AddPartition(path string) string
|
||||||
GetDiskInfoByPath(path string) *disk.UsageStat
|
GetDiskInfoByPath(path string) *disk.UsageStat
|
||||||
|
MountDisk(path, volume string)
|
||||||
|
GetSerialAll() []model2.SerialDisk
|
||||||
|
SaveMountPoint(m model2.SerialDisk)
|
||||||
|
DeleteMountPoint(path, mountPoint string)
|
||||||
|
DeleteMount(id string)
|
||||||
|
UpdateMountPoint(m model2.SerialDisk)
|
||||||
|
RemoveLSBLKCache()
|
||||||
}
|
}
|
||||||
type diskService struct {
|
type diskService struct {
|
||||||
log loger2.OLog
|
log loger2.OLog
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *diskService) RemoveLSBLKCache() {
|
||||||
|
key := "system_lsblk"
|
||||||
|
Cache.Delete(key)
|
||||||
|
}
|
||||||
|
func (d *diskService) SmartCTL(path string) model.SmartctlA {
|
||||||
|
|
||||||
|
key := "system_smart_" + path
|
||||||
|
if result, ok := Cache.Get(key); ok {
|
||||||
|
|
||||||
|
res, ok := result.(model.SmartctlA)
|
||||||
|
if ok {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var m model.SmartctlA
|
||||||
|
str := command2.ExecSmartCTLByPath(path)
|
||||||
|
if str == nil {
|
||||||
|
d.log.Error("smartctl exec error,smartctl")
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json2.Unmarshal([]byte(str), &m)
|
||||||
|
if err != nil {
|
||||||
|
d.log.Error("json ummarshal error", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(m, model.SmartctlA{}) {
|
||||||
|
Cache.Add(key, m, time.Second*10)
|
||||||
|
}
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
//通过脚本获取外挂磁盘
|
//通过脚本获取外挂磁盘
|
||||||
@@ -33,18 +78,15 @@ func (d *diskService) GetPlugInDisk() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//格式化硬盘
|
//格式化硬盘
|
||||||
func (d *diskService) FormatDisk(path, format string) string {
|
func (d *diskService) FormatDisk(path, format string) []string {
|
||||||
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;FormatDisk " + path + " " + format)
|
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;FormatDisk " + path + " " + format)
|
||||||
fmt.Println(r)
|
return r
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//移除挂载点,删除目录
|
//移除挂载点,删除目录
|
||||||
func (d *diskService) UmountPointAndRemoveDir(path string) string {
|
func (d *diskService) UmountPointAndRemoveDir(path string) []string {
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;UMountPorintAndRemoveDir " + path)
|
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;UMountPorintAndRemoveDir " + path)
|
||||||
fmt.Println(r)
|
return r
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除分区
|
//删除分区
|
||||||
@@ -54,46 +96,44 @@ func (d *diskService) DelPartition(path, num string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
//添加分区
|
//part
|
||||||
func (d *diskService) AddPartition(path, num string, size uint64) string {
|
func (d *diskService) AddPartition(path string) string {
|
||||||
|
command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
|
||||||
var maxSector uint64 = 0
|
|
||||||
|
|
||||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + path)
|
|
||||||
if len(chiList) == 0 {
|
|
||||||
d.log.Error("chiList length error")
|
|
||||||
}
|
|
||||||
for i := 0; i < len(chiList); i++ {
|
|
||||||
tempArr := strings.Split(chiList[i], ",")
|
|
||||||
tempSector, _ := strconv.ParseUint(tempArr[2], 10, 64)
|
|
||||||
if tempSector > maxSector {
|
|
||||||
maxSector = tempSector
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r := command2.ExecResultStrArray("source ./shell/helper.sh ;AddPartition " + path + " " + num + " " + strconv.FormatUint(maxSector+1, 10) + " " + strconv.FormatUint(size+maxSector+1, 10))
|
|
||||||
fmt.Println(r)
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *diskService) AddAllPartition(path string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//获取硬盘详情
|
//获取硬盘详情
|
||||||
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
||||||
diskInfo, err := disk.Usage(path + "1")
|
diskInfo, err := disk.Usage(path + "1")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
fmt.Println(path)
|
|
||||||
fmt.Println(diskInfo)
|
|
||||||
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
||||||
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
||||||
return diskInfo
|
return diskInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取磁盘信息
|
//get disk details
|
||||||
func (d *diskService) LSBLK() []model.LSBLKModel {
|
func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
|
||||||
|
key := "system_lsblk"
|
||||||
|
var n []model.LSBLKModel
|
||||||
|
|
||||||
|
if result, ok := Cache.Get(key); ok && isUseCache {
|
||||||
|
|
||||||
|
res, ok := result.([]model.LSBLKModel)
|
||||||
|
if ok {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
str := command2.ExecLSBLK()
|
str := command2.ExecLSBLK()
|
||||||
if str == nil {
|
if str == nil {
|
||||||
d.log.Error("lsblk exec error")
|
d.log.Error("lsblk exec error,lsblk")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var m []model.LSBLKModel
|
var m []model.LSBLKModel
|
||||||
@@ -102,15 +142,13 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
|||||||
d.log.Error("json ummarshal error", err)
|
d.log.Error("json ummarshal error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var n []model.LSBLKModel
|
|
||||||
|
|
||||||
var c []model.LSBLKModel
|
var c []model.LSBLKModel
|
||||||
|
|
||||||
var fsused uint64
|
var fsused uint64
|
||||||
|
|
||||||
var health = true
|
var health = true
|
||||||
for _, i := range m {
|
for _, i := range m {
|
||||||
if i.Children != nil {
|
if i.Type != "loop" && !i.RO {
|
||||||
fsused = 0
|
fsused = 0
|
||||||
for _, child := range i.Children {
|
for _, child := range i.Children {
|
||||||
if child.RM {
|
if child.RM {
|
||||||
@@ -133,7 +171,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
|||||||
i.Children = c
|
i.Children = c
|
||||||
if fsused > 0 {
|
if fsused > 0 {
|
||||||
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
||||||
fmt.Println(err)
|
d.log.Fatal("diskservice_lsblk_fsused", err)
|
||||||
}
|
}
|
||||||
n = append(n, i)
|
n = append(n, i)
|
||||||
health = true
|
health = true
|
||||||
@@ -141,15 +179,19 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
|
|||||||
fsused = 0
|
fsused = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(n) > 0 {
|
||||||
|
Cache.Add(key, n, time.Second*100)
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
||||||
str := command2.ExecLSBLKByPath(path)
|
str := command2.ExecLSBLKByPath(path)
|
||||||
if str == nil {
|
if str == nil {
|
||||||
d.log.Error("lsblk exec error")
|
d.log.Error("lsblk exec error,str")
|
||||||
return model.LSBLKModel{}
|
return model.LSBLKModel{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ml []model.LSBLKModel
|
var ml []model.LSBLKModel
|
||||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -157,9 +199,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
d.log.Error("json ummarshal error", err)
|
d.log.Error("json ummarshal error", err)
|
||||||
return model.LSBLKModel{}
|
return model.LSBLKModel{}
|
||||||
}
|
}
|
||||||
//todo 需要判断长度
|
|
||||||
m := ml[0]
|
m := model.LSBLKModel{}
|
||||||
//声明数组
|
if len(ml) > 0 {
|
||||||
|
m = ml[0]
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
// 下面为计算是否可以继续分区的部分,暂时不需要
|
||||||
chiArr := make(map[string]string)
|
chiArr := make(map[string]string)
|
||||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path)
|
||||||
if len(chiList) == 0 {
|
if len(chiList) == 0 {
|
||||||
@@ -170,7 +216,6 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
tempArr := strings.Split(chiList[i], ",")
|
tempArr := strings.Split(chiList[i], ",")
|
||||||
chiArr[tempArr[0]] = chiList[i]
|
chiArr[tempArr[0]] = chiList[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxSector uint64 = 0
|
var maxSector uint64 = 0
|
||||||
for i := 0; i < len(m.Children); i++ {
|
for i := 0; i < len(m.Children); i++ {
|
||||||
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
||||||
@@ -179,13 +224,13 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
if m.Children[i].EndSector > maxSector {
|
if m.Children[i].EndSector > maxSector {
|
||||||
maxSector = m.Children[i].EndSector
|
maxSector = m.Children[i].EndSector
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
||||||
|
|
||||||
if len(diskEndSector) < 2 {
|
if len(diskEndSector) < 2 {
|
||||||
d.log.Error("diskEndSector length error")
|
d.log.Error("diskEndSector length error")
|
||||||
}
|
}
|
||||||
|
|
||||||
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
||||||
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
||||||
//添加可以分区情况
|
//添加可以分区情况
|
||||||
@@ -196,17 +241,38 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
//func GetDiskInfo(path string) *disk.UsageStat {
|
func (d *diskService) MountDisk(path, volume string) {
|
||||||
// diskInfo, _ := disk.Usage(path)
|
r := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_mount " + path + " " + volume)
|
||||||
// diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
fmt.Print(r)
|
||||||
// diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
}
|
||||||
// return diskInfo
|
|
||||||
//}
|
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
|
||||||
|
d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
|
||||||
//func (d *diskService) GetPlugInDisk() []string {
|
d.db.Create(&m)
|
||||||
// return disk.Partitions(false)
|
}
|
||||||
//}
|
|
||||||
|
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
|
||||||
func NewDiskService(log loger2.OLog) DiskService {
|
d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint)
|
||||||
return &diskService{log: log}
|
}
|
||||||
|
|
||||||
|
func (d *diskService) DeleteMount(id string) {
|
||||||
|
|
||||||
|
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *diskService) DeleteMountPoint(path, mountPoint string) {
|
||||||
|
|
||||||
|
d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
|
||||||
|
|
||||||
|
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *diskService) GetSerialAll() []model2.SerialDisk {
|
||||||
|
var m []model2.SerialDisk
|
||||||
|
d.db.Find(&m)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDiskService(log loger2.OLog, db *gorm.DB) DiskService {
|
||||||
|
return &diskService{log: log, db: db}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,27 +7,24 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
types2 "github.com/IceWhaleTech/CasaOS/types"
|
types2 "github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/cio"
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
"github.com/IceWhaleTech/CasaOS/pkg/docker"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
|
||||||
//"github.com/containerd/containerd/oci"
|
//"github.com/containerd/containerd/oci"
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/docker/docker/api/types/container"
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
|
||||||
"github.com/docker/docker/api/types/mount"
|
|
||||||
"github.com/docker/docker/api/types/network"
|
|
||||||
client2 "github.com/docker/docker/client"
|
|
||||||
"github.com/docker/go-connections/nat"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
@@ -35,6 +32,14 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/api/types/mount"
|
||||||
|
"github.com/docker/docker/api/types/network"
|
||||||
|
client2 "github.com/docker/docker/client"
|
||||||
|
"github.com/docker/go-connections/nat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DockerService interface {
|
type DockerService interface {
|
||||||
@@ -47,7 +52,7 @@ type DockerService interface {
|
|||||||
DockerListByImage(image, version string) (*types.Container, error)
|
DockerListByImage(image, version string) (*types.Container, error)
|
||||||
DockerContainerInfo(name string) (*types.ContainerJSON, error)
|
DockerContainerInfo(name string) (*types.ContainerJSON, error)
|
||||||
DockerImageRemove(name string) error
|
DockerImageRemove(name string) error
|
||||||
DockerContainerRemove(name string) error
|
DockerContainerRemove(name string, update bool) error
|
||||||
DockerContainerStop(id string) error
|
DockerContainerStop(id string) error
|
||||||
DockerContainerUpdateName(name, id string) (err error)
|
DockerContainerUpdateName(name, id string) (err error)
|
||||||
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
||||||
@@ -55,6 +60,8 @@ type DockerService interface {
|
|||||||
DockerContainerCommit(name string)
|
DockerContainerCommit(name string)
|
||||||
DockerNetworkModelList() []types.NetworkResource
|
DockerNetworkModelList() []types.NetworkResource
|
||||||
DockerImageInfo(image string)
|
DockerImageInfo(image string)
|
||||||
|
GetNetWorkNameByNetWorkID(id string) (string, error)
|
||||||
|
ContainerExecShell(container_id string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerService struct {
|
type dockerService struct {
|
||||||
@@ -62,15 +69,20 @@ type dockerService struct {
|
|||||||
log loger2.OLog
|
log loger2.OLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func DockerPs() {
|
func (ds *dockerService) ContainerExecShell(container_id string) string {
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
|
exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
|
||||||
|
User: "1000:1000",
|
||||||
|
Cmd: []string{"echo -e \"hellow\nworld\" >> /a.txt"},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(5)
|
os.Exit(5)
|
||||||
}
|
}
|
||||||
for _, container := range containers {
|
err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
|
||||||
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
|
if err != nil {
|
||||||
|
fmt.Println("exec script error ", err)
|
||||||
}
|
}
|
||||||
|
return exec.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
//创建默认网络
|
//创建默认网络
|
||||||
@@ -79,6 +91,7 @@ func DockerNetwork() {
|
|||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
d, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
d, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
||||||
|
|
||||||
for _, resource := range d {
|
for _, resource := range d {
|
||||||
if resource.Name == docker.NETWORKNAME {
|
if resource.Name == docker.NETWORKNAME {
|
||||||
return
|
return
|
||||||
@@ -87,6 +100,19 @@ func DockerNetwork() {
|
|||||||
cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
|
cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//根据网络id获取网络名
|
||||||
|
func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
|
||||||
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
defer cli.Close()
|
||||||
|
filter := filters.NewArgs()
|
||||||
|
filter.Add("id", id)
|
||||||
|
d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{Filters: filter})
|
||||||
|
if err == nil && len(d) > 0 {
|
||||||
|
return d[0].Name, nil
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
//拉取镜像
|
//拉取镜像
|
||||||
func DockerPull() {
|
func DockerPull() {
|
||||||
|
|
||||||
@@ -131,7 +157,7 @@ func DockerEx() {
|
|||||||
importResponse.Close()
|
importResponse.Close()
|
||||||
println(string(response))
|
println(string(response))
|
||||||
if string(response) != "response" {
|
if string(response) != "response" {
|
||||||
fmt.Println("expected response to contain 'response', got %s", string(response))
|
fmt.Printf("expected response to contain 'response', got %s", string(response))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +186,6 @@ func (ds *dockerService) DockerImageInfo(image string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Print(err)
|
fmt.Print(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MsqlExec(container string) error {
|
func MsqlExec(container string) error {
|
||||||
@@ -239,6 +264,8 @@ func DockerLogs() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer i.Close()
|
||||||
|
|
||||||
hdr := make([]byte, 8)
|
hdr := make([]byte, 8)
|
||||||
for {
|
for {
|
||||||
_, err := i.Read(hdr)
|
_, err := i.Read(hdr)
|
||||||
@@ -257,7 +284,6 @@ func DockerLogs() {
|
|||||||
_, err = i.Read(dat)
|
_, err = i.Read(dat)
|
||||||
fmt.Fprint(w, string(dat))
|
fmt.Fprint(w, string(dat))
|
||||||
}
|
}
|
||||||
defer i.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//正式内容
|
//正式内容
|
||||||
@@ -306,11 +332,13 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
if !reflect.DeepEqual(m, model2.AppNotify{}) {
|
||||||
m.State = 0
|
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
|
||||||
m.Speed = 70
|
m.State = 0
|
||||||
m.Message = string(buf[:n])
|
m.Message = string(buf[:n])
|
||||||
MyService.Notify().UpdateLog(m)
|
MyService.Notify().UpdateLog(m)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -323,7 +351,7 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
|
|||||||
//param udp 容器其他udp端口
|
//param udp 容器其他udp端口
|
||||||
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
|
func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId string, m model.CustomizationPostData, net string) (containerId string, err error) {
|
||||||
if len(net) == 0 {
|
if len(net) == 0 {
|
||||||
net = "oasis"
|
net = "bridge"
|
||||||
}
|
}
|
||||||
|
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -337,9 +365,13 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
// if net != "host" {
|
// if net != "host" {
|
||||||
// portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
|
// portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
|
||||||
// }
|
// }
|
||||||
|
//port := ""
|
||||||
for _, portMap := range m.Ports {
|
for _, portMap := range m.Ports {
|
||||||
|
// if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
|
||||||
|
// port = portMap.ContainerPort
|
||||||
|
// }
|
||||||
if portMap.Protocol == "tcp" {
|
if portMap.Protocol == "tcp" {
|
||||||
|
|
||||||
tContainer, _ := strconv.Atoi(portMap.ContainerPort)
|
tContainer, _ := strconv.Atoi(portMap.ContainerPort)
|
||||||
if tContainer > 0 {
|
if tContainer > 0 {
|
||||||
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
|
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
|
||||||
@@ -379,6 +411,10 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
|
|
||||||
var envArr []string
|
var envArr []string
|
||||||
for _, e := range m.Envs {
|
for _, e := range m.Envs {
|
||||||
|
if strings.HasPrefix(e.Value, "$") {
|
||||||
|
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
|
||||||
|
continue
|
||||||
|
}
|
||||||
if len(e.Value) > 0 {
|
if len(e.Value) > 0 {
|
||||||
if e.Value == "port_map" {
|
if e.Value == "port_map" {
|
||||||
envArr = append(envArr, e.Name+"="+m.PortMap)
|
envArr = append(envArr, e.Name+"="+m.PortMap)
|
||||||
@@ -400,22 +436,34 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
|
res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hostConfingBind := []string{}
|
||||||
// volumes bind
|
// volumes bind
|
||||||
volumes := []mount.Mount{}
|
volumes := []mount.Mount{}
|
||||||
for _, v := range m.Volumes {
|
for _, v := range m.Volumes {
|
||||||
path := v.Path
|
path := v.Path
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
path = docker.GetDir(containerDbId, v.ContainerPath)
|
path = docker.GetDir(containerDbId, v.Path)
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
path = strings.ReplaceAll(path, "$AppID", containerDbId)
|
||||||
|
//reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
|
||||||
|
//result1 := reg1.FindAllStringSubmatch(path, -1)
|
||||||
|
//if len(result1) == 0 {
|
||||||
err = file.IsNotExistMkDir(path)
|
err = file.IsNotExistMkDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ds.log.Error("mkdir error", err)
|
ds.log.Error("mkdir error", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
// else {
|
||||||
|
// err = file.IsNotExistCreateFile(path)
|
||||||
|
// if err != nil {
|
||||||
|
// ds.log.Error("mkdir error", err)
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
volumes = append(volumes, mount.Mount{
|
volumes = append(volumes, mount.Mount{
|
||||||
Type: mount.TypeBind,
|
Type: mount.TypeBind,
|
||||||
@@ -423,6 +471,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
Target: v.ContainerPath,
|
Target: v.ContainerPath,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
hostConfingBind = append(hostConfingBind, v.Path+":"+v.ContainerPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
rp := container.RestartPolicy{}
|
rp := container.RestartPolicy{}
|
||||||
@@ -430,11 +479,22 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
if len(m.Restart) > 0 {
|
if len(m.Restart) > 0 {
|
||||||
rp.Name = m.Restart
|
rp.Name = m.Restart
|
||||||
}
|
}
|
||||||
|
// healthTest := []string{}
|
||||||
|
// if len(port) > 0 {
|
||||||
|
// healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
|
||||||
|
// }
|
||||||
|
|
||||||
|
// health := &container.HealthConfig{
|
||||||
|
// Test: healthTest,
|
||||||
|
// StartPeriod: 0,
|
||||||
|
// Retries: 1000,
|
||||||
|
// }
|
||||||
|
// fmt.Print(health)
|
||||||
config := &container.Config{
|
config := &container.Config{
|
||||||
Image: imageName,
|
Image: imageName,
|
||||||
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
|
||||||
Env: envArr,
|
Env: envArr,
|
||||||
|
// Healthcheck: health,
|
||||||
}
|
}
|
||||||
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)}
|
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)}
|
||||||
//if net != "host" {
|
//if net != "host" {
|
||||||
@@ -455,7 +515,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
|
|||||||
}
|
}
|
||||||
|
|
||||||
//删除容器
|
//删除容器
|
||||||
func (ds *dockerService) DockerContainerRemove(name string) error {
|
func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -464,9 +524,11 @@ func (ds *dockerService) DockerContainerRemove(name string) error {
|
|||||||
err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
|
err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
|
||||||
|
|
||||||
//路径处理
|
//路径处理
|
||||||
path := docker.GetDir(name, "/config")
|
if !update {
|
||||||
if !file.CheckNotExist(path) {
|
path := docker.GetDir(name, "/config")
|
||||||
file.RMDir(path)
|
if !file.CheckNotExist(path) {
|
||||||
|
file.RMDir(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -727,7 +789,7 @@ func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
|
|||||||
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
|
||||||
return networks
|
return networks
|
||||||
}
|
}
|
||||||
func NewDcokerService(log loger2.OLog) DockerService {
|
func NewDockerService(log loger2.OLog) DockerService {
|
||||||
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
|
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -771,7 +833,6 @@ func Containerd() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("333")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
||||||
@@ -779,7 +840,6 @@ func Containerd() {
|
|||||||
// create a task from the container
|
// create a task from the container
|
||||||
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("444")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
defer task.Delete(ctx)
|
defer task.Delete(ctx)
|
||||||
@@ -792,7 +852,6 @@ func Containerd() {
|
|||||||
|
|
||||||
// call start on the task to execute the redis server
|
// call start on the task to execute the redis server
|
||||||
if err = task.Start(ctx); err != nil {
|
if err = task.Start(ctx); err != nil {
|
||||||
fmt.Println("555")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,7 +861,6 @@ func Containerd() {
|
|||||||
|
|
||||||
// kill the process and get the exit status
|
// kill the process and get the exit status
|
||||||
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
||||||
fmt.Println("666")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,7 +869,6 @@ func Containerd() {
|
|||||||
status := <-exitStatusC
|
status := <-exitStatusC
|
||||||
code, _, err := status.Result()
|
code, _, err := status.Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("777")
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
fmt.Printf("redis-server exited with status: %d\n", code)
|
fmt.Printf("redis-server exited with status: %d\n", code)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package docker_base
|
|||||||
import "github.com/IceWhaleTech/CasaOS/model"
|
import "github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
|
||||||
//过滤mysql关键字
|
//过滤mysql关键字
|
||||||
func MysqlFilter(c MysqlConfig, envs model.EnvArrey) model.EnvArrey {
|
func MysqlFilter(c MysqlConfig, envs model.EnvArray) model.EnvArray {
|
||||||
for i := 0; i < len(envs); i++ {
|
for i := 0; i < len(envs); i++ {
|
||||||
switch envs[i].Value {
|
switch envs[i].Value {
|
||||||
case "$MYSQL_HOST":
|
case "$MYSQL_HOST":
|
||||||
|
|||||||
@@ -7,5 +7,3 @@ type MysqlConfig struct {
|
|||||||
DataBasePassword string `json:"data_base_password"`
|
DataBasePassword string `json:"data_base_password"`
|
||||||
DataBaseDB string `json:"data_base_db"`
|
DataBaseDB string `json:"data_base_db"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
85
service/file.go
Normal file
85
service/file.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// type InteruptReader struct {
|
||||||
|
// r io.Reader
|
||||||
|
// interupt chan int
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func NewInteruptReader(r io.Reader) InteruptReader {
|
||||||
|
// return InteruptReader{
|
||||||
|
// r,
|
||||||
|
// make(chan int),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (r InteruptReader) Read(p []byte) (n int, err error) {
|
||||||
|
// if r.r == nil {
|
||||||
|
// return 0, io.EOF
|
||||||
|
// }
|
||||||
|
// select {
|
||||||
|
// case <-r.interupt:
|
||||||
|
// return r.r.Read(p)
|
||||||
|
// default:
|
||||||
|
// r.r = nil
|
||||||
|
// return 0, io.EOF
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (r InteruptReader) Cancel() {
|
||||||
|
// r.interupt <- 0
|
||||||
|
// }
|
||||||
|
|
||||||
|
type reader struct {
|
||||||
|
ctx context.Context
|
||||||
|
r io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReader wraps an io.Reader to handle context cancellation.
|
||||||
|
//
|
||||||
|
// Context state is checked BEFORE every Read.
|
||||||
|
func NewReader(ctx context.Context, r io.Reader) io.Reader {
|
||||||
|
if r, ok := r.(*reader); ok && ctx == r.ctx {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return &reader{ctx: ctx, r: r}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) Read(p []byte) (n int, err error) {
|
||||||
|
select {
|
||||||
|
case <-r.ctx.Done():
|
||||||
|
return 0, r.ctx.Err()
|
||||||
|
default:
|
||||||
|
return r.r.Read(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type writer struct {
|
||||||
|
ctx context.Context
|
||||||
|
w io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
type copier struct {
|
||||||
|
writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriter(ctx context.Context, w io.Writer) io.Writer {
|
||||||
|
if w, ok := w.(*copier); ok && ctx == w.ctx {
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
return &copier{writer{ctx: ctx, w: w}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write implements io.Writer, but with context awareness.
|
||||||
|
func (w *writer) Write(p []byte) (n int, err error) {
|
||||||
|
select {
|
||||||
|
case <-w.ctx.Done():
|
||||||
|
return 0, w.ctx.Err()
|
||||||
|
default:
|
||||||
|
return w.w.Write(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
81
service/file_test.go
Normal file
81
service/file_test.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ctx context.Context
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
|
||||||
|
func TestNewInteruptReader(t *testing.T) {
|
||||||
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
// 在初始上下文的基础上创建一个有取消功能的上下文
|
||||||
|
// ctx, cancel := context.WithCancel(ctx)
|
||||||
|
fmt.Println("开始")
|
||||||
|
fIn, err := os.Open("/Users/liangjianli/Downloads/demo_data.tar.gz")
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
}
|
||||||
|
defer fIn.Close()
|
||||||
|
fmt.Println("创建新文件")
|
||||||
|
fOut, err := os.Create("/Users/liangjianli/Downloads/demo_data1.tar.gz")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer fOut.Close()
|
||||||
|
|
||||||
|
fmt.Println("准备复制")
|
||||||
|
// _, err = io.Copy(out, NewReader(ctx, f))
|
||||||
|
// time.Sleep(time.Second * 2)
|
||||||
|
//ctx.Done()
|
||||||
|
// cancel()
|
||||||
|
|
||||||
|
// interrupt context after 500ms
|
||||||
|
|
||||||
|
// interrupt context with SIGTERM (CTRL+C)
|
||||||
|
//sigs := make(chan os.Signal, 1)
|
||||||
|
//signal.Notify(sigs, os.Interrupt)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader that fails when context is canceled
|
||||||
|
in := NewReader(ctx, fIn)
|
||||||
|
// Writer that fails when context is canceled
|
||||||
|
out := NewWriter(ctx, fOut)
|
||||||
|
|
||||||
|
//time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
//cancel()
|
||||||
|
|
||||||
|
n, err := io.Copy(out, in)
|
||||||
|
log.Println(n, "bytes copied.")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Err:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Closing.")
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
//<-sigs
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
fmt.Println("退出")
|
||||||
|
ddd()
|
||||||
|
}()
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ddd() {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
@@ -26,14 +26,10 @@ type AppListDBModel struct {
|
|||||||
PortMap string `json:"port_map"`
|
PortMap string `json:"port_map"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
EnableUPNP bool `json:"enable_upnp"`
|
EnableUPNP bool `json:"enable_upnp"`
|
||||||
//Envs model.EnvArrey `json:"envs" bson:"envs"`
|
Envs string `json:"envs"`
|
||||||
//Ports model.PortArrey `json:"ports" bson:"ports"`
|
Ports string `json:"ports"`
|
||||||
//Volumes model.PathArrey `json:"volumes" bson:"volumes"`
|
Volumes string `json:"volumes"`
|
||||||
//Devices model.PathArrey `json:"devices" bson:"devices"`
|
Devices string `json:"devices"`
|
||||||
Envs string `json:"envs"`
|
|
||||||
Ports string `json:"ports"`
|
|
||||||
Volumes string `json:"volumes"`
|
|
||||||
Devices string `json:"devices"`
|
|
||||||
//Envs []model.Env `json:"envs"`
|
//Envs []model.Env `json:"envs"`
|
||||||
//Ports []model.PortMap `gorm:"type:json" json:"ports"`
|
//Ports []model.PortMap `gorm:"type:json" json:"ports"`
|
||||||
//Volumes []model.PathMap `gorm:"type:json" json:"volumes"`
|
//Volumes []model.PathMap `gorm:"type:json" json:"volumes"`
|
||||||
@@ -61,4 +57,6 @@ type MyAppList struct {
|
|||||||
UpTime string `json:"up_time"`
|
UpTime string `json:"up_time"`
|
||||||
Slogan string `json:"slogan"`
|
Slogan string `json:"slogan"`
|
||||||
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
|
||||||
|
Image string `json:"image"`
|
||||||
|
Volumes string `json:"volumes"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package model
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
func (p *DDNSUpdataDBModel) TableName() string {
|
func (p *DDNSUpdateDBModel) TableName() string {
|
||||||
return "o_ddns"
|
return "o_ddns"
|
||||||
}
|
}
|
||||||
|
|
||||||
type DDNSUpdataDBModel struct {
|
type DDNSUpdateDBModel struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
Ipv4 string `gorm:"-"`
|
Ipv4 string `gorm:"-"`
|
||||||
Ipv6 string `gorm:"-"`
|
Ipv6 string `gorm:"-"`
|
||||||
@@ -17,8 +17,8 @@ type DDNSUpdataDBModel struct {
|
|||||||
Secret string `json:"secret" form:"secret"`
|
Secret string `json:"secret" form:"secret"`
|
||||||
UserName string `json:"user_name" form:"user_name"`
|
UserName string `json:"user_name" form:"user_name"`
|
||||||
Password string `json:"password" form:"password"`
|
Password string `json:"password" form:"password"`
|
||||||
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
|
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const DDNSLISTTABLENAME = "o_ddns"
|
const DDNSLISTTABLENAME = "o_ddns"
|
||||||
@@ -39,9 +39,9 @@ type DDNSList struct {
|
|||||||
|
|
||||||
//定时任务使用
|
//定时任务使用
|
||||||
type DDNSCoreList struct {
|
type DDNSCoreList struct {
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
Domain string `json:"domain" form:"domain"`
|
Domain string `json:"domain" form:"domain"`
|
||||||
Name string `json:"domain" form:"name"`
|
Name string `json:"name" form:"name"`
|
||||||
Type uint `json:"type"`
|
Type uint `json:"type"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
|
|||||||
15
service/model/o_disk.go
Normal file
15
service/model/o_disk.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
//SerialAdvanced Technology Attachment (STAT)
|
||||||
|
type SerialDisk struct {
|
||||||
|
Id uint `gorm:"column:id;primary_key" json:"id"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
State int `json:"state"`
|
||||||
|
MountPoint string `json:"mount_point"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SerialDisk) TableName() string {
|
||||||
|
return "o_disk"
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
type AppNotify struct {
|
type AppNotify struct {
|
||||||
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
State int `json:"state"` //0:一直在变动的未读消息 1:未读 2:已读
|
||||||
ContainerId string `json:"container_id,omitempty"`
|
Message string `json:"message"`
|
||||||
State int `json:"state"` //0:一直在变动的未读消息 1:未读 2:已读
|
CreatedAt string `json:"created_at"`
|
||||||
Message string `json:"message"`
|
UpdatedAt string `json:"updated_at"`
|
||||||
CreatedAt string `gorm:"<-:create;autoCreateTime" json:"created_at"`
|
Id string `json:"id"`
|
||||||
UpdatedAt string `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at"`
|
Type int `json:"type"` // 1:显示即为已读 2:info 3:warning 4:error 5:success
|
||||||
Speed int `json:"speed"`
|
Icon string `json:"icon"`
|
||||||
Id string `gorm:"-" json:"id"`
|
Name string `json:"name"`
|
||||||
Type int `json:"type"` // 1:显示即为已读 2:必须手动点掉 3:error
|
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AppNotify) TableName() string {
|
func (p *AppNotify) TableName() string {
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
json2 "encoding/json"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type OasisService interface {
|
|
||||||
GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64)
|
|
||||||
GetServerCategoryList() []model.ServerCategoryList
|
|
||||||
GetTaskList(size int) []model2.TaskDBModel
|
|
||||||
}
|
|
||||||
|
|
||||||
type oasisService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *oasisService) GetTaskList(size int) []model2.TaskDBModel {
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
t := make(chan string)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
|
||||||
|
|
||||||
t <- gjson.Get(str, "data").String()
|
|
||||||
}()
|
|
||||||
head["Authorization"] = <-t
|
|
||||||
|
|
||||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/task/list/"+strconv.Itoa(size), head)
|
|
||||||
|
|
||||||
list := []model2.TaskDBModel{}
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *oasisService) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) {
|
|
||||||
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
t := make(chan string)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
|
||||||
|
|
||||||
t <- gjson.Get(str, "data").String()
|
|
||||||
}()
|
|
||||||
head["Authorization"] = <-t
|
|
||||||
|
|
||||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/list?index="+index+"&size="+size+"&type="+tp+"&category_id="+categoryId+"&key="+key, head)
|
|
||||||
|
|
||||||
list := []model.ServerAppList{}
|
|
||||||
|
|
||||||
count := gjson.Get(listS, "data.count").Int()
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.items").String()), &list)
|
|
||||||
|
|
||||||
return list, count
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *oasisService) GetServerCategoryList() []model.ServerCategoryList {
|
|
||||||
|
|
||||||
head := make(map[string]string)
|
|
||||||
|
|
||||||
t := make(chan string)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
|
|
||||||
|
|
||||||
t <- gjson.Get(str, "data").String()
|
|
||||||
}()
|
|
||||||
head["Authorization"] = <-t
|
|
||||||
|
|
||||||
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/category", head)
|
|
||||||
|
|
||||||
list := []model.ServerCategoryList{}
|
|
||||||
|
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewOasisService() OasisService {
|
|
||||||
return &oasisService{}
|
|
||||||
}
|
|
||||||
57
service/search.go
Normal file
57
service/search.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SearchService interface {
|
||||||
|
SearchList(key string) ([]model.SearchFileInfo, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type searchService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *searchService) SearchList(key string) ([]model.SearchFileInfo, error) {
|
||||||
|
pathName := "/Users/liangjianli/go/CasaOSNew/searchTest"
|
||||||
|
resArr := []model.SearchFileInfo{}
|
||||||
|
files, _ := ioutil.ReadDir(pathName)
|
||||||
|
for _, file := range files {
|
||||||
|
if file.IsDir() {
|
||||||
|
tempArr, err := s.SearchList(pathName + "/" + file.Name())
|
||||||
|
if err != nil {
|
||||||
|
resArr = append(resArr, tempArr...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if strings.Contains(file.Name(), key) {
|
||||||
|
resArr = append(resArr, model.SearchFileInfo{Path: pathName, Name: file.Name(), Type: GetSearchType(path.Ext(file.Name()))})
|
||||||
|
}
|
||||||
|
fmt.Println(pathName + "/" + file.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resArr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSearchType(ext string) int {
|
||||||
|
var reType int = types.UNKNOWN
|
||||||
|
switch ext {
|
||||||
|
case ".png":
|
||||||
|
reType = types.PICTURE
|
||||||
|
case ".mp4":
|
||||||
|
reType = types.MEDIA
|
||||||
|
case ".mp3":
|
||||||
|
reType = types.MUSIC
|
||||||
|
default:
|
||||||
|
reType = types.UNKNOWN
|
||||||
|
}
|
||||||
|
return reType
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSearchService() SearchService {
|
||||||
|
return &searchService{}
|
||||||
|
}
|
||||||
@@ -2,9 +2,12 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var Cache *cache.Cache
|
||||||
|
|
||||||
var MyService Repository
|
var MyService Repository
|
||||||
|
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
@@ -15,7 +18,7 @@ type Repository interface {
|
|||||||
//Redis() RedisService
|
//Redis() RedisService
|
||||||
ZeroTier() ZeroTierService
|
ZeroTier() ZeroTierService
|
||||||
ZiMa() ZiMaService
|
ZiMa() ZiMaService
|
||||||
OAPI() OasisService
|
OAPI() CasaService
|
||||||
Disk() DiskService
|
Disk() DiskService
|
||||||
Notify() NotifyServer
|
Notify() NotifyServer
|
||||||
ShareDirectory() ShareDirService
|
ShareDirectory() ShareDirService
|
||||||
@@ -23,25 +26,28 @@ type Repository interface {
|
|||||||
Rely() RelyService
|
Rely() RelyService
|
||||||
System() SystemService
|
System() SystemService
|
||||||
Shortcuts() ShortcutsService
|
Shortcuts() ShortcutsService
|
||||||
|
Search() SearchService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
func NewService(db *gorm.DB, log loger2.OLog) Repository {
|
||||||
|
|
||||||
return &store{
|
return &store{
|
||||||
app: NewAppService(db, log),
|
app: NewAppService(db, log),
|
||||||
ddns: NewDDNSService(db, log),
|
ddns: NewDDNSService(db, log),
|
||||||
user: NewUserService(),
|
user: NewUserService(),
|
||||||
docker: NewDcokerService(log),
|
docker: NewDockerService(log),
|
||||||
//redis: NewRedisService(rp),
|
//redis: NewRedisService(rp),
|
||||||
zerotier: NewZeroTierService(),
|
zerotier: NewZeroTierService(),
|
||||||
zima: NewZiMaService(),
|
zima: NewZiMaService(),
|
||||||
oapi: NewOasisService(),
|
oapi: NewOasisService(),
|
||||||
disk: NewDiskService(log),
|
disk: NewDiskService(log, db),
|
||||||
notify: NewNotifyService(db),
|
notify: NewNotifyService(db),
|
||||||
shareDirectory: NewShareDirService(db, log),
|
shareDirectory: NewShareDirService(db, log),
|
||||||
task: NewTaskService(db, log),
|
task: NewTaskService(db, log),
|
||||||
rely: NewRelyService(db, log),
|
rely: NewRelyService(db, log),
|
||||||
system: NewSystemService(log),
|
system: NewSystemService(log),
|
||||||
shortcuts: NewShortcutsService(db),
|
shortcuts: NewShortcutsService(db),
|
||||||
|
search: NewSearchService(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +59,7 @@ type store struct {
|
|||||||
docker DockerService
|
docker DockerService
|
||||||
zerotier ZeroTierService
|
zerotier ZeroTierService
|
||||||
zima ZiMaService
|
zima ZiMaService
|
||||||
oapi OasisService
|
oapi CasaService
|
||||||
disk DiskService
|
disk DiskService
|
||||||
notify NotifyServer
|
notify NotifyServer
|
||||||
shareDirectory ShareDirService
|
shareDirectory ShareDirService
|
||||||
@@ -61,6 +67,7 @@ type store struct {
|
|||||||
rely RelyService
|
rely RelyService
|
||||||
system SystemService
|
system SystemService
|
||||||
shortcuts ShortcutsService
|
shortcuts ShortcutsService
|
||||||
|
search SearchService
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *store) Rely() RelyService {
|
func (c *store) Rely() RelyService {
|
||||||
@@ -99,7 +106,7 @@ func (c *store) ZeroTier() ZeroTierService {
|
|||||||
func (c *store) ZiMa() ZiMaService {
|
func (c *store) ZiMa() ZiMaService {
|
||||||
return c.zima
|
return c.zima
|
||||||
}
|
}
|
||||||
func (c *store) OAPI() OasisService {
|
func (c *store) OAPI() CasaService {
|
||||||
return c.oapi
|
return c.oapi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,3 +119,6 @@ func (c *store) ShareDirectory() ShareDirService {
|
|||||||
func (c *store) Task() TaskService {
|
func (c *store) Task() TaskService {
|
||||||
return c.task
|
return c.task
|
||||||
}
|
}
|
||||||
|
func (c *store) Search() SearchService {
|
||||||
|
return c.search
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,67 +1,76 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SystemService interface {
|
type SystemService interface {
|
||||||
UpSystemConfig(systemConfig model.SystemConfig)
|
UpSystemConfig(str string, widget string)
|
||||||
UpdateSystemVersion(version string)
|
UpdateSystemVersion(version string)
|
||||||
GetSystemConfigDebug() []string
|
GetSystemConfigDebug() []string
|
||||||
|
GetCasaOSLogs(lineNumber int) string
|
||||||
|
UpdateAssist()
|
||||||
|
UpSystemPort(port string)
|
||||||
|
GetTimeZone() string
|
||||||
}
|
}
|
||||||
type systemService struct {
|
type systemService struct {
|
||||||
log loger.OLog
|
log loger.OLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *systemService) UpdateSystemVersion(version string) {
|
func (s *systemService) UpdateSystemVersion(version string) {
|
||||||
s.log.Error(version)
|
|
||||||
//command2.OnlyExec(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
|
//command2.OnlyExec(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
|
||||||
//s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
|
//s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
|
||||||
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/tools.sh ;update " + version))
|
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/tools.sh ;update " + version))
|
||||||
//s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version))
|
//s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version))
|
||||||
}
|
}
|
||||||
|
func (s *systemService) UpdateAssist() {
|
||||||
|
s.log.Error(command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/assist.sh"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *systemService) GetTimeZone() string {
|
||||||
|
return command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetTimeZone")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *systemService) GetSystemConfigDebug() []string {
|
func (s *systemService) GetSystemConfigDebug() []string {
|
||||||
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
|
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetSysInfo")
|
||||||
}
|
}
|
||||||
func (s *systemService) UpSystemConfig(systemConfig model.SystemConfig) {
|
func (s *systemService) UpSystemConfig(str string, widget string) {
|
||||||
if systemConfig.AutoUpdate != config.SystemConfigInfo.AutoUpdate {
|
if len(str) > 0 && str != config.SystemConfigInfo.ConfigStr {
|
||||||
config.Cfg.Section("system").Key("AutoUpdate").SetValue(strconv.FormatBool(systemConfig.AutoUpdate))
|
config.Cfg.Section("system").Key("ConfigStr").SetValue(str)
|
||||||
config.SystemConfigInfo.AutoUpdate = systemConfig.AutoUpdate
|
config.SystemConfigInfo.ConfigStr = str
|
||||||
}
|
}
|
||||||
if systemConfig.SearchSwitch != config.SystemConfigInfo.SearchSwitch {
|
if len(widget) > 0 && widget != config.SystemConfigInfo.WidgetList {
|
||||||
config.Cfg.Section("system").Key("SearchSwitch").SetValue(strconv.FormatBool(systemConfig.SearchSwitch))
|
config.Cfg.Section("system").Key("WidgetList").SetValue(widget)
|
||||||
config.SystemConfigInfo.SearchSwitch = systemConfig.SearchSwitch
|
config.SystemConfigInfo.WidgetList = widget
|
||||||
}
|
}
|
||||||
if systemConfig.WidgetsSwitch != config.SystemConfigInfo.WidgetsSwitch {
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
config.Cfg.Section("system").Key("WidgetsSwitch").SetValue(strconv.FormatBool(systemConfig.WidgetsSwitch))
|
|
||||||
config.SystemConfigInfo.WidgetsSwitch = systemConfig.WidgetsSwitch
|
|
||||||
}
|
|
||||||
if systemConfig.ShortcutsSwitch != config.SystemConfigInfo.ShortcutsSwitch {
|
|
||||||
config.Cfg.Section("system").Key("ShortcutsSwitch").SetValue(strconv.FormatBool(systemConfig.ShortcutsSwitch))
|
|
||||||
config.SystemConfigInfo.ShortcutsSwitch = systemConfig.ShortcutsSwitch
|
|
||||||
}
|
|
||||||
if len(systemConfig.SearchEngine) > 0 && systemConfig.SearchEngine != config.SystemConfigInfo.SearchEngine {
|
|
||||||
config.Cfg.Section("system").Key("SearchEngine").SetValue(systemConfig.SearchEngine)
|
|
||||||
config.SystemConfigInfo.SearchEngine = systemConfig.SearchEngine
|
|
||||||
}
|
|
||||||
// if len(systemConfig.Version) > 0 && systemConfig.Version != config.SystemConfigInfo.Version {
|
|
||||||
// config.Cfg.Section("system").Key("Version").SetValue(systemConfig.Version)
|
|
||||||
// config.SystemConfigInfo.Version = systemConfig.Version
|
|
||||||
//}
|
|
||||||
if len(systemConfig.Background) > 0 && systemConfig.Background != config.SystemConfigInfo.Background {
|
|
||||||
config.Cfg.Section("system").Key("Background").SetValue(systemConfig.Background)
|
|
||||||
config.SystemConfigInfo.Background = systemConfig.Background
|
|
||||||
}
|
|
||||||
if len(systemConfig.BackgroundType) > 0 && systemConfig.BackgroundType != config.SystemConfigInfo.BackgroundType {
|
|
||||||
config.Cfg.Section("system").Key("BackgroundType").SetValue(systemConfig.BackgroundType)
|
|
||||||
config.SystemConfigInfo.BackgroundType = systemConfig.BackgroundType
|
|
||||||
}
|
|
||||||
config.Cfg.SaveTo("conf/conf.ini")
|
|
||||||
}
|
}
|
||||||
|
func (s *systemService) UpSystemPort(port string) {
|
||||||
|
if len(port) > 0 && port != config.ServerInfo.HttpPort {
|
||||||
|
config.Cfg.Section("server").Key("HttpPort").SetValue(port)
|
||||||
|
config.ServerInfo.HttpPort = port
|
||||||
|
}
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
func (s *systemService) GetCasaOSLogs(lineNumber int) string {
|
||||||
|
file, err := os.Open(s.log.Path())
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
content, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(content)
|
||||||
|
}
|
||||||
|
|
||||||
func NewSystemService(log loger.OLog) SystemService {
|
func NewSystemService(log loger.OLog) SystemService {
|
||||||
return &systemService{log: log}
|
return &systemService{log: log}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
@@ -9,7 +11,6 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TaskService interface {
|
type TaskService interface {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserService interface {
|
type UserService interface {
|
||||||
@@ -20,6 +21,8 @@ func (c *user) SetUser(username, pwd, token, email, desc string) error {
|
|||||||
if len(username) > 0 {
|
if len(username) > 0 {
|
||||||
config.Cfg.Section("user").Key("UserName").SetValue(username)
|
config.Cfg.Section("user").Key("UserName").SetValue(username)
|
||||||
config.UserInfo.UserName = username
|
config.UserInfo.UserName = username
|
||||||
|
config.Cfg.Section("user").Key("Initialized").SetValue("true")
|
||||||
|
config.UserInfo.Initialized = true
|
||||||
}
|
}
|
||||||
if len(pwd) > 0 {
|
if len(pwd) > 0 {
|
||||||
config.Cfg.Section("user").Key("PWD").SetValue(pwd)
|
config.Cfg.Section("user").Key("PWD").SetValue(pwd)
|
||||||
@@ -37,7 +40,7 @@ func (c *user) SetUser(username, pwd, token, email, desc string) error {
|
|||||||
config.Cfg.Section("user").Key("Description").SetValue(desc)
|
config.Cfg.Section("user").Key("Description").SetValue(desc)
|
||||||
config.UserInfo.Description = desc
|
config.UserInfo.Description = desc
|
||||||
}
|
}
|
||||||
config.Cfg.SaveTo("conf/conf.ini")
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,18 +4,20 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
|
||||||
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/zerotier"
|
|
||||||
"github.com/PuerkitoBio/goquery"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/zerotier"
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ZeroTierService interface {
|
type ZeroTierService interface {
|
||||||
@@ -33,21 +35,22 @@ type ZeroTierService interface {
|
|||||||
DeleteMember(token string, id, mId string) interface{}
|
DeleteMember(token string, id, mId string) interface{}
|
||||||
DeleteNetwork(token, id string) interface{}
|
DeleteNetwork(token, id string) interface{}
|
||||||
GetJoinNetworks() string
|
GetJoinNetworks() string
|
||||||
|
NetworkIdFilter(letter rune) bool
|
||||||
}
|
}
|
||||||
type zerotierstruct struct {
|
type zerotierStruct struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var client http.Client
|
var client http.Client
|
||||||
|
|
||||||
func (c *zerotierstruct) ZeroTierJoinNetwork(networkId string) {
|
func (c *zerotierStruct) ZeroTierJoinNetwork(networkId string) {
|
||||||
command2.OnlyExec(`zerotier-cli join ` + networkId)
|
command2.OnlyExec(`zerotier-cli join ` + networkId)
|
||||||
}
|
}
|
||||||
func (c *zerotierstruct) ZeroTierLeaveNetwork(networkId string) {
|
func (c *zerotierStruct) ZeroTierLeaveNetwork(networkId string) {
|
||||||
command2.OnlyExec(`zerotier-cli leave ` + networkId)
|
command2.OnlyExec(`zerotier-cli leave ` + networkId)
|
||||||
}
|
}
|
||||||
|
|
||||||
//登录并获取token
|
//登录并获取token
|
||||||
func (c *zerotierstruct) GetToken(username, pwd string) string {
|
func (c *zerotierStruct) GetToken(username, pwd string) string {
|
||||||
if len(config.ZeroTierInfo.Token) > 0 {
|
if len(config.ZeroTierInfo.Token) > 0 {
|
||||||
return config.ZeroTierInfo.Token
|
return config.ZeroTierInfo.Token
|
||||||
} else {
|
} else {
|
||||||
@@ -55,7 +58,7 @@ func (c *zerotierstruct) GetToken(username, pwd string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) ZeroTierRegister(email, lastName, firstName, password string) string {
|
func (c *zerotierStruct) ZeroTierRegister(email, lastName, firstName, password string) string {
|
||||||
|
|
||||||
url := "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/registrations?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=state"
|
url := "https://accounts.zerotier.com/auth/realms/zerotier/protocol/openid-connect/registrations?client_id=zt-central&redirect_uri=https%3A%2F%2Fmy.zerotier.com%2Fapi%2F_auth%2Foidc%2Fcallback&response_type=code&scope=openid+profile+email+offline_access&state=state"
|
||||||
|
|
||||||
@@ -210,7 +213,7 @@ func ZeroTierGet(url string, cookies []*http.Cookie, t uint8) (action string, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
//模拟提交表单
|
//模拟提交表单
|
||||||
func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogin bool) (url, errInfo string, err error) {
|
func ZeroTierPost(str bytes.Buffer, action string, cookies []*http.Cookie, isLogin bool) (url, errInfo string, err error) {
|
||||||
req, err := http.NewRequest(http.MethodPost, action, strings.NewReader(str.String()))
|
req, err := http.NewRequest(http.MethodPost, action, strings.NewReader(str.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", errors.New("newrequest error")
|
return "", "", errors.New("newrequest error")
|
||||||
@@ -219,7 +222,7 @@ func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogi
|
|||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
for _, cookie := range cookes {
|
for _, cookie := range cookies {
|
||||||
req.AddCookie(cookie)
|
req.AddCookie(cookie)
|
||||||
}
|
}
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
@@ -273,71 +276,78 @@ func ZeroTierPost(str bytes.Buffer, action string, cookes []*http.Cookie, isLogi
|
|||||||
}
|
}
|
||||||
|
|
||||||
//获取zerotile网络列表和本地用户已加入的网络
|
//获取zerotile网络列表和本地用户已加入的网络
|
||||||
func (c *zerotierstruct) ZeroTierNetworkList(token string) (interface{}, []string) {
|
func (c *zerotierStruct) ZeroTierNetworkList(token string) (interface{}, []string) {
|
||||||
url := "https://my.zerotier.com/api/network"
|
url := "https://my.zerotier.com/api/network"
|
||||||
return zerotier.GetData(url, token), command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
|
return zerotier.GetData(url, token), command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get network info
|
// get network info
|
||||||
func (c *zerotierstruct) ZeroTierGetInfo(token, id string) (interface{}, []string) {
|
func (c *zerotierStruct) ZeroTierGetInfo(token, id string) (interface{}, []string) {
|
||||||
url := "https://my.zerotier.com/api/network/" + id
|
url := "https://my.zerotier.com/api/network/" + id
|
||||||
info := zerotier.GetData(url, token)
|
info := zerotier.GetData(url, token)
|
||||||
return info, command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
|
return info, command2.ExecResultStrArray(`zerotier-cli listnetworks | awk 'NR>1 {print $3} {line=$0}'`)
|
||||||
}
|
}
|
||||||
|
|
||||||
//get status
|
//get status
|
||||||
func (c *zerotierstruct) ZeroTierGetStatus(token string) interface{} {
|
func (c *zerotierStruct) ZeroTierGetStatus(token string) interface{} {
|
||||||
url := "https://my.zerotier.com/api/v1/status"
|
url := "https://my.zerotier.com/api/v1/status"
|
||||||
info := zerotier.GetData(url, token)
|
info := zerotier.GetData(url, token)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) EditNetwork(token string, data string, id string) interface{} {
|
func (c *zerotierStruct) EditNetwork(token string, data string, id string) interface{} {
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id
|
url := "https://my.zerotier.com/api/v1/network/" + id
|
||||||
info := zerotier.PostData(url, token, data)
|
info := zerotier.PostData(url, token, data)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) EditNetworkMember(token string, data string, id, mId string) interface{} {
|
func (c *zerotierStruct) EditNetworkMember(token string, data string, id, mId string) interface{} {
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
|
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
|
||||||
info := zerotier.PostData(url, token, data)
|
info := zerotier.PostData(url, token, data)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) MemberList(token string, id string) interface{} {
|
func (c *zerotierStruct) MemberList(token string, id string) interface{} {
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id + "/member"
|
url := "https://my.zerotier.com/api/v1/network/" + id + "/member"
|
||||||
info := zerotier.GetData(url, token)
|
info := zerotier.GetData(url, token)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) DeleteMember(token string, id, mId string) interface{} {
|
func (c *zerotierStruct) DeleteMember(token string, id, mId string) interface{} {
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
|
url := "https://my.zerotier.com/api/v1/network/" + id + "/member/" + mId
|
||||||
info := zerotier.DeleteMember(url, token)
|
info := zerotier.DeleteMember(url, token)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) DeleteNetwork(token, id string) interface{} {
|
func (c *zerotierStruct) DeleteNetwork(token, id string) interface{} {
|
||||||
url := "https://my.zerotier.com/api/v1/network/" + id
|
url := "https://my.zerotier.com/api/v1/network/" + id
|
||||||
info := zerotier.DeleteMember(url, token)
|
info := zerotier.DeleteMember(url, token)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) CreateNetwork(token string) interface{} {
|
func (c *zerotierStruct) CreateNetwork(token string) interface{} {
|
||||||
url := "https://my.zerotier.com/api/v1/network"
|
url := "https://my.zerotier.com/api/v1/network"
|
||||||
info := zerotier.PostData(url, token, "{}")
|
info := zerotier.PostData(url, token, "{}")
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *zerotierstruct) GetJoinNetworks() string {
|
func (c *zerotierStruct) GetJoinNetworks() string {
|
||||||
json := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetLocalJoinNetworks")
|
json := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetLocalJoinNetworks")
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *zerotierStruct) NetworkIdFilter(letter rune) bool {
|
||||||
|
if unicode.IsNumber(letter) || unicode.IsLetter(letter) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
func NewZeroTierService() ZeroTierService {
|
func NewZeroTierService() ZeroTierService {
|
||||||
//初始化client
|
//初始化client
|
||||||
client = http.Client{Timeout: 30 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
client = http.Client{Timeout: 30 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
return http.ErrUseLastResponse //禁止重定向
|
return http.ErrUseLastResponse //禁止重定向
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return &zerotierstruct{}
|
return &zerotierStruct{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,23 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
"github.com/shirou/gopsutil/v3/cpu"
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
"github.com/shirou/gopsutil/v3/disk"
|
||||||
"github.com/shirou/gopsutil/v3/host"
|
"github.com/shirou/gopsutil/v3/host"
|
||||||
"github.com/shirou/gopsutil/v3/mem"
|
"github.com/shirou/gopsutil/v3/mem"
|
||||||
"github.com/shirou/gopsutil/v3/net"
|
"github.com/shirou/gopsutil/v3/net"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//系统信息
|
//系统信息
|
||||||
@@ -30,6 +33,7 @@ type ZiMaService interface {
|
|||||||
GetSysInfo() host.InfoStat
|
GetSysInfo() host.InfoStat
|
||||||
GetDirPath(path string) []model.Path
|
GetDirPath(path string) []model.Path
|
||||||
MkdirAll(path string) (int, error)
|
MkdirAll(path string) (int, error)
|
||||||
|
CreateFile(path string) (int, error)
|
||||||
RenameFile(oldF, newF string) (int, error)
|
RenameFile(oldF, newF string) (int, error)
|
||||||
GetCpuInfo() []cpu.InfoStat
|
GetCpuInfo() []cpu.InfoStat
|
||||||
}
|
}
|
||||||
@@ -81,17 +85,12 @@ func (c *zima) GetDirPath(path string) []model.Path {
|
|||||||
ls, _ := ioutil.ReadDir(path)
|
ls, _ := ioutil.ReadDir(path)
|
||||||
dirs := []model.Path{}
|
dirs := []model.Path{}
|
||||||
|
|
||||||
if strings.Count(path, "/") > 1 {
|
if strings.Count(path, "/") > 0 {
|
||||||
|
|
||||||
for _, l := range ls {
|
for _, l := range ls {
|
||||||
if !strings.HasPrefix(l.Name(), ".") && l.IsDir() {
|
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir(), Date: l.ModTime()})
|
||||||
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + l.Name() + "/"})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dirs = append(dirs, model.Path{Name: "mnt", Path: "/mnt/"})
|
dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()})
|
||||||
dirs = append(dirs, model.Path{Name: "media", Path: "/media/"})
|
|
||||||
dirs = append(dirs, model.Path{Name: "home", Path: "/home/"})
|
|
||||||
}
|
}
|
||||||
return dirs
|
return dirs
|
||||||
}
|
}
|
||||||
@@ -118,7 +117,6 @@ func (c *zima) GetNetState(name string) string {
|
|||||||
|
|
||||||
//网络信息
|
//网络信息
|
||||||
func (c *zima) GetNetInfo() []net.IOCountersStat {
|
func (c *zima) GetNetInfo() []net.IOCountersStat {
|
||||||
//loger.Error("输出个内容试试")
|
|
||||||
parts, _ := net.IOCounters(true)
|
parts, _ := net.IOCounters(true)
|
||||||
//fmt.Println(net.ConntrackStatsWithContext(true))
|
//fmt.Println(net.ConntrackStatsWithContext(true))
|
||||||
return parts
|
return parts
|
||||||
@@ -133,6 +131,22 @@ func (c *zima) MkdirAll(path string) (int, error) {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
os.MkdirAll(path, os.ModePerm)
|
os.MkdirAll(path, os.ModePerm)
|
||||||
return oasis_err.SUCCESS, nil
|
return oasis_err.SUCCESS, nil
|
||||||
|
} else if strings.Contains(err.Error(), ": not a directory") {
|
||||||
|
return oasis_err.FILE_OR_DIR_EXISTS, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oasis_err.ERROR, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//create
|
||||||
|
func (c *zima) CreateFile(path string) (int, error) {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
if err == nil {
|
||||||
|
return oasis_err.FILE_OR_DIR_EXISTS, nil
|
||||||
|
} else {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
file.CreateFile(path)
|
||||||
|
return oasis_err.SUCCESS, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return oasis_err.ERROR, err
|
return oasis_err.ERROR, err
|
||||||
|
|||||||
43
shell/assist.sh
Normal file
43
shell/assist.sh
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#add in v0.2.3
|
||||||
|
version_0_2_3() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
|
||||||
|
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
|
||||||
|
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# add in v0.2.5
|
||||||
|
|
||||||
|
readonly CASA_DEPANDS="curl smartmontools parted fdisk partprobe"
|
||||||
|
|
||||||
|
version_0_2_5() {
|
||||||
|
install_depends "$CASA_DEPANDS"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#Install Depends
|
||||||
|
install_depends() {
|
||||||
|
((EUID)) && sudo_cmd="sudo"
|
||||||
|
if [[ ! -x "$(command -v '$1')" ]]; then
|
||||||
|
show 2 "Install the necessary dependencies: $1"
|
||||||
|
packagesNeeded=$1
|
||||||
|
if [ -x "$(command -v apk)" ]; then
|
||||||
|
$sudo_cmd apk add --no-cache $packagesNeeded
|
||||||
|
elif [ -x "$(command -v apt-get)" ]; then
|
||||||
|
$sudo_cmd apt-get -y -q install $packagesNeeded
|
||||||
|
elif [ -x "$(command -v dnf)" ]; then
|
||||||
|
$sudo_cmd dnf install $packagesNeeded
|
||||||
|
elif [ -x "$(command -v zypper)" ]; then
|
||||||
|
$sudo_cmd zypper install $packagesNeeded
|
||||||
|
else
|
||||||
|
show 1 "Package manager not found. You must manually install: $packagesNeeded"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
version_0_2_3
|
||||||
|
|
||||||
|
version_0_2_5
|
||||||
206
shell/helper.sh
206
shell/helper.sh
@@ -30,6 +30,11 @@ GetNetCard() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetTimeZone(){
|
||||||
|
timedatectl | grep "Time zone" | awk '{print $3}'
|
||||||
|
}
|
||||||
|
|
||||||
#查看网卡状态
|
#查看网卡状态
|
||||||
#param 网卡名称
|
#param 网卡名称
|
||||||
CatNetCardState() {
|
CatNetCardState() {
|
||||||
@@ -68,10 +73,8 @@ UMountPorintAndRemoveDir() {
|
|||||||
if [[ -z ${MOUNT_POINT} ]]; then
|
if [[ -z ${MOUNT_POINT} ]]; then
|
||||||
${log} "Warning: ${DEVICE} is not mounted"
|
${log} "Warning: ${DEVICE} is not mounted"
|
||||||
else
|
else
|
||||||
umount -l ${DEVICE}
|
umount -lf ${DEVICE}
|
||||||
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
|
||||||
/bin/rmdir "${MOUNT_POINT}"
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,11 +87,11 @@ FormatDisk() {
|
|||||||
elif [ "$2" == "ntfs" ]; then
|
elif [ "$2" == "ntfs" ]; then
|
||||||
mkfs.ntfs $1
|
mkfs.ntfs $1
|
||||||
elif [ "$2" == "ext4" ]; then
|
elif [ "$2" == "ext4" ]; then
|
||||||
mkfs.ext4 -F $1
|
mkfs.ext4 -m 1 -F $1
|
||||||
elif [ "$2" == "exfat" ]; then
|
elif [ "$2" == "exfat" ]; then
|
||||||
mkfs.exfat $1
|
mkfs.exfat $1
|
||||||
else
|
else
|
||||||
mkfs.ext4 -F $1
|
mkfs.ext4 -m 1 -F $1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,20 +106,20 @@ DelPartition() {
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
#添加分区
|
#添加分区只有一个分区
|
||||||
#param 路径 /dev/sdb
|
#param 路径 /dev/sdb
|
||||||
#param 磁盘号 最大128
|
#param 要挂载的目录
|
||||||
#param 磁盘大小 字节 512*2048=1024kb=1M
|
|
||||||
AddPartition() {
|
AddPartition() {
|
||||||
# fdisk $1 <<EOF
|
|
||||||
# n
|
|
||||||
# $2
|
|
||||||
# $3
|
|
||||||
# $4
|
|
||||||
# wq
|
|
||||||
#EOF
|
|
||||||
|
|
||||||
parted $1 mkpart primary ext4 s3 s4
|
DelPartition $1
|
||||||
|
parted -s $1 mklabel gpt
|
||||||
|
|
||||||
|
parted -s $1 mkpart primary ext4 0 100%
|
||||||
|
PATH=`lsblk -r $1 | sort | grep part | head -n 1 | awk '{print $1}'`
|
||||||
|
mkfs.ext4 -m 1 /dev/${PATH}
|
||||||
|
|
||||||
|
partprobe $1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#磁盘类型
|
#磁盘类型
|
||||||
@@ -141,17 +144,184 @@ GetDiskHealthState() {
|
|||||||
#result bytes
|
#result bytes
|
||||||
#result sectors
|
#result sectors
|
||||||
GetDiskSizeAndSectors() {
|
GetDiskSizeAndSectors() {
|
||||||
fdisk $1 -l | grep "/dev/sda:" | awk -F, 'BEGIN {OFS="\n"}{print $2,$3}' | awk '{print $1}'
|
fdisk $1 -l | grep "$1:" | awk -F, 'BEGIN {OFS="\n"}{print $2,$3}' | awk '{print $1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
#获取磁盘分区数据扇区
|
#获取磁盘分区数据扇区
|
||||||
#param 磁盘路径 /dev/sda
|
#param 磁盘路径 /dev/sda
|
||||||
#result start,end,sectors
|
#result start,end,sectors
|
||||||
GetPartitionSectors() {
|
GetPartitionSectors() {
|
||||||
fdisk $1 -l | grep "/dev/sda[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
|
fdisk $1 -l | grep "$1[1-9]" | awk 'BEGIN{OFS=","}{print $1,$2,$3,$4}'
|
||||||
|
}
|
||||||
|
|
||||||
|
#检查没有使用的挂载点删除文件夹
|
||||||
|
AutoRemoveUnuseDir() {
|
||||||
|
DIRECTORY="/DATA/"
|
||||||
|
dir=$(ls -l $DIRECTORY | grep "Storage[0-9]" | awk '/^d/ {print $NF}')
|
||||||
|
for i in $dir; do
|
||||||
|
|
||||||
|
path="$DIRECTORY$i"
|
||||||
|
mountStr=$(mountpoint $path)
|
||||||
|
notMountpoint="is not a mountpoint"
|
||||||
|
if [[ $mountStr =~ $notMountpoint ]]; then
|
||||||
|
if [ "$(ls -A $path)" = "" ]; then
|
||||||
|
rm -fr $path
|
||||||
|
else
|
||||||
|
echo "$path is not empty"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
#重载samba服务
|
#重载samba服务
|
||||||
ReloadSamba() {
|
ReloadSamba() {
|
||||||
/etc/init.d/smbd reload
|
/etc/init.d/smbd reload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# $1=sda1
|
||||||
|
# $2=volume{1}
|
||||||
|
do_mount() {
|
||||||
|
DEVBASE=$1
|
||||||
|
DEVICE="${DEVBASE}"
|
||||||
|
# See if this drive is already mounted, and if so where
|
||||||
|
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
||||||
|
|
||||||
|
if [ -n "${MOUNT_POINT}" ]; then
|
||||||
|
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
|
||||||
|
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
|
||||||
|
|
||||||
|
LABEL=$2
|
||||||
|
if grep -q " ${LABEL} " /etc/mtab; then
|
||||||
|
# Already in use, make a unique one
|
||||||
|
LABEL+="-${DEVBASE}"
|
||||||
|
fi
|
||||||
|
DEV_LABEL="${LABEL}"
|
||||||
|
|
||||||
|
# Use the device name in case the drive doesn't have label
|
||||||
|
if [ -z ${DEV_LABEL} ]; then
|
||||||
|
DEV_LABEL="${DEVBASE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MOUNT_POINT="${DEV_LABEL}"
|
||||||
|
|
||||||
|
${log} "Mount point: ${MOUNT_POINT}"
|
||||||
|
|
||||||
|
mkdir -p ${MOUNT_POINT}
|
||||||
|
|
||||||
|
case ${ID_FS_TYPE} in
|
||||||
|
vfat)
|
||||||
|
mount -t vfat -o rw,relatime,users,gid=100,umask=000,shortname=mixed,utf8=1,flush ${DEVICE} ${MOUNT_POINT}
|
||||||
|
;;
|
||||||
|
ext[2-4])
|
||||||
|
mount -o noatime ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
|
||||||
|
;;
|
||||||
|
exfat)
|
||||||
|
mount -t exfat ${DEVICE} ${MOUNT_POINT} >/dev/null 2>&1
|
||||||
|
;;
|
||||||
|
ntfs)
|
||||||
|
ntfs-3g ${DEVICE} ${MOUNT_POINT}
|
||||||
|
;;
|
||||||
|
iso9660)
|
||||||
|
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1=sda1
|
||||||
|
do_umount() {
|
||||||
|
log="logger -t usb-mount.sh -s "
|
||||||
|
DEVBASE=$1
|
||||||
|
DEVICE="${DEVBASE}"
|
||||||
|
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
||||||
|
|
||||||
|
if [[ -z ${MOUNT_POINT} ]]; then
|
||||||
|
${log} "Warning: ${DEVICE} is not mounted"
|
||||||
|
else
|
||||||
|
umount -l ${DEVICE}
|
||||||
|
${log} "Unmounted ${DEVICE} from ${MOUNT_POINT}"
|
||||||
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
|
sed -i.bak "\@${MOUNT_POINT}@d" /var/log/usb-mount.track
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
# $1=/mnt/volume1/data.img
|
||||||
|
# $2=100G
|
||||||
|
PackageDocker() {
|
||||||
|
image=$1
|
||||||
|
docker="/mnt/casa_docker"
|
||||||
|
#判断目录docker存在不存在则创建,存在检查是否为空
|
||||||
|
|
||||||
|
if [ ! -d "$docker" ]; then
|
||||||
|
mkdir ${docker}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(ls -A $docker)" = "" ]; then
|
||||||
|
echo "$docker count is 0"
|
||||||
|
else
|
||||||
|
mkdir ${docker}_bak
|
||||||
|
mv -r ${docker} ${docker}_bak
|
||||||
|
fi
|
||||||
|
|
||||||
|
daemon="/etc/docker/daemon.json"
|
||||||
|
#1创建img文件在挂载的目录
|
||||||
|
fallocate -l $2 $image
|
||||||
|
#2初始化img文件
|
||||||
|
mkfs -t ext4 $image
|
||||||
|
#3挂载img文件
|
||||||
|
sudo mount -o loop $image $docker
|
||||||
|
#4给移动/var/lib/docker数据到img挂载的目录
|
||||||
|
systemctl stop docker.socket
|
||||||
|
systemctl stop docker
|
||||||
|
cp -r /var/lib/docker/* ${docker}/
|
||||||
|
#5在/etc/docker写入daemon.json(需要检查)
|
||||||
|
if [ -d "$daemon" ]; then
|
||||||
|
mv -r $daemon ${daemon}.bak
|
||||||
|
fi
|
||||||
|
echo "{\"data-root\": \"$docker\"}" >$daemon
|
||||||
|
#删除老数据腾出空间
|
||||||
|
#rm -fr /var/lib/docker
|
||||||
|
systemctl start docker.socket
|
||||||
|
systemctl start docker
|
||||||
|
}
|
||||||
|
|
||||||
|
DockerImgMove() {
|
||||||
|
image=$1
|
||||||
|
systemctl stop docker.socket
|
||||||
|
systemctl stop docker
|
||||||
|
sudo umount -f $image
|
||||||
|
}
|
||||||
|
|
||||||
|
GetDockerDataRoot() {
|
||||||
|
docker info | grep "Docker Root Dir:"
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLink() {
|
||||||
|
ln -s /mnt/casa_sda1/AppData /DATA/AppData
|
||||||
|
#删除所有软链
|
||||||
|
find /DATA -type l -delete
|
||||||
|
}
|
||||||
|
|
||||||
|
#压缩文件夹
|
||||||
|
|
||||||
|
TarFolder() {
|
||||||
|
#压缩
|
||||||
|
tar -zcvf data.tar.gz -C/DATA/ AppDataBak/
|
||||||
|
|
||||||
|
#解压
|
||||||
|
tar zxvf data.tar.gz
|
||||||
|
|
||||||
|
#查看某文件夹下的所有包括子文件夹文件
|
||||||
|
ls /DATA/Media -lR | grep "^-" | wc -l
|
||||||
|
# ls -lR|grep "^d"| wc -l 查看某个文件夹下文件夹的个数,包括子文件夹下的文件夹个数。
|
||||||
|
|
||||||
|
#查看固定文件夹大小
|
||||||
|
du -sh /DATA
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ show() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
run_external_script() {
|
run_external_script() {
|
||||||
show 0 "run_external_script"
|
assist.sh
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
@@ -99,13 +99,13 @@ update() {
|
|||||||
target_arch="386"
|
target_arch="386"
|
||||||
;;
|
;;
|
||||||
*armv5*)
|
*armv5*)
|
||||||
target_arch="armv5"
|
target_arch="arm-5"
|
||||||
;;
|
;;
|
||||||
*armv6*)
|
*armv6*)
|
||||||
target_arch="armv6"
|
target_arch="arm-6"
|
||||||
;;
|
;;
|
||||||
*armv7*)
|
*armv7*)
|
||||||
target_arch="armv7"
|
target_arch="arm-7"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
show 1 "Aborted, unsupported or unknown architecture: $unamem"
|
show 1 "Aborted, unsupported or unknown architecture: $unamem"
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
# copy to /oasis/util/shell path
|
# copy to /casaOS/util/shell path
|
||||||
# chmod 755
|
# chmod 755
|
||||||
|
|
||||||
log="logger -t usb-mount.sh -s "
|
log="logger -t usb-mount.sh -s "
|
||||||
|
|
||||||
${log} "变量:$1 $2"
|
|
||||||
|
|
||||||
ACTION=$1
|
ACTION=$1
|
||||||
|
|
||||||
DEVBASE=$2
|
DEVBASE=$2
|
||||||
@@ -18,10 +16,10 @@ MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }')
|
|||||||
|
|
||||||
do_mount() {
|
do_mount() {
|
||||||
|
|
||||||
if [[ -n ${MOUNT_POINT} ]]; then
|
if [ -n "${MOUNT_POINT}" ]; then
|
||||||
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
${log} "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
|
||||||
exit 1
|
exit 1
|
||||||
fib
|
fi
|
||||||
|
|
||||||
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
|
# Get info for this drive: $ID_FS_LABEL and $ID_FS_TYPE
|
||||||
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
|
eval $(blkid -o udev ${DEVICE} | grep -i -e "ID_FS_LABEL" -e "ID_FS_TYPE")
|
||||||
@@ -32,23 +30,32 @@ do_mount() {
|
|||||||
|
|
||||||
# Figure out a mount point to use
|
# Figure out a mount point to use
|
||||||
# LABEL=${ID_FS_LABEL}
|
# LABEL=${ID_FS_LABEL}
|
||||||
LABEL=${DEVBASE}
|
# LABEL=${DEVBASE}
|
||||||
if grep -q " /media/${LABEL} " /etc/mtab; then
|
# if grep -q " /DATA/USB_${LABEL} " /etc/mtab; then
|
||||||
# Already in use, make a unique one
|
# # Already in use, make a unique one
|
||||||
LABEL+="-${DEVBASE}"
|
# LABEL+="-${DEVBASE}"
|
||||||
fi
|
# fi
|
||||||
DEV_LABEL="${LABEL}"
|
# DEV_LABEL="${LABEL}"
|
||||||
|
|
||||||
# Use the device name in case the drive doesn't have label
|
# # Use the device name in case the drive doesn't have label
|
||||||
if [ -z ${DEV_LABEL} ]; then
|
# if [ -z ${DEV_LABEL} ]; then
|
||||||
DEV_LABEL="${DEVBASE}"
|
# DEV_LABEL="${DEVBASE}"
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
MOUNT_POINT="/media/${DEV_LABEL}"
|
MOUNT_POINT="/DATA/USB_Storage1"
|
||||||
|
arr=("/DATA/USB_Storage1" "/DATA/USB_Storage2" "/DATA/USB_Storage3" "/DATA/USB_Storage4" "/DATA/USB_Storage5" "/DATA/USB_Storage6" "/DATA/USB_Storage7" "/DATA/USB_Storage8" "/DATA/USB_Storage9" "/DATA/USB_Storage10" "/DATA/USB_Storage11" "/DATA/USB_Storage12")
|
||||||
|
for folder in ${arr[@]}; do
|
||||||
|
#如果文件夹不存在,创建文件夹
|
||||||
|
if [ ! -d "$folder" ]; then
|
||||||
|
mkdir -p ${folder}
|
||||||
|
MOUNT_POINT=$folder
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
${log} "Mount point: ${MOUNT_POINT}"
|
${log} "Mount point: ${MOUNT_POINT}"
|
||||||
|
|
||||||
mkdir -p ${MOUNT_POINT}
|
|
||||||
|
|
||||||
# # Global mount options
|
# # Global mount options
|
||||||
# OPTS="rw,relatime"
|
# OPTS="rw,relatime"
|
||||||
@@ -86,7 +93,7 @@ do_mount() {
|
|||||||
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
mount -t iso9660 ${DEVICE} ${MOUNT_POINT}
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
/bin/rmdir "${MOUNT_POINT}"
|
/bin/rmdir "${MOUNT_POINT}"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ Description=Mount USB Drive on %i
|
|||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
RemainAfterExit=true
|
RemainAfterExit=true
|
||||||
ExecStart=/oasis/util/shell/usb-mount.sh add %i
|
ExecStart=/casaOS/server/shell/usb-mount.sh add %i
|
||||||
ExecStop=/oasis/util/shell/usb-mount.sh remove %i
|
ExecStop=/casaOS/server/shell/usb-mount.sh remove %i
|
||||||
|
|||||||
BIN
snapshot-mobile.png
Normal file
BIN
snapshot-mobile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
BIN
snapshot.png
Normal file
BIN
snapshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
10
types/search.go
Normal file
10
types/search.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
const (
|
||||||
|
APPLICATION = iota
|
||||||
|
MEDIA
|
||||||
|
PICTURE
|
||||||
|
MUSIC
|
||||||
|
SEARCH
|
||||||
|
UNKNOWN
|
||||||
|
)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user