Compare commits

..

65 Commits

Author SHA1 Message Date
link
63c6c2cebb Merge pull request #111 from IceWhaleTech/dev
Delete CasaOS-linux-amd64
2022-02-17 19:22:14 +08:00
link
6cba025679 Delete CasaOS-linux-amd64 2022-02-17 19:21:19 +08:00
link
d25b93c972 Merge pull request #110 from IceWhaleTech/dev
Dev
2022-02-17 18:53:54 +08:00
link
b14861703c Merge branch 'dev' of ssh://github.com/IceWhaleTech/CasaOS into dev 2022-02-17 18:53:29 +08:00
link
32604225ce update ui 2022-02-17 18:52:14 +08:00
link
f623b29c38 Merge pull request #109 from IceWhaleTech/dev
Dev
2022-02-17 18:47:44 +08:00
link
94ae6ee8ec Merge branch 'main' into dev 2022-02-17 18:47:36 +08:00
link
5115bf72e1 update desc 2022-02-17 18:44:51 +08:00
link
e1a928cd78 Fixed issues 2022-02-17 18:43:25 +08:00
link
3977519c43 Update assist.sh 2022-01-30 11:21:24 +08:00
link
2f87834ac9 Merge pull request #93 from IceWhaleTech/dev
Update route.go
2022-01-28 16:25:01 +08:00
link
53335012d8 Update route.go 2022-01-28 16:24:28 +08:00
link
9d6302f7e3 Merge pull request #92 from IceWhaleTech/dev
Update UI
2022-01-28 16:14:59 +08:00
link
20950e2a60 Update UI 2022-01-28 16:14:35 +08:00
link
0e0e507f8f Merge pull request #91 from IceWhaleTech/dev
update ui
2022-01-28 15:35:15 +08:00
link
46e14617b6 update ui 2022-01-28 15:34:32 +08:00
link
903c73fafb Merge pull request #90 from IceWhaleTech/dev
update web
2022-01-28 14:33:40 +08:00
link
42a56df4a5 update web 2022-01-28 14:32:49 +08:00
link
493dc5c032 Merge pull request #89 from IceWhaleTech/dev
Compatible with more types of disks
2022-01-28 14:06:58 +08:00
link
9a73bc2a18 Compatible with more types of disks
Add usb display
2022-01-28 14:06:27 +08:00
link
55a9acd9f6 Merge pull request #85 from IceWhaleTech/dev
Apply multilingual support
2022-01-26 18:51:14 +08:00
link
d060968b7a Apply multilingual support 2022-01-26 18:50:34 +08:00
link
88a7f53130 Merge pull request #82 from IceWhaleTech/dev
Dev
2022-01-26 11:33:33 +08:00
link
26e5b18a5d Merge branch 'dev' of ssh://github.com/IceWhaleTech/CasaOS into dev 2022-01-26 11:33:02 +08:00
link
011ace96f6 update ui 2022-01-26 11:32:57 +08:00
link
5c00655d14 Merge pull request #81 from IceWhaleTech/dev
Dev
2022-01-26 10:46:50 +08:00
link
eb36c262db Merge branch 'main' into dev 2022-01-26 10:46:43 +08:00
link
29d1861545 Merge branch 'main' into dev 2022-01-26 10:45:11 +08:00
link
3c9b410693 update dependency 2022-01-26 10:44:55 +08:00
link
4c3b41433b Update assist.sh 2022-01-24 22:06:31 +08:00
link
1fd13668c0 Merge pull request #78 from IceWhaleTech/dev
Dev
2022-01-24 17:22:48 +08:00
link
d1ab7261a6 Update usb-mount.sh 2022-01-24 17:21:43 +08:00
link
0fc65bcb3a update mount path 2022-01-24 17:08:28 +08:00
link
f1ce8bfd99 Merge pull request #77 from IceWhaleTech/dev
update disk
2022-01-24 11:19:47 +08:00
link
3f472f1864 update disk 2022-01-24 11:19:04 +08:00
link
229d94cae7 Merge pull request #74 from IceWhaleTech/dev
Fixed Storage Panel
2022-01-21 17:50:44 +08:00
link
c28e1bbf93 Fixed Storage Panel 2022-01-21 17:50:12 +08:00
link
a840029000 Merge pull request #73 from IceWhaleTech/dev
update UI
2022-01-20 18:45:54 +08:00
link
aad2646cf2 Merge branch 'dev' of ssh://github.com/IceWhaleTech/CasaOS into dev 2022-01-20 18:45:17 +08:00
link
ca1f8ad73e Update UI 2022-01-20 18:44:55 +08:00
link
dea02763a2 Update UI 2022-01-20 18:44:40 +08:00
link
ea67385a64 Merge pull request #72 from IceWhaleTech/dev
Storage Manager
2022-01-20 18:41:56 +08:00
link
fa2daa2767 Merge branch 'main' into dev 2022-01-20 18:41:49 +08:00
link
fcb906aa85 Storage Manager
Fix the app store classification problem
Fix the application market classification problem
2022-01-20 18:38:59 +08:00
老竭力
489a617126 Update casa.yml 2022-01-04 16:22:38 +08:00
老竭力
601e7ce10b Update casa.yml 2022-01-04 14:51:09 +08:00
老竭力
4a6fc9a945 Update system.go 2022-01-04 14:47:46 +08:00
老竭力
b377af1d24 Update casa.yml 2021-12-30 19:17:11 +08:00
老竭力
3fc00f8da7 Update casa.yml 2021-12-30 19:13:40 +08:00
老竭力
6e39fe5f8c Update casa.yml 2021-12-30 19:04:37 +08:00
老竭力
20c240a123 Update casa.yml 2021-12-30 19:00:11 +08:00
老竭力
3ea9fc0de0 Update casa.yml 2021-12-30 18:52:37 +08:00
老竭力
b80b08ef07 Update casa.yml 2021-12-30 18:50:45 +08:00
老竭力
505af8d101 Update casa.yml 2021-12-30 18:46:17 +08:00
老竭力
ae35a6d291 Update casa.yml 2021-12-30 18:44:07 +08:00
John Guan
2b95c07a47 Update casa.yml 2021-12-30 18:16:19 +08:00
John Guan
27a011e715 Update casa.yml 2021-12-30 18:01:01 +08:00
link
476831a12f Merge pull request #65 from IceWhaleTech/dev
update action system
2021-12-30 16:59:05 +08:00
link
9675eff69e update action system 2021-12-30 16:58:24 +08:00
link
85a044246e Merge pull request #64 from IceWhaleTech/dev
update action system
2021-12-30 16:53:32 +08:00
link
5c41fbcf3d update action system 2021-12-30 16:52:58 +08:00
link
6baab7a525 Merge pull request #63 from IceWhaleTech/dev
update action system
2021-12-30 16:42:39 +08:00
link
ab3b5a9077 update action system 2021-12-30 16:41:16 +08:00
link
5811c271b2 Merge pull request #62 from IceWhaleTech/dev
update web
2021-12-30 16:20:50 +08:00
link
cf5387346d update web 2021-12-30 16:20:30 +08:00
55 changed files with 4985 additions and 672 deletions

View File

@@ -90,7 +90,7 @@ jobs:
- 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

2
UI

Submodule UI updated: f3088b6354...106902c76a

View File

@@ -15,6 +15,9 @@ ProjectPath = /casaOS/server
HttpPort = 8089 HttpPort = 8089
RunMode = release RunMode = release
ServerApi = https://api.casaos.zimaboard.com ServerApi = https://api.casaos.zimaboard.com
Handshake =
Token =
[user] [user]
UserName = admin UserName = admin
@@ -22,7 +25,6 @@ PWD = zimaboard
Email = user@gmail.com Email = user@gmail.com
Description = description Description = description
Initialized = false Initialized = false
Token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImVyZXJlIiwicGFzc3dvcmQiOiJhZHNmZGYiLCJleHAiOjE2MjQwMDU0ODEsImlzcyI6Imdpbi1ibG9nIn0.JNsCccZuFCwlSMLJg62iOIB2xymk_k7xGa11xhZ07bc
[zerotier] [zerotier]
UserName = user UserName = user

10
go.mod
View File

@@ -10,10 +10,11 @@ require (
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.7 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/distribution v2.8.0+incompatible // 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
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
github.com/gin-contrib/gzip v0.0.2 // indirect github.com/gin-contrib/gzip v0.0.2
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
@@ -33,8 +34,10 @@ require (
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.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.11 // 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/image-spec 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/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
@@ -49,7 +52,6 @@ require (
github.com/swaggo/gin-swagger v1.3.0 github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.3 github.com/swaggo/swag v1.7.3
github.com/tidwall/gjson v1.10.2 github.com/tidwall/gjson v1.10.2
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
@@ -67,6 +69,6 @@ require (
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
gorm.io/driver/sqlite v1.1.5 gorm.io/driver/sqlite v1.2.6
gorm.io/gorm v1.21.15 gorm.io/gorm v1.22.5
) )

16
go.sum
View File

@@ -261,6 +261,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@@ -492,6 +494,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@@ -553,6 +557,9 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
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=
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ=
github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
@@ -608,6 +615,8 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/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-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@@ -747,8 +756,6 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
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=
@@ -1225,8 +1232,13 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.1.5 h1:JU8G59VyKu1x1RMQgjefQnkZjDe9wHc1kARDZPu5dZs= gorm.io/driver/sqlite v1.1.5 h1:JU8G59VyKu1x1RMQgjefQnkZjDe9wHc1kARDZPu5dZs=
gorm.io/driver/sqlite v1.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc= gorm.io/driver/sqlite v1.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc=
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=
gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY=
gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk= gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk=
gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU=
gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=

View File

@@ -58,8 +58,9 @@ func main() {
r := route.InitRouter() r := route.InitRouter()
//service.SyncTask(sqliteDB) //service.SyncTask(sqliteDB)
cron2 := cron.New() //创建一个cron实例 cron2 := cron.New() //创建一个cron实例
//执行定时任务每5秒执行一次 //every day execution
err := cron2.AddFunc("0 0 0 1/1 * *", func() { err := cron2.AddFunc("0 0/1 * * * *", func() {
//service.PushIpInfo(*&config.ServerInfo.Token)
//service.UpdataDDNSList(mysqldb) //service.UpdataDDNSList(mysqldb)
//service.SyncTask(sqliteDB) //service.SyncTask(sqliteDB)
}) })
@@ -77,6 +78,7 @@ func main() {
WriteTimeout: 60 * time.Second, WriteTimeout: 60 * time.Second,
MaxHeaderBytes: 1 << 20, MaxHeaderBytes: 1 << 20,
} }
s.ListenAndServe() s.ListenAndServe()
} }

View File

@@ -39,6 +39,10 @@ type ServerAppList struct {
Origin string `json:"origin"` Origin string `json:"origin"`
Type int `json:"type"` Type int `json:"type"`
Developer string `json:"developer"` Developer string `json:"developer"`
HostName string `json:"host_name"`
Privileged bool `json:"privileged"`
CapAdd Strings `json:"cap_add"`
Cmd Strings `json:"cmd"`
} }
type Ports struct { type Ports struct {

View File

@@ -20,13 +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"` 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"`
}

6
model/heart.go Normal file
View File

@@ -0,0 +1,6 @@
package model
type CasaOSHeart struct {
UuId string `json:"uuid"`
Type string `json:"type"`
}

View File

@@ -122,4 +122,8 @@ type CustomizationPostData struct {
Label string `json:"label"` Label string `json:"label"`
Description string `json:"description"` Description string `json:"description"`
Position bool `json:"position"` Position bool `json:"position"`
HostName string `json:"host_name"`
Privileged bool `json:"privileged"`
CapAdd []string `json:"cap_add"`
Cmd []string `json:"cmd"`
} }

6
model/notify.go Normal file
View File

@@ -0,0 +1,6 @@
package model
type NotifyMssage struct {
Type string `json:"type"`
Data string `json:"data"`
}

19
model/person.go Normal file
View File

@@ -0,0 +1,19 @@
package model
import "time"
type PersionModel struct {
Token string `json:"token"`
Ips []string `json:"ips"`
CreatedAt time.Time `gorm:"<-:create;autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
}
//记录链接状态
type ConnectState struct {
From string `json:"from"`
To string `json:"to"`
Type string `json:"type"` //current state 1:ready 2:ok
CreatedAt time.Time `json:"created_at"`
UUId string `json:"uuid"` //对接标识
}

69
model/smartctl_model.go Normal file
View 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"`
}

View File

@@ -24,6 +24,8 @@ type ServerModel struct {
RunMode string RunMode string
ServerApi string ServerApi string
LockAccount bool LockAccount bool
Handshake string
Token string
} }
//服务配置 //服务配置

View File

@@ -1,7 +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"` IsDir bool `json:"is_dir"`
Date time.Time `json:"date"`
} }

View File

@@ -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) {
@@ -85,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()
}

View File

@@ -2,6 +2,7 @@ package file
import ( import (
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"mime/multipart" "mime/multipart"
"os" "os"
@@ -159,3 +160,68 @@ func ReadFullFile(path string) []byte {
} }
return content return content
} }
// File copies a single file from src to dst
func CopyFile(src, dst string) error {
var err error
var srcfd *os.File
var dstfd *os.File
var srcinfo os.FileInfo
if srcfd, err = os.Open(src); err != nil {
return err
}
defer srcfd.Close()
if dstfd, err = os.Create(dst); err != nil {
return err
}
defer dstfd.Close()
if _, err = io.Copy(dstfd, srcfd); err != nil {
return err
}
if srcinfo, err = os.Stat(src); err != nil {
return err
}
return os.Chmod(dst, srcinfo.Mode())
}
// Dir copies a whole directory recursively
func CopyDir(src string, dst string) error {
var err error
var fds []os.FileInfo
var srcinfo os.FileInfo
if srcinfo, err = os.Stat(src); err != nil {
return err
}
if !srcinfo.IsDir() {
if err = CopyFile(src, dst); err != nil {
fmt.Println(err)
}
return nil
}
if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
return err
}
if fds, err = ioutil.ReadDir(src); err != nil {
return err
}
for _, fd := range fds {
srcfp := path.Join(src, fd.Name())
dstfp := path.Join(dst, fd.Name())
if fd.IsDir() {
if err = CopyDir(srcfp, dstfp); err != nil {
fmt.Println(err)
}
} else {
if err = CopyFile(srcfp, dstfp); err != nil {
fmt.Println(err)
}
}
}
return nil
}

View File

@@ -21,6 +21,13 @@ const (
//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
@@ -29,6 +36,7 @@ const (
//file //file
FILE_DOES_NOT_EXIST = 60001 FILE_DOES_NOT_EXIST = 60001
FILE_READ_ERROR = 60002 FILE_READ_ERROR = 60002
FILE_DELETE_ERROR = 60003
//shortcuts //shortcuts
SHORTCUTS_URL_ERROR = 70001 SHORTCUTS_URL_ERROR = 70001
@@ -37,34 +45,42 @@ 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_IS_EMPTY: "Password is empty",
PWD_INVALID_OLD: "Old Password invalid", PWD_INVALID_OLD: "Invalid old password",
ACCOUNT_LOCK: "Account Lock", 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_ALREADY_EXISTS: "File already exists",
FILE_OR_DIR_EXISTS: "File or directory already exists", FILE_OR_DIR_EXISTS: "File or folder already exists",
PORT_IS_OCCUPIED: "Port is occupied", 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", FILE_DELETE_ERROR: "Delete error",
SHORTCUTS_URL_ERROR: "URL error",
} }
//获取错误信息 //获取错误信息

View File

@@ -3,6 +3,7 @@ package route
import ( import (
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"fmt"
"strconv" "strconv"
"time" "time"
@@ -24,6 +25,8 @@ func InitFunction() {
Update2_3() Update2_3()
CheckSerialDiskMount() CheckSerialDiskMount()
CheckToken2_9()
} }
var syncIsExistence = false var syncIsExistence = false
@@ -34,10 +37,9 @@ func installSyncthing(appId string) {
m := model.CustomizationPostData{} m := model.CustomizationPostData{}
var dockerImage string var dockerImage string
var dockerImageVersion string var dockerImageVersion string
appInfo = service.MyService.OAPI().GetServerAppInfo(appId, "system", "us_en")
appInfo = service.MyService.OAPI().GetServerAppInfo(appId)
dockerImage = appInfo.Image dockerImage = appInfo.Image
dockerImageVersion = appInfo.ImageVersion
if len(appInfo.ImageVersion) == 0 { if len(appInfo.ImageVersion) == 0 {
dockerImageVersion = "latest" dockerImageVersion = "latest"
@@ -84,9 +86,9 @@ func installSyncthing(appId string) {
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog) err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
if err != nil { if err != nil {
//pull image error //pull image error
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
return return
} }
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) { for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
time.Sleep(time.Second) time.Sleep(time.Second)
} }
@@ -101,8 +103,8 @@ func installSyncthing(appId string) {
m.Volumes = appInfo.Volumes m.Volumes = appInfo.Volumes
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel) containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
if err != nil { if err != nil {
fmt.Println("container create error", err)
// create container error // create container error
return return
} }
@@ -170,7 +172,7 @@ func checkSystemApp() {
path := "" path := ""
for _, i := range paths { for _, i := range paths {
if i.ContainerPath == "/config" { if i.ContainerPath == "/config" {
path = docker.GetDir(v.CustomId, i.Path) + "config.xml" path = docker.GetDir(v.CustomId, i.Path) + "/config.xml"
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
if file.CheckNotExist(path) { if file.CheckNotExist(path) {
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
@@ -195,25 +197,50 @@ func CheckSerialDiskMount() {
// check mount point // check mount point
dbList := service.MyService.Disk().GetSerialAll() dbList := service.MyService.Disk().GetSerialAll()
list := service.MyService.Disk().LSBLK() list := service.MyService.Disk().LSBLK(true)
mountPoint := make(map[string]string, len(dbList)) mountPoint := make(map[string]string, len(dbList))
//remount
for _, v := range dbList {
mountPoint[v.UUID] = v.MountPoint
}
for _, v := range list { for _, v := range list {
command.ExecEnabledSMART(v.Path)
if v.Children != nil { if v.Children != nil {
for _, h := range v.Children { for _, h := range v.Children {
mountPoint[h.MountPoint] = "1" 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)
} }
//remount
for _, item := range dbList {
if _, ok := mountPoint[item.MountPoint]; !ok {
service.MyService.Disk().MountDisk(item.Path, item.MountPoint)
} }
} }
}
}
}
service.MyService.Disk().RemoveLSBLKCache()
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir")
} }
func Update2_3() { func Update2_3() {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh") command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")
} }
func CheckToken2_9() {
if len(config.ServerInfo.Token) == 0 {
token := uuid.NewV4().String
config.ServerInfo.Token = token()
config.Cfg.Section("server").Key("Token").SetValue(token())
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
}

View File

@@ -8,6 +8,7 @@ import (
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-contrib/gzip"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@@ -18,6 +19,7 @@ func InitRouter() *gin.Engine {
r := gin.Default() r := gin.Default()
r.Use(middleware.Cors()) r.Use(middleware.Cors())
r.Use(gzip.Gzip(gzip.DefaultCompression))
gin.SetMode(config.ServerInfo.RunMode) gin.SetMode(config.ServerInfo.RunMode)
r.StaticFS("/ui", http.FS(web.Static)) r.StaticFS("/ui", http.FS(web.Static))
@@ -33,7 +35,7 @@ func InitRouter() *gin.Engine {
r.GET("/v1/guide/check", v1.GetGuideCheck) r.GET("/v1/guide/check", v1.GetGuideCheck)
r.GET("/debug", v1.GetSystemConfigDebug) r.GET("/v1/debug", v1.GetSystemConfigDebug)
//set user //set user
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd) r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
//get user info //get user info
@@ -206,42 +208,44 @@ func InitRouter() *gin.Engine {
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("/dirpath", v1.DirPath)
//创建目录 //create folder
v1FileGroup.POST("/mkdir", v1.MkdirAll) v1FileGroup.POST("/mkdir", v1.MkdirAll)
v1FileGroup.POST("/create", v1.PostCreateFile) v1FileGroup.POST("/create", v1.PostCreateFile)
v1FileGroup.GET("/download", v1.GetDownloadFile) v1FileGroup.GET("/download", v1.GetDownloadFile)
v1FileGroup.PUT("/move", v1.PutFileMove) v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
v1FileGroup.DELETE("delete", v1.DeleteFile)
//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("/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("/part", 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)
//mount SATA disk
v1DiskGroup.POST("/mount", v1.PostMountDisk)
//umount SATA disk
v1DiskGroup.POST("/umount", v1.PostDiskUmount)
v1DiskGroup.DELETE("/remove/:id", v1.DeleteDisk)
} }
v1ShareGroup := v1Group.Group("/share") v1ShareGroup := v1Group.Group("/share")
v1ShareGroup.Use() v1ShareGroup.Use()
@@ -280,6 +284,11 @@ func InitRouter() *gin.Engine {
{ {
v1SearchGroup.GET("/search", v1.GetSearchList) v1SearchGroup.GET("/search", v1.GetSearchList)
} }
v1PersonGroup := v1Group.Group("/persion")
v1PersonGroup.Use()
{
v1PersonGroup.GET("/test", v1.PersonTest)
}
v1Group.GET("/sync/config", v1.GetSyncConfig) v1Group.GET("/sync/config", v1.GetSyncConfig)
v1Group.Any("/syncthing/*url", v1.SyncToSyncthing) v1Group.Any("/syncthing/*url", v1.SyncToSyncthing)

View File

@@ -35,25 +35,26 @@ func AppList(c *gin.Context) {
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", "")
recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key) language := c.GetHeader("Language")
for i := 0; i < len(recommend); i++ { recommend, list, community := service.MyService.OAPI().GetServerList(index, size, t, categoryId, key, language)
ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[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
} // }
for i := 0; i < len(list); i++ { // }
ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion) // for i := 0; i < len(list); i++ {
if ct != nil { // ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
list[i].State = ct.State // 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) // for i := 0; i < len(community); i++ {
if ct != nil { // ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
list[i].State = ct.State // if ct != nil {
} // community[i].State = ct.State
} // }
// }
data := make(map[string]interface{}, 3) data := make(map[string]interface{}, 3)
data["recommend"] = recommend data["recommend"] = recommend
data["list"] = list data["list"] = list
@@ -137,7 +138,8 @@ func AppUsageList(c *gin.Context) {
func AppInfo(c *gin.Context) { func AppInfo(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
info := service.MyService.OAPI().GetServerAppInfo(id) language := c.GetHeader("Language")
info := service.MyService.OAPI().GetServerAppInfo(id, "", language)
if info.NetworkModel != "host" { if info.NetworkModel != "host" {
for i := 0; i < len(info.Ports); i++ { for i := 0; i < len(info.Ports); i++ {
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) { if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {

View File

@@ -1,10 +1,16 @@
package v1 package v1
import ( import (
"fmt"
"net/http" "net/http"
"reflect"
"strconv" "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" model2 "github.com/IceWhaleTech/CasaOS/service/model"
@@ -12,18 +18,143 @@ import (
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
) )
// @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
list := service.MyService.Disk().LSBLK() disks := []model.Drive{}
storage := []model.Storage{}
avail := []model.Drive{}
for i := 0; i < len(list); i++ {
disk := model.Drive{}
if list[i].Rota {
disk.DiskType = "HDD"
} else {
disk.DiskType = "SSD"
}
disk.Serial = list[i].Serial
disk.Name = list[i].Name
disk.Size = list[i].Size
disk.Path = list[i].Path
disk.Model = list[i].Model
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list}) 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 == "/" {
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 get disk list // @Summary get disk list
@@ -35,7 +166,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))
@@ -60,25 +191,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 format disk // @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 "for example /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 return
} }
service.MyService.Disk().FormatDisk(path, t) 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)
format := service.MyService.Disk().FormatDisk(path, t)
if len(format) == 0 {
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)})
} }
@@ -115,23 +267,77 @@ 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 serial number // @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 serial formData string true "serial" // @Param serial formData string true "serial"
// @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")
serial := c.PostForm("serial") format, _ := strconv.ParseBool(c.PostForm("format"))
if len(path) == 0 || len(serial) == 0 { if len(name) == 0 || 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 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) service.MyService.Disk().AddPartition(path)
}
formatBool := true
for formatBool {
currentDisk = service.MyService.Disk().GetDiskInfo(path)
fmt.Println(currentDisk.Children)
if len(currentDisk.Children) > 0 {
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)})
} }
@@ -149,7 +355,7 @@ func PostMountDisk(c *gin.Context) {
path := c.PostForm("path") path := c.PostForm("path")
serial := c.PostForm("serial") serial := c.PostForm("serial")
mountPath := "/mnt/volume" mountPath := "/DATA/volume"
var list = service.MyService.Disk().GetSerialAll() var list = service.MyService.Disk().GetSerialAll()
var pathMapList = make(map[string]string, len(list)) var pathMapList = make(map[string]string, len(list))
for _, v := range list { for _, v := range list {
@@ -165,13 +371,13 @@ func PostMountDisk(c *gin.Context) {
//mount dir //mount dir
service.MyService.Disk().MountDisk(path, mountPath) service.MyService.Disk().MountDisk(path, mountPath)
//save to data
m := model2.SerialDisk{} m := model2.SerialDisk{}
m.MountPoint = mountPath m.MountPoint = mountPath
m.Path = path m.Path = path
m.Serial = serial m.UUID = serial
m.State = 0 m.State = 0
service.MyService.Disk().SaveMountPoint(m) //service.MyService.Disk().SaveMountPoint(m)
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)})
} }
@@ -180,19 +386,35 @@ func PostMountDisk(c *gin.Context) {
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags disk // @Tags disk
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string true "for example: /dev/sda1" // @Param path formData string true "e.g. /dev/sda1"
// @Param mount_point formData string true "for example: /mnt/volume1" // @Param mount_point formData string true "e.g. /mnt/volume1"
// @Param pwd formData string true "user password"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /disk/umount [post] // @Router /disk/umount [post]
func PostDiskUmount(c *gin.Context) { func PostDiskUmount(c *gin.Context) {
//
path := c.PostForm("path") path := c.PostForm("path")
mountPoint := c.PostForm("mount_point") mountPoint := c.PostForm("volume")
service.MyService.Disk().UmountPointAndRemoveDir(path) 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 //delete data
service.MyService.Disk().DeleteMountPoint(path, mountPoint) 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)}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
} }
@@ -220,7 +442,7 @@ func DeleteDisk(c *gin.Context) {
func GetDiskCheck(c *gin.Context) { func GetDiskCheck(c *gin.Context) {
dbList := service.MyService.Disk().GetSerialAll() dbList := service.MyService.Disk().GetSerialAll()
list := service.MyService.Disk().LSBLK() list := service.MyService.Disk().LSBLK(true)
mapList := make(map[string]string) mapList := make(map[string]string)
@@ -229,7 +451,7 @@ func GetDiskCheck(c *gin.Context) {
} }
for _, v := range dbList { for _, v := range dbList {
if _, ok := mapList[v.Serial]; !ok { if _, ok := mapList[v.UUID]; !ok {
//disk undefind //disk undefind
c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"}) c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"})
return return
@@ -238,3 +460,38 @@ func GetDiskCheck(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 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})
}

View File

@@ -2,6 +2,7 @@ package v1
import ( import (
"bytes" "bytes"
"encoding/json"
json2 "encoding/json" json2 "encoding/json"
"net/http" "net/http"
"reflect" "reflect"
@@ -145,6 +146,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)
@@ -174,7 +176,7 @@ func InstallApp(c *gin.Context) {
dockerImageVersion = "latest" dockerImageVersion = "latest"
} }
if m.Origin != "custom" { if m.Origin != "custom" {
appInfo = service.MyService.OAPI().GetServerAppInfo(appId) appInfo = service.MyService.OAPI().GetServerAppInfo(appId, "", language)
} else { } else {
@@ -253,9 +255,11 @@ func InstallApp(c *gin.Context) {
installLog.State = 0 installLog.State = 0
installLog.CustomId = id installLog.CustomId = id
installLog.Message = "installing rely" installLog.Message = "installing rely"
installLog.Class = types.NOTIFY_APP
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)
installLog.Id = uuid.NewV4().String()
service.MyService.Notify().AddLog(installLog) service.MyService.Notify().AddLog(installLog)
if m.Origin != "custom" { if m.Origin != "custom" {
for _, plugin := range appInfo.Plugins { for _, plugin := range appInfo.Plugins {
@@ -441,6 +445,8 @@ func InstallApp(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)
cmd, _ := json2.Marshal(m.Cmd)
capAdd, _ := json.Marshal(m.CapAdd)
//step: 保存数据到数据库 //step: 保存数据到数据库
md := model2.AppListDBModel{ md := model2.AppListDBModel{
CustomId: id, CustomId: id,
@@ -471,6 +477,10 @@ func InstallApp(c *gin.Context) {
Origin: m.Origin, Origin: m.Origin,
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10), CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10), UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
Cmd: string(cmd),
CapAdd: string(capAdd),
HostName: m.HostName,
Privileged: m.Privileged,
} }
//if appInfo.NetworkModel == "host" { //if appInfo.NetworkModel == "host" {
// m.PortMap = m.Port // m.PortMap = m.Port
@@ -714,7 +724,7 @@ func UnInstallApp(c *gin.Context) {
} }
//step: 删除install log //step: 删除install log
service.MyService.Notify().DelLog(appId) //service.MyService.Notify().DelLog(appId)
// for k, v := range info.Rely { // for k, v := range info.Rely {
// //
@@ -754,6 +764,13 @@ func UnInstallApp(c *gin.Context) {
//} //}
} }
config.CasaOSGlobalVariables.AppChange = true config.CasaOSGlobalVariables.AppChange = true
unInstallLog := model2.AppNotify{}
unInstallLog.State = 0
unInstallLog.CustomId = appId
unInstallLog.Message = "uninstalled"
unInstallLog.Id = uuid.NewV4().String()
service.MyService.Notify().UpdateLog(unInstallLog)
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)})
} }
@@ -925,7 +942,9 @@ 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 || m.NetworkModel != appInfo.NetModel { capAddStr, _ := json2.Marshal(m.CapAdd)
cmdStr, _ := json.Marshal(m.Cmd)
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 || m.HostName != appInfo.HostName || !reflect.DeepEqual(string(cmdStr), appInfo.Cmd) || !reflect.DeepEqual(string(capAddStr), appInfo.CapAdd) || m.Privileged != appInfo.Privileged {
var newUUid = uuid.NewV4().String() var newUUid = uuid.NewV4().String()
var err error var err error
@@ -1043,6 +1062,10 @@ func UpdateSetting(c *gin.Context) {
appInfo.Restart = m.Restart appInfo.Restart = m.Restart
appInfo.Memory = m.Memory appInfo.Memory = m.Memory
appInfo.CpuShares = m.CpuShares appInfo.CpuShares = m.CpuShares
appInfo.Cmd = string(cmdStr)
appInfo.Privileged = m.Privileged
appInfo.CapAdd = string(capAddStr)
appInfo.HostName = m.HostName
appInfo.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10) appInfo.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
service.MyService.App().UpdateApp(appInfo) service.MyService.App().UpdateApp(appInfo)
@@ -1138,7 +1161,6 @@ func ContainerRelyInfo(c *gin.Context) {
func ContainerUpdateInfo(c *gin.Context) { func ContainerUpdateInfo(c *gin.Context) {
appId := c.Param("id") appId := c.Param("id")
appInfo := service.MyService.App().GetAppDBInfo(appId) appInfo := service.MyService.App().GetAppDBInfo(appId)
info, err := service.MyService.Docker().DockerContainerInfo(appId) info, err := service.MyService.Docker().DockerContainerInfo(appId)
if err != nil { if err != nil {
//todo 需要自定义错误 //todo 需要自定义错误
@@ -1161,6 +1183,10 @@ func ContainerUpdateInfo(c *gin.Context) {
var dir model.PathArray var dir model.PathArray
json2.Unmarshal([]byte(appInfo.Devices), &dir) json2.Unmarshal([]byte(appInfo.Devices), &dir)
var cmd []string
json2.Unmarshal([]byte(appInfo.Cmd), &cmd)
var capAdd []string
json2.Unmarshal([]byte(appInfo.CapAdd), &capAdd)
//volumesStr, _ := json2.Marshal(m.Volumes) //volumesStr, _ := json2.Marshal(m.Volumes)
//devicesStr, _ := json2.Marshal(m.Devices) //devicesStr, _ := json2.Marshal(m.Devices)
m := model.CustomizationPostData{} m := model.CustomizationPostData{}
@@ -1182,6 +1208,11 @@ func ContainerUpdateInfo(c *gin.Context) {
m.EnableUPNP = appInfo.EnableUPNP m.EnableUPNP = appInfo.EnableUPNP
m.Position = appInfo.Position m.Position = appInfo.Position
m.CapAdd = capAdd
m.Cmd = cmd
m.HostName = appInfo.HostName
m.Privileged = appInfo.Privileged
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m})
} }

View File

@@ -9,8 +9,7 @@ import (
"net/http" "net/http"
"os" "os"
"path" "path"
"path/filepath" "strings"
"time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
@@ -127,12 +126,12 @@ func GetLocalFile(c *gin.Context) {
return return
} }
// @Summary 下载文件 // @Summary download
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path query string true "路径" // @Param path query string true "path of file"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/download [get] // @Router /file/download [get]
func GetDownloadFile(c *gin.Context) { func GetDownloadFile(c *gin.Context) {
@@ -165,7 +164,6 @@ func GetDownloadFile(c *gin.Context) {
c.Header("Content-Transfer-Encoding", "binary") c.Header("Content-Transfer-Encoding", "binary")
c.File(filePath) c.File(filePath)
return
} }
// @Summary 获取目录列表 // @Summary 获取目录列表
@@ -177,18 +175,18 @@ func GetDownloadFile(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/dirpath [get] // @Router /file/dirpath [get]
func DirPath(c *gin.Context) { func DirPath(c *gin.Context) {
path := c.DefaultQuery("path", "/") path := c.DefaultQuery("path", "")
info := service.MyService.ZiMa().GetDirPath(path) info := service.MyService.ZiMa().GetDirPath(path)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
} }
// @Summary 重命名目录或文件 // @Summary rename file or dir
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param oldpath formData string true "旧的路径" // @Param oldpath formData string true "path of old"
// @Param newpath formData string true "新路径" // @Param newpath formData string true "path of new"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/rename [put] // @Router /file/rename [put]
func RenamePath(c *gin.Context) { func RenamePath(c *gin.Context) {
@@ -202,12 +200,12 @@ func RenamePath(c *gin.Context) {
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)})
} }
// @Summary 创建文件夹 // @Summary create folder
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string false "路径" // @Param path formData string true "path of folder"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/mkdir [post] // @Router /file/mkdir [post]
func MkdirAll(c *gin.Context) { func MkdirAll(c *gin.Context) {
@@ -240,82 +238,85 @@ func PostCreateFile(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 上传文件 // @Summary upload file
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string false "路径" // @Param path formData string false "file path"
// @Param file formData file true "file"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/mkdir [post] // @Router /file/upload [post]
func PostFileUpload(c *gin.Context) { func PostFileUpload(c *gin.Context) {
file, _, _ := c.Request.FormFile("file") f, _, _ := c.Request.FormFile("file")
//file.Read()
path := c.Query("path") path := c.Query("path")
//上传文件 if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if !file.CheckNotExist(path) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644) out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
defer out.Close() defer out.Close()
io.Copy(out, file) _, err := io.Copy(out, f)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
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) { // @Summary copy or move file
from := "/Users/liangjianli/go/CasaOS" // @Produce application/json
to := "/Users/liangjianli/go/CasaOS/test" // @Accept multipart/form-data
//t := 1 //是否覆盖 // @Tags file
// @Security ApiKeyAuth
//方法体 // @Param from formData string true "from path"
stopCh := make(chan int) // @Param to formData string true "to path"
f, err := os.Stat(from) // @Param t formData string true "action" Enums(move,copy)
// @Success 200 {string} string "ok"
// @Router /file/operate [post]
func PostOperateFileOrDir(c *gin.Context) {
from := c.PostForm("from")
to := c.PostForm("to")
t := c.PostForm("type")
if len(from) == 0 || len(t) == 0 || len(to) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if t == "move" {
lastPath := from[strings.LastIndex(from, "/")+1:]
if !file.CheckNotExist(to + "/" + lastPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_OR_DIR_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
err := os.Rename(from, to+"/"+lastPath)
if err != nil { if err != nil {
//未拿到文件信息 c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
fmt.Println("stat", err) return
}
//未创建新的文件夹
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 if t == "copy" {
err := file.CopyDir(from, to)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
} }
} else { } else {
p := filepath.Dir(to) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
if _, err = os.Stat(p); err != nil { return
if err = os.MkdirAll(p, 0777); err != nil {
fmt.Println("mkdir", err)
} }
} c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
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 { func DeleteFile(c *gin.Context) {
path := c.Query("path")
for { //err := os.Remove(path)
select { err := os.RemoveAll(path)
case <-stop: if err != nil {
return nil fmt.Println(err)
default: c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
fmt.Println(from) return
} }
} c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
return nil
} }

View File

@@ -1,15 +1,13 @@
package v1 package v1
import ( import (
json2 "encoding/json" "fmt"
"github.com/IceWhaleTech/CasaOS/model" "net/http"
"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/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"net/http"
"time"
) )
var upGrader = websocket.Upgrader{ var upGrader = websocket.Upgrader{
@@ -33,24 +31,17 @@ func NotifyWS(c *gin.Context) {
return return
} }
defer ws.Close() defer ws.Close()
service.WebSocketConns = append(service.WebSocketConns, ws)
if !service.SocketRun {
service.SocketRun = true
service.SendMeg()
}
for { for {
mt, message, err := ws.ReadMessage() mt, message, err := ws.ReadMessage()
if err != nil { fmt.Println(mt, message, err)
break
}
if string(message) != "notify" {
return
}
for {
list := service.MyService.Notify().GetList()
json, _ := json2.Marshal(list)
err = ws.WriteMessage(mt, json)
if err != nil {
break
}
time.Sleep(time.Second * 2)
}
} }
} }
// @Summary 标记notify已读 // @Summary 标记notify已读
@@ -62,9 +53,10 @@ func NotifyWS(c *gin.Context) {
// @Router /notify/read/{id} [put] // @Router /notify/read/{id} [put]
func PutNotifyRead(c *gin.Context) { func PutNotifyRead(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
if len(id) == 0 { // if len(id) == 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 // return
} // }
fmt.Println(id)
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ) service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
} }

25
route/v1/persion.go Normal file
View File

@@ -0,0 +1,25 @@
package v1
import (
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
)
func PersonTest(c *gin.Context) {
//service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9")
m := model.ConnectState{}
m.CreatedAt = time.Now()
m.From = config.ServerInfo.Token
m.To = "fb2333a1-72b2-4cb4-9e31-61ccaffa55b9"
m.Type = ""
m.UUId = uuid.NewV4().String()
service.MyService.Person().Handshake(m)
}

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
"reflect"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -107,9 +108,33 @@ 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,total:%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()
@@ -234,10 +259,104 @@ func PostKillCasaOS(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/info [get] // @Router /sys/info [get]
func Info(c *gin.Context) { func Info(c *gin.Context) {
var data = make(map[string]interface{}, 5) var data = make(map[string]interface{}, 6)
list := service.MyService.Disk().LSBLK() list := service.MyService.Disk().LSBLK(true)
data["disk"] = list
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() cpu := service.MyService.ZiMa().GetCpuPercent()
num := service.MyService.ZiMa().GetCpuCoreNum() num := service.MyService.ZiMa().GetCpuCoreNum()
cpuData := make(map[string]interface{}) cpuData := make(map[string]interface{})

View File

@@ -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)})
} }

View File

@@ -1,6 +1,7 @@
package service package service
import ( import (
"encoding/json"
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
"strconv" "strconv"
@@ -13,11 +14,12 @@ import (
) )
type CasaService interface { type CasaService interface {
GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList) GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList)
GetServerCategoryList() []model.ServerCategoryList GetServerCategoryList() []model.ServerCategoryList
GetTaskList(size int) []model2.TaskDBModel GetTaskList(size int) []model2.TaskDBModel
GetServerAppInfo(id string) model.ServerAppList GetServerAppInfo(id, t string, language string) model.ServerAppList
ShareAppFile(body []byte) string ShareAppFile(body []byte) string
PushHeart(id, t string, language string)
} }
type casaService struct { type casaService struct {
@@ -45,9 +47,9 @@ func (o *casaService) GetTaskList(size int) []model2.TaskDBModel {
return list return list
} }
func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (recommend, list, community []model.ServerAppList) { func (o *casaService) GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList) {
keyName := fmt.Sprintf("list_%s_%s_%s_%s", index, size, tp, categoryId) keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, language)
if result, ok := Cache.Get(keyName); ok { if result, ok := Cache.Get(keyName); ok {
res, ok := result.(string) res, ok := result.(string)
@@ -63,7 +65,7 @@ func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (re
head["Authorization"] = GetToken() head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index="+index+"&size="+size+"&rank="+tp+"&category_id="+categoryId+"&key="+key, head) 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.list").String()), &list)
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend) json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend)
@@ -88,13 +90,12 @@ func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
return list return list
} }
func (o *casaService) GetServerAppInfo(id string) model.ServerAppList { func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {
head := make(map[string]string) head := make(map[string]string)
head["Authorization"] = GetToken() head["Authorization"] = GetToken()
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t+"&language="+language, head)
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id, head)
info := model.ServerAppList{} info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info) json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
@@ -124,6 +125,24 @@ func GetToken() string {
return auth return auth
} }
func (o *casaService) PushHeart(id, t string, language string) {
m := model.CasaOSHeart{}
m.UuId = id
m.Type = t
b, _ := json.Marshal(m)
head := make(map[string]string)
head["Authorization"] = GetToken()
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/heart", b, "application/json", head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
}
func NewOasisService() CasaService { func NewOasisService() CasaService {
return &casaService{} return &casaService{}
} }

View File

@@ -3,6 +3,7 @@ package service
import ( import (
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
"reflect"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -19,9 +20,10 @@ import (
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 string) string AddPartition(path string) string
@@ -31,30 +33,60 @@ type DiskService interface {
SaveMountPoint(m model2.SerialDisk) SaveMountPoint(m model2.SerialDisk)
DeleteMountPoint(path, mountPoint string) DeleteMountPoint(path, mountPoint string)
DeleteMount(id string) DeleteMount(id string)
UpdateMountPoint(m model2.SerialDisk)
RemoveLSBLKCache()
} }
type diskService struct { type diskService struct {
log loger2.OLog log loger2.OLog
db *gorm.DB 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
}
//通过脚本获取外挂磁盘 //通过脚本获取外挂磁盘
func (d *diskService) GetPlugInDisk() []string { func (d *diskService) GetPlugInDisk() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPlugInDisk") return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPlugInDisk")
} }
//格式化硬盘 //格式化硬盘
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 ""
} }
//删除分区 //删除分区
@@ -66,8 +98,7 @@ func (d *diskService) DelPartition(path, num string) string {
//part //part
func (d *diskService) AddPartition(path string) string { func (d *diskService) AddPartition(path string) string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path) command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path)
fmt.Println(r)
return "" return ""
} }
@@ -78,23 +109,21 @@ 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 //get disk details
func (d *diskService) LSBLK() []model.LSBLKModel { func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
key := "system_lsblk" key := "system_lsblk"
var n []model.LSBLKModel var n []model.LSBLKModel
if result, ok := Cache.Get(key); ok { if result, ok := Cache.Get(key); ok && isUseCache {
res, ok := result.([]model.LSBLKModel) res, ok := result.([]model.LSBLKModel)
if ok { if ok {
@@ -151,7 +180,7 @@ func (d *diskService) LSBLK() []model.LSBLKModel {
} }
} }
if len(n) > 0 { if len(n) > 0 {
Cache.Add(key, n, time.Second*10) Cache.Add(key, n, time.Second*100)
} }
return n return n
} }
@@ -162,6 +191,7 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
d.log.Error("lsblk exec error,str") 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 {
@@ -169,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 {
@@ -182,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], ",")
@@ -191,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 {
//添加可以分区情况 //添加可以分区情况
@@ -214,9 +247,14 @@ func (d *diskService) MountDisk(path, volume string) {
} }
func (d *diskService) SaveMountPoint(m model2.SerialDisk) { func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
d.db.Create(&m) d.db.Create(&m)
} }
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint)
}
func (d *diskService) DeleteMount(id string) { func (d *diskService) DeleteMount(id string) {
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id) d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
@@ -224,7 +262,7 @@ func (d *diskService) DeleteMount(id string) {
func (d *diskService) DeleteMountPoint(path, mountPoint string) { func (d *diskService) DeleteMountPoint(path, mountPoint string) {
d.db.Delete(&model2.SerialDisk{}).Where("path= ? && mount_point = ?", path, mountPoint) d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path) command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path)
} }

View File

@@ -433,7 +433,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
} }
for _, p := range m.Devices { for _, p := range m.Devices {
if len(p.Path) > 0 { if len(p.Path) > 0 {
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, CgroupPermissions: "rwm"})
} }
} }
hostConfingBind := []string{} hostConfingBind := []string{}
@@ -490,13 +490,18 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
// Retries: 1000, // Retries: 1000,
// } // }
// fmt.Print(health) // fmt.Print(health)
if len(m.HostName) == 0 {
m.HostName = m.Label
}
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, // Healthcheck: health,
Hostname: m.HostName,
Cmd: m.Cmd,
} }
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), Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" { //if net != "host" {
config.ExposedPorts = ports config.ExposedPorts = ports
hostConfig.PortBindings = portMaps hostConfig.PortBindings = portMaps
@@ -754,7 +759,7 @@ func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id
res.CPUShares = m.CpuShares res.CPUShares = m.CpuShares
} }
for _, p := range m.Devices { for _, p := range m.Devices {
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, CgroupPermissions: "rwm"})
} }
_, err = cli.ContainerUpdate(context.Background(), id, container.UpdateConfig{RestartPolicy: rp, Resources: res}) _, err = cli.ContainerUpdate(context.Background(), id, container.UpdateConfig{RestartPolicy: rp, Resources: res})
if err != nil { if err != nil {

View File

@@ -41,6 +41,10 @@ type AppListDBModel struct {
Restart string `json:"restart"` Restart string `json:"restart"`
//Rely model.MapStrings `gorm:"type:json" json:"rely"` //[{"mysql":"id"},{"mysql":"id"}] //Rely model.MapStrings `gorm:"type:json" json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
Origin string `json:"origin"` Origin string `json:"origin"`
HostName string `json:"host_name"`
Privileged bool `json:"privileged"`
CapAdd string `json:"cap_add"`
Cmd string `gorm:"type:json" json:"cmd"`
} }
func (p *AppListDBModel) TableName() string { func (p *AppListDBModel) TableName() string {

View File

@@ -3,10 +3,11 @@ package model
//SerialAdvanced Technology Attachment (STAT) //SerialAdvanced Technology Attachment (STAT)
type SerialDisk struct { type SerialDisk struct {
Id uint `gorm:"column:id;primary_key" json:"id"` Id uint `gorm:"column:id;primary_key" json:"id"`
Serial string `json:"serial"` UUID string `json:"uuid"`
Path string `json:"path"` Path string `json:"path"`
State int `json:"state"` State int `json:"state"`
MountPoint string `json:"mount_point"` MountPoint string `json:"mount_point"`
CreatedAt int64 `json:"created_at"`
} }
func (p *SerialDisk) TableName() string { func (p *SerialDisk) TableName() string {

View File

@@ -6,9 +6,10 @@ type AppNotify struct {
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"` UpdatedAt string `json:"updated_at"`
Id string `json:"id"` Id string `json:"id"`
Type int `json:"type"` // 1:显示即为已读 2:info 3:warning 4:error 5:success Type int `json:"type"`
Icon string `json:"icon"` Icon string `json:"icon"`
Name string `json:"name"` Name string `json:"name"`
Class int `json:"class"`
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"` CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
} }

View File

@@ -1,8 +1,12 @@
package service package service
import ( import (
json2 "encoding/json"
"time"
"github.com/IceWhaleTech/CasaOS/service/model" "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
"github.com/gorilla/websocket"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -10,8 +14,9 @@ type NotifyServer interface {
GetLog(id string) model.AppNotify GetLog(id string) model.AppNotify
AddLog(log model.AppNotify) AddLog(log model.AppNotify)
UpdateLog(log model.AppNotify) UpdateLog(log model.AppNotify)
UpdateLogByCustomId(log model.AppNotify)
DelLog(id string) DelLog(id string)
GetList() (list []model.AppNotify) GetList(c int) (list []model.AppNotify)
MarkRead(id string, state int) MarkRead(id string, state int)
} }
@@ -19,8 +24,8 @@ type notifyServer struct {
db *gorm.DB db *gorm.DB
} }
func (i notifyServer) GetList() (list []model.AppNotify) { func (i notifyServer) GetList(c int) (list []model.AppNotify) {
i.db.Where("state=? or state=?", types.NOTIFY_DYNAMICE, types.NOTIFY_UNREAD).Find(&list) i.db.Where("class = ?", c).Where(i.db.Where("state = ?", types.NOTIFY_DYNAMICE).Or("state = ?", types.NOTIFY_UNREAD)).Find(&list)
return return
} }
@@ -31,20 +36,72 @@ func (i *notifyServer) AddLog(log model.AppNotify) {
func (i *notifyServer) UpdateLog(log model.AppNotify) { func (i *notifyServer) UpdateLog(log model.AppNotify) {
i.db.Save(&log) i.db.Save(&log)
} }
func (i *notifyServer) UpdateLogByCustomId(log model.AppNotify) {
if len(log.CustomId) == 0 {
return
}
i.db.Model(&model.AppNotify{}).Select("*").Where("custom_id = ? ", log.CustomId).Updates(log)
}
func (i *notifyServer) GetLog(id string) model.AppNotify { func (i *notifyServer) GetLog(id string) model.AppNotify {
var log model.AppNotify var log model.AppNotify
i.db.Where("custom_id = ? ", id).First(&log) i.db.Where("custom_id = ? ", id).First(&log)
return log return log
} }
func (i *notifyServer) MarkRead(id string, state int) { func (i *notifyServer) MarkRead(id string, state int) {
i.db.Update("state=", state).Where("custom_id = ? ", id) if id == "0" {
i.db.Model(&model.AppNotify{}).Where("1 = ?", 1).Update("state", state)
return
}
i.db.Model(&model.AppNotify{}).Where("id = ? ", id).Update("state", state)
} }
func (i *notifyServer) DelLog(id string) { func (i *notifyServer) DelLog(id string) {
var log model.AppNotify var log model.AppNotify
i.db.Where("custom_id = ?", id).Delete(&log) i.db.Where("custom_id = ?", id).Delete(&log)
} }
func SendMeg() {
// for {
// mt, message, err := ws.ReadMessage()
// if err != nil {
// break
// }
// notify := model.NotifyMssage{}
// json2.Unmarshal(message, &notify)
// if notify.Type == "read" {
// service.MyService.Notify().MarkRead(notify.Data, types.NOTIFY_READ)
// }
// if notify.Type == "app" {
// go func(ws *websocket.Conn) {
for {
list := MyService.Notify().GetList(types.NOTIFY_APP)
json, _ := json2.Marshal(list)
if len(list) > 0 {
var temp []*websocket.Conn
for _, v := range WebSocketConns {
err := v.WriteMessage(1, json)
if err == nil {
temp = append(temp, v)
}
}
WebSocketConns = temp
for _, v := range list {
MyService.Notify().MarkRead(v.Id, types.NOTIFY_READ)
}
}
if len(WebSocketConns) == 0 {
SocketRun = false
}
time.Sleep(time.Second * 2)
}
// }(ws)
// }
// }
}
func NewNotifyService(db *gorm.DB) NotifyServer { func NewNotifyService(db *gorm.DB) NotifyServer {
return &notifyServer{db: db} return &notifyServer{db: db}
} }

117
service/person.go Normal file
View File

@@ -0,0 +1,117 @@
package service
import (
"encoding/json"
"fmt"
"log"
"net"
"reflect"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
)
type PersonService interface {
GetPersionInfo(token string) (m model.PersionModel, err error)
Handshake(m model.ConnectState)
}
type personService struct {
}
var IpInfo model.PersionModel
func PushIpInfo(token string) {
m := model.PersionModel{}
m.Ips = GetDeviceAllIP()
m.Token = token
b, _ := json.Marshal(m)
if reflect.DeepEqual(IpInfo, m) {
return
}
head := make(map[string]string)
infoS := httper2.Post(config.ServerInfo.Handshake+"/v1/update", b, "application/json", head)
fmt.Println(infoS)
}
func (p *personService) GetPersionInfo(token string) (m model.PersionModel, err error) {
infoS := httper2.Get(config.ServerInfo.Handshake+"/v1/ips/"+token, nil)
err = json.Unmarshal([]byte(infoS), &m)
return
}
//尝试连接
func (p *personService) Handshake(m model.ConnectState) {
//1先进行udp打通成功
srcAddr := &net.UDPAddr{
IP: net.IPv4zero, Port: 9901} //注意端口必须固定
dstAddr := &net.UDPAddr{
IP: net.ParseIP(config.ServerInfo.Handshake), Port: 9527}
//DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6"如果laddr不是nil将使用它作为本地地址否则自动选择一个本地地址。
//(conn)UDPConn代表一个UDP网络连接实现了Conn和PacketConn接口
conn, err := net.DialUDP("udp", srcAddr, dstAddr)
if err != nil {
fmt.Println(err)
}
b, _ := json.Marshal(m)
if _, err = conn.Write(b); err != nil {
fmt.Println(err)
}
data := make([]byte, 1024)
//ReadFromUDP从c读取一个UDP数据包将有效负载拷贝到b返回拷贝字节数和数据包来源地址。
//ReadFromUDP方***在超过一个固定的时间点之后超时,并返回一个错误。
n, _, err := conn.ReadFromUDP(data)
if err != nil {
fmt.Printf("error during read: %s", err)
}
conn.Close()
toPersion := model.PersionModel{}
err = json.Unmarshal(data[:n], &toPersion)
if err != nil {
fmt.Println(err)
}
// bidirectionHole(srcAddr, &anotherPeer)
//2udp打洞成功向服务器汇报打洞结果
//3转udp打洞
}
func bidirectionHole(srcAddr *net.UDPAddr, anotherAddr *net.UDPAddr) {
conn, err := net.DialUDP("udp", srcAddr, anotherAddr)
if err != nil {
fmt.Println("send handshake:", err)
}
go func() {
for {
time.Sleep(10 * time.Second)
if _, err = conn.Write([]byte("from []")); err != nil {
log.Println("send msg fail", err)
}
}
}()
for {
data := make([]byte, 1024)
n, _, err := conn.ReadFromUDP(data)
if err != nil {
log.Printf("error during read:%s\n", err)
} else {
log.Printf("收到数据:%s\n", data[:n])
}
}
}
func NewPersonService() PersonService {
return &personService{}
}

View File

@@ -2,6 +2,7 @@ package service
import ( import (
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/gorilla/websocket"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -10,6 +11,10 @@ var Cache *cache.Cache
var MyService Repository var MyService Repository
var WebSocketConns []*websocket.Conn
var SocketRun bool
type Repository interface { type Repository interface {
App() AppService App() AppService
DDNS() DDNSService DDNS() DDNSService
@@ -27,6 +32,7 @@ type Repository interface {
System() SystemService System() SystemService
Shortcuts() ShortcutsService Shortcuts() ShortcutsService
Search() SearchService Search() SearchService
Person() PersonService
} }
func NewService(db *gorm.DB, log loger2.OLog) Repository { func NewService(db *gorm.DB, log loger2.OLog) Repository {
@@ -48,6 +54,7 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
system: NewSystemService(log), system: NewSystemService(log),
shortcuts: NewShortcutsService(db), shortcuts: NewShortcutsService(db),
search: NewSearchService(), search: NewSearchService(),
person: NewPersonService(),
} }
} }
@@ -68,6 +75,7 @@ type store struct {
system SystemService system SystemService
shortcuts ShortcutsService shortcuts ShortcutsService
search SearchService search SearchService
person PersonService
} }
func (c *store) Rely() RelyService { func (c *store) Rely() RelyService {
@@ -76,6 +84,9 @@ func (c *store) Rely() RelyService {
func (c *store) Shortcuts() ShortcutsService { func (c *store) Shortcuts() ShortcutsService {
return c.shortcuts return c.shortcuts
} }
func (c *store) Person() PersonService {
return c.person
}
func (c *store) System() SystemService { func (c *store) System() SystemService {
return c.system return c.system
} }

View File

@@ -2,6 +2,7 @@ package service
import ( import (
"io/ioutil" "io/ioutil"
"net"
"os" "os"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
@@ -71,6 +72,21 @@ func (s *systemService) GetCasaOSLogs(lineNumber int) string {
return string(content) return string(content)
} }
func GetDeviceAllIP() []string {
var address []string
addrs, err := net.InterfaceAddrs()
if err != nil {
return address
}
for _, a := range addrs {
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To16() != nil {
address = append(address, ipNet.IP.String())
}
}
}
return address
}
func NewSystemService(log loger.OLog) SystemService { func NewSystemService(log loger.OLog) SystemService {
return &systemService{log: log} return &systemService{log: log}
} }

View File

@@ -28,10 +28,6 @@ func (c *user) SetUser(username, pwd, token, email, desc string) error {
config.Cfg.Section("user").Key("PWD").SetValue(pwd) config.Cfg.Section("user").Key("PWD").SetValue(pwd)
config.UserInfo.PWD = pwd config.UserInfo.PWD = pwd
} }
if len(token) > 0 {
config.Cfg.Section("user").Key("Token").SetValue(token)
config.UserInfo.Token = token
}
if len(email) > 0 { if len(email) > 0 {
config.Cfg.Section("user").Key("Email").SetValue(email) config.Cfg.Section("user").Key("Email").SetValue(email)
config.UserInfo.Email = email config.UserInfo.Email = email

View File

@@ -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,6 +35,7 @@ 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 {
} }
@@ -333,6 +336,13 @@ func (c *zerotierStruct) GetJoinNetworks() string {
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 {

View File

@@ -7,6 +7,7 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
@@ -84,12 +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, "/") > 0 { if len(path) > 0 {
for _, l := range ls { for _, l := range ls {
dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir()}) dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir(), Date: l.ModTime()})
} }
} else { } else {
dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true}) dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()})
} }
return dirs return dirs
} }

View File

@@ -9,4 +9,32 @@ version_0_2_3() {
} }
# add in v0.2.5
readonly CASA_DEPANDS="curl smartmontools parted fdisk ntfs-3g"
version_0_2_5() {
install_depends "$CASA_DEPANDS"
}
#Install Depends
install_depends() {
((EUID)) && sudo_cmd="sudo"
if [[ ! -x "$(command -v '$1')" ]]; then
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
fi
fi
}
version_0_2_3 version_0_2_3
version_0_2_5

View File

@@ -73,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
} }
@@ -89,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
} }
@@ -117,13 +115,11 @@ AddPartition() {
parted -s $1 mklabel gpt parted -s $1 mklabel gpt
parted -s $1 mkpart primary ext4 0 100% parted -s $1 mkpart primary ext4 0 100%
PATH=`lsblk -r $1 | sort | grep part | head -n 1 | awk '{print $1}'`
mkfs.ext4 $11 mkfs.ext4 -m 1 /dev/${PATH}
partprobe $1 partprobe $1
# mount $11 $2
} }
#磁盘类型 #磁盘类型
@@ -148,20 +144,20 @@ 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() { AutoRemoveUnuseDir() {
DIRECTORY="/mnt/" DIRECTORY="/DATA/"
dir=$(ls -l $DIRECTORY | awk '/^d/ {print $NF}') dir=$(ls -l $DIRECTORY | grep "Storage[0-9]" | awk '/^d/ {print $NF}')
for i in $dir; do for i in $dir; do
path="$DIRECTORY$i" path="$DIRECTORY$i"
@@ -188,7 +184,7 @@ do_mount() {
DEVBASE=$1 DEVBASE=$1
DEVICE="${DEVBASE}" DEVICE="${DEVBASE}"
# See if this drive is already mounted, and if so where # See if this drive is already mounted, and if so where
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }') MOUNT_POINT=$(lsblk -o name,mountpoint | grep ${DEVICE} | awk '{print $2}')
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}"

View File

@@ -1,4 +1,4 @@
#!/bin/sh #!/bin/bash
# copy to /casaOS/util/shell path # copy to /casaOS/util/shell path
# chmod 755 # chmod 755
@@ -12,7 +12,7 @@ DEVBASE=$2
DEVICE="/dev/${DEVBASE}" DEVICE="/dev/${DEVBASE}"
# See if this drive is already mounted, and if so where # See if this drive is already mounted, and if so where
MOUNT_POINT=$(mount | grep ${DEVICE} | awk '{ print $3 }') MOUNT_POINT=$(lsblk -o name,mountpoint | grep ${DEVICE} | awk '{print $2}')
do_mount() { do_mount() {
@@ -30,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 " /mnt/casa_${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="/mnt/casa_${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"

View File

@@ -11,3 +11,7 @@ const (
NOTIFY_TYPE_ERROR NOTIFY_TYPE_ERROR
NOTIFY_TYPE_INSTALL_LOG NOTIFY_TYPE_INSTALL_LOG
) )
const (
NOTIFY_APP = iota
)

View File

@@ -1,4 +1,5 @@
package types package types
const CURRENTVERSION = "0.2.4" const CURRENTVERSION = "0.2.9"
const BODY = "<li>New App Store</li><li>Fix minor bugs</li>"
const BODY = "<li>Custom installation of new parameters</li><li>Fixed issues</li><li>Update front-end translation</li>"

BIN
web/img/USB.3ba78dec.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@@ -15,7 +15,7 @@
<meta name="msapplication-TileColor" content="#da532c"> <meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<link rel="icon" href="/ui/favicon.svg" type="image/svg+xml"> <link rel="icon" href="/ui/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@mdi/font@6.2.95/css/materialdesignicons.min.css"> <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@mdi/font@6.5.95/css/materialdesignicons.min.css">
<title> <title>
CasaOS CasaOS
</title> </title>

View File

@@ -214,7 +214,7 @@ eval("module.exports = __webpack_require__.p + \"img/Account.1bc4a418.png\";\n\n
/***/ (function(module, __webpack_exports__, __webpack_require__) { /***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict"; "use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_jerry_Desktop_CasaOS_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/objectSpread2 */ \"./node_modules/@babel/runtime/helpers/esm/objectSpread2.js\");\n/* harmony import */ var vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vee-validate/dist/rules */ \"./node_modules/vee-validate/dist/rules.js\");\n/* harmony import */ var vee_validate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vee-validate */ \"./node_modules/vee-validate/dist/vee-validate.esm.js\");\n\n\n\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"required\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"required\"]), {}, {\n message: \"This field is required\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"email\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"email\"]), {}, {\n message: \"This field must be a valid email\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"confirmed\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"confirmed\"]), {}, {\n message: \"This field confirmation does not match\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"length\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"length\"]), {}, {\n message: \"This field must have 2 options\"\n}));\nObject(vee_validate__WEBPACK_IMPORTED_MODULE_2__[\"extend\"])(\"min\", Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(Object(_Users_liangjianli_go_CasaOSNew_CasaOS_UI_node_modules_babel_runtime_helpers_esm_objectSpread2__WEBPACK_IMPORTED_MODULE_0__[\"default\"])({}, vee_validate_dist_rules__WEBPACK_IMPORTED_MODULE_1__[\"min\"]), {}, {\n message: \"This field must have more than {length} characters\"\n}));\n\n//# sourceURL=webpack:///./src/plugins/vee-validate.js?");
/***/ }) /***/ })

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long